diff options
author | Martin Poirier <theeth@yahoo.com> | 2009-02-24 00:00:42 +0300 |
---|---|---|
committer | Martin Poirier <theeth@yahoo.com> | 2009-02-24 00:00:42 +0300 |
commit | 7c830b75f160db4de8c415dcf1c0b3bf554a4821 (patch) | |
tree | 4892c025ae6bffdb20fb81213ba57f538a4b2e53 | |
parent | e25318ebefb4dd34443430ab0b7408d3a6118b3d (diff) | |
parent | 334da0fa57195af65c2877ee2882714efe5431f9 (diff) |
merging trunk 17520:19093
396 files changed, 14084 insertions, 3547 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index e01a37d3b3e..4b96ca585a6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -175,7 +175,7 @@ IF(UNIX) SET(FFMPEG /usr) SET(FFMPEG_INC ${FFMPEG}/include) - SET(FFMPEG_LIB avformat avcodec avutil) + SET(FFMPEG_LIB avformat avcodec avutil avdevice swscale) SET(FFMPEG_LIBPATH ${FFMPEG}/lib) SET(JPEG_LIB jpeg) diff --git a/SConstruct b/SConstruct index 16e98e64f6b..809166586e6 100644 --- a/SConstruct +++ b/SConstruct @@ -115,8 +115,9 @@ if toolset: env.Tool('mstoolkit', ['tools']) else: env = BlenderEnvironment(tools=[toolset], ENV = os.environ) - if env: - btools.SetupSpawn(env) + # xxx commented out, as was supressing warnings under mingw.. + #if env: + # btools.SetupSpawn(env) else: env = BlenderEnvironment(ENV = os.environ) @@ -321,10 +322,15 @@ if not quickie and do_clean: print "remove file %s"%(B.root_build_dir+entry) os.remove(B.root_build_dir+entry) for confile in ['extern/ffmpeg/config.mak', 'extern/x264/config.mak', - 'extern/xvidcore/build/generic/platform.inc']: + 'extern/xvidcore/build/generic/platform.inc', 'extern/ffmpeg/include']: if os.path.exists(confile): print "clean file %s"%confile - os.remove(confile) + if os.path.isdir(confile): + for root, dirs, files in os.walk(confile): + for name in files: + os.remove(os.path.join(root, name)) + else: + os.remove(confile) print B.bc.OKGREEN+'...done'+B.bc.ENDC else: print B.bc.HEADER+'Already Clean, nothing to do.'+B.bc.ENDC diff --git a/config/darwin-config.py b/config/darwin-config.py index 3ef7b7132d9..cfd6a9395bb 100644 --- a/config/darwin-config.py +++ b/config/darwin-config.py @@ -40,7 +40,11 @@ else: # enable ffmpeg support WITH_BF_FFMPEG = True # -DWITH_FFMPEG BF_FFMPEG = "#extern/ffmpeg" -BF_FFMPEG_INC = '${BF_FFMPEG}/include' +# trick : The version of ffmpeg in extern/ffmpeg uses explicit libav.. directory in #include statements +# To keep Blender compatible with older versions, I add ${BF_FFMPEG} to the inc dir so that ffmpeg +# finds the files directly in extern/ffmpeg/libav... while blender finds them in +# extern/ffmpeg/include. +BF_FFMPEG_INC = '${BF_FFMPEG}/include ${BF_FFMPEG}' if USE_SDK==True: BF_FFMPEG_EXTRA = '-isysroot '+MACOSX_SDK+' -mmacosx-version-min='+MAC_MIN_VERS #BF_FFMPEG_LIBPATH='${BF_FFMPEG}/lib' diff --git a/config/irix6-config.py b/config/irix6-config.py new file mode 100644 index 00000000000..81a301fbb03 --- /dev/null +++ b/config/irix6-config.py @@ -0,0 +1,231 @@ +import os + +LCGDIR = os.getcwd()+"/../lib/irix-6.5-mips" +LIBDIR = LCGDIR +print LCGDIR + +WITH_BF_VERSE = 'false' +BF_VERSE_INCLUDE = "#extern/verse/dist" + +BF_PYTHON = LCGDIR+'/python' +BF_PYTHON_VERSION = '2.5' +WITH_BF_STATICPYTHON = 'true' +BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}' +BF_PYTHON_BINARY = '${BF_PYTHON}/bin/python${BF_PYTHON_VERSION}' +BF_PYTHON_LIB = 'python${BF_PYTHON_VERSION}' #BF_PYTHON+'/lib/python'+BF_PYTHON_VERSION+'/config/libpython'+BF_PYTHON_VERSION+'.a' +BF_PYTHON_LINKFLAGS = ['-Xlinker', '-export-dynamic'] +BF_PYTHON_LIB_STATIC = '${BF_PYTHON}/lib/python2.5/config/libpython${BF_PYTHON_VERSION}.a' + +WITH_BF_OPENAL = 'true' +WITH_BF_STATICOPENAL = 'true' +BF_OPENAL = LCGDIR+'/openal' +BF_OPENAL_INC = '${BF_OPENAL}/include' +BF_OPENAL_LIB = 'openal' +BF_OPENAL_LIB_STATIC = '${BF_OPENAL}/lib/libopenal.a' +BF_OPENAL_LIBPATH = LIBDIR + '/lib' + +# some distros have a separate libalut +# if you get linker complaints, you need to uncomment the line below +# BF_OPENAL_LIB = 'openal alut' +# BF_OPENAL_LIB_STATIC = '${BF_OPENAL}/lib/libopenal.a ${BF_OPENAL}/lib/libalut.a' + +BF_CXX = '/usr' +WITH_BF_STATICCXX = 'false' +BF_CXX_LIB_STATIC = '${BF_CXX}/lib/libstdc++.a' + +WITH_BF_SDL = 'true' +BF_SDL = LCGDIR+'/SDL' #$(shell sdl-config --prefix) +BF_SDL_INC = '${BF_SDL}/include/SDL' #$(shell $(BF_SDL)/bin/sdl-config --cflags) +BF_SDL_LIB = 'SDL audio iconv charset' #BF_SDL #$(shell $(BF_SDL)/bin/sdl-config --libs) -lSDL_mixer +BF_SDL_LIBPATH = '${BF_SDL}/lib' + +WITH_BF_FMOD = 'false' +BF_FMOD = LIBDIR + '/fmod' + +WITH_BF_OPENEXR = 'false' +WITH_BF_STATICOPENEXR = 'false' +BF_OPENEXR = '/usr' +# when compiling with your own openexr lib you might need to set... +# BF_OPENEXR_INC = '${BF_OPENEXR}/include/OpenEXR ${BF_OPENEXR}/include' + +BF_OPENEXR_INC = '${BF_OPENEXR}/include/OpenEXR' +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 = 'false' + +WITH_BF_JPEG = 'false' +BF_JPEG = LCGDIR+'/jpeg' +BF_JPEG_INC = '${BF_JPEG}/include' +BF_JPEG_LIB = 'jpeg' +BF_JPEG_LIBPATH = '${BF_JPEG}/lib' + +WITH_BF_PNG = 'false' +BF_PNG = LCGDIR+"/png" +BF_PNG_INC = '${BF_PNG}/include' +BF_PNG_LIB = 'png' +BF_PNG_LIBPATH = '${BF_PNG}/lib' + +BF_TIFF = '/usr/nekoware' +BF_TIFF_INC = '${BF_TIFF}/include' + +WITH_BF_ZLIB = 'true' +BF_ZLIB = LCGDIR+"/zlib" +BF_ZLIB_INC = '${BF_ZLIB}/include' +BF_ZLIB_LIB = 'z' +BF_ZLIB_LIBPATH = '${BF_ZLIB}/lib' + +WITH_BF_INTERNATIONAL = 'true' + +BF_GETTEXT = LCGDIR+'/gettext' +BF_GETTEXT_INC = '${BF_GETTEXT}/include' +BF_GETTEXT_LIB = 'gettextpo intl' +BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib' + +WITH_BF_FTGL = 'true' +BF_FTGL = '#extern/bFTGL' +BF_FTGL_INC = '${BF_FTGL}/include' +BF_FTGL_LIB = 'extern_ftgl' + +WITH_BF_GAMEENGINE='false' + +WITH_BF_ODE = 'false' +BF_ODE = LIBDIR + '/ode' +BF_ODE_INC = BF_ODE + '/include' +BF_ODE_LIB = BF_ODE + '/lib/libode.a' + +WITH_BF_BULLET = 'true' +BF_BULLET = '#extern/bullet2/src' +BF_BULLET_INC = '${BF_BULLET}' +BF_BULLET_LIB = 'extern_bullet' + +BF_SOLID = '#extern/solid' +BF_SOLID_INC = '${BF_SOLID}' +BF_SOLID_LIB = 'extern_solid' + +WITH_BF_YAFRAY = 'true' + +#WITH_BF_NSPR = 'true' +#BF_NSPR = $(LIBDIR)/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 = $(LIBDIR)/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 +BF_FREETYPE = LCGDIR+'/freetype' +BF_FREETYPE_INC = '${BF_FREETYPE}/include ${BF_FREETYPE}/include/freetype2' +BF_FREETYPE_LIB = 'freetype' +BF_FREETYPE_LIBPATH = '${BF_FREETYPE}/lib' + +WITH_BF_QUICKTIME = 'false' # -DWITH_QUICKTIME +BF_QUICKTIME = '/usr/local' +BF_QUICKTIME_INC = '${BF_QUICKTIME}/include' + +WITH_BF_ICONV = 'true' +BF_ICONV = LIBDIR + "/iconv" +BF_ICONV_INC = '${BF_ICONV}/include' +BF_ICONV_LIB = 'iconv charset' +BF_ICONV_LIBPATH = '${BF_ICONV}/lib' + +WITH_BF_BINRELOC = 'false' + +# enable ffmpeg support +WITH_BF_FFMPEG = 'true' # -DWITH_FFMPEG +# Uncomment the following two lines to use system's ffmpeg +BF_FFMPEG = LCGDIR+'/ffmpeg' +BF_FFMPEG_LIB = 'avformat avcodec swscale avutil avdevice faad faac vorbis x264 ogg mp3lame z' +BF_FFMPEG_INC = '${BF_FFMPEG}/include' +BF_FFMPEG_LIBPATH='${BF_FFMPEG}/lib' + +# enable ogg, vorbis and theora in ffmpeg +WITH_BF_OGG = 'false' # -DWITH_OGG +BF_OGG = '/usr' +BF_OGG_INC = '${BF_OGG}/include' +BF_OGG_LIB = 'ogg vorbis theoraenc theoradec' + +WITH_BF_OPENJPEG = 'false' +BF_OPENJPEG = '#extern/libopenjpeg' +BF_OPENJPEG_LIB = '' +BF_OPENJPEG_INC = '${BF_OPENJPEG}' +BF_OPENJPEG_LIBPATH='${BF_OPENJPEG}/lib' + +WITH_BF_REDCODE = 'false' +BF_REDCODE = '#extern/libredcode' +BF_REDCODE_LIB = '' +BF_REDCODE_INC = '${BF_REDCODE}/include' +BF_REDCODE_LIBPATH='${BF_REDCODE}/lib' + +# Mesa Libs should go here if your using them as well.... +WITH_BF_STATICOPENGL = 'false' +BF_OPENGL = '/usr' +BF_OPENGL_INC = '${BF_OPENGL}/include' +BF_OPENGL_LIB = 'GL GLU X11 Xi Xext' +BF_OPENGL_LIBPATH = '/usr/X11R6/lib' +BF_OPENGL_LIB_STATIC = '${BF_OPENGL}/libGL.a ${BF_OPENGL}/libGLU.a ${BF_OPENGL}/libXxf86vm.a ${BF_OPENGL}/libX11.a ${BF_OPENGL}/libXi.a ${BF_OPENGL}/libXext.a ${BF_OPENGL}/libXxf86vm.a' + + +CC = 'c99' +CXX = 'CC' + + +CCFLAGS = ['-pipe','-fPIC', '-n32'] + +CPPFLAGS = ['-DXP_UNIX'] +CXXFLAGS = ['-pipe','-fPIC', '-n32'] +REL_CFLAGS = ['-O2'] +REL_CCFLAGS = ['-O2'] +##BF_DEPEND = 'true' +## +##AR = ar +##ARFLAGS = ruv +##ARFLAGSQUIET = ru +## +C_WARN = '-no_prelink -ptused' + +CC_WARN = '-no_prelink -ptused' + +##FIX_STUBS_WARNINGS = -Wno-unused + +LLIBS = 'c m dl pthread dmedia movie' +##LOPTS = --dynamic +##DYNLDFLAGS = -shared $(LDFLAGS) + +BF_PROFILE_FLAGS = ['-pg','-g'] +BF_PROFILE = 'false' + +BF_DEBUG = 'false' +BF_DEBUG_FLAGS = '-g' + +BF_BUILDDIR = '../build/irix6' +BF_INSTALLDIR='../install/irix6' +BF_DOCDIR='../install/doc' + +#Link against pthread +LDIRS = [] +LDIRS.append(BF_FREETYPE_LIBPATH) +LDIRS.append(BF_PNG_LIBPATH) +LDIRS.append(BF_ZLIB_LIBPATH) +LDIRS.append(BF_SDL_LIBPATH) +LDIRS.append(BF_OPENAL_LIBPATH) +LDIRS.append(BF_ICONV_LIBPATH) + +PLATFORM_LINKFLAGS = [] +for x in LDIRS: + PLATFORM_LINKFLAGS.append("-L"+x) + +PLATFORM_LINKFLAGS += ['-L${LCGDIR}/jpeg/lib' , '-L/usr/lib32', '-n32', '-v', '-no_prelink'] +print PLATFORM_LINKFLAGS +LINKFLAGS= PLATFORM_LINKFLAGS diff --git a/config/linux2-config.py b/config/linux2-config.py index 2984c06d2df..6ba3052048d 100644 --- a/config/linux2-config.py +++ b/config/linux2-config.py @@ -139,8 +139,13 @@ BF_FFMPEG = '#extern/ffmpeg' BF_FFMPEG_LIB = '' # Uncomment the following two lines to use system's ffmpeg # BF_FFMPEG = '/usr' -# BF_FFMPEG_LIB = 'avformat avcodec swscale avutil' -BF_FFMPEG_INC = '${BF_FFMPEG}/include' +# BF_FFMPEG_LIB = 'avformat avcodec swscale avutil avdevice' +# trick : The version of ffmpeg in extern/ffmpeg uses explicit libav.. directory in #include statements +# To keep Blender compatible with older version, I add ${BF_FFMPEG} to the inc dir so that ffmpeg +# finds the files directly in extern/ffmpeg/libav... while blender finds them in +# extern/ffmpeg/include. When using system ffmpeg, you don't need that, assuming the system library +# still use the flat directory model, otherwise will not compile anyway +BF_FFMPEG_INC = '${BF_FFMPEG}/include ${BF_FFMPEG}' BF_FFMPEG_LIBPATH='${BF_FFMPEG}/lib' # enable ogg, vorbis and theora in ffmpeg @@ -152,13 +157,14 @@ BF_OGG_LIB = 'ogg vorbis theoraenc theoradec' WITH_BF_OPENJPEG = True BF_OPENJPEG = '#extern/libopenjpeg' BF_OPENJPEG_LIB = '' -BF_OPENJPEG_INC = '${BF_OPENJPEG}/include' +BF_OPENJPEG_INC = '${BF_OPENJPEG}' BF_OPENJPEG_LIBPATH='${BF_OPENJPEG}/lib' WITH_BF_REDCODE = False BF_REDCODE = '#extern/libredcode' BF_REDCODE_LIB = '' -BF_REDCODE_INC = '${BF_REDCODE}/include' +# BF_REDCODE_INC = '${BF_REDCODE}/include' +BF_REDCODE_INC = '${BF_REDCODE}/../' #C files request "libredcode/format.h" which is in "#extern/libredcode/format.h", stupid but compiles for now. BF_REDCODE_LIBPATH='${BF_REDCODE}/lib' # Mesa Libs should go here if your using them as well.... diff --git a/config/sunos5-config.py b/config/sunos5-config.py index a44a9df7c75..dda7d0ff2f3 100644 --- a/config/sunos5-config.py +++ b/config/sunos5-config.py @@ -131,7 +131,7 @@ WITH_BF_FFMPEG = False # -DWITH_FFMPEG BF_FFMPEG = '/usr/local' BF_FFMPEG_INC = '${BF_FFMPEG}/include' BF_FFMPEG_LIBPATH='${BF_FFMPEG}/lib' -BF_FFMPEG_LIB = 'avformat avcodec avutil' +BF_FFMPEG_LIB = 'avformat avcodec avutil avdevice' # Mesa Libs should go here if your using them as well.... WITH_BF_STATICOPENGL = False diff --git a/config/win32-mingw-config.py b/config/win32-mingw-config.py index 6278672ca3d..b94747637e9 100644 --- a/config/win32-mingw-config.py +++ b/config/win32-mingw-config.py @@ -6,10 +6,12 @@ BF_VERSE_INCLUDE = "#extern/verse/dist" BF_PYTHON = LIBDIR + '/python' BF_PYTHON_VERSION = '2.5' +WITH_BF_STATICPYTHON = False BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}' BF_PYTHON_BINARY = 'python' BF_PYTHON_LIB = 'python25' BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib/lib25_vs2005' +BF_PYTHON_LIB_STATIC = '${BF_PYTHON}/lib/lib25_vs2005/libpython25.a' WITH_BF_OPENAL = True WITH_BF_STATICOPENAL = False @@ -21,7 +23,7 @@ BF_OPENAL_LIBPATH = '${BF_OPENAL}/lib' BF_OPENAL_LIB_STATIC = '${BF_OPENAL}/lib/libopenal.a' WITH_BF_FFMPEG = False -BF_FFMPEG_LIB = 'avformat swscale avcodec avutil xvidcore x264' +BF_FFMPEG_LIB = 'avformat swscale avcodec avutil avdevice xvidcore x264' BF_FFMPEG_LIBPATH = LIBDIR + '/gcc/ffmpeg/lib' BF_FFMPEG_INC = LIBDIR + '/gcc/ffmpeg/include' @@ -170,4 +172,4 @@ BF_PROFILE = False BF_BUILDDIR = '..\\build\\win32-mingw' BF_INSTALLDIR='..\\install\\win32-mingw' -BF_DOCDIR = '..\\install\\doc'
\ No newline at end of file +BF_DOCDIR = '..\\install\\doc' diff --git a/config/win32-vc-config.py b/config/win32-vc-config.py index d7165401705..d4e9fa9b30e 100644 --- a/config/win32-vc-config.py +++ b/config/win32-vc-config.py @@ -153,6 +153,10 @@ BF_QUICKTIME_LIB = 'qtmlClient' BF_QUICKTIME_LIBPATH = '${BF_QUICKTIME}/Libraries' WITH_BF_OPENJPEG = True +BF_OPENJPEG = '#extern/libopenjpeg' +BF_OPENJPEG_LIB = '' +BF_OPENJPEG_INC = '${BF_OPENJPEG}' +BF_OPENJPEG_LIBPATH='${BF_OPENJPEG}/lib' WITH_BF_REDCODE = False BF_REDCODE_INC = '#extern' diff --git a/extern/Makefile b/extern/Makefile index 26ee25b608f..51213698ebb 100644 --- a/extern/Makefile +++ b/extern/Makefile @@ -57,10 +57,7 @@ ifeq ($(WITH_BINRELOC), true) DIRS += binreloc endif -TARGET = -ifneq ($(OS),irix) - TARGET=solid -endif +TARGET = solid all:: @[ -d $(OCGDIR)/extern ] || mkdir -p $(OCGDIR)/extern diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.cpp index f08b810eadb..997361a5069 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.cpp @@ -49,8 +49,6 @@ void btCompoundShape::addChildShape(const btTransform& localTransform,btCollisio child.m_childShapeType = shape->getShapeType(); child.m_childMargin = shape->getMargin(); - m_children.push_back(child); - //extend the local aabbMin/aabbMax btVector3 localAabbMin,localAabbMax; shape->getAabb(localTransform,localAabbMin,localAabbMax); @@ -69,10 +67,11 @@ void btCompoundShape::addChildShape(const btTransform& localTransform,btCollisio if (m_dynamicAabbTree) { const btDbvtVolume bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax); - int index = m_children.size()-1; + int index = m_children.size(); child.m_node = m_dynamicAabbTree->insert(bounds,(void*)index); } + m_children.push_back(child); } void btCompoundShape::removeChildShapeByIndex(int childShapeIndex) diff --git a/extern/bullet2/src/SConscript b/extern/bullet2/src/SConscript index 203407569b1..48e30cdf58a 100644 --- a/extern/bullet2/src/SConscript +++ b/extern/bullet2/src/SConscript @@ -10,7 +10,7 @@ cflags = [] if env['OURPLATFORM']=='win32-vc': defs += ' WIN32 NDEBUG _WINDOWS _LIB' #cflags += ['/MT', '/W3', '/GX', '/O2', '/Op'] - cflags += ['/MT', '/W3', '/GX', '/Og', '/Ot', '/Ob1', '/Op', '/G6'] + cflags += ['/MT', '/W3', '/GX', '/Og', '/Ot', '/Ob1', '/Op', '/G6', '/O3'] elif env['OURPLATFORM']=='win32-mingw': defs += ' NDEBUG' cflags += ['-O2'] diff --git a/extern/libopenjpeg/SConscript b/extern/libopenjpeg/SConscript index 837701eeae0..eb408c1e9c0 100644 --- a/extern/libopenjpeg/SConscript +++ b/extern/libopenjpeg/SConscript @@ -6,9 +6,12 @@ Import('env') sources = env.Glob('*.c') incs = '.' +flags = [] +defs = [] if env['OURPLATFORM'] == 'win32-vc': flags = [] + defs.append('OPJ_STATIC') else: flags = ['-Wall', '-O3', '-ffast-math', '-std=c99'] @@ -19,6 +22,6 @@ if not env['OURPLATFORM'] == 'win32-vc': oj_env.BlenderLib ( libname='extern_openjpeg', sources=sources, includes=Split(incs), - defines=[], + defines=defs, libtype=['core','intern','player'], - priority=[10, 10, 300], compileflags = flags) + priority=[300, 300, 300], compileflags = flags) diff --git a/extern/libopenjpeg/openjpeg.h b/extern/libopenjpeg/openjpeg.h index ffcaacaf6e5..ae7764eab2f 100644 --- a/extern/libopenjpeg/openjpeg.h +++ b/extern/libopenjpeg/openjpeg.h @@ -40,25 +40,8 @@ ========================================================== */ -#if defined(OPJ_STATIC) || !(defined(WIN32) || defined(__WIN32__)) #define OPJ_API #define OPJ_CALLCONV -#else -#define OPJ_CALLCONV __stdcall -/* -The following ifdef block is the standard way of creating macros which make exporting -from a DLL simpler. All files within this DLL are compiled with the OPJ_EXPORTS -symbol defined on the command line. this symbol should not be defined on any project -that uses this DLL. This way any other project whose source files include this file see -OPJ_API functions as being imported from a DLL, wheras this DLL sees symbols -defined with this macro as being exported. -*/ -#ifdef OPJ_EXPORTS -#define OPJ_API __declspec(dllexport) -#else -#define OPJ_API __declspec(dllimport) -#endif /* OPJ_EXPORTS */ -#endif /* !OPJ_STATIC || !WIN32 */ #ifndef __cplusplus #if defined(HAVE_STDBOOL_H) diff --git a/extern/libredcode/codec.c b/extern/libredcode/codec.c index e0b79119e80..f47a85cbb13 100644 --- a/extern/libredcode/codec.c +++ b/extern/libredcode/codec.c @@ -64,7 +64,7 @@ struct redcode_frame_raw * redcode_decode_video_raw( /* setup the decoder decoding parameters using the current image and user parameters */ opj_setup_decoder(dinfo, ¶meters); - + /* open a byte stream */ cio = opj_cio_open((opj_common_ptr)dinfo, frame->data + frame->offset, frame->length); diff --git a/extern/libredcode/format.c b/extern/libredcode/format.c index 4677c49b8a5..cf8f9d5faa7 100644 --- a/extern/libredcode/format.c +++ b/extern/libredcode/format.c @@ -1,49 +1,50 @@ -#ifdef _WIN32 -#include <Winsock2.h> -#else -#include <netinet/in.h> -#endif - #include <stdio.h> #include <stdlib.h> #include <string.h> #include "format.h" struct red_reob { - unsigned long len; - char head[4]; + unsigned int len; + unsigned int head; - unsigned long rdvo; - unsigned long rdvs; - unsigned long rdao; - unsigned long rdas; + unsigned int rdvo; + unsigned int rdvs; + unsigned int rdao; + unsigned int rdas; - unsigned long unknown1; - unsigned long unknown2; - unsigned long totlen; + unsigned int unknown1; + unsigned int unknown2; + unsigned int totlen; - unsigned long avgv; - unsigned long avgs; + unsigned int avgv; + unsigned int avgs; - unsigned long unknown3; - unsigned long unknown4; - unsigned long unknown5; + unsigned int unknown3; + unsigned int unknown4; + unsigned int unknown5; }; struct redcode_handle { FILE * fp; struct red_reob * reob; - unsigned long * rdvo; - unsigned long * rdvs; - unsigned long * rdao; - unsigned long * rdas; + unsigned int * rdvo; + unsigned int * rdvs; + unsigned int * rdao; + unsigned int * rdas; long cfra; + long length; }; +unsigned int read_be32(unsigned int val) +{ + unsigned char * v = (unsigned char*) & val; + + return (v[0] << 24) | (v[1] << 16) | (v[2] << 8) | v[3]; +} static unsigned char* read_packet(FILE * fp, char * expect) { - unsigned long len; + unsigned int len; char head[5]; unsigned char * rv; @@ -52,7 +53,7 @@ static unsigned char* read_packet(FILE * fp, char * expect) head[4] = 0; - len = ntohl(len); + len = read_be32(len); if (strcmp(expect, head) != 0) { fprintf(stderr, "Read: %s, expect: %s\n", head, expect); @@ -69,9 +70,9 @@ static unsigned char* read_packet(FILE * fp, char * expect) return rv; } -static unsigned long * read_index_packet(FILE * fp, char * expect) +static unsigned int * read_index_packet(FILE * fp, char * expect) { - unsigned long * rv = (unsigned long*) read_packet(fp, expect); + unsigned int * rv = (unsigned int*) read_packet(fp, expect); int i; if (!rv) { @@ -79,7 +80,7 @@ static unsigned long * read_index_packet(FILE * fp, char * expect) } for (i = 2; i < rv[0]/4; i++) { - rv[i] = ntohl(rv[i]); + rv[i] = read_be32(rv[i]); } return rv; } @@ -91,14 +92,14 @@ static struct red_reob * read_reob(FILE * fp) return (struct red_reob *) read_index_packet(fp, "REOB"); } -static unsigned long * read_index(FILE * fp, unsigned long i, char * expect) +static unsigned int * read_index(FILE * fp, unsigned int i, char * expect) { fseek(fp, i, SEEK_SET); - return (unsigned long*) read_index_packet(fp, expect); + return (unsigned int*) read_index_packet(fp, expect); } -static unsigned char * read_data(FILE * fp, unsigned long i, char * expect) +static unsigned char * read_data(FILE * fp, unsigned int i, char * expect) { fseek(fp, i, SEEK_SET); @@ -109,6 +110,7 @@ struct redcode_handle * redcode_open(const char * fname) { struct redcode_handle * rv = NULL; struct red_reob * reob = NULL; + int i; FILE * fp = fopen(fname, "rb"); @@ -136,6 +138,12 @@ struct redcode_handle * redcode_open(const char * fname) return NULL; } + for (i = 0; i < (rv->rdvo[0] - 8)/4; i++) { + if (rv->rdvo[i + 2]) { + rv->length = i; + } + } + return rv; } @@ -162,7 +170,7 @@ void redcode_close(struct redcode_handle * handle) long redcode_get_length(struct redcode_handle * handle) { - return handle->rdvo[0]/4; + return handle->length; } struct redcode_frame * redcode_read_video_frame( @@ -182,7 +190,7 @@ struct redcode_frame * redcode_read_video_frame( rv = (struct redcode_frame*) calloc(1, sizeof(struct redcode_frame)); rv->offset = 12+8; - rv->length = *(unsigned long*)data - rv->offset; + rv->length = *(unsigned int*)data - rv->offset; rv->data = data; return rv; @@ -205,7 +213,7 @@ struct redcode_frame * redcode_read_audio_frame( rv = (struct redcode_frame*) calloc(1, sizeof(struct redcode_frame)); rv->offset = 24+8; - rv->length = *(unsigned long*)data - rv->offset; + rv->length = *(unsigned int*)data - rv->offset; rv->data = data; return rv; diff --git a/extern/libredcode/format.h b/extern/libredcode/format.h index e09ea8a3b64..b2c6b2d885b 100644 --- a/extern/libredcode/format.h +++ b/extern/libredcode/format.h @@ -3,8 +3,8 @@ struct redcode_handle; struct redcode_frame { - unsigned long length; - unsigned long offset; + unsigned int length; + unsigned int offset; unsigned char * data; }; diff --git a/intern/SoundSystem/Makefile b/intern/SoundSystem/Makefile index d00339f351c..051e2643a87 100644 --- a/intern/SoundSystem/Makefile +++ b/intern/SoundSystem/Makefile @@ -47,6 +47,9 @@ ifneq ($(NAN_NO_OPENAL),true) ifeq ($(OS),$(findstring $(OS), "linux freebsd solaris")) DIRS += openal sdl endif + ifeq ($(OS), irix) + DIRS += sdl + endif else export CPPFLAGS += -DNO_SOUND endif diff --git a/intern/SoundSystem/openal/SND_OpenALDevice.cpp b/intern/SoundSystem/openal/SND_OpenALDevice.cpp index c660e9aecba..9ce30f985ac 100644 --- a/intern/SoundSystem/openal/SND_OpenALDevice.cpp +++ b/intern/SoundSystem/openal/SND_OpenALDevice.cpp @@ -235,7 +235,8 @@ SND_OpenALDevice::SND_OpenALDevice() if (m_context) { #ifdef AL_VERSION_1_1 - alcMakeContextCurrent((ALCcontext*)m_context); + alcMakeContextCurrent((ALCcontext*)m_context); + alutInitWithoutContext(NULL, NULL); /* in this case we dont want alut to initialize the context, see above */ #else alcMakeContextCurrent(m_context); #endif @@ -380,6 +381,9 @@ SND_OpenALDevice::~SND_OpenALDevice() #else if (m_device) alcCloseDevice((ALCdevice*) m_device); +#ifdef AL_VERSION_1_1 + alutExit(); +#endif #endif } @@ -437,7 +441,9 @@ SND_WaveSlot* SND_OpenALDevice::LoadSample(const STR_String& name, alutLoadWAVMemory((char*)memlocation, &sampleformat, &data, &numberofsamples, &samplerate); // openal_2.12 #else #ifdef AL_VERSION_1_1 - alutLoadWAVMemory((ALbyte*)memlocation, &sampleformat, &data, &numberofsamples, &samplerate, &loop);// openal_2.14+ + float frequency = 0.0f; + data = alutLoadMemoryFromFileImage(memlocation, size, &sampleformat, &numberofsamples, &frequency); + samplerate = (int)frequency; #else alutLoadWAVMemory((signed char*)memlocation, &sampleformat, &data, &numberofsamples, &samplerate, &loop);// openal_2.14+ @@ -480,7 +486,11 @@ SND_WaveSlot* SND_OpenALDevice::LoadSample(const STR_String& name, } /* and free the original stuff (copy was made in openal) */ +#if defined(OUDE_OPENAL) || defined (__APPLE__) || !defined(AL_VERSION_1_1) alutUnloadWAV(sampleformat, data, numberofsamples, samplerate); +#else + free(data); +#endif } } else diff --git a/intern/SoundSystem/openal/SND_OpenALDevice.h b/intern/SoundSystem/openal/SND_OpenALDevice.h index b8c64762a56..a7b97cc314f 100644 --- a/intern/SoundSystem/openal/SND_OpenALDevice.h +++ b/intern/SoundSystem/openal/SND_OpenALDevice.h @@ -32,7 +32,7 @@ #include "SND_AudioDevice.h" #include "SoundDefines.h" -typedef struct SDL_CD; +struct SDL_CD; class SND_OpenALDevice : public SND_AudioDevice { diff --git a/intern/SoundSystem/sdl/SND_SDLCDDevice.h b/intern/SoundSystem/sdl/SND_SDLCDDevice.h index 15cb1975d74..96600d53630 100644 --- a/intern/SoundSystem/sdl/SND_SDLCDDevice.h +++ b/intern/SoundSystem/sdl/SND_SDLCDDevice.h @@ -29,7 +29,7 @@ #ifndef SND_SDLCDDEVICE #define SND_SDLCDDEVICE -typedef struct SDL_CD; +struct SDL_CD; class SND_SDLCDDevice { diff --git a/intern/elbeem/intern/utilities.h b/intern/elbeem/intern/utilities.h index 825e92251fe..a5f63e696a6 100644 --- a/intern/elbeem/intern/utilities.h +++ b/intern/elbeem/intern/utilities.h @@ -154,12 +154,18 @@ int writePng(const char *fileName, unsigned char **rowsp, int w, int h); */ /* minimum */ +#ifdef MIN +#undef MIN +#endif template < class T > inline T MIN( T a, T b ) { return (a < b) ? a : b ; } /* maximum */ +#ifdef MAX +#undef MAX +#endif template < class T > inline T MAX( T a, T b ) diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index 8073756e453..02dfdc2e25c 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -981,11 +981,11 @@ getClipboard(int flag ) const { //Flag //0 = Regular clipboard 1 = selection - static Atom Primary_atom, clip_String, compound_text; + static Atom Primary_atom, clip_String, compound_text, a_text, a_string; Atom rtype; Window m_window, owner; unsigned char *data, *tmp_data; - int bits; + int bits, count; unsigned long len, bytes; XEvent xevent; @@ -996,6 +996,8 @@ getClipboard(int flag clip_String = XInternAtom(m_display, "_BLENDER_STRING", False); compound_text = XInternAtom(m_display, "COMPOUND_TEXT", False); + a_text= XInternAtom(m_display, "TEXT", False); + a_string= XInternAtom(m_display, "STRING", False); //lets check the owner and if it is us then return the static buffer if(flag == 0) { @@ -1029,18 +1031,46 @@ getClipboard(int flag XFlush(m_display); //This needs to change so we do not wait for ever or check owner first + count= 1; while(1) { XNextEvent(m_display, &xevent); if(xevent.type == SelectionNotify) { - if(XGetWindowProperty(m_display, m_window, xevent.xselection.property, 0L, 4096L, False, AnyPropertyType, &rtype, &bits, &len, &bytes, &data) == Success) { - if (data) { - tmp_data = (unsigned char*) malloc(strlen((char*)data)+1); - strcpy((char*)tmp_data, (char*)data); - XFree(data); - return (GHOST_TUns8*)tmp_data; + if (xevent.xselection.property == None) { + /* Ok, the client can't convert the property + * to some that we can handle, try other types.. + */ + if (count == 1) { + XConvertSelection(m_display, Primary_atom, a_text, clip_String, m_window, CurrentTime); + count++; + } + else if (count == 2) { + XConvertSelection(m_display, Primary_atom, a_string, clip_String, m_window, CurrentTime); + count++; + } + else { + /* Ok, the owner of the selection can't + * convert the data to something that we can + * handle. + */ + return(NULL); } } - return NULL; + else { + if(XGetWindowProperty(m_display, m_window, xevent.xselection.property , 0L, 4096L, False, AnyPropertyType, &rtype, &bits, &len, &bytes, &data) == Success) { + if (data) { + if (bits == 8 && (rtype == compound_text || rtype == a_text || rtype == a_string)) { + tmp_data = (unsigned char*) malloc(strlen((char*)data)+1); + strcpy((char*)tmp_data, (char*)data); + } + else + tmp_data= NULL; + + XFree(data); + return (GHOST_TUns8*)tmp_data; + } + } + return(NULL); + } } } } diff --git a/projectfiles_vc9/blender/blender.sln b/projectfiles_vc9/blender/blender.sln index 4a12fcb2963..ac4c7f60c95 100644 --- a/projectfiles_vc9/blender/blender.sln +++ b/projectfiles_vc9/blender/blender.sln @@ -151,6 +151,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "blenderplayer", "..\gameeng {415BFD6E-64CF-422B-AF88-C07F040A7292} = {415BFD6E-64CF-422B-AF88-C07F040A7292}
{670EC17A-0548-4BBF-A27B-636C7C188139} = {670EC17A-0548-4BBF-A27B-636C7C188139}
{4C3AB78A-52CA-4276-A041-39776E52D8C8} = {4C3AB78A-52CA-4276-A041-39776E52D8C8}
+ {E784098D-3ED8-433A-9353-9679415DDDC5} = {E784098D-3ED8-433A-9353-9679415DDDC5}
{6B801390-5F95-4F07-81A7-97FBA046AACC} = {6B801390-5F95-4F07-81A7-97FBA046AACC}
{CAE37E91-6570-43AC-A4B4-7A37A4B0FC94} = {CAE37E91-6570-43AC-A4B4-7A37A4B0FC94}
{76D90B92-ECC7-409C-9F98-A8814B90F3C0} = {76D90B92-ECC7-409C-9F98-A8814B90F3C0}
@@ -167,13 +168,16 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "blenderplayer", "..\gameeng {E90C7BC2-CF30-4A60-A8F2-0050D592E358} = {E90C7BC2-CF30-4A60-A8F2-0050D592E358}
{8B8D4FC3-3234-4E54-8376-5AB83D00D164} = {8B8D4FC3-3234-4E54-8376-5AB83D00D164}
{4B6AFCC5-968C-424A-8F20-76E41B3BEF74} = {4B6AFCC5-968C-424A-8F20-76E41B3BEF74}
+ {0112CAD5-3584-412A-A2E5-1315A00437B4} = {0112CAD5-3584-412A-A2E5-1315A00437B4}
{5A2EA6DC-1A53-4E87-9166-52870CE3B4EA} = {5A2EA6DC-1A53-4E87-9166-52870CE3B4EA}
{E86B7BDE-C33C-4E55-9433-E74C141D7538} = {E86B7BDE-C33C-4E55-9433-E74C141D7538}
{32CC75E2-EE85-45E6-8E3D-513F58464F43} = {32CC75E2-EE85-45E6-8E3D-513F58464F43}
{9A307EE5-CD77-47BC-BD87-62508C7E19D8} = {9A307EE5-CD77-47BC-BD87-62508C7E19D8}
{AB590CED-F71F-4A17-A89B-18583ECD633D} = {AB590CED-F71F-4A17-A89B-18583ECD633D}
+ {B83C6BED-11EC-46C8-AFFA-121EEDE94373} = {B83C6BED-11EC-46C8-AFFA-121EEDE94373}
{1CC733F1-6AB5-4904-8F63-C08C46B79DD9} = {1CC733F1-6AB5-4904-8F63-C08C46B79DD9}
{B789C2F3-279E-4A85-8F0A-7F7AC068E598} = {B789C2F3-279E-4A85-8F0A-7F7AC068E598}
+ {524264F4-DF21-4B79-847F-E7CA643ECD0B} = {524264F4-DF21-4B79-847F-E7CA643ECD0B}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KX_blenderhook", "..\gameengine\blenderhook\KX_blenderhook.vcproj", "{8154A59A-CAED-403D-AB94-BC4E7C032666}"
@@ -621,19 +625,25 @@ Global {0112CAD5-3584-412A-A2E5-1315A00437B4}.Blender Release|Win32.ActiveCfg = Blender Release|Win32
{0112CAD5-3584-412A-A2E5-1315A00437B4}.Blender Release|Win32.Build.0 = Blender Release|Win32
{0112CAD5-3584-412A-A2E5-1315A00437B4}.BlenderPlayer Debug|Win32.ActiveCfg = Blender Debug|Win32
+ {0112CAD5-3584-412A-A2E5-1315A00437B4}.BlenderPlayer Debug|Win32.Build.0 = Blender Debug|Win32
{0112CAD5-3584-412A-A2E5-1315A00437B4}.BlenderPlayer Release|Win32.ActiveCfg = Blender Release|Win32
+ {0112CAD5-3584-412A-A2E5-1315A00437B4}.BlenderPlayer Release|Win32.Build.0 = Blender Release|Win32
{B83C6BED-11EC-46C8-AFFA-121EEDE94373}.Blender Debug|Win32.ActiveCfg = Blender Debug|Win32
{B83C6BED-11EC-46C8-AFFA-121EEDE94373}.Blender Debug|Win32.Build.0 = Blender Debug|Win32
{B83C6BED-11EC-46C8-AFFA-121EEDE94373}.Blender Release|Win32.ActiveCfg = Blender Release|Win32
{B83C6BED-11EC-46C8-AFFA-121EEDE94373}.Blender Release|Win32.Build.0 = Blender Release|Win32
{B83C6BED-11EC-46C8-AFFA-121EEDE94373}.BlenderPlayer Debug|Win32.ActiveCfg = Blender Debug|Win32
+ {B83C6BED-11EC-46C8-AFFA-121EEDE94373}.BlenderPlayer Debug|Win32.Build.0 = Blender Debug|Win32
{B83C6BED-11EC-46C8-AFFA-121EEDE94373}.BlenderPlayer Release|Win32.ActiveCfg = Blender Release|Win32
+ {B83C6BED-11EC-46C8-AFFA-121EEDE94373}.BlenderPlayer Release|Win32.Build.0 = Blender Release|Win32
{524264F4-DF21-4B79-847F-E7CA643ECD0B}.Blender Debug|Win32.ActiveCfg = Blender Debug|Win32
{524264F4-DF21-4B79-847F-E7CA643ECD0B}.Blender Debug|Win32.Build.0 = Blender Debug|Win32
{524264F4-DF21-4B79-847F-E7CA643ECD0B}.Blender Release|Win32.ActiveCfg = Blender Release|Win32
{524264F4-DF21-4B79-847F-E7CA643ECD0B}.Blender Release|Win32.Build.0 = Blender Release|Win32
{524264F4-DF21-4B79-847F-E7CA643ECD0B}.BlenderPlayer Debug|Win32.ActiveCfg = Blender Debug|Win32
+ {524264F4-DF21-4B79-847F-E7CA643ECD0B}.BlenderPlayer Debug|Win32.Build.0 = Blender Debug|Win32
{524264F4-DF21-4B79-847F-E7CA643ECD0B}.BlenderPlayer Release|Win32.ActiveCfg = Blender Release|Win32
+ {524264F4-DF21-4B79-847F-E7CA643ECD0B}.BlenderPlayer Release|Win32.Build.0 = Blender Release|Win32
{D696C86B-0B53-4471-A50D-5B983A6FA4AD}.Blender Debug|Win32.ActiveCfg = Blender Debug|Win32
{D696C86B-0B53-4471-A50D-5B983A6FA4AD}.Blender Debug|Win32.Build.0 = Blender Debug|Win32
{D696C86B-0B53-4471-A50D-5B983A6FA4AD}.Blender Release|Win32.ActiveCfg = Blender Release|Win32
@@ -669,6 +679,7 @@ Global {6461F05D-4698-47AB-A8E8-1CA2ACC9948B}.Blender Release|Win32.ActiveCfg = Blender Release|Win32
{6461F05D-4698-47AB-A8E8-1CA2ACC9948B}.Blender Release|Win32.Build.0 = Blender Release|Win32
{6461F05D-4698-47AB-A8E8-1CA2ACC9948B}.BlenderPlayer Debug|Win32.ActiveCfg = Blender Debug|Win32
+ {6461F05D-4698-47AB-A8E8-1CA2ACC9948B}.BlenderPlayer Debug|Win32.Build.0 = Blender Debug|Win32
{6461F05D-4698-47AB-A8E8-1CA2ACC9948B}.BlenderPlayer Release|Win32.ActiveCfg = Blender Release|Win32
{6461F05D-4698-47AB-A8E8-1CA2ACC9948B}.BlenderPlayer Release|Win32.Build.0 = Blender Release|Win32
{531D4862-D0E7-4B9B-A0B6-B3A6A25B547A}.Blender Debug|Win32.ActiveCfg = Blender Debug|Win32
@@ -694,7 +705,9 @@ Global {E784098D-3ED8-433A-9353-9679415DDDC5}.Blender Release|Win32.ActiveCfg = Blender Release|Win32
{E784098D-3ED8-433A-9353-9679415DDDC5}.Blender Release|Win32.Build.0 = Blender Release|Win32
{E784098D-3ED8-433A-9353-9679415DDDC5}.BlenderPlayer Debug|Win32.ActiveCfg = Blender Debug|Win32
+ {E784098D-3ED8-433A-9353-9679415DDDC5}.BlenderPlayer Debug|Win32.Build.0 = Blender Debug|Win32
{E784098D-3ED8-433A-9353-9679415DDDC5}.BlenderPlayer Release|Win32.ActiveCfg = Blender Release|Win32
+ {E784098D-3ED8-433A-9353-9679415DDDC5}.BlenderPlayer Release|Win32.Build.0 = Blender Release|Win32
{EB75F4D6-2970-4A3A-8D99-2BAD7201C0E9}.Blender Debug|Win32.ActiveCfg = Blender Debug|Win32
{EB75F4D6-2970-4A3A-8D99-2BAD7201C0E9}.Blender Debug|Win32.Build.0 = Blender Debug|Win32
{EB75F4D6-2970-4A3A-8D99-2BAD7201C0E9}.Blender Release|Win32.ActiveCfg = Blender Release|Win32
diff --git a/projectfiles_vc9/blender/blender.vcproj b/projectfiles_vc9/blender/blender.vcproj index 8950ef822a1..a8c5fb0a5b5 100644 --- a/projectfiles_vc9/blender/blender.vcproj +++ b/projectfiles_vc9/blender/blender.vcproj @@ -73,7 +73,7 @@ <Tool
Name="VCLinkerTool"
AdditionalOptions="/MACHINE:I386"
- AdditionalDependencies="SDL.lib freetype2ST.lib gnu_gettext.lib qtmlClient.lib openal_static.lib ws2_32.lib dxguid.lib opengl32.lib libjpeg.lib glu32.lib vfw32.lib winmm.lib libpng_st.lib zlib.lib python25.lib pthreadVSE2.lib pthreadVC2.lib libtiff.lib Half.lib Iex.lib IlmImf.lib Imath.lib IlmThread.lib avcodec-51.lib avformat-52.lib avutil-49.lib swscale-0.lib"
+ AdditionalDependencies="SDL.lib freetype2ST.lib gnu_gettext.lib qtmlClient.lib openal_static.lib ws2_32.lib dxguid.lib opengl32.lib libjpeg.lib glu32.lib vfw32.lib winmm.lib libpng_st.lib zlib.lib python25.lib pthreadVSE2.lib pthreadVC2.lib libtiff.lib Half.lib Iex.lib IlmImf.lib Imath.lib IlmThread.lib avcodec-51.lib avformat-52.lib avutil-49.lib swscale-0.lib avdevice-52.lib"
ShowProgress="0"
OutputFile="..\..\bin\blender.exe"
LinkIncremental="1"
diff --git a/projectfiles_vc9/blender/imbuf/BL_imbuf.vcproj b/projectfiles_vc9/blender/imbuf/BL_imbuf.vcproj index 703a6407f9a..ed57fca060a 100644 --- a/projectfiles_vc9/blender/imbuf/BL_imbuf.vcproj +++ b/projectfiles_vc9/blender/imbuf/BL_imbuf.vcproj @@ -4,6 +4,7 @@ Version="9,00"
Name="BL_imbuf"
ProjectGUID="{415BFD6E-64CF-422B-AF88-C07F040A7292}"
+ RootNamespace="BL_imbuf"
TargetFrameworkVersion="131072"
>
<Platforms>
@@ -552,6 +553,10 @@ >
</File>
<File
+ RelativePath="..\..\..\source\blender\imbuf\intern\jp2.c"
+ >
+ </File>
+ <File
RelativePath="..\..\..\source\blender\imbuf\intern\jpeg.c"
>
</File>
@@ -830,6 +835,10 @@ >
</File>
<File
+ RelativePath="..\..\..\source\blender\imbuf\intern\IMB_jp2.h"
+ >
+ </File>
+ <File
RelativePath="..\..\..\source\blender\imbuf\intern\IMB_jpeg.h"
>
</File>
diff --git a/projectfiles_vc9/blender/nodes/nodes.vcproj b/projectfiles_vc9/blender/nodes/nodes.vcproj index d32ef98da2f..e782da120e1 100644 --- a/projectfiles_vc9/blender/nodes/nodes.vcproj +++ b/projectfiles_vc9/blender/nodes/nodes.vcproj @@ -4,6 +4,7 @@ Version="9,00"
Name="BL_nodes"
ProjectGUID="{4C3AB78A-52CA-4276-A041-39776E52D8C8}"
+ RootNamespace="BL_nodes"
Keyword="Win32Proj"
TargetFrameworkVersion="131072"
>
@@ -616,10 +617,26 @@ >
</File>
<File
+ RelativePath="..\..\..\source\blender\nodes\intern\TEX_nodes\TEX_compose.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\source\blender\nodes\intern\TEX_nodes\TEX_coord.c"
+ >
+ </File>
+ <File
RelativePath="..\..\..\source\blender\nodes\intern\TEX_nodes\TEX_curves.c"
>
</File>
<File
+ RelativePath="..\..\..\source\blender\nodes\intern\TEX_nodes\TEX_decompose.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\source\blender\nodes\intern\TEX_nodes\TEX_distance.c"
+ >
+ </File>
+ <File
RelativePath="..\..\..\source\blender\nodes\intern\TEX_nodes\TEX_hueSatVal.c"
>
</File>
@@ -652,6 +669,10 @@ >
</File>
<File
+ RelativePath="..\..\..\source\blender\nodes\intern\TEX_nodes\TEX_scale.c"
+ >
+ </File>
+ <File
RelativePath="..\..\..\source\blender\nodes\intern\TEX_nodes\TEX_texture.c"
>
</File>
@@ -660,6 +681,10 @@ >
</File>
<File
+ RelativePath="..\..\..\source\blender\nodes\intern\TEX_nodes\TEX_valToNor.c"
+ >
+ </File>
+ <File
RelativePath="..\..\..\source\blender\nodes\intern\TEX_nodes\TEX_valToRgb.c"
>
</File>
diff --git a/projectfiles_vc9/gameengine/blenderhook/KX_blenderhook.vcproj b/projectfiles_vc9/gameengine/blenderhook/KX_blenderhook.vcproj index 64f6b92ef29..8e027fd1854 100644 --- a/projectfiles_vc9/gameengine/blenderhook/KX_blenderhook.vcproj +++ b/projectfiles_vc9/gameengine/blenderhook/KX_blenderhook.vcproj @@ -4,6 +4,7 @@ Version="9,00"
Name="KX_blenderhook"
ProjectGUID="{8154A59A-CAED-403D-AB94-BC4E7C032666}"
+ RootNamespace="KX_blenderhook"
TargetFrameworkVersion="131072"
>
<Platforms>
@@ -43,7 +44,7 @@ Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\intern\bmfont\include;..\..\..\..\build\msvc_9\intern\soundsystem\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\..\build\msvc_9\extern\solid\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\blender;..\..\..\source\blender\misc;..\..\..\source\blender\imbuf;..\..\..\source\blender\blenlib;..\..\..\source\blender\include;..\..\..\source\blender\makesdna;..\..\..\source\blender\blenloader;..\..\..\source\blender\blenkernel;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\ketsji;..\..\..\source\gameengine\network;..\..\..\source\gameengine\rasterizer;..\..\..\source\gameengine\Converter;..\..\..\source\gameengine\gamelogic;..\..\..\source\gameengine\scenegraph;..\..\..\source\gameengine\expressions;..\..\..\source\gameengine\Physics\Sumo;..\..\..\source\gameengine\Physics\common;..\..\..\source\gameengine\network\loopbacknetwork;..\..\..\source\gameengine\rasterizer\ras_openglrasterizer;..\..\..\source\gameengine\Physics\Sumo\Fuzzics\include;..\..\..\source\blender\gpu"
- PreprocessorDefinitions="WIN32;_LIB;_DEBUG;WITH_GLEXT"
+ PreprocessorDefinitions="WIN32;_LIB;_DEBUG;WITH_GLEXT;WITH_FFMPEG"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
DefaultCharIsUnsigned="true"
@@ -119,7 +120,7 @@ Name="VCCLCompilerTool"
InlineFunctionExpansion="1"
AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\intern\bmfont\include;..\..\..\..\build\msvc_9\intern\soundsystem\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\..\build\msvc_9\extern\solid\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\blender;..\..\..\source\blender\misc;..\..\..\source\blender\imbuf;..\..\..\source\blender\blenlib;..\..\..\source\blender\include;..\..\..\source\blender\makesdna;..\..\..\source\blender\blenloader;..\..\..\source\blender\blenkernel;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\ketsji;..\..\..\source\gameengine\network;..\..\..\source\gameengine\rasterizer;..\..\..\source\gameengine\Converter;..\..\..\source\gameengine\gamelogic;..\..\..\source\gameengine\scenegraph;..\..\..\source\gameengine\expressions;..\..\..\source\gameengine\Physics\Sumo;..\..\..\source\gameengine\Physics\common;..\..\..\source\gameengine\network\loopbacknetwork;..\..\..\source\gameengine\rasterizer\ras_openglrasterizer;..\..\..\source\gameengine\Physics\Sumo\Fuzzics\include;..\..\..\source\blender\gpu"
- PreprocessorDefinitions="NDEBUG;WIN32;_LIB;USE_SUMO_SOLID;WITH_GLEXT"
+ PreprocessorDefinitions="NDEBUG;WIN32;_LIB;USE_SUMO_SOLID;WITH_GLEXT;WITH_FFMPEG"
StringPooling="true"
BasicRuntimeChecks="0"
RuntimeLibrary="0"
diff --git a/projectfiles_vc9/gameengine/gameplayer/ghost/GP_ghost.vcproj b/projectfiles_vc9/gameengine/gameplayer/ghost/GP_ghost.vcproj index 43e692e9bad..b539b64d374 100644 --- a/projectfiles_vc9/gameengine/gameplayer/ghost/GP_ghost.vcproj +++ b/projectfiles_vc9/gameengine/gameplayer/ghost/GP_ghost.vcproj @@ -45,7 +45,7 @@ Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\..\build\msvc_9\intern\ghost\include;..\..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\..\build\msvc_9\intern\openal\include;..\..\..\..\..\build\msvc_9\intern\opennl\include;..\..\..\..\..\build\msvc_9\intern\bmfont\include;..\..\..\..\..\build\msvc_9\intern\iksolver\include;..\..\..\..\..\build\msvc_9\intern\SoundSystem\include;..\..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\source\blender\include;..\..\..\..\source\blender\imbuf;..\..\..\..\source\blender\blenlib;..\..\..\..\source\blender\blenkernel;..\..\..\..\source\blender\makesdna;..\..\..\..\source\blender\blenloader;..\..\..\..\source\blender\readblenfile;..\..\..\..\source\blender\render\extern\include;..\..\..\..\source\kernel\gen_system;..\..\..\..\source\kernel\gen_messaging;..\..\..\..\source\gameengine\ketsji;..\..\..\..\source\gameengine\Physics;..\..\..\..\source\gameengine\network;..\..\..\..\source\gameengine\rasterizer;..\..\..\..\source\gameengine\converter;..\..\..\..\source\gameengine\gamelogic;..\..\..\..\source\gameengine\expressions;..\..\..\..\source\gameengine\scenegraph;..\..\..\..\source\gameengine\Physics\Ode;..\..\..\..\source\gameengine\soundsystem;..\..\..\..\source\gameengine\ketsji\kxnetwork;..\..\..\..\source\gameengine\gameplayer\common;..\..\..\..\source\gameengine\soundsystem\snd_openal;..\..\..\..\source\gameengine\network\loopbacknetwork;..\..\..\..\source\gameengine\rasterizer\ras_openglrasterizer;..\..\..\..\source\gameengine\gameplayer\common\windows;..\..\..\..\source\sumo\include;..\..\..\..\source\sumo\fuzzics\include;..\..\..\..\source\blender\gpu;..\..\..\..\..\build\msvc_9\intern\guardedalloc\include"
- PreprocessorDefinitions="WIN32,_CONSOLE,dSINGLE, _DEBUG"
+ PreprocessorDefinitions="WIN32,_CONSOLE,dSINGLE, _DEBUG;WITH_FFMPEG"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
@@ -72,12 +72,12 @@ <Tool
Name="VCLinkerTool"
AdditionalOptions="/MACHINE:I386
"
- AdditionalDependencies="odelib.lib fmodvc.lib libbmfont.lib ws2_32.lib vfw32.lib odbc32.lib odbccp32.lib opengl32.lib glu32.lib openal_static.lib libjpeg.lib dxguid.lib libeay32.lib libpng.lib libz.lib qtmlClient.lib SDL.lib freetype2ST.lib python25_d.lib pthreadVSE2.lib pthreadVC2.lib Half.lib Iex.lib IlmImf.lib IlmThread.lib Imath.lib avcodec-51.lib avformat-52.lib avutil-49.lib swscale-0.lib"
+ AdditionalDependencies="odelib.lib fmodvc.lib ws2_32.lib vfw32.lib odbc32.lib odbccp32.lib opengl32.lib glu32.lib openal_static.lib libjpeg.lib dxguid.lib libeay32.lib libpng.lib libz.lib qtmlClient.lib SDL.lib freetype2ST.lib python25_d.lib pthreadVSE2.lib pthreadVC2.lib Half.lib Iex.lib IlmImf.lib IlmThread.lib Imath.lib avcodec-51.lib avformat-52.lib avutil-49.lib swscale-0.lib"
ShowProgress="0"
OutputFile="..\..\..\..\bin\debug\blenderplayer.exe"
LinkIncremental="2"
SuppressStartupBanner="true"
- AdditionalLibraryDirectories="..\..\..\..\..\lib\windows\sdl\lib;..\..\..\..\..\lib\windows\zlib\lib;..\..\..\..\..\lib\windows\ode\lib;..\..\..\..\..\lib\windows\png\lib;..\..\..\..\..\lib\windows\jpeg\lib;..\..\..\..\..\lib\windows\fmod\lib;..\..\..\..\..\lib\windows\openal\lib;..\..\..\..\..\lib\windows\freetype\lib;..\..\..\..\..\lib\windows\openexr\lib_vs2008;..\..\..\..\..\lib\windows\python\lib\lib25_vs2008;..\..\..\..\..\lib\windows\openssl\lib;..\..\..\..\..\lib\windows\QTDevWin\Libraries;..\..\..\..\..\build\msvc_9\libs\intern\debug;..\..\..\..\..\build\msvc_9\libs\extern\debug;..\..\..\..\..\lib\windows\pthreads\lib;..\..\..\..\..\lib\windows\ffmpeg\lib"
+ AdditionalLibraryDirectories="..\..\..\..\..\lib\windows\sdl\lib;..\..\..\..\..\lib\windows\zlib\lib;..\..\..\..\..\lib\windows\ode\lib;..\..\..\..\..\lib\windows\png\lib;..\..\..\..\..\lib\windows\jpeg\lib;..\..\..\..\..\lib\windows\fmod\lib;..\..\..\..\..\lib\windows\openal\lib;..\..\..\..\..\lib\windows\freetype\lib;..\..\..\..\..\lib\windows\openexr\lib_vs2008;..\..\..\..\..\lib\windows\python\lib\lib25_vs2008;..\..\..\..\..\lib\windows\openssl\lib;..\..\..\..\..\lib\windows\QTDevWin\Libraries;..\..\..\..\..\lib\windows\pthreads\lib;..\..\..\..\..\lib\windows\ffmpeg\lib"
IgnoreDefaultLibraryNames="libc.lib;libcmt.lib;msvcrt.lib;libcd.lib;msvcrtd.lib"
GenerateDebugInformation="true"
ProgramDatabaseFile="..\..\..\..\..\build\msvc_9\libs\debug\blenderplayer.pdb"
@@ -138,7 +138,7 @@ Name="VCCLCompilerTool"
InlineFunctionExpansion="1"
AdditionalIncludeDirectories="..\..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\..\build\msvc_9\intern\ghost\include;..\..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\..\build\msvc_9\intern\openal\include;..\..\..\..\..\build\msvc_9\intern\opennl\include;..\..\..\..\..\build\msvc_9\intern\bmfont\include;..\..\..\..\..\build\msvc_9\intern\iksolver\include;..\..\..\..\..\build\msvc_9\intern\SoundSystem\include;..\..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\source\blender\include;..\..\..\..\source\blender\imbuf;..\..\..\..\source\blender\blenlib;..\..\..\..\source\blender\blenkernel;..\..\..\..\source\blender\makesdna;..\..\..\..\source\blender\blenloader;..\..\..\..\source\blender\readblenfile;..\..\..\..\source\blender\render\extern\include;..\..\..\..\source\kernel\gen_system;..\..\..\..\source\kernel\gen_messaging;..\..\..\..\source\gameengine\ketsji;..\..\..\..\source\gameengine\Physics;..\..\..\..\source\gameengine\network;..\..\..\..\source\gameengine\rasterizer;..\..\..\..\source\gameengine\converter;..\..\..\..\source\gameengine\gamelogic;..\..\..\..\source\gameengine\expressions;..\..\..\..\source\gameengine\scenegraph;..\..\..\..\source\gameengine\Physics\Ode;..\..\..\..\source\gameengine\soundsystem;..\..\..\..\source\gameengine\ketsji\kxnetwork;..\..\..\..\source\gameengine\gameplayer\common;..\..\..\..\source\gameengine\soundsystem\snd_openal;..\..\..\..\source\gameengine\network\loopbacknetwork;..\..\..\..\source\gameengine\rasterizer\ras_openglrasterizer;..\..\..\..\source\gameengine\gameplayer\common\windows;..\..\..\..\source\sumo\include;..\..\..\..\source\sumo\fuzzics\include;..\..\..\..\source\blender\gpu;..\..\..\..\..\build\msvc_9\intern\guardedalloc\include"
- PreprocessorDefinitions="WIN32,NDEBUG,_CONSOLE"
+ PreprocessorDefinitions="WIN32,NDEBUG,_CONSOLE;WITH_FFMPEG"
StringPooling="true"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
@@ -166,11 +166,11 @@ <Tool
Name="VCLinkerTool"
AdditionalOptions="/MACHINE:I386"
- AdditionalDependencies="odelib.lib fmodvc.lib libbmfont.lib ws2_32.lib vfw32.lib odbc32.lib odbccp32.lib opengl32.lib glu32.lib openal_static.lib libjpeg.lib dxguid.lib libeay32.lib libpng.lib libz.lib qtmlClient.lib SDL.lib freetype2ST.lib python25.lib pthreadVSE2.lib pthreadVC2.lib Half.lib Iex.lib IlmImf.lib IlmThread.lib Imath.lib avcodec-51.lib avformat-52.lib avutil-49.lib swscale-0.lib"
+ AdditionalDependencies="odelib.lib fmodvc.lib ws2_32.lib vfw32.lib odbc32.lib odbccp32.lib opengl32.lib glu32.lib openal_static.lib libjpeg.lib dxguid.lib libeay32.lib libpng.lib libz.lib qtmlClient.lib SDL.lib freetype2ST.lib python25_d.lib pthreadVSE2.lib pthreadVC2.lib Half.lib Iex.lib IlmImf.lib IlmThread.lib Imath.lib avcodec-51.lib avformat-52.lib avutil-49.lib swscale-0.lib"
OutputFile="..\..\..\..\bin\blenderplayer.exe"
LinkIncremental="1"
SuppressStartupBanner="true"
- AdditionalLibraryDirectories="..\..\..\..\..\lib\windows\sdl\lib;..\..\..\..\..\lib\windows\zlib\lib;..\..\..\..\..\lib\windows\ode\lib;..\..\..\..\..\lib\windows\png\lib;..\..\..\..\..\lib\windows\jpeg\lib;..\..\..\..\..\lib\windows\fmod\lib;..\..\..\..\..\lib\windows\openal\lib;..\..\..\..\..\lib\windows\freetype\lib;..\..\..\..\..\lib\windows\openexr\lib_vs2008;..\..\..\..\..\lib\windows\python\lib\lib25_vs2008;..\..\..\..\..\lib\windows\openssl\lib;..\..\..\..\..\lib\windows\QTDevWin\Libraries;..\..\..\..\..\build\msvc_9\libs\intern;..\..\..\..\..\build\msvc_9\libs\extern;..\..\..\..\..\lib\windows\pthreads\lib;..\..\..\..\..\lib\windows\ffmpeg\lib"
+ AdditionalLibraryDirectories="..\..\..\..\..\lib\windows\sdl\lib;..\..\..\..\..\lib\windows\zlib\lib;..\..\..\..\..\lib\windows\ode\lib;..\..\..\..\..\lib\windows\png\lib;..\..\..\..\..\lib\windows\jpeg\lib;..\..\..\..\..\lib\windows\fmod\lib;..\..\..\..\..\lib\windows\openal\lib;..\..\..\..\..\lib\windows\freetype\lib;..\..\..\..\..\lib\windows\openexr\lib_vs2008;..\..\..\..\..\lib\windows\python\lib\lib25_vs2008;..\..\..\..\..\lib\windows\openssl\lib;..\..\..\..\..\lib\windows\QTDevWin\Libraries;..\..\..\..\..\lib\windows\pthreads\lib;..\..\..\..\..\lib\windows\ffmpeg\lib"
IgnoreDefaultLibraryNames="libc.lib, msvcrt.lib, libcd.lib, libcmtd.lib, msvcrtd.lib"
ProgramDatabaseFile="..\..\..\..\..\build\msvc_9\libs\blenderplayer.pdb"
SubSystem="1"
diff --git a/release/Makefile b/release/Makefile index f440e2dface..43a369d8f77 100644 --- a/release/Makefile +++ b/release/Makefile @@ -57,6 +57,12 @@ ifeq ($(OS),$(findstring $(OS), "freebsd irix linux openbsd solaris")) NOPLUGINS?=true endif endif + # don"t build plugins on irix if using gcc + ifeq ($(OS), irix) + ifeq ($(IRIX_USE_GCC), true) + NOPLUGINS?=true + endif + endif endif ifeq ($(OS),windows) diff --git a/release/scripts/ac3d_import.py b/release/scripts/ac3d_import.py index 6a2b290e010..2f5512e7150 100644 --- a/release/scripts/ac3d_import.py +++ b/release/scripts/ac3d_import.py @@ -10,7 +10,7 @@ Tip: 'Import an AC3D (.ac) file.' __author__ = "Willian P. Germano" __url__ = ("blender", "blenderartists.org", "AC3D's homepage, http://www.ac3d.org", "PLib 3d gaming lib, http://plib.sf.net") -__version__ = "2.43.1 2007-02-21" +__version__ = "2.48.1 2009-01-11" __bpydoc__ = """\ This script imports AC3D models into Blender. @@ -31,6 +31,7 @@ Known issues:<br> Config Options:<br> - display transp (toggle): if "on", objects that have materials with alpha < 1.0 are shown with translucency (transparency) in the 3D View.<br> - subdiv (toggle): if "on", ac3d objects meant to be subdivided receive a SUBSURF modifier in Blender.<br> + - emis as mircol: store the emissive rgb color from AC3D as mirror color in Blender -- this is a hack to preserve the values and be able to export them using the equivalent option in the exporter.<br> - textures dir (string): if non blank, when imported texture paths are wrong in the .ac file, Blender will also look for them at this dir. @@ -50,11 +51,12 @@ users can configure (see config options above). # -------------------------------------------------------------------------- # Thanks: Melchior Franz for extensive bug testing and reporting, making this # version cope much better with old or bad .ac files, among other improvements; -# Stewart Andreason for reporting a serious crash. +# Stewart Andreason for reporting a serious crash; Francesco Brisa for the +# emis as mircol functionality (w/ patch). # -------------------------------------------------------------------------- # ***** BEGIN GPL LICENSE BLOCK ***** # -# Copyright (C) 2004-2007: Willian P. Germano, wgermano _at_ ig.com.br +# Copyright (C) 2004-2009: Willian P. Germano, wgermano _at_ ig.com.br # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -89,15 +91,19 @@ DISPLAY_TRANSP = True SUBDIV = True +EMIS_AS_MIRCOL = False + + tooltips = { 'DISPLAY_TRANSP': 'Turn transparency on in the 3d View for objects using materials with alpha < 1.0.', 'SUBDIV': 'Apply a SUBSURF modifier to objects meant to appear subdivided.', - 'TEXTURES_DIR': 'Additional folder to look for missing textures.' + 'TEXTURES_DIR': 'Additional folder to look for missing textures.', + 'EMIS_AS_MIRCOL': 'Store emis color as mirror color in Blender.' } def update_registry(): - global TEXTURES_DIR, DISPLAY_TRANSP - rd = dict([('tooltips', tooltips), ('TEXTURES_DIR', TEXTURES_DIR), ('DISPLAY_TRANSP', DISPLAY_TRANSP), ('SUBDIV', SUBDIV)]) + global TEXTURES_DIR, DISPLAY_TRANSP, EMIS_AS_MIRCOL + rd = dict([('tooltips', tooltips), ('TEXTURES_DIR', TEXTURES_DIR), ('DISPLAY_TRANSP', DISPLAY_TRANSP), ('SUBDIV', SUBDIV), ('EMIS_AS_MIRCOL', EMIS_AS_MIRCOL)]) Registry.SetKey('ac3d_import', rd, True) rd = Registry.GetKey('ac3d_import', True) @@ -109,6 +115,7 @@ if rd: TEXTURES_DIR = rd['TEXTURES_DIR'] DISPLAY_TRANSP = rd['DISPLAY_TRANSP'] SUBDIV = rd['SUBDIV'] + EMIS_AS_MIRCOL = rd['EMIS_AS_MIRCOL'] except: update_registry() else: update_registry() @@ -299,7 +306,7 @@ class AC3DImport: lines = self.lines line = lines[i].split() mat_name = '' - mat_col = mat_amb = mat_emit = mat_spec_col = [0,0,0] + mat_col = mat_amb = mat_emit = mat_spec_col = mat_mir_col = [0,0,0] mat_alpha = 1 mat_spec = 1.0 @@ -310,11 +317,15 @@ class AC3DImport: mat_amb = (v[0]+v[1]+v[2]) / 3.0 v = map(float,[line[11],line[12],line[13]]) mat_emit = (v[0]+v[1]+v[2]) / 3.0 + if EMIS_AS_MIRCOL: + mat_emit = 0 + mat_mir_col = map(float,[line[11],line[12],line[13]]) + mat_spec_col = map(float,[line[15],line[16],line[17]]) mat_spec = float(line[19]) / 64.0 mat_alpha = float(line[-1]) mat_alpha = 1 - mat_alpha - self.mlist.append([mat_name, mat_col, mat_amb, mat_emit, mat_spec_col, mat_spec, mat_alpha]) + self.mlist.append([mat_name, mat_col, mat_amb, mat_emit, mat_spec_col, mat_spec, mat_mir_col, mat_alpha]) i += 1 line = lines[i].split() @@ -590,7 +601,8 @@ class AC3DImport: m.emit = mat[3] m.specCol = (mat[4][0], mat[4][1], mat[4][2]) m.spec = mat[5] - m.alpha = mat[6] + m.mirCol = (mat[6][0], mat[6][1], mat[6][2]) + m.alpha = mat[7] if m.alpha < 1.0: m.mode |= MAT_MODE_ZTRANSP has_transp_mats = True diff --git a/release/scripts/animation_bake_constraints.py b/release/scripts/animation_bake_constraints.py index 58e9e2b1d02..16855828460 100644 --- a/release/scripts/animation_bake_constraints.py +++ b/release/scripts/animation_bake_constraints.py @@ -155,7 +155,7 @@ usrObjectNamePrefix= "" # if that armature had bones (spine, neck, arm) and the bone prefix was "a." # the bones and IPO curves will be (a.spine, a.neck, a.arm) -R2D = 18/3.1415 # radian to grad +R2D = 18/3.141592653589793 # radian to grad BLENDER_VERSION = Blender.Get('version') # Gets the current scene, there can be many scenes in 1 blend file. diff --git a/release/scripts/bpymodules/BPyImage.py b/release/scripts/bpymodules/BPyImage.py index 2c342ddec39..504e4ee29ba 100644 --- a/release/scripts/bpymodules/BPyImage.py +++ b/release/scripts/bpymodules/BPyImage.py @@ -79,7 +79,7 @@ def addSlash(path): return path + sys.sep -def comprehensiveImageLoad(imagePath, filePath, PLACE_HOLDER= True, RECURSIVE=True, VERBOSE=False): +def comprehensiveImageLoad(imagePath, filePath, PLACE_HOLDER= True, RECURSIVE=True, VERBOSE=False, CONVERT_CALLBACK=None): ''' imagePath: The image filename If a path precedes it, this will be searched as well. @@ -93,13 +93,30 @@ def comprehensiveImageLoad(imagePath, filePath, PLACE_HOLDER= True, RECURSIVE=Tr RECURSIVE: If True, directories will be recursivly searched. Be carefull with this if you have files in your root directory because it may take a long time. + + CASE_INSENSITIVE: for non win32 systems, find the correct case for the file. + + CONVERT_CALLBACK: a function that takes an existing path and returns a new one. + Use this when loading image formats blender may not support, the CONVERT_CALLBACK + can take the path for a GIF (for example), convert it to a PNG and return the PNG's path. + For formats blender can read, simply return the path that is given. ''' + # VERBOSE = True + if VERBOSE: print 'img:', imagePath, 'file:', filePath + + if os == None and CASE_INSENSITIVE: + CASE_INSENSITIVE = True + # When we have the file load it with this. try/except niceness. def imageLoad(path): #if path.endswith('\\') or path.endswith('/'): # raise 'INVALID PATH' + + if CONVERT_CALLBACK: + path = CONVERT_CALLBACK(path) + try: img = bpy.data.images.new(filename=path) if VERBOSE: print '\t\tImage loaded "%s"' % path diff --git a/release/scripts/bpymodules/BPyMathutils.py b/release/scripts/bpymodules/BPyMathutils.py index 27736b4169e..bfa1dcc3c61 100644 --- a/release/scripts/bpymodules/BPyMathutils.py +++ b/release/scripts/bpymodules/BPyMathutils.py @@ -225,15 +225,5 @@ from math import pi, sin, cos, sqrt def angleToLength(angle): # Alredy accounted for - if angle < 0.000001: - return 1.0 - - angle = 2*pi*angle/360 - x,y = cos(angle), sin(angle) - # print "YX", x,y - # 0 d is hoz to the right. - # 90d is vert upward. - fac=1/x - x=x*fac - y=y*fac - return sqrt((x*x)+(y*y)) + if angle < 0.000001: return 1.0 + else: return abs(1.0 / cos(pi*angle/180)); diff --git a/release/scripts/bpymodules/BPyMesh.py b/release/scripts/bpymodules/BPyMesh.py index 415c2a12c69..6bbfaa463d0 100644 --- a/release/scripts/bpymodules/BPyMesh.py +++ b/release/scripts/bpymodules/BPyMesh.py @@ -479,7 +479,7 @@ def pickMeshRayFaceWeight(me, orig, rdir): w0 = (l1+l2) w1 = (l0+l2) - w2 = (l1+l2) + w2 = (l1+l0) totw= w0 + w1 + w2 w0=w0/totw diff --git a/release/scripts/bpymodules/BPySys.py b/release/scripts/bpymodules/BPySys.py index 594264fad84..a2d2120ebff 100644 --- a/release/scripts/bpymodules/BPySys.py +++ b/release/scripts/bpymodules/BPySys.py @@ -12,3 +12,63 @@ def cleanName(name): for ch in invalid: name = name.replace(ch, '_') return name +def caseInsensitivePath(path, RET_FOUND=False): + ''' + Get a case insensitive path on a case sensitive system + + RET_FOUND is for internal use only, to avoid too many calls to os.path.exists + # Example usage + getCaseInsensitivePath('/hOmE/mE/sOmEpAtH.tXt') + ''' + import os # todo, what happens with no os? + + if os==None: + if RET_FOUND: ret = path, True + else: ret = path + return ret + + if path=='' or os.path.exists(path): + if RET_FOUND: ret = path, True + else: ret = path + return ret + + f = os.path.basename(path) # f may be a directory or a file + d = os.path.dirname(path) + + suffix = '' + if not f: # dir ends with a slash? + if len(d) < len(path): + suffix = path[:len(path)-len(d)] + + f = os.path.basename(d) + d = os.path.dirname(d) + + if not os.path.exists(d): + d, found = caseInsensitivePath(d, True) + + if not found: + if RET_FOUND: ret = path, False + else: ret = path + return ret + + # at this point, the directory exists but not the file + + try: # we are expecting 'd' to be a directory, but it could be a file + files = os.listdir(d) + except: + if RET_FOUND: ret = path, False + else: ret = path + + f_low = f.lower() + + try: f_nocase = [fl for fl in files if fl.lower() == f_low][0] + except: f_nocase = None + + if f_nocase: + if RET_FOUND: ret = os.path.join(d, f_nocase) + suffix, True + else: ret = os.path.join(d, f_nocase) + suffix + return ret + else: + if RET_FOUND: ret = path, False + else: ret = path + return ret # cant find the right one, just return the path as is.
\ No newline at end of file diff --git a/release/scripts/bpymodules/dxfLibrary.py b/release/scripts/bpymodules/dxfLibrary.py index 5c63e7f5bf5..96caa50cc41 100644 --- a/release/scripts/bpymodules/dxfLibrary.py +++ b/release/scripts/bpymodules/dxfLibrary.py @@ -1,10 +1,10 @@ #dxfLibrary.py : provides functions for generating DXF files # -------------------------------------------------------------------------- -__version__ = "v1.27beta - 2008.10.05" -__author__ = "Stani Michiels(Stani), Remigiusz Fiedler(migius)" +__version__ = "v1.28beta - 2008.12.13" +__author__ = "Stani Michiels(Stani), Remigiusz Fiedler(migius)" __license__ = "GPL" -__url__ = "http://wiki.blender.org/index.php/Scripts/Manual/Export/autodesk_dxf" -__bpydoc__ ="""The script exports geometry data to DXF format r12 version. +__url__ = "http://wiki.blender.org/index.php/Scripts/Manual/Export/autodesk_dxf" +__bpydoc__ ="""The library to export geometry data to DXF format r12 version. Copyright %s Version %s @@ -12,15 +12,17 @@ License %s Homepage %s See the homepage for documentation. -url: +Dedicated thread on BlenderArtists: http://blenderartists.org/forum/showthread.php?t=136439 IDEAs: - - + TODO: -- +- add support for SPLINEs History +v1.28 - 2008.12.13 by Steeve/BlenderArtists +- bugfix for EXTMIN/EXTMAX to suit Cycas-CAD v1.27 - 2008.10.07 by migius - beautifying output code: keys whitespace prefix - refactoring DXF-strings format: NewLine moved to the end of @@ -154,56 +156,56 @@ BYBLOCK=0 BYLAYER=256 #---block-type flags (bit coded values, may be combined): -ANONYMOUS =1 # This is an anonymous block generated by hatching, associative dimensioning, other internal operations, or an application +ANONYMOUS =1 # This is an anonymous block generated by hatching, associative dimensioning, other internal operations, or an application NON_CONSTANT_ATTRIBUTES =2 # This block has non-constant attribute definitions (this bit is not set if the block has any attribute definitions that are constant, or has no attribute definitions at all) -XREF =4 # This block is an external reference (xref) -XREF_OVERLAY =8 # This block is an xref overlay -EXTERNAL =16 # This block is externally dependent -RESOLVED =32 # This is a resolved external reference, or dependent of an external reference (ignored on input) -REFERENCED =64 # This definition is a referenced external reference (ignored on input) +XREF =4 # This block is an external reference (xref) +XREF_OVERLAY =8 # This block is an xref overlay +EXTERNAL =16 # This block is externally dependent +RESOLVED =32 # This is a resolved external reference, or dependent of an external reference (ignored on input) +REFERENCED =64 # This definition is a referenced external reference (ignored on input) #---mtext flags #attachment point -TOP_LEFT = 1 -TOP_CENTER = 2 -TOP_RIGHT = 3 -MIDDLE_LEFT = 4 -MIDDLE_CENTER = 5 +TOP_LEFT = 1 +TOP_CENTER = 2 +TOP_RIGHT = 3 +MIDDLE_LEFT = 4 +MIDDLE_CENTER = 5 MIDDLE_RIGHT = 6 -BOTTOM_LEFT = 7 -BOTTOM_CENTER = 8 -BOTTOM_RIGHT = 9 +BOTTOM_LEFT = 7 +BOTTOM_CENTER = 8 +BOTTOM_RIGHT = 9 #drawing direction -LEFT_RIGHT = 1 -TOP_BOTTOM = 3 -BY_STYLE = 5 #the flow direction is inherited from the associated text style +LEFT_RIGHT = 1 +TOP_BOTTOM = 3 +BY_STYLE = 5 #the flow direction is inherited from the associated text style #line spacing style (optional): -AT_LEAST = 1 #taller characters will override -EXACT = 2 #taller characters will not override +AT_LEAST = 1 #taller characters will override +EXACT = 2 #taller characters will not override #---polyline flags -CLOSED =1 # This is a closed polyline (or a polygon mesh closed in the M direction) -CURVE_FIT =2 # Curve-fit vertices have been added -SPLINE_FIT =4 # Spline-fit vertices have been added -POLYLINE_3D =8 # This is a 3D polyline -POLYGON_MESH =16 # This is a 3D polygon mesh -CLOSED_N =32 # The polygon mesh is closed in the N direction -POLYFACE_MESH =64 # The polyline is a polyface mesh -CONTINOUS_LINETYPE_PATTERN =128 # The linetype pattern is generated continuously around the vertices of this polyline +CLOSED =1 # This is a closed polyline (or a polygon mesh closed in the M direction) +CURVE_FIT =2 # Curve-fit vertices have been added +SPLINE_FIT =4 # Spline-fit vertices have been added +POLYLINE_3D =8 # This is a 3D polyline +POLYGON_MESH =16 # This is a 3D polygon mesh +CLOSED_N =32 # The polygon mesh is closed in the N direction +POLYFACE_MESH =64 # The polyline is a polyface mesh +CONTINOUS_LINETYPE_PATTERN =128 # The linetype pattern is generated continuously around the vertices of this polyline #---text flags #horizontal -LEFT = 0 -CENTER = 1 -RIGHT = 2 -ALIGNED = 3 #if vertical alignment = 0 -MIDDLE = 4 #if vertical alignment = 0 -FIT = 5 #if vertical alignment = 0 +LEFT = 0 +CENTER = 1 +RIGHT = 2 +ALIGNED = 3 #if vertical alignment = 0 +MIDDLE = 4 #if vertical alignment = 0 +FIT = 5 #if vertical alignment = 0 #vertical -BASELINE = 0 -BOTTOM = 1 -MIDDLE = 2 -TOP = 3 +BASELINE = 0 +BOTTOM = 1 +MIDDLE = 2 +TOP = 3 ####3) Classes #---entitities ----------------------------------------------- @@ -239,7 +241,7 @@ class Face(_Entity): """3dface""" def __init__(self,points,**common): _Entity.__init__(self,**common) - if len(points)<4: #fix for r12 format + while len(points)<4: #fix for r12 format points.append(points[-1]) self.points=points @@ -336,10 +338,14 @@ class PolyLine(_Entity): #----------------------------------------------- class Point(_Entity): - """Colored solid fill.""" + """Point.""" def __init__(self,points=None,**common): _Entity.__init__(self,**common) self.points=points + def __str__(self): #TODO: + return ' 0\nPOINT\n%s%s\n' %(self._common(), + _points(self.points) + ) #----------------------------------------------- class Solid(_Entity): @@ -468,7 +474,7 @@ class Block(_Collection): self.name=name self.flag=0 self.base=base - def __str__(self): + def __str__(self): #TODO: e=''.join([str(x)for x in self.entities]) return ' 0\nBLOCK\n 8\n%s\n 2\n%s\n 70\n%s\n%s\n 3\n%s\n%s 0\nENDBLK\n'%\ (self.layer,self.name.upper(),self.flag,_point(self.base),self.name.upper(),e) @@ -552,11 +558,12 @@ def ViewByWindow(name,leftBottom=(0,0),rightTop=(1,1),**options): #----------------------------------------------- class Drawing(_Collection): """Dxf drawing. Use append or any other list methods to add objects.""" - def __init__(self,insbase=(0.0,0.0,0.0),extmin=(0.0,0.0),extmax=(0.0,0.0), + def __init__(self,insbase=(0.0,0.0,0.0),extmin=(0.0,0.0,0.0),extmax=(0.0,0.0,0.0), layers=[Layer()],linetypes=[LineType()],styles=[Style()],blocks=[], views=[],entities=None,fileName='test.dxf'): # TODO: replace list with None,arial - if not entities:entities=[] + if not entities: + entities=[] _Collection.__init__(self,entities) self.insbase=insbase self.extmin=extmin @@ -680,9 +687,9 @@ def test(): #Drawing d=Drawing() #tables - d.blocks.append(b) #table blocks - d.styles.append(Style()) #table styles - d.views.append(View('Normal')) #table view + d.blocks.append(b) #table blocks + d.styles.append(Style()) #table styles + d.views.append(View('Normal')) #table view d.views.append(ViewByWindow('Window',leftBottom=(1,0),rightTop=(2,1))) #idem #entities diff --git a/release/scripts/bpymodules/paths_svg2obj.py b/release/scripts/bpymodules/paths_svg2obj.py index de40bea3191..d51fe74190d 100644 --- a/release/scripts/bpymodules/paths_svg2obj.py +++ b/release/scripts/bpymodules/paths_svg2obj.py @@ -1,7 +1,7 @@ # -*- coding: latin-1 -*- """ -SVG 2 OBJ translater, 0.5.9h -Copyright (c) jm soler juillet/novembre 2004-april 2007, +SVG 2 OBJ translater, 0.5.9n +Copyright (c) jm soler juillet/novembre 2004-february 2009, # --------------------------------------------------------------- released under GNU Licence for the Blender 2.42 Python Scripts Bundle. @@ -20,7 +20,6 @@ en même temps que ce programme ; si ce n'est pas le cas, écrivez à la Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, États-Unis. - 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 @@ -35,7 +34,7 @@ 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 St, Fifth Floor, Boston, MA 02110-1301 USA # --------------------------------------------------------------- - +# #--------------------------------------------------------------------------- # Page officielle : # http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_import_svg.htm @@ -253,15 +252,27 @@ Changelog: 0.5.9h : - 2007/5/2 - script was updated with the modifs by cambo - - removed all debug statements + - removed all debug statements - correction of a zero division error in the calc_arc function. + 0.5.9f: - 2007/15/7 + - Correction de plusieurs bugs sur l'attributions des couleurs et le nommage + des courbes + + 0.5.9i : - ??/??/?? + - Patch externe réalisé sur blender.org project. + + 0.5.9j : - 08/11/2008 + 0.5.9k : - 14/01/2009 + 0.5.9l : - 31/01/2009 + 0.5.9n : - 01/02/2009 + ================================================================================== ==================================================================================""" SHARP_IMPORT=0 SCALE=1 scale_=1 -DEBUG = 0#print +DEBUG = 0 DEVELOPPEMENT=0 TESTCOLOR=0 @@ -533,7 +544,7 @@ def createCURVES(curves, name): scene.objects.selected = [] if not SEPARATE_CURVES: - c = Curve.New() + c = Curve.New() c.setResolu(24) MATNAME=[] @@ -709,7 +720,6 @@ def circle(prp): else : cx =float(prp['cx']) if 'cy' not in prp: cy=0.0 else : cy =float(prp['cy']) - #print prp.keys() r = float(prp['r']) D=['M',str(cx),str(cy+r), 'C',str(cx-r), str(cy+r*0.552),str(cx-0.552*r),str(cy+r), str(cx),str(cy+r), @@ -852,7 +862,7 @@ def calc_arc (cpx,cpy, rx, ry, ang, fa , fs , x, y) : #-------------------- # 0.3.9 #-------------------- -def curve_to_a(c,D,n0,CP): #A,a +def curve_to_a(curves, c,D,n0,CP): #A,a global SCALE l=[float(D[c[1]+1]),float(D[c[1]+2]),float(D[c[1]+3]), int(D[c[1]+4]),int(D[c[1]+5]),float(D[c[1]+6]),float(D[c[1]+7])] @@ -866,8 +876,7 @@ def curve_to_a(c,D,n0,CP): #A,a POINTS= calc_arc (CP[0],CP[1], l[0], l[1], l[2]*(PI / 180.0), l[3], l[4], - l[5], l[6] ) - #if DEBUG == 1 : print POINTS + l[5], l[6] ) for p in POINTS : B=Bez() B.co=[ p[2][0],p[2][1], p[0][0],p[0][1], p[1][0],p[1][1]] @@ -881,16 +890,23 @@ def curve_to_a(c,D,n0,CP): #A,a BP.co[2]=BP.co[0] BP.co[3]=BP.co[1] CP=[l[5], l[6]] + #---------- 059m------------ + if len(D)>c[1]+7 and D[c[1]+8] not in TAGcourbe : + c[1]+=7 + curves,n0,CP=curve_to_a(curves, c, D, n0,CP) + #---------- 059m------------ return curves,n0,CP -def move_to(c, D, n0,CP, proprietes): +def move_to(curves, c, D, n0,CP, proprietes): global DEBUG,TAGcourbe, LAST_ID global USE_COLORS l=[float(D[c[1]+1]),float(D[c[1]+2])] + if c[0]=='m': l=[l[0]+CP[0], l[1] + CP[1]] + if n0 in curves.ITEM: n0+=1 CP=[l[0],l[1]] @@ -917,14 +933,12 @@ def move_to(c, D, n0,CP, proprietes): B.co=[CP[0],CP[1],CP[0],CP[1],CP[0],CP[1]] B.ha=['L','C'] B.tag=c[0] - curves.ITEM[n0].beziers_knot.append(B) - #if DEBUG==1: print curves.ITEM[n0], CP + curves.ITEM[n0].beziers_knot.append(B) return curves,n0,CP -def close_z(c,D,n0,CP): #Z,z +def close_z(curves, c,D,n0,CP): #Z,z curves.ITEM[n0].flagUV[0]=1 if len(curves.ITEM[n0].beziers_knot)>1: - #print len(curves.ITEM[n0].beziers_knot) BP=curves.ITEM[n0].beziers_knot[-1] BP0=curves.ITEM[n0].beziers_knot[0] if BP.tag in ['c','C','s','S',]: @@ -936,7 +950,7 @@ def close_z(c,D,n0,CP): #Z,z n0-=1 return curves,n0,CP -def curve_to_q(c,D,n0,CP): #Q,q +def curve_to_q(curves, c,D,n0,CP): #Q,q l=[float(D[c[1]+1]),float(D[c[1]+2]),float(D[c[1]+3]),float(D[c[1]+4])] if c[0]=='q': l=[l[0]+CP[0], l[1]+CP[1], l[2]+CP[0], l[3]+CP[1]] @@ -948,15 +962,14 @@ def curve_to_q(c,D,n0,CP): #Q,q BP.co[2]=BP.co[0] BP.co[3]=BP.co[1] curves.ITEM[n0].beziers_knot.append(B) - #if DEBUG==1: print B.co,BP.co CP=[l[2],l[3]] #if DEBUG==1: pass if len(D)>c[1]+5 and D[c[1]+5] not in TAGcourbe : c[1]+=4 - curve_to_q(c, D, n0,CP) + curves,n0,CP=curve_to_q(curves, c, D, n0,CP) return curves,n0,CP -def curve_to_t(c,D,n0,CP): #T,t +def curve_to_t(curves, c,D,n0,CP): #T,t l=[float(D[c[1]+1]),float(D[c[1]+2])] if c[0]=='t': l=[l[0]+CP[0], l[1]+CP[1]] @@ -970,11 +983,10 @@ def curve_to_t(c,D,n0,CP): #T,t BP.co[2]=l0[2] BP.co[3]=l0[3] curves.ITEM[n0].beziers_knot.append(B) - #if DEBUG==1: print B.co,BP.co CP=[l[0],l[1]] if len(D)>c[1]+3 and D[c[1]+3] not in TAGcourbe : c[1]+=4 - curve_to_t(c, D, n0,CP) + curves,n0,CP=curve_to_t(curves, c, D, n0,CP) return curves,n0,CP #-------------------- @@ -985,7 +997,7 @@ def build_SYMETRIC(l): Y=l[3]-(l[1]-l[3]) return X,Y -def curve_to_s(c,D,n0,CP): #S,s +def curve_to_s(curves, c,D,n0,CP): #S,s l=[float(D[c[1]+1]), float(D[c[1]+2]), float(D[c[1]+3]), @@ -1003,17 +1015,16 @@ def curve_to_s(c,D,n0,CP): #S,s #-------------------- BP.co[2],BP.co[3]=build_SYMETRIC([BP.co[4],BP.co[5],BP.co[0],BP.co[1]]) curves.ITEM[n0].beziers_knot.append(B) - #if DEBUG==1: print B.co,BP.co #-------------------- # 0.4.3 #-------------------- CP=[l[2],l[3]] if len(D)>c[1]+5 and D[c[1]+5] not in TAGcourbe : c[1]+=4 - curve_to_c(c, D, n0,CP) + curves,n0,CP=curve_to_c(curves, c, D, n0,CP) return curves,n0,CP -def curve_to_c(c, D, n0,CP): #c,C +def curve_to_c(curves, c, D, n0,CP): #c,C l=[float(D[c[1]+1]),float(D[c[1]+2]),float(D[c[1]+3]), float(D[c[1]+4]),float(D[c[1]+5]),float(D[c[1]+6])] if c[0]=='c': @@ -1030,6 +1041,8 @@ def curve_to_c(c, D, n0,CP): #c,C l[5], l[2], l[3]] #plus toucher au 2-3 + + B.ha=['C','C'] B.tag=c[0] BP=curves.ITEM[n0].beziers_knot[-1] @@ -1037,32 +1050,38 @@ def curve_to_c(c, D, n0,CP): #c,C BP.co[3]=l[1] BP.ha[1]='C' curves.ITEM[n0].beziers_knot.append(B) - #if DEBUG==1: print B.co,BP.co CP=[l[4],l[5]] if len(D)>c[1]+7 and D[c[1]+7] not in TAGcourbe : - c[1]+=6 - curve_to_c(c, D, n0,CP) + c[1]+=6 + curves,n0,CP=curve_to_c(curves, c, D, n0,CP) return curves,n0,CP -def draw_line_l(c, D, n0,CP): #L,l - l=[float(D[c[1]+1]),float(D[c[1]+2])] +def draw_line_l(curves, c, D, n0,CP): #L,l + + l=[float(D[c[1]+1]),float(D[c[1]+2])] if c[0]=='l': l=[l[0]+CP[0], - l[1]+CP[1]] + l[1]+CP[1]] B=Bez() - B.co=[l[0],l[1],l[0],l[1],l[0],l[1]] + B.co=[l[0],l[1], + l[0],l[1], + l[0],l[1]] + B.ha=['L','L'] B.tag=c[0] BP=curves.ITEM[n0].beziers_knot[-1] BP.ha[1]='L' + curves.ITEM[n0].beziers_knot.append(B) - CP=[B.co[0],B.co[1]] + CP=[B.co[4],B.co[5]] + if len(D)>c[1]+3 and D[c[1]+3] not in TAGcourbe : c[1]+=2 - draw_line_l(c, D, n0,CP) #L + curves,n0,CP=draw_line_l(curves, c, D, n0,CP) #L + return curves,n0,CP -def draw_line_h(c,D,n0,CP): #H,h +def draw_line_h(curves, c,D,n0,CP): #H,h if c[0]=='h': l=[float(D[c[1]+1])+float(CP[0]),CP[1]] else: @@ -1077,7 +1096,7 @@ def draw_line_h(c,D,n0,CP): #H,h CP=[l[0],l[1]] return curves,n0,CP -def draw_line_v(c,D,n0,CP): #V, v +def draw_line_v(curves, c,D,n0,CP): #V, v if c[0]=='v': l=[CP[0], float(D[c[1]+1])+CP[1]] else: @@ -1121,17 +1140,31 @@ TAGtransform=['M','L','C','S','H','V','T','Q'] tagTRANSFORM=0 def wash_DATA(ndata): - if ndata: - #if DEBUG==1: print ndata + if ndata: ndata = ndata.strip() + if ndata[0]==',':ndata=ndata[1:] if ndata[-1]==',':ndata=ndata[:-1] + #-------------------- # 0.4.0 : 'e' #-------------------- - i = ndata.find('-') - if i != -1 and ndata[i-1] not in ' ,e': - ndata=ndata.replace('-',',-') + ni=0 + i = ndata.find('-',ni) + if i != -1: + while i>-1 : + i = ndata.find('-',ni) + # 059l ------ + if i>0 : + if ndata[i-1] not in [' ',',','e']: + ndata=ndata[:i]+','+ndata[i:] + ni=i+2 + else: + ni=i+1 + elif i>-1: + ni=1 + # 059l ------ + ndata=ndata.replace(',,',',') ndata=ndata.replace(' ',',') ndata=ndata.split(',') @@ -1153,7 +1186,7 @@ def list_DATA(DATA): # borner les differents segments qui devront etre # traites # pour cela construire une liste avec chaque - # la position de chaqe emplacement tag de type + # position de chaque emplacement tag de type # commande path... # ---------------------------------------- tagplace=[] @@ -1169,8 +1202,10 @@ def list_DATA(DATA): # d'apparition des tags #------------------------------------------ tagplace.sort() - + tpn=range(len(tagplace)) + + #-------------------- # 0.3.5 :: short data, only one tag #-------------------- @@ -1179,14 +1214,18 @@ def list_DATA(DATA): for t in tpn[:-1]: DATA2.append(DATA[tagplace[t]:tagplace[t]+1]) ndata=DATA[tagplace[t]+1:tagplace[t+1]] + if DATA2[-1] not in ['z','Z'] : ndata=wash_DATA(ndata) DATA2.extend(ndata) + DATA2.append(DATA[tagplace[t+1]:tagplace[t+1]+1]) + if DATA2[-1] not in ['z','Z'] and len(DATA)-1>=tagplace[t+1]+1: ndata=DATA[tagplace[t+1]+1:] ndata=wash_DATA(ndata) DATA2.extend(ndata) #059a + else: #-------------------- # 0.3.5 : short data,only one tag @@ -1276,15 +1315,13 @@ def control_CONTAINT(txt): nt0=txt[t0:t1+1] t2=nt0[nt0.find('(')+1:-1] val=nt0[:nt0.find('(')] + while t2.find(' ')!=-1: t2=t2.replace(' ',' ') - t2=t2.replace(' ',',') + while t2.find(', ')!=-1: #059l + t2=t2.replace(', ',',') #059l - """ - t2=t2.split(',') - for index, t in enumerate(t2): - t2[index]=float(t) - """ + t2=t2.replace(' ',',') t2=[float(t) for t in t2.split(',')] if val=='rotate' : @@ -1314,12 +1351,24 @@ def curve_FILL(Courbe,proprietes): i= i+6 Courbe[n].color=[int(pr[i:i+2],16),int(pr[i+2:i+4],16),int(pr[i+4:i+6],16)] Courbe[n].mat=1 - elif ';fill-opacity' in pr: - i= pr.find('fill:')+5 - i2= pr.find(';',i) - COLORNAME= pr[i:i2] - Courbe[n].color=SVGCOLORNAMELIST[COLORNAME] - Courbe[n].mat=1 + elif ';fill-opacity' in pr: + if pr.find('fill:url')==-1: + i= pr.find('fill:')+5 + i2= pr.find(';',i) + COLORNAME= pr[i:i2] + Courbe[n].color=SVGCOLORNAMELIST[COLORNAME] + Courbe[n].mat=1 + elif 'color:' in pr: + i= pr.find('color:')+6 + i2= pr.find(';',i) + COLORNAME= pr[i:i2] + Courbe[n].color=SVGCOLORNAMELIST[COLORNAME] + Courbe[n].mat=1 + else : + COLORNAME= 'white' + Courbe[n].color=SVGCOLORNAMELIST[COLORNAME] + Courbe[n].mat=1 + #---------------------------------------------- # 0.4.1 : apply transform stack #---------------------------------------------- @@ -1367,9 +1416,8 @@ def filter(d): def get_BOUNDBOX(BOUNDINGBOX,SVG): if 'viewbox' not in SVG: h=float(filter(SVG['height'])) - #if DEBUG==1 : print 'h : ',h + w=float(filter(SVG['width'])) - #if DEBUG==1 : print 'w :',w BOUNDINGBOX['rec']=[0.0,0.0,w,h] r=BOUNDINGBOX['rec'] BOUNDINGBOX['coef']=w/h @@ -1444,7 +1492,6 @@ def build_HIERARCHY(t): b=balisetype.index(t[t0+1]) if t[t0+2]=='-': b=balisetype.index(t[t0+1])+1 - #print t[t0:t1] balise=BALISES[b] if b==2: parent=STACK.pop(-1) @@ -1465,12 +1512,8 @@ def build_HIERARCHY(t): if balise=='E' or balise=='O': proprietes=collect_ATTRIBUTS(t[t0:t1+ouvrante]) - #print proprietes if 'id' in proprietes: LAST_ID=proprietes['id'] - #print LAST_ID - - if balise=='O' and 'transform' in proprietes: STACK.append(proprietes['transform']) @@ -1489,20 +1532,20 @@ def build_HIERARCHY(t): # 0.5.8, to remove exec #-------------------- D=OTHERSSHAPES[proprietes['TYPE']](proprietes) - + CP=[0.0,0.0] if len(D)>0: cursor=0 proprietes['n']=[] for cell in D: - #if DEBUG==2 : print 'cell : ',cell ,' --' + if len(cell)>=1 and cell[0] in TAGcourbe: #-------------------- # 0.5.8, to remove exec #-------------------- if cell[0] in ['m','M']: - curves,n0,CP=Actions[cell]([cell,cursor], D, n0,CP,proprietes) + curves,n0,CP=Actions[cell](curves, [cell,cursor], D, n0,CP,proprietes) else: - curves,n0,CP=Actions[cell]([cell,cursor], D, n0,CP) + curves,n0,CP=Actions[cell](curves, [cell,cursor], D, n0,CP) cursor+=1 if TRANSFORM>0 or 'transform' in proprietes : @@ -1513,7 +1556,6 @@ def build_HIERARCHY(t): elif proprietes['TYPE'] == 'svg': - #print 'proprietes.keys()',proprietes.keys() BOUNDINGBOX = get_BOUNDBOX(BOUNDINGBOX,proprietes) else: #-------------------- diff --git a/release/scripts/export_fbx.py b/release/scripts/export_fbx.py index 3f02a71f951..730776bf1b8 100644 --- a/release/scripts/export_fbx.py +++ b/release/scripts/export_fbx.py @@ -66,8 +66,6 @@ import BPyMesh import BPySys import BPyMessages -import sys - ## This was used to make V, but faster not to do all that ##valid = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_,.()[]{}' ##v = range(255) @@ -184,7 +182,19 @@ def sane_texname(data): return sane_name(data, sane_name_mapping_tex) def sane_takename(data): return sane_name(data, sane_name_mapping_take) def sane_groupname(data): return sane_name(data, sane_name_mapping_group) - +def derived_paths(fname_orig, basepath, FORCE_CWD=False): + ''' + 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. + use when we know the file will be in the basepath. + ''' + fname = Blender.sys.expandpath(fname_orig) + fname_strip = strip_path(fname) + if FORCE_CWD: fname_rel = '.' + Blender.sys.sep + fname_strip + else: fname_rel = Blender.sys.relpath(fname, basepath) + if fname_rel.startswith('//'): fname_rel = '.' + Blender.sys.sep + fname_rel[2:] + return fname, fname_strip, fname_rel def mat4x4str(mat): @@ -342,6 +352,8 @@ def write(filename, batch_objects = None, \ # end batch support + # Use this for working out paths relative to the export location + basepath = Blender.sys.dirname(filename) # ---------------------------------------------- # storage classes @@ -1141,10 +1153,9 @@ def write(filename, batch_objects = None, \ Property: "Width", "int", "",0 Property: "Height", "int", "",0''') if tex: - fname = tex.filename - fname_strip = strip_path(fname) + fname, fname_strip, fname_rel = derived_paths(tex.filename, basepath, EXP_IMAGE_COPY) else: - fname = fname_strip = '' + fname = fname_strip = fname_rel = '' file.write('\n\t\t\tProperty: "Path", "charptr", "", "%s"' % fname_strip) @@ -1163,7 +1174,7 @@ def write(filename, batch_objects = None, \ file.write('\n\t\tFilename: "%s"' % fname_strip) if fname_strip: fname_strip = '/' + fname_strip - file.write('\n\t\tRelativeFilename: "fbx%s"' % fname_strip) # make relative + file.write('\n\t\tRelativeFilename: "%s"' % fname_rel) # make relative file.write('\n\t}') @@ -1202,13 +1213,14 @@ def write(filename, batch_objects = None, \ }''') file.write('\n\t\tMedia: "Video::%s"' % texname) + if tex: - fname = tex.filename - file.write('\n\t\tFileName: "%s"' % strip_path(fname)) - file.write('\n\t\tRelativeFilename: "fbx/%s"' % strip_path(fname)) # need some make relative command + fname, fname_strip, fname_rel = derived_paths(tex.filename, basepath, EXP_IMAGE_COPY) else: - file.write('\n\t\tFileName: ""') - file.write('\n\t\tRelativeFilename: "fbx"') + fname = fname_strip = fname_rel = '' + + file.write('\n\t\tFileName: "%s"' % fname_strip) + file.write('\n\t\tRelativeFilename: "%s"' % fname_rel) # need some make relative command file.write(''' ModelUVTranslation: 0,0 @@ -1434,13 +1446,13 @@ def write(filename, batch_objects = None, \ for f in me.faces: for col in f.col: if i==-1: - file.write('%i,%i,%i' % (col[0], col[1], col[2])) + file.write('%.4f,%.4f,%.4f,1' % (col[0]/255.0, col[1]/255.0, col[2]/255.0)) i=0 else: if i==7: file.write('\n\t\t\t\t') i=0 - file.write(',%i,%i,%i' % (col[0], col[1], col[2])) + file.write(',%.4f,%.4f,%.4f,1' % (col[0]/255.0, col[1]/255.0, col[2]/255.0)) i+=1 ii+=1 # One more Color @@ -2658,7 +2670,7 @@ Takes: {''') # copy images if enabled if EXP_IMAGE_COPY: - copy_images( Blender.sys.dirname(filename), [ tex[1] for tex in textures if tex[1] != None ]) + copy_images( basepath, [ tex[1] for tex in textures if tex[1] != None ]) print 'export finished in %.4f sec.' % (Blender.sys.time() - start_time) return True diff --git a/release/scripts/export_obj.py b/release/scripts/export_obj.py index 9feb02638c3..28e1443e953 100644 --- a/release/scripts/export_obj.py +++ b/release/scripts/export_obj.py @@ -120,7 +120,7 @@ def write_mtl(filename): if img: # We have an image on the face! file.write('map_Kd %s\n' % img.filename.split('\\')[-1].split('/')[-1]) # Diffuse mapping image - elif not mat: # No face image. if we havea material search for MTex image. + elif mat: # No face image. if we havea material search for MTex image. for mtex in mat.getTextures(): if mtex and mtex.tex.type == Blender.Texture.Types.IMAGE: try: diff --git a/release/scripts/help_bpy_api.py b/release/scripts/help_bpy_api.py index 484663b32b3..9c3a24af288 100644 --- a/release/scripts/help_bpy_api.py +++ b/release/scripts/help_bpy_api.py @@ -1,17 +1,17 @@ #!BPY """ Name: 'Blender/Python Scripting API' -Blender: 244 +Blender: 248 Group: 'Help' Tooltip: 'The Blender Python API reference manual' """ __author__ = "Matt Ebb" __url__ = ("blender", "blenderartist") -__version__ = "1.0" +__version__ = "1.0.1" __bpydoc__ = """\ This script opens the user's default web browser at http://www.blender.org's -"Blenders Python API" page. +"Blender Python API Reference" page. """ # -------------------------------------------------------------------------- @@ -38,4 +38,4 @@ This script opens the user's default web browser at http://www.blender.org's import Blender, webbrowser version = str(int(Blender.Get('version'))) -webbrowser.open('http://www.blender.org/documentation/'+ version +'PythonDoc/index.html') +webbrowser.open('http://www.blender.org/documentation/'+ version +'PythonDoc/') diff --git a/release/scripts/help_browser.py b/release/scripts/help_browser.py index b27e266f368..c207a12068f 100644 --- a/release/scripts/help_browser.py +++ b/release/scripts/help_browser.py @@ -8,7 +8,7 @@ Tooltip: 'Show help information about a chosen installed script.' """ __author__ = "Willian P. Germano" -__version__ = "0.1 11/02/04" +__version__ = "0.3 01/21/09" __email__ = ('scripts', 'Author, wgermano:ig*com*br') __url__ = ('blender', 'blenderartists.org') @@ -47,8 +47,6 @@ Hotkeys:<br> # $Id$ # # -------------------------------------------------------------------------- -# sysinfo.py version 0.1 Jun 09, 2004 -# -------------------------------------------------------------------------- # ***** BEGIN GPL LICENSE BLOCK ***** # # Copyright (C) 2004: Willian P. Germano, wgermano _at_ ig.com.br @@ -69,6 +67,9 @@ Hotkeys:<br> # # ***** END GPL LICENCE BLOCK ***** # -------------------------------------------------------------------------- +# Thanks: Brendon Murphy (suggestion) and Kevin Morgan (implementation) +# for the "run" button; Jean-Michel Soler for pointing a parsing error +# with multilines using triple single quotes. import Blender from Blender import sys as bsys, Draw, Window, Registry @@ -355,7 +356,12 @@ def parse_pyobj(var, lines, i): l = "ERROR" elif l[0] == "'": - if l[-1] == '\\': + if l[1:3] == "''": # ''' + if l.find("'''", 3) < 0: # multiline + l2, i = parse_pyobj_close("'''", lines, i) + if l[-1] == '\\': l = l[:-1] + l = "%s%s" % (l, l2) + elif l[-1] == '\\': l2, i = parse_pyobj_close("'", lines, i) l = "%s%s" % (l, l2) elif l[-1] == "'" and l[-2] != '\\': # single line: '...' @@ -543,6 +549,7 @@ BEVT_GMENU = range(100, len_gmenus + 100) BEVT_VIEWSOURCE = 1 BEVT_EXIT = 2 BEVT_BACK = 3 +BEVT_EXEC = 4 # Executes Script # gui callbacks: @@ -551,7 +558,7 @@ def gui(): # drawing the screen global SCREEN, START_SCREEN, SCRIPT_SCREEN global SCRIPT_INFO, AllGroups, GROUP_MENUS global BEVT_EMAIL, BEVT_LINK - global BEVT_VIEWSOURCE, BEVT_EXIT, BEVT_BACK, BEVT_GMENU, BUT_GMENU + global BEVT_VIEWSOURCE, BEVT_EXIT, BEVT_BACK, BEVT_GMENU, BUT_GMENU, BEVT_EXEC global PADDING, WIN_W, WIN_H, SCROLL_DOWN, COLUMNS, FMODE theme = Theme.Get()[0] @@ -674,8 +681,11 @@ def gui(): # drawing the screen 'View this script\'s source code in the Text Editor (hotkey: S)') Draw.PushButton('exit', BEVT_EXIT, x + 45, 17, 45, bh, 'Exit from Scripts Help Browser (hotkey: Q)') - if not FMODE: Draw.PushButton('back', BEVT_BACK, x + 2*45, 17, 45, bh, + if not FMODE: + Draw.PushButton('back', BEVT_BACK, x + 2*45, 17, 45, bh, 'Back to scripts selection screen (hotkey: ESC)') + Draw.PushButton('run script', BEVT_EXEC, x + 3*45, 17, 60, bh, 'Run this script') + BGL.glColor3ub(COL_TXTHI[0],COL_TXTHI[1], COL_TXTHI[2]) BGL.glRasterPos2i(x, 5) Draw.Text('use the arrow keys or the mouse wheel to scroll text', 'small') @@ -766,6 +776,14 @@ def button_event(evt): # gui button events SCRIPT_INFO = None SCROLL_DOWN = 0 Draw.Redraw() + elif evt == BEVT_EXEC: # Execute script + exec_line = '' + if SCRIPT_INFO.script.userdir: + exec_line = bsys.join(Blender.Get('uscriptsdir'), SCRIPT_INFO.script.fname) + else: + exec_line = bsys.join(Blender.Get('scriptsdir'), SCRIPT_INFO.script.fname) + + Blender.Run(exec_line) keepon = True FMODE = False # called by Blender.ShowHelp(name) API function ? diff --git a/release/scripts/help_getting_started.py b/release/scripts/help_getting_started.py index 81b002da4e4..a4f6da5cc55 100644 --- a/release/scripts/help_getting_started.py +++ b/release/scripts/help_getting_started.py @@ -1,16 +1,16 @@ #!BPY """ Name: 'Getting Started' -Blender: 234 +Blender: 248 Group: 'Help' Tooltip: 'Help for new users' """ __author__ = "Matt Ebb" __url__ = ("blender", "blenderartists.org") -__version__ = "1.0" +__version__ = "1.0.1" __bpydoc__ = """\ -This script opens the user's default web browser at www.blender3d.org's +This script opens the user's default web browser at www.blender.org's "Getting Started" page. """ @@ -39,5 +39,4 @@ This script opens the user's default web browser at www.blender3d.org's # -------------------------------------------------------------------------- import Blender, webbrowser -version = str(Blender.Get('version')) -webbrowser.open('http://www.blender3d.org/Help/?pg=GettingStarted&ver=' + version) +webbrowser.open('http://www.blender.org/education-help/tutorials/getting-started/') diff --git a/release/scripts/help_manual.py b/release/scripts/help_manual.py index cf293bf7c2c..b830975e593 100644 --- a/release/scripts/help_manual.py +++ b/release/scripts/help_manual.py @@ -1,17 +1,17 @@ #!BPY """ Name: 'Manual' -Blender: 234 +Blender: 248 Group: 'Help' -Tooltip: 'The Blender reference manual' +Tooltip: 'The Blender Wiki manual' """ __author__ = "Matt Ebb" __url__ = ("blender", "blenderartists.org") -__version__ = "1.0" +__version__ = "1.0.1" __bpydoc__ = """\ -This script opens the user's default web browser at www.blender3d.org's -"Blender Manual" page. +This script opens the user's default web browser at www.blender.org's +"Manual" page. """ # -------------------------------------------------------------------------- @@ -37,5 +37,4 @@ This script opens the user's default web browser at www.blender3d.org's # -------------------------------------------------------------------------- import Blender, webbrowser -version = str(Blender.Get('version')) -webbrowser.open('http://www.blender3d.org/Help/?pg=Manual&ver=' + version) +webbrowser.open('http://wiki.blender.org/index.php/Manual') diff --git a/release/scripts/help_release_notes.py b/release/scripts/help_release_notes.py index af7a7042489..919ec72da3c 100644 --- a/release/scripts/help_release_notes.py +++ b/release/scripts/help_release_notes.py @@ -1,17 +1,17 @@ #!BPY """ -Name: 'Release Notes' -Blender: 234 +Name: 'Release Logs' +Blender: 248 Group: 'Help' Tooltip: 'Information about the changes in this version of Blender' """ __author__ = "Matt Ebb" __url__ = ("blender", "blenderartists.org") -__version__ = "1.0" +__version__ = "1.0.1" __bpydoc__ = """\ -This script opens the user's default web browser at www.blender3d.org's -"Release Notes" page. +This script opens the user's default web browser at www.blender.org's +"Release Logs" page. """ # -------------------------------------------------------------------------- @@ -37,5 +37,5 @@ This script opens the user's default web browser at www.blender3d.org's # -------------------------------------------------------------------------- import Blender, webbrowser -version = str(Blender.Get('version')) -webbrowser.open('http://www.blender3d.org/Help/?pg=ReleaseNotes&ver=' + version) + +webbrowser.open('http://www.blender.org/development/release-logs/') diff --git a/release/scripts/help_tutorials.py b/release/scripts/help_tutorials.py index 04d6c799455..1fe466560f0 100644 --- a/release/scripts/help_tutorials.py +++ b/release/scripts/help_tutorials.py @@ -2,17 +2,17 @@ """ Name: 'Tutorials' -Blender: 234 +Blender: 248 Group: 'Help' Tooltip: 'Tutorials for learning to use Blender' """ __author__ = "Matt Ebb" __url__ = ("blender", "blenderartists.org") -__version__ = "1.0" +__version__ = "1.0.1" __bpydoc__ = """\ -This script opens the user's default web browser at www.blender3d.org's -"Blender Tutorials" page. +This script opens the user's default web browser at www.blender.org's +"Tutorials" page. """ # -------------------------------------------------------------------------- @@ -38,5 +38,4 @@ This script opens the user's default web browser at www.blender3d.org's # -------------------------------------------------------------------------- import Blender, webbrowser -version = str(Blender.Get('version')) -webbrowser.open('http://www.blender3d.org/Help/?pg=Tutorials&ver=' + version) +webbrowser.open('http://www.blender.org/education-help/tutorials/') diff --git a/release/scripts/help_web_blender.py b/release/scripts/help_web_blender.py index 0f9e32dea0e..db0a78d90f7 100644 --- a/release/scripts/help_web_blender.py +++ b/release/scripts/help_web_blender.py @@ -2,17 +2,17 @@ """ Name: 'Blender Website' -Blender: 234 +Blender: 248 Group: 'HelpWebsites' Tooltip: 'The official Blender website' """ __author__ = "Matt Ebb" __url__ = ("blender", "blenderartists.org") -__version__ = "1.0" +__version__ = "1.0.1" __bpydoc__ = """\ This script opens the user's default web browser at Blender's main site, -www.blender3d.org. +www.blender.org. """ @@ -39,4 +39,4 @@ www.blender3d.org. # -------------------------------------------------------------------------- import Blender, webbrowser -webbrowser.open('http://www.blender3d.org/') +webbrowser.open('http://www.blender.org/') diff --git a/release/scripts/help_web_devcomm.py b/release/scripts/help_web_devcomm.py index 344622cc113..e04a54501f7 100644 --- a/release/scripts/help_web_devcomm.py +++ b/release/scripts/help_web_devcomm.py @@ -2,17 +2,17 @@ """ Name: 'Developer Community' -Blender: 234 +Blender: 248 Group: 'HelpWebsites' Tooltip: 'Get involved with Blender development' """ __author__ = "Matt Ebb" __url__ = ("blender", "blenderartists.org") -__version__ = "1.0" +__version__ = "1.0.1" __bpydoc__ = """\ -This script opens the user's default web browser at www.blender.org, the -Blender development portal. +This script opens the user's default web browser at www.blender.org's +"Get Involved" page. """ # -------------------------------------------------------------------------- @@ -38,4 +38,4 @@ Blender development portal. # -------------------------------------------------------------------------- import webbrowser -webbrowser.open('http://www.blender.org') +webbrowser.open('http://www.blender.org/community/get-involved/') diff --git a/release/scripts/help_web_eshop.py b/release/scripts/help_web_eshop.py index 451fd735150..c33849ac419 100644 --- a/release/scripts/help_web_eshop.py +++ b/release/scripts/help_web_eshop.py @@ -2,16 +2,16 @@ """ Name: 'Blender E-Shop' -Blender: 234 +Blender: 248 Group: 'HelpWebsites' Tooltip: 'Buy official Blender resources and merchandise online' """ __author__ = "Matt Ebb" __url__ = ("blender", "blenderartists.org") -__version__ = "1.0" +__version__ = "1.0.1" __bpydoc__ = """\ -This script opens the user's default web browser at www.blender3d.org's +This script opens the user's default web browser at www.blender.org's "E-Shop" section. """ diff --git a/release/scripts/help_web_usercomm.py b/release/scripts/help_web_usercomm.py index fbe19956eb7..a77a2bb9fef 100644 --- a/release/scripts/help_web_usercomm.py +++ b/release/scripts/help_web_usercomm.py @@ -2,16 +2,16 @@ """ Name: 'User Community' -Blender: 234 +Blender: 248 Group: 'HelpWebsites' Tooltip: 'Get involved with other Blender users' """ __author__ = "Matt Ebb" __url__ = ("blender", "blenderartists.org") -__version__ = "1.0" +__version__ = "1.0.1" __bpydoc__ = """\ -This script opens the user's default web browser at www.blender3d.org's +This script opens the user's default web browser at www.blender.org's "User Community" page. """ @@ -38,4 +38,4 @@ This script opens the user's default web browser at www.blender3d.org's # -------------------------------------------------------------------------- import webbrowser -webbrowser.open('http://www.blender3d.org/Community') +webbrowser.open('http://www.blender.org/community/user-community/') diff --git a/release/scripts/import_obj.py b/release/scripts/import_obj.py index 3aad0800cf7..42cdac4dc35 100644 --- a/release/scripts/import_obj.py +++ b/release/scripts/import_obj.py @@ -424,8 +424,8 @@ def create_mesh(scn, new_objects, has_ngons, CREATE_FGONS, CREATE_EDGES, verts_l sharp_edges[key]= None - # mat the material names to an index - material_mapping= dict([(name, i) for i, name in enumerate(unique_materials.keys())]) + # map the material names to an index + material_mapping= dict([(name, i) for i, name in enumerate(unique_materials)]) # enumerate over unique_materials keys() materials= [None] * len(unique_materials) diff --git a/release/scripts/import_web3d.py b/release/scripts/import_web3d.py index 9447f15fb79..87a259cbe56 100755 --- a/release/scripts/import_web3d.py +++ b/release/scripts/import_web3d.py @@ -36,6 +36,8 @@ __bpydoc__ = """\ This script is an importer for the X3D and VRML97 file formats. """ +DEBUG = False + # This should work without a blender at all try: from Blender.sys import exists @@ -48,6 +50,27 @@ def baseName(path): def dirName(path): return path[:-len(baseName(path))] +def imageConvertCompat(path): + + try: import os + except: return path + if os.sep=='\\': return path # assime win32 has quicktime, dont convert + + if path.lower().endswith('.gif'): + path_to = path[:-3] + 'png' + + ''' + if exists(path_to): + return path_to + ''' + # print '\n'+path+'\n'+path_to+'\n' + os.system('convert "%s" "%s"' % (path, path_to)) # for now just hope we have image magick + + if exists(path_to): + return path_to + + return path + # notes # transform are relative # order dosnt matter for loc/size/rot @@ -78,6 +101,7 @@ def vrmlFormat(data): return l # Most cases accounted for! if we have a comment at the end of the line do this... + #j = l.find('url "') j = l.find('"') if j == -1: # simple no strings @@ -96,7 +120,39 @@ def vrmlFormat(data): data = '\n'.join([strip_comment(l) for l in data.split('\n') ]) # remove all whitespace + EXTRACT_STRINGS = True # only needed when strings or filesnames containe ,[]{} chars :/ + + if EXTRACT_STRINGS: + # We need this so we can detect URL's + data = '\n'.join([' '.join(l.split()) for l in data.split('\n')]) # remove all whitespace + + string_ls = [] + + #search = 'url "' + search = '"' + + ok = True + last_i = 0 + while ok: + ok = False + i = data.find(search, last_i) + if i != -1: + + start = i + len(search) # first char after end of search + end = data.find('"', start) + if end != -1: + item = data[start:end] + string_ls.append( item ) + data = data[:start] + data[end:] + ok = True # keep looking + + last_i = (end - len(item)) + 1 + # print last_i, item, '|' + data[last_i] + '|' + + # done with messy extracting strings part + + # Bad, dont take strings into account ''' data = data.replace('#', '\n#') @@ -108,6 +164,28 @@ def vrmlFormat(data): data = data.replace(']', '\n]\n') data = data.replace(',', ' , ') # make sure comma's seperate + if EXTRACT_STRINGS: + # add strings back in + + search = '"' # fill in these empty strings + + ok = True + last_i = 0 + while ok: + ok = False + i = data.find(search + '"', last_i) + # print i + if i != -1: + start = i + len(search) # first char after end of search + item = string_ls.pop(0) + # print item + data = data[:start] + item + data[start:] + + last_i = start + len(item) + 1 + + ok = True + + # More annoying obscure cases where USE or DEF are placed on a newline # data = data.replace('\nDEF ', ' DEF ') # data = data.replace('\nUSE ', ' USE ') @@ -125,6 +203,7 @@ def vrmlFormat(data): NODE_NORMAL = 1 # {} NODE_ARRAY = 2 # [] NODE_REFERENCE = 3 # USE foobar +# NODE_PROTO = 4 # lines = [] @@ -135,6 +214,10 @@ def getNodePreText(i, words): if i>=len(lines): break + ''' + elif lines[i].startswith('PROTO'): + return NODE_PROTO, i+1 + ''' elif lines[i]=='{': # words.append(lines[i]) # no need # print "OK" @@ -168,6 +251,23 @@ def is_nodeline(i, words): if not lines[i][0].isalpha(): return 0, 0 + #if lines[i].startswith('field'): + # return 0, 0 + + # Is this a prototype?? + if lines[i].startswith('PROTO'): + words[:] = lines[i].split() + return NODE_NORMAL, i+1 # TODO - assumes the next line is a '[\n', skip that + if lines[i].startswith('EXTERNPROTO'): + words[:] = lines[i].split() + return NODE_ARRAY, i+1 # TODO - assumes the next line is a '[\n', skip that + + ''' + proto_type, new_i = is_protoline(i, words, proto_field_defs) + if new_i != -1: + return proto_type, new_i + ''' + # Simple "var [" type if lines[i+1] == '[': if lines[i].count('"') % 2 == 0: @@ -177,6 +277,7 @@ def is_nodeline(i, words): node_type, new_i = getNodePreText(i, words) if not node_type: + if DEBUG: print "not node_type", lines[i] return 0, 0 # Ok, we have a { after some values @@ -199,21 +300,46 @@ def is_numline(i): ''' Does this line start with a number? ''' + + # Works but too slow. + ''' + l = lines[i] + for w in l.split(): + if w==',': + pass + else: + try: + float(w) + return True + + except: + return False + + return False + ''' + l = lines[i] + + line_start = 0 + + if l.startswith(', '): + line_start += 2 + line_end = len(l)-1 - line_end_new = l.find(' ') # comma's always have a space before them + line_end_new = l.find(' ', line_start) # comma's always have a space before them if line_end_new != -1: line_end = line_end_new try: - float(l[:line_end]) # works for a float or int + float(l[line_start:line_end]) # works for a float or int return True except: return False + class vrmlNode(object): - __slots__ = 'id', 'fields', 'node_type', 'parent', 'children', 'parent', 'array_data', 'reference', 'lineno', 'filename', 'blendObject', 'DEF_NAMESPACE', 'FIELD_NAMESPACE', 'x3dNode' + __slots__ = 'id', 'fields', 'proto_node', 'proto_field_defs', 'proto_fields', 'node_type', 'parent', 'children', 'parent', 'array_data', 'reference', 'lineno', 'filename', 'blendObject', 'DEF_NAMESPACE', 'ROUTE_IPO_NAMESPACE', 'PROTO_NAMESPACE', 'x3dNode' def __init__(self, parent, node_type, lineno): self.id = None self.node_type = node_type @@ -228,10 +354,17 @@ class vrmlNode(object): # This is only set from the root nodes. # Having a filename also denotes a root node self.filename = None + self.proto_node = None # proto field definition eg: "field SFColor seatColor .6 .6 .1" # Store in the root node because each inline file needs its own root node and its own namespace self.DEF_NAMESPACE = None + self.ROUTE_IPO_NAMESPACE = None + ''' self.FIELD_NAMESPACE = None + ''' + + + self.PROTO_NAMESPACE = None self.reference = None @@ -241,28 +374,52 @@ class vrmlNode(object): return self.fields = [] # fields have no order, in some cases rool level values are not unique so dont use a dict + + self.proto_field_defs = [] # proto field definition eg: "field SFColor seatColor .6 .6 .1" + self.proto_fields = [] # proto field usage "diffuseColor IS seatColor" self.children = [] self.array_data = [] # use for arrays of data - should only be for NODE_ARRAY types # Only available from the root node + ''' def getFieldDict(self): if self.FIELD_NAMESPACE != None: return self.FIELD_NAMESPACE else: return self.parent.getFieldDict() + ''' + def getProtoDict(self): + if self.PROTO_NAMESPACE != None: + return self.PROTO_NAMESPACE + else: + return self.parent.getProtoDict() def getDefDict(self): if self.DEF_NAMESPACE != None: return self.DEF_NAMESPACE else: return self.parent.getDefDict() + + def getRouteIpoDict(self): + if self.ROUTE_IPO_NAMESPACE != None: + return self.ROUTE_IPO_NAMESPACE + else: + return self.parent.getRouteIpoDict() def setRoot(self, filename): self.filename = filename - self.FIELD_NAMESPACE = {} - self.DEF_NAMESPACE= {} - + # self.FIELD_NAMESPACE = {} + self.DEF_NAMESPACE = {} + self.ROUTE_IPO_NAMESPACE = {} + self.PROTO_NAMESPACE = {} + + def isRoot(self): + if self.filename == None: + return False + else: + return True + def getFilename(self): if self.filename: return self.filename @@ -284,15 +441,36 @@ class vrmlNode(object): except: return None - def getDefName(self): + def findSpecRecursive(self, spec): self_real = self.getRealNode() + if spec == self_real.getSpec(): + return self - if 'DEF' in self_real.id: - # print self_real.id - return self_real.id[ list(self_real.id).index('DEF')+1 ] - else: - return None + for child in self_real.children: + if child.findSpecRecursive(spec): + return child + + return None + + def getPrefix(self): + if self.id: + return self.id[0] + return None + + def getSpecialTypeName(self, typename): + self_real = self.getRealNode() + try: return self_real.id[ list(self_real.id).index(typename)+1 ] + except: return None + + + def getDefName(self): + return self.getSpecialTypeName('DEF') + + def getProtoName(self): + return self.getSpecialTypeName('PROTO') + def getExternprotoName(self): + return self.getSpecialTypeName('EXTERNPROTO') def getChildrenBySpec(self, node_spec): # spec could be Transform, Shape, Appearance self_real = self.getRealNode() @@ -329,7 +507,26 @@ class vrmlNode(object): ancestry.append(self) for child in self.getRealNode().children: if child not in ancestry: - child.getSerialized(results, ancestry) + # We dont want to load proto's, they are only references + # We could enforce this elsewhere + + # Only add this in a very special case + # where the parent of this object is not the real parent + # - In this case we have added the proto as a child to a node instancing it. + # This is a bit arbitary, but its how Proto's are done with this importer. + if child.getProtoName() == None and child.getExternprotoName() == None: + child.getSerialized(results, ancestry) + else: + + if DEBUG: print 'getSerialized() is proto:', child.getProtoName(), child.getExternprotoName(), self.getSpec() + + self_spec = self.getSpec() + + if child.getProtoName() == self_spec or child.getExternprotoName() == self_spec: + if DEBUG: "FoundProto!" + child.getSerialized(results, ancestry) + + return results @@ -342,7 +539,7 @@ class vrmlNode(object): child.searchNodeTypeID(node_spec, results) return results - def getFieldName(self, field): + def getFieldName(self, field, ancestry, AS_CHILD=False): self_real = self.getRealNode() # incase we're an instance for f in self_real.fields: @@ -350,14 +547,81 @@ class vrmlNode(object): if f and f[0] == field: # print '\tfound field', f - return f[1:] + if len(f)>=3 and f[1] == 'IS': # eg: 'diffuseColor IS legColor' + field_id = f[2] + + # print "\n\n\n\n\n\nFOND IS!!!" + f_proto_lookup = None + f_proto_child_lookup = None + i = len(ancestry) + while i: + i -= 1 + node = ancestry[i] + node = node.getRealNode() + + # proto settings are stored in "self.proto_node" + if node.proto_node: + # Get the default value from the proto, this can be overwridden by the proto instace + # 'field SFColor legColor .8 .4 .7' + if AS_CHILD: + for child in node.proto_node.children: + #if child.id and len(child.id) >= 3 and child.id[2]==field_id: + if child.id and ('point' in child.id or 'points' in child.id): + f_proto_child_lookup = child + + else: + for f_def in node.proto_node.proto_field_defs: + if len(f_def) >= 4: + if f_def[0]=='field' and f_def[2]==field_id: + f_proto_lookup = f_def[3:] + + # Node instance, Will be 1 up from the proto-node in the ancestry list. but NOT its parent. + # This is the setting as defined by the instance, including this setting is optional, + # and will override the default PROTO value + # eg: 'legColor 1 0 0' + if AS_CHILD: + for child in node.children: + if child.id and child.id[0]==field_id: + f_proto_child_lookup = child + else: + for f_def in node.fields: + if len(f_def) >= 2: + if f_def[0]==field_id: + if DEBUG: print "getFieldName(), found proto", f_def + f_proto_lookup = f_def[1:] + + + if AS_CHILD: + if f_proto_child_lookup: + if DEBUG: + print "getFieldName() - AS_CHILD=True, child found" + print f_proto_child_lookup + return f_proto_child_lookup + else: + return f_proto_lookup + else: + if AS_CHILD: + return None + else: + # Not using a proto + return f[1:] + # print '\tfield not found', field + + + # See if this is a proto name + if AS_CHILD: + child_array = None + for child in self_real.children: + if child.id and len(child.id) == 1 and child.id[0] == field: + return child + return None - def getFieldAsInt(self, field, default): + def getFieldAsInt(self, field, default, ancestry): self_real = self.getRealNode() # incase we're an instance - f = self_real.getFieldName(field) + f = self_real.getFieldName(field, ancestry) if f==None: return default if ',' in f: f = f[:f.index(',')] # strip after the comma @@ -371,10 +635,10 @@ class vrmlNode(object): print '\tvalue "%s" could not be used as an int for field "%s"' % (f[0], field) return default - def getFieldAsFloat(self, field, default): + def getFieldAsFloat(self, field, default, ancestry): self_real = self.getRealNode() # incase we're an instance - f = self_real.getFieldName(field) + f = self_real.getFieldName(field, ancestry) if f==None: return default if ',' in f: f = f[:f.index(',')] # strip after the comma @@ -388,10 +652,10 @@ class vrmlNode(object): print '\tvalue "%s" could not be used as a float for field "%s"' % (f[0], field) return default - def getFieldAsFloatTuple(self, field, default): + def getFieldAsFloatTuple(self, field, default, ancestry): self_real = self.getRealNode() # incase we're an instance - f = self_real.getFieldName(field) + f = self_real.getFieldName(field, ancestry) if f==None: return default # if ',' in f: f = f[:f.index(',')] # strip after the comma @@ -412,10 +676,10 @@ class vrmlNode(object): print '\tvalue "%s" could not be used as a float tuple for field "%s"' % (f, field) return default - def getFieldAsBool(self, field, default): + def getFieldAsBool(self, field, default, ancestry): self_real = self.getRealNode() # incase we're an instance - f = self_real.getFieldName(field) + f = self_real.getFieldName(field, ancestry) if f==None: return default if ',' in f: f = f[:f.index(',')] # strip after the comma @@ -431,10 +695,10 @@ class vrmlNode(object): print '\t"%s" could not be used as a bool for field "%s"' % (f[1], field) return default - def getFieldAsString(self, field, default=None): + def getFieldAsString(self, field, default, ancestry): self_real = self.getRealNode() # incase we're an instance - f = self_real.getFieldName(field) + f = self_real.getFieldName(field, ancestry) if f==None: return default if len(f) < 1: print '\t"%s" wrong length for string conversion for field "%s"' % (f, field) @@ -456,22 +720,22 @@ class vrmlNode(object): print '\tvalue "%s" could not be used as a string for field "%s"' % (f[0], field) return default - def getFieldAsArray(self, field, group): + def getFieldAsArray(self, field, group, ancestry): ''' For this parser arrays are children ''' self_real = self.getRealNode() # incase we're an instance - child_array = None - for child in self_real.children: - if child.id and len(child.id) == 1 and child.id[0] == field: - child_array = child - break + child_array = self_real.getFieldName(field, ancestry, True) + #if type(child_array)==list: # happens occasionaly + # array_data = child_array + if child_array==None: + # For x3d, should work ok with vrml too # for x3d arrays are fields, vrml they are nodes, annoying but not tooo bad. - data_split = self.getFieldName(field) + data_split = self.getFieldName(field, ancestry) if not data_split: return [] array_data = ' '.join(data_split) @@ -489,9 +753,12 @@ class vrmlNode(object): print '\tWarning, could not parse array data from field' array_data = [] else: - + # print child_array # Normal vrml array_data = child_array.array_data + + + # print 'array_data', array_data if group==-1 or len(array_data)==0: return array_data @@ -520,8 +787,6 @@ class vrmlNode(object): # We requested a flat array if group == 0: return flat_array - - new_array = [] sub_array = [] @@ -537,6 +802,30 @@ class vrmlNode(object): return new_array + def getFieldAsStringArray(self, field, ancestry): + ''' + Get a list of strings + ''' + self_real = self.getRealNode() # incase we're an instance + + child_array = None + for child in self_real.children: + if child.id and len(child.id) == 1 and child.id[0] == field: + child_array = child + break + if not child_array: + return [] + + # each string gets its own list, remove ""'s + try: + new_array = [f[0][1:-1] for f in child_array.fields] + except: + print '\twarning, string array could not be made' + new_array = [] + + return new_array + + def getLevel(self): # Ignore self_real level = 0 @@ -551,7 +840,6 @@ class vrmlNode(object): def __repr__(self): level = self.getLevel() ind = ' ' * level - if self.node_type==NODE_REFERENCE: brackets = '' elif self.node_type==NODE_NORMAL: @@ -564,38 +852,102 @@ class vrmlNode(object): else: text = '' - text += ind + 'ID: ' + str(self.id) + ' ' + str(level) + ('lineno %d\n' % self.lineno) + text += ind + 'ID: ' + str(self.id) + ' ' + str(level) + (' lineno %d\n' % self.lineno) if self.node_type==NODE_REFERENCE: + text += ind + "(reference node)\n" return text - for item in self.fields: + if self.proto_node: + text += ind + 'PROTO NODE...\n' + text += str(self.proto_node) + text += ind + 'PROTO NODE_DONE\n' + + text += ind + 'FIELDS:' + str(len(self.fields)) + '\n' + + for i,item in enumerate(self.fields): + text += ind + 'FIELD:\n' text += ind + str(item) +'\n' + + text += ind + 'PROTO_FIELD_DEFS:' + str(len(self.proto_field_defs)) + '\n' - #text += ind + 'ARRAY: ' + str(len(self.array_data)) + ' ' + str(self.array_data) + '\n' - text += ind + 'ARRAY: ' + str(len(self.array_data)) + '[...] \n' + for i,item in enumerate(self.proto_field_defs): + text += ind + 'PROTO_FIELD:\n' + text += ind + str(item) +'\n' + + text += ind + 'ARRAY: ' + str(len(self.array_data)) + ' ' + str(self.array_data) + '\n' + #text += ind + 'ARRAY: ' + str(len(self.array_data)) + '[...] \n' text += ind + 'CHILDREN: ' + str(len(self.children)) + '\n' - for child in self.children: + for i, child in enumerate(self.children): + text += ind + ('CHILD%d:\n' % i) text += str(child) text += '\n' + ind + brackets[1] return text - def parse(self, i): - new_i = self.__parse(i) + def parse(self, i, IS_PROTO_DATA=False): + new_i = self.__parse(i, IS_PROTO_DATA) # print self.id, self.getFilename() - # If we were an inline then try load the file + # Check if this node was an inline or externproto + + url_ls = [] + if self.node_type == NODE_NORMAL and self.getSpec() == 'Inline': - url = self.getFieldAsString('url', None) + ancestry = [] # Warning! - PROTO's using this wont work at all. + url = self.getFieldAsString('url', None, ancestry) + if url: + url_ls = [(url, None)] + del ancestry + + elif self.getExternprotoName(): + # externproto + url_ls = [] + for f in self.fields: + + if type(f)==str: + f = [f] + + for ff in f: + for f_split in ff.split('"'): + # print f_split + # "someextern.vrml#SomeID" + if '#' in f_split: + + f_split, f_split_id = f_split.split('#') # there should only be 1 # anyway + + url_ls.append( (f_split, f_split_id) ) + else: + url_ls.append( (f_split, None) ) + + + # Was either an Inline or an EXTERNPROTO + if url_ls: - if url != None: - if not exists(url): - url = dirName(self.getFilename()) + baseName(url) - if not exists(url): + # print url_ls + + for url, extern_key in url_ls: + print url + urls = [] + urls.append( url ) + urls.append( BPySys.caseInsensitivePath(urls[-1]) ) + + urls.append( dirName(self.getFilename()) + url ) + urls.append( BPySys.caseInsensitivePath(urls[-1]) ) + + urls.append( dirName(self.getFilename()) + baseName(url) ) + urls.append( BPySys.caseInsensitivePath(urls[-1]) ) + + try: + url = [url for url in urls if exists(url)][0] + url_found = True + except: + url_found = False + + if not url_found: print '\tWarning: Inline URL could not be found:', url else: if url==self.getFilename(): @@ -603,12 +955,12 @@ class vrmlNode(object): else: try: - f = open(url, 'rU') + data = gzipOpen(url) except: print '\tWarning: cant open the file:', url - f = None + data = None - if f: + if data: # Tricky - inline another VRML print '\tLoading Inline:"%s"...' % url @@ -616,26 +968,50 @@ class vrmlNode(object): lines_old = lines[:] - lines[:] = vrmlFormat( f.read() ) - f.close() + lines[:] = vrmlFormat( data ) lines.insert(0, '{') lines.insert(0, 'root_node____') lines.append('}') + ''' + ff = open('/tmp/test.txt', 'w') + ff.writelines([l+'\n' for l in lines]) + ''' child = vrmlNode(self, NODE_NORMAL, -1) child.setRoot(url) # initialized dicts child.parse(0) + # if self.getExternprotoName(): + if self.getExternprotoName(): + if not extern_key: # if none is spesified - use the name + extern_key = self.getSpec() + + if extern_key: + + self.children.remove(child) + child.parent = None + + extern_child = child.findSpecRecursive(extern_key) + + if extern_child: + self.children.append(extern_child) + extern_child.parent = self + + if DEBUG: print "\tEXTERNPROTO ID found!:", extern_key + else: + print "\tEXTERNPROTO ID not found!:", extern_key + # Watch it! - restore lines lines[:] = lines_old - return new_i - def __parse(self, i): - # print 'parsing at', i, - # print i, self.id, self.lineno + def __parse(self, i, IS_PROTO_DATA=False): + ''' + print 'parsing at', i, + print i, self.id, self.lineno + ''' l = lines[i] if l=='[': @@ -644,9 +1020,11 @@ class vrmlNode(object): i+=1 else: words = [] + node_type, new_i = is_nodeline(i, words) if not node_type: # fail for parsing new node. - raise "error" + print "Failed to parse new node" + raise ValueError if self.node_type==NODE_REFERENCE: # Only assign the reference and quit @@ -660,40 +1038,72 @@ class vrmlNode(object): # fill in DEF/USE key = self.getDefName() - if key != None: self.getDefDict()[ key ] = self + key = self.getProtoName() + if not key: key = self.getExternprotoName() + + proto_dict = self.getProtoDict() + if key != None: + proto_dict[ key ] = self + + # Parse the proto nodes fields + self.proto_node = vrmlNode(self, NODE_ARRAY, new_i) + new_i = self.proto_node.parse(new_i) + + self.children.remove(self.proto_node) + + # print self.proto_node + + new_i += 1 # skip past the { + + + else: # If we're a proto instance, add the proto node as our child. + spec = self.getSpec() + try: + self.children.append( proto_dict[spec] ) + #pass + except: + pass + + del spec + + del proto_dict, key + i = new_i # print self.id ok = True while ok: + if i>=len(lines): + return len(lines)-1 + l = lines[i] - # print '\t', i, l + # print '\tDEBUG:', i, self.node_type, l if l=='': i+=1 continue if l=='}': - if self.node_type != NODE_NORMAL: - print 'wrong node ending, expected an } ' + str(i) - raise "" + if self.node_type != NODE_NORMAL: # also ends proto nodes, we may want a type for these too. + print 'wrong node ending, expected an } ' + str(i) + ' ' + str(self.node_type) + if DEBUG: + raise ValueError ### print "returning", i return i+1 if l==']': if self.node_type != NODE_ARRAY: - print 'wrong node ending, expected a ] ' + str(i) - raise "" + print 'wrong node ending, expected a ] ' + str(i) + ' ' + str(self.node_type) + if DEBUG: + raise ValueError ### print "returning", i return i+1 node_type, new_i = is_nodeline(i, []) if node_type: # check text\n{ - ### print '\t\tgroup', i child = vrmlNode(self, node_type, i) i = child.parse(i) - # print child.id, 'YYY' elif l=='[': # some files have these anonymous lists child = vrmlNode(self, NODE_ARRAY, i) @@ -723,7 +1133,9 @@ class vrmlNode(object): values = l_split # This should not extend over multiple lines however it is possible - self.array_data.extend( values ) + # print self.array_data + if values: + self.array_data.extend( values ) i+=1 else: words = l.split() @@ -774,6 +1186,7 @@ class vrmlNode(object): # this IS a key but the previous value was not a key, ot it was a defined field. if (not iskey(field_context[-1])) or ((len(field_context)==3 and field_context[1]=='IS')): field_list.append(field_context) + field_context = [value[j]] else: # The last item was not a value, multiple keys are needed in some cases. @@ -796,18 +1209,9 @@ class vrmlNode(object): if value[0]=='field': # field SFFloat creaseAngle 4 - self.getFieldDict()[value[2]] = value[3:] # skip the first 3 values + self.proto_field_defs.append(value) else: - # Get referenced field - if len(value) >= 3 and value[1]=='IS': - try: - value = [ value[0] ] + self.getFieldDict()[ value[2] ] - except: - print '\tWarning, field could not be found:', value, 'TODO add support for exposedField' - print '\t', self.getFieldDict() - self.fields.append(value) - else: - self.fields.append(value) + self.fields.append(value) i+=1 def gzipOpen(path): @@ -843,12 +1247,13 @@ def vrml_parse(path): lines.insert(0, '{') lines.insert(0, 'dymmy_node') lines.append('}') - # Use for testing our parsed output, so we can check on line numbers. - ## ff = open('m:\\test.txt', 'w') - ## ff.writelines([l+'\n' for l in lines]) - + ''' + ff = open('/tmp/test.txt', 'w') + ff.writelines([l+'\n' for l in lines]) + ff.close() + ''' # Now evaluate it node_type, new_i = is_nodeline(0, []) @@ -866,9 +1271,13 @@ def vrml_parse(path): # Parse recursively root.parse(0) - # print root + # This prints a load of text + if DEBUG: + print root + return root, '' + # ====================== END VRML @@ -881,7 +1290,7 @@ class x3dNode(vrmlNode): vrmlNode.__init__(self, parent, node_type, -1) self.x3dNode = x3dNode - def parse(self): + def parse(self, IS_PROTO_DATA=False): # print self.x3dNode.tagName define = self.x3dNode.getAttributeNode('DEF') @@ -996,6 +1405,9 @@ for i, f in enumerate(files): # ----------------------------------------------------------------------------------- import bpy import BPyImage +import BPySys +reload(BPySys) +reload(BPyImage) import Blender from Blender import Texture, Material, Mathutils, Mesh, Types, Window from Blender.Mathutils import TranslationMatrix @@ -1018,12 +1430,12 @@ def translateScale(sca): mat[2][2] = sca[2] return mat -def translateTransform(node): - cent = node.getFieldAsFloatTuple('center', None) # (0.0, 0.0, 0.0) - rot = node.getFieldAsFloatTuple('rotation', None) # (0.0, 0.0, 1.0, 0.0) - sca = node.getFieldAsFloatTuple('scale', None) # (1.0, 1.0, 1.0) - scaori = node.getFieldAsFloatTuple('scaleOrientation', None) # (0.0, 0.0, 1.0, 0.0) - tx = node.getFieldAsFloatTuple('translation', None) # (0.0, 0.0, 0.0) +def translateTransform(node, ancestry): + cent = node.getFieldAsFloatTuple('center', None, ancestry) # (0.0, 0.0, 0.0) + rot = node.getFieldAsFloatTuple('rotation', None, ancestry) # (0.0, 0.0, 1.0, 0.0) + sca = node.getFieldAsFloatTuple('scale', None, ancestry) # (1.0, 1.0, 1.0) + scaori = node.getFieldAsFloatTuple('scaleOrientation', None, ancestry) # (0.0, 0.0, 1.0, 0.0) + tx = node.getFieldAsFloatTuple('translation', None, ancestry) # (0.0, 0.0, 0.0) if cent: cent_mat = TranslationMatrix(Vector(cent)).resize4x4() @@ -1055,11 +1467,11 @@ def translateTransform(node): return new_mat -def translateTexTransform(node): - cent = node.getFieldAsFloatTuple('center', None) # (0.0, 0.0) - rot = node.getFieldAsFloat('rotation', None) # 0.0 - sca = node.getFieldAsFloatTuple('scale', None) # (1.0, 1.0) - tx = node.getFieldAsFloatTuple('translation', None) # (0.0, 0.0) +def translateTexTransform(node, ancestry): + cent = node.getFieldAsFloatTuple('center', None, ancestry) # (0.0, 0.0) + rot = node.getFieldAsFloat('rotation', None, ancestry) # 0.0 + sca = node.getFieldAsFloatTuple('scale', None, ancestry) # (1.0, 1.0) + tx = node.getFieldAsFloatTuple('translation', None, ancestry) # (0.0, 0.0) if cent: @@ -1090,6 +1502,7 @@ def translateTexTransform(node): return new_mat + def getFinalMatrix(node, mtx, ancestry): transform_nodes = [node_tx for node_tx in ancestry if node_tx.getSpec() == 'Transform'] @@ -1101,17 +1514,17 @@ def getFinalMatrix(node, mtx, ancestry): mtx = Matrix() for node_tx in transform_nodes: - mat = translateTransform(node_tx) + mat = translateTransform(node_tx, ancestry) mtx = mtx * mat return mtx -def importMesh_IndexedFaceSet(geom, bpyima): +def importMesh_IndexedFaceSet(geom, bpyima, ancestry): # print geom.lineno, geom.id, vrmlNode.DEF_NAMESPACE.keys() - ccw = geom.getFieldAsBool('ccw', True) - ifs_colorPerVertex = geom.getFieldAsBool('colorPerVertex', True) # per vertex or per face - ifs_normalPerVertex = geom.getFieldAsBool('normalPerVertex', True) + ccw = geom.getFieldAsBool('ccw', True, ancestry) + ifs_colorPerVertex = geom.getFieldAsBool('colorPerVertex', True, ancestry) # per vertex or per face + ifs_normalPerVertex = geom.getFieldAsBool('normalPerVertex', True, ancestry) # This is odd how point is inside Coordinate @@ -1120,14 +1533,14 @@ def importMesh_IndexedFaceSet(geom, bpyima): coord = geom.getChildBySpec('Coordinate') # works for x3d and vrml - if coord: ifs_points = coord.getFieldAsArray('point', 3) + if coord: ifs_points = coord.getFieldAsArray('point', 3, ancestry) else: coord = [] if not coord: print '\tWarnint: IndexedFaceSet has no points' return None, ccw - ifs_faces = geom.getFieldAsArray('coordIndex', 0) + ifs_faces = geom.getFieldAsArray('coordIndex', 0, ancestry) coords_tex = None if ifs_faces: # In rare cases this causes problems - no faces but UVs??? @@ -1137,8 +1550,8 @@ def importMesh_IndexedFaceSet(geom, bpyima): coords_tex = geom.getChildBySpec('TextureCoordinate') if coords_tex: - ifs_texpoints = coords_tex.getFieldAsArray('point', 2) - ifs_texfaces = geom.getFieldAsArray('texCoordIndex', 0) + ifs_texpoints = coords_tex.getFieldAsArray('point', 2, ancestry) + ifs_texfaces = geom.getFieldAsArray('texCoordIndex', 0, ancestry) if not ifs_texpoints: # IF we have no coords, then dont bother @@ -1151,11 +1564,11 @@ def importMesh_IndexedFaceSet(geom, bpyima): vcolor_spot = None # spot color when we dont have an array of colors if vcolor: # float to char - ifs_vcol = [[int(c*256) for c in col] for col in vcolor.getFieldAsArray('color', 3)] - ifs_color_index = geom.getFieldAsArray('colorIndex', 0) + ifs_vcol = [[int(c*256) for c in col] for col in vcolor.getFieldAsArray('color', 3, ancestry)] + ifs_color_index = geom.getFieldAsArray('colorIndex', 0, ancestry) if not ifs_vcol: - vcolor_spot = [int(c*256) for c in vcolor.getFieldAsFloatTuple('color', [])] + vcolor_spot = [int(c*256) for c in vcolor.getFieldAsFloatTuple('color', [], ancestry)] # Convert faces into somthing blender can use edges = [] @@ -1338,12 +1751,18 @@ def importMesh_IndexedFaceSet(geom, bpyima): fv = f.verts for i,c in enumerate(fcol): color_index = fv[i].index # color index is vert index - if ifs_color_index: color_index = ifs_color_index[color_index] + if ifs_color_index: + try: + color_index = ifs_color_index[color_index] + except: + print '\tWarning: per vertex color index out of range' + continue - if len(ifs_vcol) < color_index: + if color_index < len(ifs_vcol): c.r, c.g, c.b = ifs_vcol[color_index] else: - print '\tWarning: per face color index out of range' + #print '\tWarning: per face color index out of range' + pass else: if vcolor_spot: # use 1 color, when ifs_vcol is [] for c in fcol: @@ -1361,24 +1780,27 @@ def importMesh_IndexedFaceSet(geom, bpyima): col = ifs_vcol[color_index] for i,c in enumerate(fcol): - c.r, c.g, c.b = col + try: + c.r, c.g, c.b = col + except: + pass # incase its not between 0 and 255 bpymesh.verts.delete([0,]) # EEKADOODLE return bpymesh, ccw -def importMesh_IndexedLineSet(geom): +def importMesh_IndexedLineSet(geom, ancestry): # VRML not x3d #coord = geom.getChildByName('coord') # 'Coordinate' coord = geom.getChildBySpec('Coordinate') # works for x3d and vrml - if coord: points = coord.getFieldAsArray('point', 3) + if coord: points = coord.getFieldAsArray('point', 3, ancestry) else: points = [] if not points: print '\tWarning: IndexedLineSet had no points' return None - ils_lines = geom.getFieldAsArray('coordIndex', 0) + ils_lines = geom.getFieldAsArray('coordIndex', 0, ancestry) lines = [] line = [] @@ -1417,11 +1839,11 @@ def importMesh_IndexedLineSet(geom): return bpycurve -def importMesh_PointSet(geom): +def importMesh_PointSet(geom, ancestry): # VRML not x3d #coord = geom.getChildByName('coord') # 'Coordinate' coord = geom.getChildBySpec('Coordinate') # works for x3d and vrml - if coord: points = coord.getFieldAsArray('point', 3) + if coord: points = coord.getFieldAsArray('point', 3, ancestry) else: points = [] # vcolor = geom.getChildByName('color') # blender dosnt have per vertex color @@ -1435,26 +1857,26 @@ GLOBALS['CIRCLE_DETAIL'] = 12 MATRIX_Z_TO_Y = RotationMatrix(90, 4, 'x') -def importMesh_Sphere(geom): +def importMesh_Sphere(geom, ancestry): # bpymesh = bpy.data.meshes.new() - diameter = geom.getFieldAsFloat('radius', 0.5) * 2 # * 2 for the diameter + diameter = geom.getFieldAsFloat('radius', 0.5, ancestry) * 2 # * 2 for the diameter bpymesh = Mesh.Primitives.UVsphere(GLOBALS['CIRCLE_DETAIL'], GLOBALS['CIRCLE_DETAIL'], diameter) bpymesh.transform(MATRIX_Z_TO_Y) return bpymesh -def importMesh_Cylinder(geom): +def importMesh_Cylinder(geom, ancestry): # bpymesh = bpy.data.meshes.new() - diameter = geom.getFieldAsFloat('radius', 1.0) * 2 # * 2 for the diameter - height = geom.getFieldAsFloat('height', 2) + diameter = geom.getFieldAsFloat('radius', 1.0, ancestry) * 2 # * 2 for the diameter + height = geom.getFieldAsFloat('height', 2, ancestry) bpymesh = Mesh.Primitives.Cylinder(GLOBALS['CIRCLE_DETAIL'], diameter, height) bpymesh.transform(MATRIX_Z_TO_Y) # Warning - Rely in the order Blender adds verts # not nice design but wont change soon. - bottom = geom.getFieldAsBool('bottom', True) - side = geom.getFieldAsBool('side', True) - top = geom.getFieldAsBool('top', True) + bottom = geom.getFieldAsBool('bottom', True, ancestry) + side = geom.getFieldAsBool('side', True, ancestry) + top = geom.getFieldAsBool('top', True, ancestry) if not top: # last vert is top center of tri fan. bpymesh.verts.delete([(GLOBALS['CIRCLE_DETAIL']+GLOBALS['CIRCLE_DETAIL'])+1]) @@ -1468,18 +1890,18 @@ def importMesh_Cylinder(geom): return bpymesh -def importMesh_Cone(geom): +def importMesh_Cone(geom, ancestry): # bpymesh = bpy.data.meshes.new() - diameter = geom.getFieldAsFloat('bottomRadius', 1.0) * 2 # * 2 for the diameter - height = geom.getFieldAsFloat('height', 2) + diameter = geom.getFieldAsFloat('bottomRadius', 1.0, ancestry) * 2 # * 2 for the diameter + height = geom.getFieldAsFloat('height', 2, ancestry) bpymesh = Mesh.Primitives.Cone(GLOBALS['CIRCLE_DETAIL'], diameter, height) bpymesh.transform(MATRIX_Z_TO_Y) # Warning - Rely in the order Blender adds verts # not nice design but wont change soon. - bottom = geom.getFieldAsBool('bottom', True) - side = geom.getFieldAsBool('side', True) + bottom = geom.getFieldAsBool('bottom', True, ancestry) + side = geom.getFieldAsBool('side', True, ancestry) if not bottom: # last vert is on the bottom bpymesh.verts.delete([GLOBALS['CIRCLE_DETAIL']+1]) @@ -1488,10 +1910,10 @@ def importMesh_Cone(geom): return bpymesh -def importMesh_Box(geom): +def importMesh_Box(geom, ancestry): # bpymesh = bpy.data.meshes.new() - size = geom.getFieldAsFloatTuple('size', (2.0, 2.0, 2.0)) + size = geom.getFieldAsFloatTuple('size', (2.0, 2.0, 2.0), ancestry) bpymesh = Mesh.Primitives.Cube(1.0) # Scale the box to the size set @@ -1517,6 +1939,9 @@ def importShape(node, ancestry): bpymat = None bpyima = None texmtx = None + + depth = 0 # so we can set alpha face flag later + if appr: #mat = appr.getChildByName('material') # 'Material' @@ -1532,7 +1957,7 @@ def importShape(node, ancestry): textx = appr.getChildBySpec('TextureTransform') if textx: - texmtx = translateTexTransform(textx) + texmtx = translateTexTransform(textx, ancestry) @@ -1544,29 +1969,34 @@ def importShape(node, ancestry): # all values between 0.0 and 1.0, defaults from VRML docs bpymat = bpy.data.materials.new() - bpymat.amb = mat.getFieldAsFloat('ambientIntensity', 0.2) - bpymat.rgbCol = mat.getFieldAsFloatTuple('diffuseColor', [0.8, 0.8, 0.8]) + bpymat.amb = mat.getFieldAsFloat('ambientIntensity', 0.2, ancestry) + bpymat.rgbCol = mat.getFieldAsFloatTuple('diffuseColor', [0.8, 0.8, 0.8], ancestry) # NOTE - blender dosnt support emmisive color # Store in mirror color and approximate with emit. - emit = mat.getFieldAsFloatTuple('emissiveColor', [0.0, 0.0, 0.0]) + emit = mat.getFieldAsFloatTuple('emissiveColor', [0.0, 0.0, 0.0], ancestry) bpymat.mirCol = emit bpymat.emit = (emit[0]+emit[1]+emit[2])/3.0 - bpymat.hard = int(1+(510*mat.getFieldAsFloat('shininess', 0.2))) # 0-1 -> 1-511 - bpymat.specCol = mat.getFieldAsFloatTuple('specularColor', [0.0, 0.0, 0.0]) - bpymat.alpha = 1.0 - mat.getFieldAsFloat('transparency', 0.0) + bpymat.hard = int(1+(510*mat.getFieldAsFloat('shininess', 0.2, ancestry))) # 0-1 -> 1-511 + bpymat.specCol = mat.getFieldAsFloatTuple('specularColor', [0.0, 0.0, 0.0], ancestry) + bpymat.alpha = 1.0 - mat.getFieldAsFloat('transparency', 0.0, ancestry) if bpymat.alpha < 0.999: bpymat.mode |= Material.Modes.ZTRANSP if ima: - # print ima - ima_url = ima.getFieldAsString('url') + + ima_url = ima.getFieldAsString('url', None, ancestry) + + if ima_url==None: + try: ima_url = ima.getFieldAsStringArray('url', ancestry)[0] # in some cases we get a list of images. + except: ima_url = None + if ima_url==None: print "\twarning, image with no URL, this is odd" else: - bpyima= BPyImage.comprehensiveImageLoad(ima_url, dirName(node.getFilename()), PLACE_HOLDER= False, RECURSIVE= False) + bpyima= BPyImage.comprehensiveImageLoad(ima_url, dirName(node.getFilename()), PLACE_HOLDER= False, RECURSIVE= False, CONVERT_CALLBACK= imageConvertCompat) if bpyima: texture= bpy.data.textures.new() texture.setType('Image') @@ -1585,10 +2015,11 @@ def importShape(node, ancestry): else: bpymat.setTexture(0, texture, Texture.TexCo.UV, Texture.MapTo.COL) - ima_repS = ima.getFieldAsBool('repeatS', True) - ima_repT = ima.getFieldAsBool('repeatT', True) + ima_repS = ima.getFieldAsBool('repeatS', True, ancestry) + ima_repT = ima.getFieldAsBool('repeatT', True, ancestry) - texture.repeat = max(1, ima_repS * 512), max(1, ima_repT * 512) + # To make this work properly we'd need to scale the UV's too, better to ignore th + # texture.repeat = max(1, ima_repS * 512), max(1, ima_repT * 512) if not ima_repS: bpyima.clampX = True if not ima_repT: bpyima.clampY = True @@ -1597,19 +2028,19 @@ def importShape(node, ancestry): geom_spec = geom.getSpec() ccw = True if geom_spec == 'IndexedFaceSet': - bpydata, ccw = importMesh_IndexedFaceSet(geom, bpyima) + bpydata, ccw = importMesh_IndexedFaceSet(geom, bpyima, ancestry) elif geom_spec == 'IndexedLineSet': - bpydata = importMesh_IndexedLineSet(geom) + bpydata = importMesh_IndexedLineSet(geom, ancestry) elif geom_spec == 'PointSet': - bpydata = importMesh_PointSet(geom) + bpydata = importMesh_PointSet(geom, ancestry) elif geom_spec == 'Sphere': - bpydata = importMesh_Sphere(geom) + bpydata = importMesh_Sphere(geom, ancestry) elif geom_spec == 'Box': - bpydata = importMesh_Box(geom) + bpydata = importMesh_Box(geom, ancestry) elif geom_spec == 'Cylinder': - bpydata = importMesh_Cylinder(geom) + bpydata = importMesh_Cylinder(geom, ancestry) elif geom_spec == 'Cone': - bpydata = importMesh_Cone(geom) + bpydata = importMesh_Cone(geom, ancestry) else: print '\tWarning: unsupported type "%s"' % geom_spec return @@ -1622,8 +2053,8 @@ def importShape(node, ancestry): bpyob = node.blendObject = bpy.data.scenes.active.objects.new(bpydata) if type(bpydata) == Types.MeshType: - is_solid = geom.getFieldAsBool('solid', True) - creaseAngle = geom.getFieldAsFloat('creaseAngle', None) + is_solid = geom.getFieldAsBool('solid', True, ancestry) + creaseAngle = geom.getFieldAsFloat('creaseAngle', None, ancestry) if creaseAngle != None: bpydata.maxSmoothAngle = 1+int(min(79, creaseAngle * RAD_TO_DEG)) @@ -1632,15 +2063,22 @@ def importShape(node, ancestry): # Only ever 1 material per shape if bpymat: bpydata.materials = [bpymat] - if bpydata.faceUV and texmtx: - # Apply texture transform? - uv_copy = Vector() - for f in bpydata.faces: - for uv in f.uv: - uv_copy.x = uv.x - uv_copy.y = uv.y - - uv.x, uv.y = (uv_copy * texmtx)[0:2] + if bpydata.faceUV: + + if depth==32: # set the faces alpha flag? + transp = Mesh.FaceTranspModes.ALPHA + for f in bpydata.faces: + f.transp = transp + + if texmtx: + # Apply texture transform? + uv_copy = Vector() + for f in bpydata.faces: + for uv in f.uv: + uv_copy.x = uv.x + uv_copy.y = uv.y + + uv.x, uv.y = (uv_copy * texmtx)[0:2] # Done transforming the texture @@ -1657,17 +2095,17 @@ def importShape(node, ancestry): bpyob.setMatrix( getFinalMatrix(node, None, ancestry) ) -def importLamp_PointLight(node): +def importLamp_PointLight(node, ancestry): vrmlname = node.getDefName() if not vrmlname: vrmlname = 'PointLight' - # ambientIntensity = node.getFieldAsFloat('ambientIntensity', 0.0) # TODO - # attenuation = node.getFieldAsFloatTuple('attenuation', (1.0, 0.0, 0.0)) # TODO - color = node.getFieldAsFloatTuple('color', (1.0, 1.0, 1.0)) - intensity = node.getFieldAsFloat('intensity', 1.0) # max is documented to be 1.0 but some files have higher. - location = node.getFieldAsFloatTuple('location', (0.0, 0.0, 0.0)) - # is_on = node.getFieldAsBool('on', True) # TODO - radius = node.getFieldAsFloat('radius', 100.0) + # ambientIntensity = node.getFieldAsFloat('ambientIntensity', 0.0, ancestry) # TODO + # attenuation = node.getFieldAsFloatTuple('attenuation', (1.0, 0.0, 0.0), ancestry) # TODO + color = node.getFieldAsFloatTuple('color', (1.0, 1.0, 1.0), ancestry) + intensity = node.getFieldAsFloat('intensity', 1.0, ancestry) # max is documented to be 1.0 but some files have higher. + location = node.getFieldAsFloatTuple('location', (0.0, 0.0, 0.0), ancestry) + # is_on = node.getFieldAsBool('on', True, ancestry) # TODO + radius = node.getFieldAsFloat('radius', 100.0, ancestry) bpylamp = bpy.data.lamps.new() bpylamp.setType('Lamp') @@ -1679,15 +2117,15 @@ def importLamp_PointLight(node): return bpylamp, mtx -def importLamp_DirectionalLight(node): +def importLamp_DirectionalLight(node, ancestry): vrmlname = node.getDefName() if not vrmlname: vrmlname = 'DirectLight' # ambientIntensity = node.getFieldAsFloat('ambientIntensity', 0.0) # TODO - color = node.getFieldAsFloatTuple('color', (1.0, 1.0, 1.0)) - direction = node.getFieldAsFloatTuple('direction', (0.0, 0.0, -1.0)) - intensity = node.getFieldAsFloat('intensity', 1.0) # max is documented to be 1.0 but some files have higher. - # is_on = node.getFieldAsBool('on', True) # TODO + color = node.getFieldAsFloatTuple('color', (1.0, 1.0, 1.0), ancestry) + direction = node.getFieldAsFloatTuple('direction', (0.0, 0.0, -1.0), ancestry) + intensity = node.getFieldAsFloat('intensity', 1.0, ancestry) # max is documented to be 1.0 but some files have higher. + # is_on = node.getFieldAsBool('on', True, ancestry) # TODO bpylamp = bpy.data.lamps.new(vrmlname) bpylamp.setType('Sun') @@ -1701,20 +2139,20 @@ def importLamp_DirectionalLight(node): # looks like default values for beamWidth and cutOffAngle were swapped in VRML docs. -def importLamp_SpotLight(node): +def importLamp_SpotLight(node, ancestry): vrmlname = node.getDefName() if not vrmlname: vrmlname = 'SpotLight' - # ambientIntensity = geom.getFieldAsFloat('ambientIntensity', 0.0) # TODO - # attenuation = geom.getFieldAsFloatTuple('attenuation', (1.0, 0.0, 0.0)) # TODO - beamWidth = node.getFieldAsFloat('beamWidth', 1.570796) * RAD_TO_DEG # max is documented to be 1.0 but some files have higher. - color = node.getFieldAsFloatTuple('color', (1.0, 1.0, 1.0)) - cutOffAngle = node.getFieldAsFloat('cutOffAngle', 0.785398) * RAD_TO_DEG # max is documented to be 1.0 but some files have higher. - direction = node.getFieldAsFloatTuple('direction', (0.0, 0.0, -1.0)) - intensity = node.getFieldAsFloat('intensity', 1.0) # max is documented to be 1.0 but some files have higher. - location = node.getFieldAsFloatTuple('location', (0.0, 0.0, 0.0)) - # is_on = node.getFieldAsBool('on', True) # TODO - radius = node.getFieldAsFloat('radius', 100.0) + # ambientIntensity = geom.getFieldAsFloat('ambientIntensity', 0.0, ancestry) # TODO + # attenuation = geom.getFieldAsFloatTuple('attenuation', (1.0, 0.0, 0.0), ancestry) # TODO + beamWidth = node.getFieldAsFloat('beamWidth', 1.570796, ancestry) * RAD_TO_DEG # max is documented to be 1.0 but some files have higher. + color = node.getFieldAsFloatTuple('color', (1.0, 1.0, 1.0), ancestry) + cutOffAngle = node.getFieldAsFloat('cutOffAngle', 0.785398, ancestry) * RAD_TO_DEG # max is documented to be 1.0 but some files have higher. + direction = node.getFieldAsFloatTuple('direction', (0.0, 0.0, -1.0), ancestry) + intensity = node.getFieldAsFloat('intensity', 1.0, ancestry) # max is documented to be 1.0 but some files have higher. + location = node.getFieldAsFloatTuple('location', (0.0, 0.0, 0.0), ancestry) + # is_on = node.getFieldAsBool('on', True, ancestry) # TODO + radius = node.getFieldAsFloat('radius', 100.0, ancestry) bpylamp = bpy.data.lamps.new(vrmlname) bpylamp.setType('Spot') @@ -1733,21 +2171,21 @@ def importLamp_SpotLight(node): # Convert # lamps have their direction as -z, y==up - mtx = TranslationMatrix(Vector(location)) * Vector(direction).toTrackQuat('-z', 'y').toMatrix().resize4x4() + mtx = Vector(direction).toTrackQuat('-z', 'y').toMatrix().resize4x4() * TranslationMatrix(Vector(location)) return bpylamp, mtx def importLamp(node, spec, ancestry): if spec=='PointLight': - bpylamp,mtx = importLamp_PointLight(node) + bpylamp,mtx = importLamp_PointLight(node, ancestry) elif spec=='DirectionalLight': - bpylamp,mtx = importLamp_DirectionalLight(node) + bpylamp,mtx = importLamp_DirectionalLight(node, ancestry) elif spec=='SpotLight': - bpylamp,mtx = importLamp_SpotLight(node) + bpylamp,mtx = importLamp_SpotLight(node, ancestry) else: print "Error, not a lamp" - raise "" + raise ValueError bpyob = node.blendObject = bpy.data.scenes.active.objects.new(bpylamp) bpyob.setMatrix( getFinalMatrix(node, mtx, ancestry) ) @@ -1757,17 +2195,17 @@ def importViewpoint(node, ancestry): name = node.getDefName() if not name: name = 'Viewpoint' - fieldOfView = node.getFieldAsFloat('fieldOfView', 0.785398) * RAD_TO_DEG # max is documented to be 1.0 but some files have higher. - # jump = node.getFieldAsBool('jump', True) - orientation = node.getFieldAsFloatTuple('orientation', (0.0, 0.0, 1.0, 0.0)) - position = node.getFieldAsFloatTuple('position', (0.0, 0.0, 10.0)) - description = node.getFieldAsString('description', '') + fieldOfView = node.getFieldAsFloat('fieldOfView', 0.785398, ancestry) * RAD_TO_DEG # max is documented to be 1.0 but some files have higher. + # jump = node.getFieldAsBool('jump', True, ancestry) + orientation = node.getFieldAsFloatTuple('orientation', (0.0, 0.0, 1.0, 0.0), ancestry) + position = node.getFieldAsFloatTuple('position', (0.0, 0.0, 0.0), ancestry) + description = node.getFieldAsString('description', '', ancestry) bpycam = bpy.data.cameras.new(name) bpycam.angle = fieldOfView - mtx = TranslationMatrix(Vector(position)) * translateRotation(orientation) * MATRIX_Z_TO_Y + mtx = translateRotation(orientation) * TranslationMatrix(Vector(position)) bpyob = node.blendObject = bpy.data.scenes.active.objects.new(bpycam) @@ -1781,6 +2219,173 @@ def importTransform(node, ancestry): bpyob = node.blendObject = bpy.data.scenes.active.objects.new('Empty', name) # , name) bpyob.setMatrix( getFinalMatrix(node, None, ancestry) ) + # so they are not too annoying + bpyob.emptyShape= Blender.Object.EmptyShapes.AXES + bpyob.drawSize= 0.2 + + +#def importTimeSensor(node): + + +def translatePositionInterpolator(node, ipo, ancestry): + key = node.getFieldAsArray('key', 0, ancestry) + keyValue = node.getFieldAsArray('keyValue', 3, ancestry) + + try: + loc_x = ipo.addCurve('LocX') + loc_y = ipo.addCurve('LocY') + loc_z = ipo.addCurve('LocZ') + except ValueError: + return + + loc_x.interpolation = loc_y.interpolation = loc_z.interpolation = Blender.IpoCurve.InterpTypes.LINEAR + + for i, time in enumerate(key): + try: x,y,z = keyValue[i] + except: continue + + loc_x.append((time,x)) + loc_y.append((time,y)) + loc_z.append((time,z)) + +def translateOrientationInterpolator(node, ipo, ancestry): + key = node.getFieldAsArray('key', 0, ancestry) + keyValue = node.getFieldAsArray('keyValue', 4, ancestry) + + try: + rot_x = ipo.addCurve('RotX') + rot_y = ipo.addCurve('RotY') + rot_z = ipo.addCurve('RotZ') + except ValueError: + return + + rot_x.interpolation = rot_y.interpolation = rot_z.interpolation = Blender.IpoCurve.InterpTypes.LINEAR + + for i, time in enumerate(key): + try: x,y,z,w = keyValue[i] + except: continue + + mtx = translateRotation((x,y,z,w)) + eul = mtx.toEuler() + rot_x.append((time,eul.x/10.0)) + rot_y.append((time,eul.y/10.0)) + rot_z.append((time,eul.z/10.0)) + +# Untested! +def translateScalarInterpolator(node, ipo, ancestry): + key = node.getFieldAsArray('key', 0, ancestry) + keyValue = node.getFieldAsArray('keyValue', 4, ancestry) + + try: + sca_x = ipo.addCurve('ScaleX') + sca_y = ipo.addCurve('ScaleY') + sca_z = ipo.addCurve('ScaleZ') + except ValueError: + return + + sca_x.interpolation = sca_y.interpolation = sca_z.interpolation = Blender.IpoCurve.InterpTypes.LINEAR + + for i, time in enumerate(key): + try: x,y,z = keyValue[i] + except: continue + sca_x.append((time,x/10.0)) + sca_y.append((time,y/10.0)) + sca_z.append((time,z/10.0)) + +def translateTimeSensor(node, ipo, ancestry): + ''' + Apply a time sensor to an IPO, VRML has many combinations of loop/start/stop/cycle times + to give different results, for now just do the basics + ''' + + time_cu = ipo.addCurve('Time') + time_cu.interpolation = Blender.IpoCurve.InterpTypes.LINEAR + + cycleInterval = node.getFieldAsFloat('cycleInterval', None, ancestry) + + startTime = node.getFieldAsFloat('startTime', 0.0, ancestry) + stopTime = node.getFieldAsFloat('stopTime', 250.0, ancestry) + + if cycleInterval != None: + stopTime = startTime+cycleInterval + + loop = node.getFieldAsBool('loop', False, ancestry) + + time_cu.append((1+startTime, 0.0)) + time_cu.append((1+stopTime, 1.0/10.0))# anoying, the UI uses /10 + + + if loop: + time_cu.extend = Blender.IpoCurve.ExtendTypes.CYCLIC # or - EXTRAP, CYCLIC_EXTRAP, CONST, + + +def importRoute(node, ancestry): + ''' + Animation route only at the moment + ''' + + if not hasattr(node, 'fields'): + return + + routeIpoDict = node.getRouteIpoDict() + + def getIpo(id): + try: ipo = routeIpoDict[id] + except: ipo = routeIpoDict[id] = bpy.data.ipos.new('web3d_ipo', 'Object') + return ipo + + # for getting definitions + defDict = node.getDefDict() + ''' + Handles routing nodes to eachother + +ROUTE vpPI.value_changed TO champFly001.set_position +ROUTE vpOI.value_changed TO champFly001.set_orientation +ROUTE vpTs.fraction_changed TO vpPI.set_fraction +ROUTE vpTs.fraction_changed TO vpOI.set_fraction +ROUTE champFly001.bindTime TO vpTs.set_startTime + ''' + + #from_id, from_type = node.id[1].split('.') + #to_id, to_type = node.id[3].split('.') + + #value_changed + set_position_node = None + set_orientation_node = None + time_node = None + + for field in node.fields: + if field and field[0]=='ROUTE': + try: + from_id, from_type = field[1].split('.') + to_id, to_type = field[3].split('.') + except: + print "Warning, invalid ROUTE", field + continue + + if from_type == 'value_changed': + if to_type == 'set_position': + ipo = getIpo(to_id) + set_data_from_node = defDict[from_id] + translatePositionInterpolator(set_data_from_node, ipo, ancestry) + + if to_type in ('set_orientation', 'rotation'): + ipo = getIpo(to_id) + set_data_from_node = defDict[from_id] + translateOrientationInterpolator(set_data_from_node, ipo, ancestry) + + if to_type == 'set_scale': + ipo = getIpo(to_id) + set_data_from_node = defDict[from_id] + translateScalarInterpolator(set_data_from_node, ipo, ancestry) + + elif from_type =='bindTime': + ipo = getIpo(from_id) + time_node = defDict[to_id] + translateTimeSensor(time_node, ipo, ancestry) + + + def load_web3d(path, PREF_FLAT=False, PREF_CIRCLE_DIV=16, HELPER_FUNC = None): @@ -1809,6 +2414,16 @@ def load_web3d(path, PREF_FLAT=False, PREF_CIRCLE_DIV=16, HELPER_FUNC = None): # continue spec = node.getSpec() + ''' + prefix = node.getPrefix() + if prefix=='PROTO': + pass + else + ''' + if HELPER_FUNC and HELPER_FUNC(node, ancestry): + # Note, include this function so the VRML/X3D importer can be extended + # by an external script. - gets first pick + pass if spec=='Shape': importShape(node, ancestry) elif spec in ('PointLight', 'DirectionalLight', 'SpotLight'): @@ -1818,14 +2433,38 @@ def load_web3d(path, PREF_FLAT=False, PREF_CIRCLE_DIV=16, HELPER_FUNC = None): elif spec=='Transform': # Only use transform nodes when we are not importing a flat object hierarchy if PREF_FLAT==False: - importTransform(node, ancestry) - else: - - # Note, include this function so the VRML/X3D importer can be extended - # by an external script. - if HELPER_FUNC: - HELPER_FUNC(node, ancestry) + importTransform(node, ancestry) + ''' + # These are delt with later within importRoute + elif spec=='PositionInterpolator': + ipo = bpy.data.ipos.new('web3d_ipo', 'Object') + translatePositionInterpolator(node, ipo) + ''' + + + + # After we import all nodes, route events - anim paths + for node, ancestry in all_nodes: + importRoute(node, ancestry) + + for node, ancestry in all_nodes: + if node.isRoot(): + # we know that all nodes referenced from will be in + # routeIpoDict so no need to run node.getDefDict() for every node. + routeIpoDict = node.getRouteIpoDict() + defDict = node.getDefDict() + for key, ipo in routeIpoDict.iteritems(): + + # Assign anim curves + node = defDict[key] + if node.blendObject==None: # Add an object if we need one for animation + node.blendObject = bpy.data.scenes.active.objects.new('Empty', 'AnimOb') # , name) + + node.blendObject.setIpo(ipo) + + + # Add in hierarchy if PREF_FLAT==False: child_dict = {} @@ -1886,7 +2525,7 @@ def load_ui(path): if __name__ == '__main__': Window.FileSelector(load_ui, 'Import X3D/VRML97') - + # Testing stuff # load_web3d('/test.x3d') @@ -1921,24 +2560,32 @@ if __name__ == '__main__': # load_web3d('/fe/x3d/www.web3d.org/x3d/content/examples/Basic/StudentProjects/PlayRoom.x3d') # invalid UVs -''' -import os -# files = os.popen('find /fe/wrl -iname "*.wrl"').readlines() -# files = os.popen('find /fe/x3d -iname "*.x3d"').readlines() -files = os.popen('find /fe/x3d/X3dExamplesSavage -iname "*.x3d"').readlines() -files.sort() -tot = len(files) -for i, f in enumerate(files): - if i < 12803 or i > 1000000: - continue - #if i != 12686: - # continue + +def test(): + import os - f = f.strip() - print f, i, tot - sce = bpy.data.scenes.new(f.split('/')[-1]) - bpy.data.scenes.active = sce - # Window. - load_web3d(f, PREF_FLAT=True) -'''
\ No newline at end of file + files = os.popen('find /fe/wrl -iname "*.wrl"').readlines() + # files = os.popen('find /fe/x3d -iname "*.x3d"').readlines() + # files = os.popen('find /fe/x3d/X3dExamplesSavage -iname "*.x3d"').readlines() + + files.sort() + tot = len(files) + for i, f in enumerate(files): + if i < 124 or i > 1000000: + continue + + #if i != 1068: + # continue + + #if i != 12686: + # continue + + f = f.strip() + print f, i, tot + sce = bpy.data.scenes.new(str(i) + '_' + f.split('/')[-1]) + bpy.data.scenes.active = sce + # Window. + load_web3d(f, PREF_FLAT=True) + +# test() diff --git a/release/scripts/mesh_edges2curves.py b/release/scripts/mesh_edges2curves.py index 006bdf10b49..670165dda51 100644 --- a/release/scripts/mesh_edges2curves.py +++ b/release/scripts/mesh_edges2curves.py @@ -112,7 +112,7 @@ def mesh2polys(): Window.EditMode(0) me = meshOb.getData(mesh=1) polygons= polysFromMesh(me) - w=t=1 + w = 1.0 cu= Curve.New() cu.name = me.name cu.setFlag(1) @@ -128,7 +128,7 @@ def mesh2polys(): vIdx= 0 v= poly[vIdx] - cu.appendNurb([v.co.x, v.co.y, v.co.z, w, t]) + cu.appendNurb((v.co.x, v.co.y, v.co.z, w)) vIdx += 1 cu[i].type= 0 # Poly Line @@ -139,7 +139,7 @@ def mesh2polys(): # Add all the points in the polyline. while vIdx<len(poly): v= poly[vIdx] - cu.appendPoint(i, [v.co.x, v.co.y, v.co.z, w]) + cu.appendPoint(i, (v.co.x, v.co.y, v.co.z, w)) vIdx+=1 i+=1 Window.WaitCursor(0) diff --git a/release/scripts/scripttemplate_gamelogic.py b/release/scripts/scripttemplate_gamelogic.py index 7184d7e424f..01348e86d0a 100644 --- a/release/scripts/scripttemplate_gamelogic.py +++ b/release/scripts/scripttemplate_gamelogic.py @@ -11,6 +11,9 @@ import bpy script_data = \ ''' +# This script must be assigned to a python controller +# where it can access the object that owns it and the sensors/actuators that it connects to. + # GameLogic has been added to the global namespace no need to import # for keyboard event comparison @@ -50,7 +53,7 @@ def main(): for actu in cont.getActuators(): # The actuator can be on another object, we may want to use it own_actu = actu.getOwner() - print ' actuator:', sens.getName() + print ' actuator:', actu.getName() # This runs the actuator or turns it off # note that actuators will continue to run unless explicitly turned off. diff --git a/release/scripts/uvcalc_follow_active_coords.py b/release/scripts/uvcalc_follow_active_coords.py index 79a445329cc..83df200991f 100644 --- a/release/scripts/uvcalc_follow_active_coords.py +++ b/release/scripts/uvcalc_follow_active_coords.py @@ -42,28 +42,15 @@ from Blender import * import bpy import BPyMesh -def extend(): - sce = bpy.data.scenes.active - ob = sce.objects.active - - # print ob, ob.type - if ob == None or ob.type != 'Mesh': - Draw.PupMenu('ERROR: No mesh object.') +def extend(EXTEND_MODE,ob): + if EXTEND_MODE == -1: return - - # Toggle Edit mode + me = ob.getData(mesh=1) + me_verts = me.verts + # Toggle Edit mode is_editmode = Window.EditMode() if is_editmode: Window.EditMode(0) - - me = ob.getData(mesh=1) - me_verts = me.verts - - # 0:normal extend, 1:edge length - EXTEND_MODE = Draw.PupMenu("Use Face Area%t|Loop Average%x2|None%x0") - if EXTEND_MODE == -1: - return - Window.WaitCursor(1) t = sys.time() edge_average_lengths = {} @@ -153,8 +140,7 @@ def extend(): 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 not me.faceUV: - Draw.PupMenu('ERROR: Mesh has no face UV coords.') - return + me.faceUV= True face_act = me.activeFace if face_act == -1: @@ -247,7 +233,22 @@ def extend(): Window.RedrawAll() Window.WaitCursor(0) -if __name__ == '__main__': - extend() + +def main(): + sce = bpy.data.scenes.active + ob = sce.objects.active + + # print ob, ob.type + if ob == None or ob.type != 'Mesh': + Draw.PupMenu('ERROR: No mesh object.') + return -
\ No newline at end of file + + + # 0:normal extend, 1:edge length + EXTEND_MODE = Draw.PupMenu("Use Face Area%t|Loop Average%x2|None%x0") + extend(EXTEND_MODE,ob) + +if __name__ == '__main__': + main() + diff --git a/release/scripts/uvcalc_quad_clickproj.py b/release/scripts/uvcalc_quad_clickproj.py index 0bba747e010..130a7e5af77 100644 --- a/release/scripts/uvcalc_quad_clickproj.py +++ b/release/scripts/uvcalc_quad_clickproj.py @@ -171,6 +171,9 @@ def main(): f_uv = f.uv return [(v.co-face_corner_main, f_uv[i]) for i,v in enumerate(f.v)] + if me.faceUV==False: + me.faceUV= True + coords = [ (co,uv) for f in me.faces if f.sel for co, uv in get_face_coords(f)] coords_orig = [uv.copy() for co, uv in coords] @@ -264,4 +267,5 @@ def main(): if __name__=='__main__': main() - Window.DrawProgressBar(1.0, '')
\ No newline at end of file + Window.DrawProgressBar(1.0, '') + diff --git a/release/scripts/vertexpaint_from_material.py b/release/scripts/vertexpaint_from_material.py index 2df5b7e721f..9668c521f3a 100644 --- a/release/scripts/vertexpaint_from_material.py +++ b/release/scripts/vertexpaint_from_material.py @@ -27,6 +27,7 @@ def matcol(mat): int(mat.R*255),\ int(mat.G*255),\ int(mat.B*255) + else: return None def mat2vcol(PREF_SEL_FACES_ONLY, PREF_ACTOB_ONLY, PREF_MULTIPLY_COLOR): @@ -47,7 +48,7 @@ def mat2vcol(PREF_SEL_FACES_ONLY, PREF_ACTOB_ONLY, PREF_MULTIPLY_COLOR): me= ob.getData(mesh=1) try: - me.faceUV=True + me.vertexColors=True except: # no faces continue diff --git a/source/Makefile b/source/Makefile index 662cb1df0a6..e9671cdae35 100644 --- a/source/Makefile +++ b/source/Makefile @@ -194,7 +194,7 @@ ifeq ($(WITH_FREETYPE2), true) else COMLIB += $(NAN_FTGL)/lib/libftgl.a ifeq ($(OS), irix) - COMLIB += $(NAN_FREETYPE)/lib32/libfreetype.a + COMLIB += $(NAN_FREETYPE)/lib/libfreetype.a else COMLIB += $(NAN_FREETYPE)/lib/libfreetype.a endif @@ -395,9 +395,16 @@ else NAN_SND_LIBS += $(ALUT) NAN_SND_LIBS += $(SOUNDSYSTEM) else - NAN_SND_LIBS = $(SOUNDSYSTEM) - NAN_SND_LIBS += $(DUMMYSOUND) - NAN_SND_LIBS += $(SOUNDSYSTEM) + ifeq ($(OS), irix) + NAN_SND_LIBS = $(SOUNDSYSTEM) + NAN_SND_LIBS += $(DUMMYSOUND) + NAN_SND_LIBS += $(SDLSOUND) + NAN_SND_LIBS += $(SOUNDSYSTEM) + else + NAN_SND_LIBS = $(SOUNDSYSTEM) + NAN_SND_LIBS += $(DUMMYSOUND) + NAN_SND_LIBS += $(SOUNDSYSTEM) + endif endif endif endif diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h index f1f4653f092..398d203709f 100644 --- a/source/blender/blenkernel/BKE_brush.h +++ b/source/blender/blenkernel/BKE_brush.h @@ -53,6 +53,7 @@ int brush_clone_image_delete(struct Brush *brush); /* sampling */ float brush_sample_falloff(struct Brush *brush, float dist); +float brush_sample_falloff_noalpha(struct Brush *brush, float dist); void brush_sample_tex(struct Brush *brush, float *xy, float *rgba); void brush_imbuf_new(struct Brush *brush, short flt, short texfalloff, int size, struct ImBuf **imbuf); diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h index c84b690bc49..10791968f79 100644 --- a/source/blender/blenkernel/BKE_customdata.h +++ b/source/blender/blenkernel/BKE_customdata.h @@ -198,8 +198,12 @@ int CustomData_get_layer_index(const struct CustomData *data, int type); int CustomData_get_named_layer_index(const struct CustomData *data, int type, char *name); int CustomData_get_active_layer_index(const struct CustomData *data, int type); int CustomData_get_render_layer_index(const struct CustomData *data, int type); +int CustomData_get_clone_layer_index(const struct CustomData *data, int type); +int CustomData_get_mask_layer_index(const struct CustomData *data, int type); int CustomData_get_active_layer(const struct CustomData *data, int type); int CustomData_get_render_layer(const struct CustomData *data, int type); +int CustomData_get_clone_layer(const struct CustomData *data, int type); +int CustomData_get_mask_layer(const struct CustomData *data, int type); /* copies the data from source to the data element at index in the first * layer of type @@ -227,10 +231,14 @@ void *CustomData_set_layer_n(const struct CustomData *data, int type, int n, voi /* sets the nth layer of type as active */ void CustomData_set_layer_active(struct CustomData *data, int type, int n); void CustomData_set_layer_render(struct CustomData *data, int type, int n); +void CustomData_set_layer_clone(struct CustomData *data, int type, int n); +void CustomData_set_layer_mask(struct CustomData *data, int type, int n); /* same as above but works with an index from CustomData_get_layer_index */ void CustomData_set_layer_active_index(struct CustomData *data, int type, int n); void CustomData_set_layer_render_index(struct CustomData *data, int type, int n); +void CustomData_set_layer_clone_index(struct CustomData *data, int type, int n); +void CustomData_set_layer_mask_index(struct CustomData *data, int type, int n); /* adds flag to the layer flags */ void CustomData_set_layer_flag(struct CustomData *data, int type, int flag); diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h index bb474d3f8c8..eb89e1699ea 100644 --- a/source/blender/blenkernel/BKE_global.h +++ b/source/blender/blenkernel/BKE_global.h @@ -226,6 +226,7 @@ typedef struct Global { #define G_FILE_GLSL_NO_RAMPS (1 << 19) #define G_FILE_GLSL_NO_NODES (1 << 20) #define G_FILE_GLSL_NO_EXTRA_TEX (1 << 21) +#define G_FILE_IGNORE_DEPRECATION_WARNINGS (1 << 22) /* G.windowstate */ #define G_WINDOWSTATE_USERDEF 0 diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index fa3a654c1c2..3f04330f2a3 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -401,6 +401,12 @@ struct TexResult; #define TEX_NODE_ROTATE 114 #define TEX_NODE_VIEWER 115 #define TEX_NODE_TRANSLATE 116 +#define TEX_NODE_COORD 117 +#define TEX_NODE_DISTANCE 118 +#define TEX_NODE_COMPOSE 119 +#define TEX_NODE_DECOMPOSE 120 +#define TEX_NODE_VALTONOR 121 +#define TEX_NODE_SCALE 122 /* 201-299 reserved. Use like this: TEX_NODE_PROC + TEX_CLOUDS, etc */ #define TEX_NODE_PROC 200 diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 0ed4f38e457..04ca5c79a11 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -65,8 +65,6 @@ IF(WITH_PLAYER) SUBDIRS(bad_level_call_stubs) ENDIF(WITH_PLAYER) -ADD_DEFINITIONS(-DWITH_CCGSUBSURF) - BLENDERLIB(bf_blenkernel "${SRC}" "${INC}") IF(WITH_VERSE) diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript index ab122e40bfc..fb67c855b81 100644 --- a/source/blender/blenkernel/SConscript +++ b/source/blender/blenkernel/SConscript @@ -42,6 +42,9 @@ if env['WITH_BF_VERSE']: if env['WITH_BF_OPENEXR']: defs += ' WITH_OPENEXR' +if env['WITH_BF_OPENJPEG']: + defs += ' WITH_OPENJPEG' + if env['WITH_BF_DDS']: defs += ' WITH_DDS' @@ -53,6 +56,9 @@ if env['WITH_BF_QUICKTIME']: defs += ' WITH_QUICKTIME' incs += ' ' + env['BF_QUICKTIME_INC'] +if env['WITH_BF_BULLET']: + defs += ' WITH_BULLET' + if env['BF_NO_ELBEEM']: defs += ' DISABLE_ELBEEM' diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index 1c53af97dbb..021f76fd2f1 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -328,6 +328,23 @@ float brush_sample_falloff(Brush *brush, float dist) return 0.0f; } +float brush_sample_falloff_noalpha(Brush *brush, float dist) +{ + float outer, inner; + + outer = brush->size >> 1; + inner = outer*brush->innerradius; + + if (dist <= inner) { + return 1.0f; + } + else if ((dist < outer) && (inner < outer)) { + return 1.0f - sqrt((dist - inner)/(outer - inner)); + } + else + return 0.0f; +} + void brush_sample_tex(Brush *brush, float *xy, float *rgba) { MTex *mtex= brush->mtex[brush->texact]; diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 775f1dee241..0b5465ea25d 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -1236,7 +1236,7 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat if(out_normalVelocity < 0.0) { out_normalVelocity*= -1.0; - VecMulf(out_normal, -1.0); + VecNegf(out_normal); } */ /* Inelastic repulsion impulse. */ diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 5639f00ee39..b668a1f214d 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -1044,7 +1044,7 @@ static void vectomat (float *vec, float *target_up, short axis, short upflag, sh n[2] = 1.0; } if (axis > 2) axis -= 3; - else VecMulf(n,-1); + else VecNegf(n); /* n specifies the transformation of the track axis */ if (flags & TARGET_Z_UP) { @@ -2182,7 +2182,7 @@ static void locktrack_evaluate (bConstraint *con, bConstraintOb *cob, ListBase * Projf(vec2, vec, cob->matrix[0]); VecSubf(totmat[1], vec, vec2); Normalize(totmat[1]); - VecMulf(totmat[1],-1); + VecNegf(totmat[1]); /* the x axis is fixed */ totmat[0][0] = cob->matrix[0][0]; @@ -2200,7 +2200,7 @@ static void locktrack_evaluate (bConstraint *con, bConstraintOb *cob, ListBase * Projf(vec2, vec, cob->matrix[0]); VecSubf(totmat[2], vec, vec2); Normalize(totmat[2]); - VecMulf(totmat[2],-1); + VecNegf(totmat[2]); /* the x axis is fixed */ totmat[0][0] = cob->matrix[0][0]; @@ -2265,7 +2265,7 @@ static void locktrack_evaluate (bConstraint *con, bConstraintOb *cob, ListBase * Projf(vec2, vec, cob->matrix[1]); VecSubf(totmat[0], vec, vec2); Normalize(totmat[0]); - VecMulf(totmat[0],-1); + VecNegf(totmat[0]); /* the y axis is fixed */ totmat[1][0] = cob->matrix[1][0]; @@ -2283,7 +2283,7 @@ static void locktrack_evaluate (bConstraint *con, bConstraintOb *cob, ListBase * Projf(vec2, vec, cob->matrix[1]); VecSubf(totmat[2], vec, vec2); Normalize(totmat[2]); - VecMulf(totmat[2],-1); + VecNegf(totmat[2]); /* the y axis is fixed */ totmat[1][0] = cob->matrix[1][0]; @@ -2348,7 +2348,7 @@ static void locktrack_evaluate (bConstraint *con, bConstraintOb *cob, ListBase * Projf(vec2, vec, cob->matrix[2]); VecSubf(totmat[0], vec, vec2); Normalize(totmat[0]); - VecMulf(totmat[0],-1); + VecNegf(totmat[0]); /* the z axis is fixed */ totmat[2][0] = cob->matrix[2][0]; @@ -2366,7 +2366,7 @@ static void locktrack_evaluate (bConstraint *con, bConstraintOb *cob, ListBase * Projf(vec2, vec, cob->matrix[2]); VecSubf(totmat[1], vec, vec2); Normalize(totmat[1]); - VecMulf(totmat[1],-1); + VecNegf(totmat[1]); /* the z axis is fixed */ totmat[2][0] = cob->matrix[2][0]; diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 1a671dfe771..7fa4f406c7b 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -833,7 +833,6 @@ void makeNurbcurve(Nurb *nu, float *coord_array, float *tilt_array, float *radiu sum= (float *)MEM_callocN(sizeof(float)*len, "makeNurbcurve1"); resolu= (resolu*SEGMENTSU(nu)); - if((nu->flagu & CU_CYCLIC)==0) resolu++; if(resolu==0) { MEM_freeN(sum); @@ -1685,7 +1684,6 @@ void makeBevelList(Object *ob) else if((nu->type & 7)==CU_NURBS) { if(nu->pntsv==1) { len= (resolu*SEGMENTSU(nu)); - if((nu->flagu & CU_CYCLIC)==0) len++; bl= MEM_callocN(sizeof(BevList)+len*sizeof(BevPoint), "makeBevelList3"); BLI_addtail(&(cu->bev), bl); diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index e93266c85f3..05271aa59a7 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -606,7 +606,7 @@ void CustomData_merge(const struct CustomData *source, struct CustomData *dest, { const LayerTypeInfo *typeInfo; CustomDataLayer *layer, *newlayer; - int i, type, number = 0, lasttype = -1, lastactive = 0, lastrender = 0; + int i, type, number = 0, lasttype = -1, lastactive = 0, lastrender = 0, lastclone = 0, lastmask = 0; for(i = 0; i < source->totlayer; ++i) { layer = &source->layers[i]; @@ -618,6 +618,8 @@ void CustomData_merge(const struct CustomData *source, struct CustomData *dest, number = 0; lastactive = layer->active; lastrender = layer->active_rnd; + lastclone = layer->active_clone; + lastmask = layer->active_mask; lasttype = type; } else @@ -637,6 +639,8 @@ void CustomData_merge(const struct CustomData *source, struct CustomData *dest, if(newlayer) { newlayer->active = lastactive; newlayer->active_rnd = lastrender; + newlayer->active_clone = lastclone; + newlayer->active_mask = lastmask; } } } @@ -736,6 +740,28 @@ int CustomData_get_render_layer_index(const CustomData *data, int type) return -1; } +int CustomData_get_clone_layer_index(const CustomData *data, int type) +{ + int i; + + for(i=0; i < data->totlayer; ++i) + if(data->layers[i].type == type) + return i + data->layers[i].active_clone; + + return -1; +} + +int CustomData_get_mask_layer_index(const CustomData *data, int type) +{ + int i; + + for(i=0; i < data->totlayer; ++i) + if(data->layers[i].type == type) + return i + data->layers[i].active_mask; + + return -1; +} + int CustomData_get_active_layer(const CustomData *data, int type) { int i; @@ -758,6 +784,27 @@ int CustomData_get_render_layer(const CustomData *data, int type) return -1; } +int CustomData_get_clone_layer(const CustomData *data, int type) +{ + int i; + + for(i=0; i < data->totlayer; ++i) + if(data->layers[i].type == type) + return data->layers[i].active_clone; + + return -1; +} + +int CustomData_get_mask_layer(const CustomData *data, int type) +{ + int i; + + for(i=0; i < data->totlayer; ++i) + if(data->layers[i].type == type) + return data->layers[i].active_mask; + + return -1; +} void CustomData_set_layer_active(CustomData *data, int type, int n) { @@ -777,6 +824,24 @@ void CustomData_set_layer_render(CustomData *data, int type, int n) data->layers[i].active_rnd = n; } +void CustomData_set_layer_clone(CustomData *data, int type, int n) +{ + int i; + + for(i=0; i < data->totlayer; ++i) + if(data->layers[i].type == type) + data->layers[i].active_clone = n; +} + +void CustomData_set_layer_mask(CustomData *data, int type, int n) +{ + int i; + + for(i=0; i < data->totlayer; ++i) + if(data->layers[i].type == type) + data->layers[i].active_mask = n; +} + /* for using with an index from CustomData_get_active_layer_index and CustomData_get_render_layer_index */ void CustomData_set_layer_active_index(CustomData *data, int type, int n) { @@ -796,6 +861,23 @@ void CustomData_set_layer_render_index(CustomData *data, int type, int n) data->layers[i].active_rnd = n-i; } +void CustomData_set_layer_clone_index(CustomData *data, int type, int n) +{ + int i; + + for(i=0; i < data->totlayer; ++i) + if(data->layers[i].type == type) + data->layers[i].active_clone = n-i; +} + +void CustomData_set_layer_mask_index(CustomData *data, int type, int n) +{ + int i; + + for(i=0; i < data->totlayer; ++i) + if(data->layers[i].type == type) + data->layers[i].active_mask = n-i; +} void CustomData_set_layer_flag(struct CustomData *data, int type, int flag) { @@ -882,9 +964,13 @@ static CustomDataLayer *customData_add_layer__internal(CustomData *data, if(index > 0 && data->layers[index-1].type == type) { data->layers[index].active = data->layers[index-1].active; data->layers[index].active_rnd = data->layers[index-1].active_rnd; + data->layers[index].active_clone = data->layers[index-1].active_clone; + data->layers[index].active_mask = data->layers[index-1].active_mask; } else { data->layers[index].active = 0; data->layers[index].active_rnd = 0; + data->layers[index].active_clone = 0; + data->layers[index].active_mask = 0; } customData_update_offsets(data); @@ -944,6 +1030,8 @@ int CustomData_free_layer(CustomData *data, int type, int totelem, int index) for (; i < data->totlayer && data->layers[i].type == type; i++) { data->layers[i].active--; data->layers[i].active_rnd--; + data->layers[i].active_clone--; + data->layers[i].active_mask--; } } diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index 35097c05358..7716d71225e 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -887,7 +887,6 @@ static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase) } else if((nu->type & 7)==CU_NURBS) { len= (resolu*SEGMENTSU(nu)); - if((nu->flagu & CU_CYCLIC)==0) len++; dl= MEM_callocN(sizeof(DispList), "makeDispListsurf"); dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts"); @@ -1381,7 +1380,7 @@ void makeDispListSurf(Object *ob, ListBase *dispbase, int forRender) for (nu=nubase->first; nu; nu=nu->next) { if(forRender || nu->hide==0) { if(nu->pntsv==1) { - len= nu->pntsu*nu->resolu; + len= SEGMENTSU(nu)*nu->resolu; dl= MEM_callocN(sizeof(DispList), "makeDispListsurf"); dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts"); diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index 122c6c71a6c..0338ec92414 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -251,7 +251,7 @@ static float eff_calc_visibility(Object *ob, float *co, float *dir) return 0; VECCOPY(norm, dir); - VecMulf(norm, -1.0); + VecNegf(norm); len = Normalize(norm); // check all collision objects diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index d5166fc7a83..e817c38618f 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -767,6 +767,10 @@ int BKE_imtype_to_ftype(int imtype) return RAWTGA; else if(imtype==R_HAMX) return AN_hamx; +#ifdef WITH_OPENJPEG + else if(imtype==R_JP2) + return JP2; +#endif else return JPG|90; } @@ -801,6 +805,10 @@ int BKE_ftype_to_imtype(int ftype) return R_RAWTGA; else if(ftype == AN_hamx) return R_HAMX; +#ifdef WITH_OPENJPEG + else if(ftype & JP2) + return R_JP2; +#endif else return R_JPEG90; } @@ -877,6 +885,12 @@ void BKE_add_image_extension(char *string, int imtype) if(!BLI_testextensie(string, ".tga")) extension= ".tga"; } +#ifdef WITH_OPENJPEG + else if(imtype==R_JP2) { + if(!BLI_testextensie(string, ".jp2")) + extension= ".jp2"; + } +#endif else { // R_MOVIE, R_AVICODEC, R_AVIRAW, R_AVIJPEG, R_JPEG90, R_QUICKTIME etc if(!( BLI_testextensie(string, ".jpg") || BLI_testextensie(string, ".jpeg"))) extension= ".jpg"; @@ -1220,6 +1234,28 @@ int BKE_write_ibuf(ImBuf *ibuf, char *name, int imtype, int subimtype, int quali else if(imtype==R_HAMX) { ibuf->ftype= AN_hamx; } +#ifdef WITH_OPENJPEG + else if(imtype==R_JP2) { + if(quality < 10) quality= 90; + ibuf->ftype= JP2|quality; + + if (subimtype & R_JPEG2K_16BIT) { + ibuf->ftype |= JP2_16BIT; + } else if (subimtype & R_JPEG2K_12BIT) { + ibuf->ftype |= JP2_12BIT; + } + + if (subimtype & R_JPEG2K_YCC) { + ibuf->ftype |= JP2_YCC; + } + + if (subimtype & R_JPEG2K_CINE_PRESET) { + ibuf->ftype |= JP2_CINE; + if (subimtype & R_JPEG2K_CINE_48FPS) + ibuf->ftype |= JP2_CINE_48FPS; + } + } +#endif else { /* R_JPEG90, R_MOVIE, etc. default we save jpegs */ if(quality < 10) quality= 90; diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 6bdd395a2ac..566a139f72c 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -6380,20 +6380,11 @@ static DerivedMesh * particleInstanceModifier_applyModifier( psys->lattice=psys_get_lattice(ob, psys); if(psys->flag & (PSYS_HAIR_DONE|PSYS_KEYED)){ - float co[3]; - for(i=0; i< totvert; i++){ - dm->getVertCo(dm,i,co); - if(i==0){ - min_co=max_co=co[track]; - } - else{ - if(co[track]<min_co) - min_co=co[track]; - if(co[track]>max_co) - max_co=co[track]; - } - } + float min_r[3], max_r[3]; + dm->getMinMax(dm, min_r, max_r); + min_co=min_r[track]; + max_co=max_r[track]; } result = CDDM_from_template(dm, maxvert,dm->getNumEdges(dm)*totpart,maxface); diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index ae81a31c373..9a78f8ea02a 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -1999,19 +1999,23 @@ static bNodeThreadStack *ntreeGetThreadStack(bNodeTree *ntree, int thread) { ListBase *lb= &ntree->threadstack[thread]; bNodeThreadStack *nts; - + + /* for material shading this is called quite a lot (perhaps too much locking unlocking) + * however without locking we get bug #18058 - Campbell */ + BLI_lock_thread(LOCK_CUSTOM1); + for(nts=lb->first; nts; nts=nts->next) { if(!nts->used) { nts->used= 1; + BLI_unlock_thread(LOCK_CUSTOM1); return nts; } } - nts= MEM_callocN(sizeof(bNodeThreadStack), "bNodeThreadStack"); nts->stack= MEM_dupallocN(ntree->stack); nts->used= 1; BLI_addtail(lb, nts); - + BLI_unlock_thread(LOCK_CUSTOM1); return nts; } @@ -2882,10 +2886,15 @@ static void registerTextureNodes(ListBase *ntypelist) nodeRegisterType(ntypelist, &tex_node_mix_rgb); nodeRegisterType(ntypelist, &tex_node_valtorgb); nodeRegisterType(ntypelist, &tex_node_rgbtobw); + nodeRegisterType(ntypelist, &tex_node_valtonor); nodeRegisterType(ntypelist, &tex_node_curve_rgb); nodeRegisterType(ntypelist, &tex_node_curve_time); nodeRegisterType(ntypelist, &tex_node_invert); nodeRegisterType(ntypelist, &tex_node_hue_sat); + nodeRegisterType(ntypelist, &tex_node_coord); + nodeRegisterType(ntypelist, &tex_node_distance); + nodeRegisterType(ntypelist, &tex_node_compose); + nodeRegisterType(ntypelist, &tex_node_decompose); nodeRegisterType(ntypelist, &tex_node_output); nodeRegisterType(ntypelist, &tex_node_viewer); @@ -2897,6 +2906,7 @@ static void registerTextureNodes(ListBase *ntypelist) nodeRegisterType(ntypelist, &tex_node_rotate); nodeRegisterType(ntypelist, &tex_node_translate); + nodeRegisterType(ntypelist, &tex_node_scale); nodeRegisterType(ntypelist, &tex_node_proc_voronoi); nodeRegisterType(ntypelist, &tex_node_proc_blend); diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 39226faff1e..8a964c5b32e 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -831,7 +831,7 @@ void psys_thread_distribute_particle(ParticleThread *thread, ParticleData *pa, C VecCopyf(tan,seam->tan); VecSubf(temp2,co1,temp); if(Inpf(tan,temp2)<0.0f) - VecMulf(tan,-1.0f); + VecNegf(tan); } for(w=0; w<maxw; w++){ VecSubf(temp2,ptn[w].co,temp); @@ -1877,7 +1877,7 @@ void reset_particle(ParticleData *pa, ParticleSystem *psys, ParticleSystemModifi } /* create rotation quat */ - VecMulf(rot_vec,-1.0); + VecNegf(rot_vec); vectoquat(rot_vec, OB_POSX, OB_POSZ, q2); /* randomize rotation quat */ @@ -3022,7 +3022,7 @@ static void particle_intersect_face(void *userdata, int index, const BVHTreeRay CalcNormFloat(t0, t1, t2, col->nor); VECSUB(temp, co2, co1); if(Inpf(col->nor, temp) > 0.0f) - VecMulf(col->nor, -1.0f); + VecNegf(col->nor); VECCOPY(col->vel,vel); @@ -3802,7 +3802,7 @@ static void boid_body(BoidVecFunc *bvf, ParticleData *pa, ParticleSystem *psys, VecRotToQuat(pa->state.vel,bank,q); VECCOPY(dvec,pa->state.vel); - VecMulf(dvec,-1.0f); + VecNegf(dvec); vectoquat(dvec, OB_POSX, OB_POSZ, q2); QuatMul(pa->state.rot,q,q2); diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index 5d93f10526a..f63f6edf4b3 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -1562,7 +1562,7 @@ static void _scan_for_ext_spring_forces(Object *ob,float timenow,int ifirst,int /* note we don't use sb->mediafrict but use sb->aeroedge for magnitude of effect*/ if(sb->aeroedge){ float vel[3],sp[3],pr[3],force[3]; - float f,windfactor = 250.0f; + float f,windfactor = 0.25f; /*see if we have wind*/ if(do_effector) { float speed[3]={0.0f,0.0f,0.0f}; @@ -2392,7 +2392,7 @@ static void softbody_calc_forcesEx(Object *ob, float forcetime, float timenow, i BodyPoint *bproot; ListBase *do_effector; float iks, gravity; - float fieldfactor = 1000.0f, windfactor = 250.0f; + float fieldfactor = -1.0f, windfactor = 0.25; int do_deflector,do_selfcollision,do_springcollision,do_aero; gravity = sb->grav * sb_grav_force_scale(ob); @@ -2454,7 +2454,7 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow, int BodySpring *bs; ListBase *do_effector; float iks, ks, kd, gravity; - float fieldfactor = 1000.0f, windfactor = 250.0f; + float fieldfactor = -1.0f, windfactor = 0.25f; float tune = sb->ballstiff; int a, b, do_deflector,do_selfcollision,do_springcollision,do_aero; diff --git a/source/blender/blenlib/BLI_arithb.h b/source/blender/blenlib/BLI_arithb.h index 1d4b5cf16b2..6a2db92d25f 100644 --- a/source/blender/blenlib/BLI_arithb.h +++ b/source/blender/blenlib/BLI_arithb.h @@ -241,6 +241,7 @@ int VecLen(int *v1, int *v2); float VecLenf(float *v1, float *v2); float VecLength(float *v); void VecMulf(float *v1, float f); +void VecNegf(float *v1); int VecLenCompare(float *v1, float *v2, float limit); int VecCompare(float *v1, float *v2, float limit); diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c index 783acb9cc97..5f94df6f5eb 100644 --- a/source/blender/blenlib/intern/arithb.c +++ b/source/blender/blenlib/intern/arithb.c @@ -2183,6 +2183,13 @@ void VecMulf(float *v1, float f) v1[2]*= f; } +void VecNegf(float *v1) +{ + v1[0] = -v1[0]; + v1[1] = -v1[1]; + v1[2] = -v1[2]; +} + void VecOrthoBasisf(float *v, float *v1, float *v2) { float f = sqrt(v[0]*v[0] + v[1]*v[1]); @@ -3945,7 +3952,7 @@ int SweepingSphereIntersectsTriangleUV(float p1[3], float p2[3], float radius, f Normalize(nor); /* flip normal */ - if(Inpf(nor,vel)>0.0f) VecMulf(nor,-1.0f); + if(Inpf(nor,vel)>0.0f) VecNegf(nor); a=Inpf(p1,nor)-Inpf(v0,nor); nordotv=Inpf(nor,vel); @@ -4677,7 +4684,7 @@ void tangent_from_uv(float *uv1, float *uv2, float *uv3, float *co1, float *co2, /* check flip */ if ((ct[0]*n[0] + ct[1]*n[1] + ct[2]*n[2]) < 0.0f) - VecMulf(tang, -1.0f); + VecNegf(tang); } /* used for zoom values*/ diff --git a/source/blender/blenlib/intern/bpath.c b/source/blender/blenlib/intern/bpath.c index e23c2658399..ac0c4bf4efd 100644 --- a/source/blender/blenlib/intern/bpath.c +++ b/source/blender/blenlib/intern/bpath.c @@ -339,9 +339,9 @@ void BLI_bpathIterator_step( struct BPathIterator *bpi) { bSound *snd = (bSound *)bpi->data; bpi->lib = snd->id.lib ? snd->id.lib->filename : NULL; - bpi->path = snd->sample->name; + bpi->path = snd->name; bpi->name = snd->id.name+2; - bpi->len = sizeof(snd->sample->name); + bpi->len = sizeof(snd->name); /* we are done, advancing to the next item, this type worked fine */ break; diff --git a/source/blender/blenlib/intern/graph.c b/source/blender/blenlib/intern/graph.c index ca82fcac844..52277063a8f 100644 --- a/source/blender/blenlib/intern/graph.c +++ b/source/blender/blenlib/intern/graph.c @@ -807,15 +807,15 @@ static void testAxialSymmetry(BGraph *graph, BNode* root_node, BNode* node1, BNo if (abs(nor[0]) > abs(nor[1]) && abs(nor[0]) > abs(nor[2]) && nor[0] < 0) { - VecMulf(nor, -1); + VecNegf(nor); } else if (abs(nor[1]) > abs(nor[0]) && abs(nor[1]) > abs(nor[2]) && nor[1] < 0) { - VecMulf(nor, -1); + VecNegf(nor); } else if (abs(nor[2]) > abs(nor[1]) && abs(nor[2]) > abs(nor[0]) && nor[2] < 0) { - VecMulf(nor, -1); + VecNegf(nor); } /* mirror node2 along axis */ diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c index ca7a376d3a2..8ba03ad1343 100644 --- a/source/blender/blenlib/intern/storage.c +++ b/source/blender/blenlib/intern/storage.c @@ -47,9 +47,9 @@ #include <time.h> #include <sys/stat.h> -#if defined (__sun__) || defined (__sun) +#if defined (__sun__) || defined (__sun) || defined (__sgi) #include <sys/statvfs.h> /* Other modern unix os's should probably use this also */ -#elif !defined(__FreeBSD__) && !defined(linux) && (defined(__sgi) || defined(__sparc) || defined(__sparc__)) +#elif !defined(__FreeBSD__) && !defined(linux) && (defined(__sparc) || defined(__sparc__)) #include <sys/statfs.h> #endif @@ -179,7 +179,7 @@ double BLI_diskfree(char *dir) return (double) (freec*bytesps*sectorspc); #else -#if defined (__sun__) || defined (__sun) +#if defined (__sun__) || defined (__sun) || defined (__sgi) struct statvfs disk; #else struct statfs disk; @@ -204,9 +204,9 @@ double BLI_diskfree(char *dir) return -1; #endif -#if defined (__sun__) || defined (__sun) +#if defined (__sun__) || defined (__sun) || defined (__sgi) if (statvfs(name, &disk)) return(-1); -#elif !defined(__FreeBSD__) && !defined(linux) && (defined (__sgi) || defined(__sparc) || defined(__sparc__)) +#elif !defined(__FreeBSD__) && !defined(linux) && (defined(__sparc) || defined(__sparc__)) /* WARNING - This may not be supported by geeneric unix os's - Campbell */ if (statfs(name, &disk, sizeof(struct statfs), 0)) return(-1); #endif diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 18dff78c050..7fc2a995a2f 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -3179,6 +3179,7 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb) FluidsimModifierData *fluidmd = (FluidsimModifierData*) md; fluidmd->fss= newdataadr(fd, fluidmd->fss); + fluidmd->fss->meshSurfNormals = 0; } else if (md->type==eModifierType_Collision) { @@ -7819,6 +7820,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) fluidmd->fss->lastgoodframe = INT_MAX; fluidmd->fss->flag = 0; + fluidmd->fss->meshSurfNormals = 0; } } } @@ -7974,9 +7976,13 @@ static void do_versions(FileData *fd, Library *lib, Main *main) { Scene *sce; - /* initialize skeleton generation toolsettings */ for(sce=main->scene.first; sce; sce = sce->id.next) { + /* Note, these will need to be added for painting */ + sce->toolsettings->imapaint.seam_bleed = 2; + sce->toolsettings->imapaint.normal_angle = 80; + + /* initialize skeleton generation toolsettings */ sce->toolsettings->skgen_resolution = 250; sce->toolsettings->skgen_threshold_internal = 0.1f; sce->toolsettings->skgen_threshold_external = 0.1f; @@ -8003,7 +8009,6 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } - /* WATCH IT!!!: pointers from libdata have not been converted yet here! */ /* WATCH IT 2!: Userdef struct init has to be in src/usiblender.c! */ @@ -8800,6 +8805,9 @@ static void expand_scene(FileData *fd, Main *mainvar, Scene *sce) expand_doit(fd, mainvar, sce->camera); expand_doit(fd, mainvar, sce->world); + if(sce->set) + expand_doit(fd, mainvar, sce->set); + if(sce->nodetree) expand_nodetree(fd, mainvar, sce->nodetree); diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index e06e7eb2d85..92d847d4782 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -2032,7 +2032,7 @@ static void write_global(WriteData *wd) fg.subversion= BLENDER_SUBVERSION; fg.minversion= BLENDER_MINVERSION; fg.minsubversion= BLENDER_MINSUBVERSION; - + fg.pads= 0; /* prevent mem checkers from complaining */ writestruct(wd, GLOB, "FileGlobal", 1, &fg); } diff --git a/source/blender/blenpluginapi/iff.h b/source/blender/blenpluginapi/iff.h index 92cbd7dd093..e7f328d870f 100644 --- a/source/blender/blenpluginapi/iff.h +++ b/source/blender/blenpluginapi/iff.h @@ -56,6 +56,10 @@ #endif #define RADHDR (1<<24) +#ifdef WITH_OPENJPEG +#define JP2 (1 << 18) +#endif + #define RAWTGA (TGA | 1) #define JPG_STD (JPG | (0 << 8)) @@ -113,6 +117,7 @@ #define IS_tim(x) (x->ftype & TIM) #define IS_tiff(x) (x->ftype & TIFF) #define IS_openexr(x) (x->ftype & OPENEXR) +#define IS_jp2(x) (x->ftype & JP2) #define IMAGIC 0732 diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h index 2399e7b6a8c..a5a2e2dd13e 100644 --- a/source/blender/gpu/GPU_draw.h +++ b/source/blender/gpu/GPU_draw.h @@ -82,7 +82,7 @@ int GPU_set_tpage(struct MTFace *tface); int GPU_default_lights(void); int GPU_scene_object_lights(struct Scene *scene, struct Object *ob, - int lay, float viewmat[][4]); + int lay, float viewmat[][4], int ortho); /* Text render * - based on moving uv coordinates */ diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index 4025a12a867..3c1c280a727 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -167,6 +167,8 @@ static int smaller_pow2(int num) static int is_pow2_limit(int num) { /* take texture clamping into account */ + if (G.f & G_TEXTUREPAINT) + return 1; if (U.glreslimit != 0 && num > U.glreslimit) return 0; @@ -175,6 +177,9 @@ static int is_pow2_limit(int num) static int smaller_pow2_limit(int num) { + if (G.f & G_TEXTUREPAINT) + return 1; + /* take texture clamping into account */ if (U.glreslimit != 0 && num > U.glreslimit) return U.glreslimit; @@ -993,6 +998,8 @@ int GPU_default_lights(void) U.light[2].spec[3]= 1.0; } + glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_FALSE); + glLightfv(GL_LIGHT0, GL_POSITION, U.light[0].vec); glLightfv(GL_LIGHT0, GL_DIFFUSE, U.light[0].col); glLightfv(GL_LIGHT0, GL_SPECULAR, U.light[0].spec); @@ -1030,7 +1037,7 @@ int GPU_default_lights(void) return count; } -int GPU_scene_object_lights(Scene *scene, Object *ob, int lay, float viewmat[][4]) +int GPU_scene_object_lights(Scene *scene, Object *ob, int lay, float viewmat[][4], int ortho) { Base *base; Lamp *la; @@ -1041,6 +1048,10 @@ int GPU_scene_object_lights(Scene *scene, Object *ob, int lay, float viewmat[][4 for(count=0; count<8; count++) glDisable(GL_LIGHT0+count); + /* view direction for specular is not compute correct by default in + * opengl, so we set the settings ourselfs */ + glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, (ortho)? GL_FALSE: GL_TRUE); + count= 0; for(base=scene->base.first; base; base=base->next) { @@ -1127,9 +1138,6 @@ void GPU_state_init(void) GPU_default_lights(); - /* no local viewer, looks ugly in ortho mode */ - /* glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, &one); */ - glDepthFunc(GL_LEQUAL); /* scaling matrices */ glEnable(GL_NORMALIZE); diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index 46df003cbbc..87703bc73bf 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -306,7 +306,7 @@ void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[][4], float v if(material->dynproperty & DYN_LAMP_VEC) { VECCOPY(lamp->dynvec, lamp->vec); Normalize(lamp->dynvec); - VecMulf(lamp->dynvec, -1.0f); + VecNegf(lamp->dynvec); Mat4Mul3Vecfl(viewmat, lamp->dynvec); } diff --git a/source/blender/imbuf/IMB_imbuf_types.h b/source/blender/imbuf/IMB_imbuf_types.h index 73ef83393b0..eadd7affe6a 100644 --- a/source/blender/imbuf/IMB_imbuf_types.h +++ b/source/blender/imbuf/IMB_imbuf_types.h @@ -181,6 +181,15 @@ typedef enum { #define DDS (1 << 19) #endif +#ifdef WITH_OPENJPEG +#define JP2 (1 << 18) +#define JP2_12BIT (1 << 17) +#define JP2_16BIT (1 << 16) +#define JP2_YCC (1 << 15) +#define JP2_CINE (1 << 14) +#define JP2_CINE_48FPS (1 << 13) +#endif + #define RAWTGA (TGA | 1) #define JPG_STD (JPG | (0 << 8)) @@ -217,6 +226,7 @@ typedef enum { #define IS_tga(x) (x->ftype & TGA) #define IS_png(x) (x->ftype & PNG) #define IS_openexr(x) (x->ftype & OPENEXR) +#define IS_jp2(x) (x->ftype & JP2) #define IS_cineon(x) (x->ftype & CINEON) #define IS_dpx(x) (x->ftype & DPX) #define IS_bmp(x) (x->ftype & BMP) diff --git a/source/blender/imbuf/intern/IMB_jp2.h b/source/blender/imbuf/intern/IMB_jp2.h new file mode 100644 index 00000000000..fcdd4589fca --- /dev/null +++ b/source/blender/imbuf/intern/IMB_jp2.h @@ -0,0 +1,49 @@ +/* + * IMB_jp2.h + * + * $Id: IMB_bmp.h 14444 2008-04-16 22:40:48Z hos $ + * + * ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ +/** + * \file IMB_jp2.h + * \ingroup imbuf + * \brief Function declarations for jp2.c + */ + +#ifndef IMB_JP2_H +#define IMB_JP2_H + +#ifdef WITH_OPENJPEG +struct ImBuf; + +int imb_is_a_jp2(void *buf); +struct ImBuf *imb_jp2_decode(unsigned char *mem, int size, int flags); +short imb_savejp2(struct ImBuf *ibuf, char *name, int flags); +#endif /* WITH_OPENJPEG */ + +#endif + diff --git a/source/blender/imbuf/intern/cineon/cineon_dpx.c b/source/blender/imbuf/intern/cineon/cineon_dpx.c index 514d6b5522b..203eb8fe314 100644 --- a/source/blender/imbuf/intern/cineon/cineon_dpx.c +++ b/source/blender/imbuf/intern/cineon/cineon_dpx.c @@ -56,7 +56,6 @@ static void cineon_conversion_parameters(LogImageByteConversionParameters *param static struct ImBuf *imb_load_dpx_cineon(unsigned char *mem, int use_cineon, int size, int flags) { - LogImageByteConversionParameters conversion; ImBuf *ibuf; LogImageFile *image; int x, y; @@ -64,7 +63,7 @@ static struct ImBuf *imb_load_dpx_cineon(unsigned char *mem, int use_cineon, int int width, height, depth; float *frow; - cineon_conversion_parameters(&conversion); + logImageSetVerbose((G.f & G_DEBUG) ? 1:0); image = logImageOpenFromMem(mem, size, use_cineon); @@ -85,15 +84,13 @@ static struct ImBuf *imb_load_dpx_cineon(unsigned char *mem, int use_cineon, int return NULL; } - logImageSetByteConversion(image, &conversion); - ibuf = IMB_allocImBuf(width, height, 32, IB_rectfloat | flags, 0); row = MEM_mallocN(sizeof(unsigned short)*width*depth, "row in cineon_dpx.c"); frow = ibuf->rect_float+width*height*4; for (y = 0; y < height; y++) { - logImageGetRowBytes(image, row, y); + logImageGetRowBytes(image, row, y); /* checks image->params.doLogarithm and convert */ upix = row; frow -= width*4; @@ -143,7 +140,7 @@ static int imb_save_dpx_cineon(ImBuf *buf, char *filename, int use_cineon, int f } } - logImageSetVerbose(0); + logImageSetVerbose((G.f & G_DEBUG) ? 1:0); logImage = logImageCreate(filename, use_cineon, width, height, depth); if (!logImage) return 0; diff --git a/source/blender/imbuf/intern/cineon/dpxlib.c b/source/blender/imbuf/intern/cineon/dpxlib.c index 8a9adc73cdc..37e7ef3fc33 100644 --- a/source/blender/imbuf/intern/cineon/dpxlib.c +++ b/source/blender/imbuf/intern/cineon/dpxlib.c @@ -477,19 +477,49 @@ intern_dpxOpen(int mode, const char* bytestuff, int bufsize) { logImageGetByteConversionDefaults(&dpx->params); /* The SMPTE define this code: + * 0 - User-defined + * 1 - Printing density * 2 - Linear * 3 - Logarithmic + * 4 - Unspecified video + * 5 - SMPTE 240M + * 6 - CCIR 709-1 + * 7 - CCIR 601-2 system B or G + * 8 - CCIR 601-2 system M + * 9 - NTSC composite video + * 10 - PAL composite video + * 11 - Z linear + * 12 - homogeneous * * Note that transfer_characteristics is U8, don't need * check the byte order. */ + switch (header.imageInfo.channel[0].transfer_characteristics) { - case 2: + case 1: + case 2: /* linear */ dpx->params.doLogarithm= 0; break; + case 3: dpx->params.doLogarithm= 1; break; + + /* TODO - Unsupported, but for now just load them, + * colors may look wrong, but can solve color conversion later + */ + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + if (verbose) d_printf("Un-supported Transfer Characteristics: %d using linear color conversion\n", header.imageInfo.channel[0].transfer_characteristics); + dpx->params.doLogarithm= 0; + break; default: if (verbose) d_printf("Un-supported Transfer Characteristics: %d\n", header.imageInfo.channel[0].transfer_characteristics); dpxClose(dpx); diff --git a/source/blender/imbuf/intern/jp2.c b/source/blender/imbuf/intern/jp2.c new file mode 100644 index 00000000000..6217cd6bea2 --- /dev/null +++ b/source/blender/imbuf/intern/jp2.c @@ -0,0 +1,736 @@ +/** + * + * ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contributor(s): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifdef WITH_OPENJPEG + +#include "BLI_blenlib.h" + +#include "imbuf.h" +#include "imbuf_patch.h" + +#include "IMB_imbuf_types.h" +#include "IMB_imbuf.h" +#include "IMB_allocimbuf.h" +#include "IMB_jp2.h" + +#include "openjpeg.h" + +#define JP2_FILEHEADER_SIZE 14 + +static char JP2_HEAD[]= {0x0, 0x0, 0x0, 0x0C, 0x6A, 0x50, 0x20, 0x20, 0x0D, 0x0A, 0x87, 0x0A}; + +/* We only need this because of how the presets are set */ +typedef struct img_folder{ + /** The directory path of the folder containing input images*/ + char *imgdirpath; + /** Output format*/ + char *out_format; + /** Enable option*/ + char set_imgdir; + /** Enable Cod Format for output*/ + char set_out_format; + /** User specified rate stored in case of cinema option*/ + float *rates; +}img_fol_t; + +static int checkj2p(unsigned char *mem) /* J2K_CFMT */ +{ + return memcmp(JP2_HEAD, mem, 12) ? 0 : 1; +} + +int imb_is_a_jp2(void *buf) +{ + return checkj2p(buf); +} + + +/** +sample error callback expecting a FILE* client object +*/ +void error_callback(const char *msg, void *client_data) { + FILE *stream = (FILE*)client_data; + fprintf(stream, "[ERROR] %s", msg); +} +/** +sample warning callback expecting a FILE* client object +*/ +void warning_callback(const char *msg, void *client_data) { + FILE *stream = (FILE*)client_data; + fprintf(stream, "[WARNING] %s", msg); +} +/** +sample debug callback expecting no client object +*/ +void info_callback(const char *msg, void *client_data) { + (void)client_data; + fprintf(stdout, "[INFO] %s", msg); +} + + + +struct ImBuf *imb_jp2_decode(unsigned char *mem, int size, int flags) +{ + struct ImBuf *ibuf = 0; + int use_float = 0; /* for precissions higher then 8 use float */ + unsigned char *rect= NULL; + float *rect_float= NULL; + + long signed_offsets[4] = {0,0,0,0}; + int float_divs[4]; + + int index; + + int w, h, depth; + + opj_dparameters_t parameters; /* decompression parameters */ + + opj_event_mgr_t event_mgr; /* event manager */ + opj_image_t *image = NULL; + + int i; + + opj_dinfo_t* dinfo = NULL; /* handle to a decompressor */ + opj_cio_t *cio = NULL; + + if (checkj2p(mem) == 0) return(0); + + /* configure the event callbacks (not required) */ + memset(&event_mgr, 0, sizeof(opj_event_mgr_t)); + event_mgr.error_handler = error_callback; + event_mgr.warning_handler = warning_callback; + event_mgr.info_handler = info_callback; + + + /* set decoding parameters to default values */ + opj_set_default_decoder_parameters(¶meters); + + + /* JPEG 2000 compressed image data */ + + /* get a decoder handle */ + dinfo = opj_create_decompress(CODEC_JP2); + + /* catch events using our callbacks and give a local context */ + opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr); + + /* setup the decoder decoding parameters using the current image and user parameters */ + opj_setup_decoder(dinfo, ¶meters); + + /* open a byte stream */ + cio = opj_cio_open((opj_common_ptr)dinfo, mem, size); + + /* decode the stream and fill the image structure */ + image = opj_decode(dinfo, cio); + + if(!image) { + fprintf(stderr, "ERROR -> j2k_to_image: failed to decode image!\n"); + opj_destroy_decompress(dinfo); + opj_cio_close(cio); + return NULL; + } + + /* close the byte stream */ + opj_cio_close(cio); + + + if((image->numcomps * image->x1 * image->y1) == 0) + { + fprintf(stderr,"\nError: invalid raw image parameters\n"); + return NULL; + } + + w = image->comps[0].w; + h = image->comps[0].h; + + switch (image->numcomps) { + case 1: /* Greyscale */ + case 3: /* Color */ + depth= 24; + break; + default: /* 2 or 4 - Greyscale or Color + alpha */ + depth= 32; /* greyscale + alpha */ + break; + } + + + i = image->numcomps; + if (i>4) i= 4; + + while (i) { + i--; + + if (image->comps[i].prec > 8) + use_float = 1; + + if (image->comps[i].sgnd) + signed_offsets[i]= 1 << (image->comps[i].prec - 1); + + /* only needed for float images but dosnt hurt to calc this */ + float_divs[i]= (1<<image->comps[i].prec)-1; + } + + if (use_float) { + ibuf= IMB_allocImBuf(w, h, depth, IB_rectfloat, 0); + rect_float = ibuf->rect_float; + } else { + ibuf= IMB_allocImBuf(w, h, depth, IB_rect, 0); + rect = (unsigned char *) ibuf->rect; + } + + if (ibuf==NULL) { + if(dinfo) + opj_destroy_decompress(dinfo); + return NULL; + } + + ibuf->ftype = JP2; + + if (use_float) { + rect_float = ibuf->rect_float; + + if (image->numcomps < 3) { + /* greyscale 12bits+ */ + for (i = 0; i < w * h; i++, rect_float+=4) { + index = w * h - ((i) / (w) + 1) * w + (i) % (w); + + rect_float[0]= rect_float[1]= rect_float[2]= (float)(image->comps[0].data[index] + signed_offsets[0]) / float_divs[0]; + + if (image->numcomps == 2) + rect_float[3]= (image->comps[1].data[index] + signed_offsets[1]) / float_divs[1]; + else + rect_float[3]= 1.0f; + } + } else { + /* rgb or rgba 12bits+ */ + for (i = 0; i < w * h; i++, rect_float+=4) { + index = w * h - ((i) / (w) + 1) * w + (i) % (w); + + rect_float[0]= (float)(image->comps[0].data[index] + signed_offsets[0]) / float_divs[0]; + rect_float[1]= (float)(image->comps[1].data[index] + signed_offsets[1]) / float_divs[1]; + rect_float[2]= (float)(image->comps[2].data[index] + signed_offsets[2]) / float_divs[2]; + + if (image->numcomps >= 4) + rect_float[3]= (float)(image->comps[2].data[index] + signed_offsets[3]) / float_divs[3]; + else + rect_float[3]= 1.0f; + } + } + + } else { + + if (image->numcomps < 3) { + /* greyscale */ + for (i = 0; i < w * h; i++, rect+=4) { + index = w * h - ((i) / (w) + 1) * w + (i) % (w); + + rect_float[0]= rect_float[1]= rect_float[2]= (image->comps[0].data[index] + signed_offsets[0]); + + if (image->numcomps == 2) + rect[3]= image->comps[1].data[index] + signed_offsets[1]; + else + rect[3]= 255; + } + } else { + /* 8bit rgb or rgba */ + for (i = 0; i < w * h; i++, rect+=4) { + int index = w * h - ((i) / (w) + 1) * w + (i) % (w); + + rect[0]= image->comps[0].data[index] + signed_offsets[0]; + rect[1]= image->comps[1].data[index] + signed_offsets[1]; + rect[2]= image->comps[2].data[index] + signed_offsets[2]; + + if (image->numcomps >= 4) + rect[3]= image->comps[2].data[index] + signed_offsets[3]; + else + rect[3]= 255; + } + } + } + + /* free remaining structures */ + if(dinfo) { + opj_destroy_decompress(dinfo); + } + + /* free image data structure */ + opj_image_destroy(image); + + if (flags & IB_rect) { + IMB_rect_from_float(ibuf); + } + + return(ibuf); +} + +//static opj_image_t* rawtoimage(const char *filename, opj_cparameters_t *parameters, raw_cparameters_t *raw_cp) { +/* prec can be 8, 12, 16 */ + +#define UPSAMPLE_8_TO_12(_val) ((_val<<4) | (_val & ((1<<4)-1))) +#define UPSAMPLE_8_TO_16(_val) ((_val<<8)+_val) + +#define DOWNSAMPLE_FLOAT_TO_8BIT(_val) (_val)<=0.0f?0: ((_val)>=1.0f?255: (int)(255.0f*(_val))) +#define DOWNSAMPLE_FLOAT_TO_12BIT(_val) (_val)<=0.0f?0: ((_val)>=1.0f?4095: (int)(4095.0f*(_val))) +#define DOWNSAMPLE_FLOAT_TO_16BIT(_val) (_val)<=0.0f?0: ((_val)>=1.0f?65535: (int)(65535.0f*(_val))) + + +/* +2048x1080 (2K) at 24 fps or 48 fps, or 4096x2160 (4K) at 24 fps; 3×12 bits per pixel, XYZ color space + + * In 2K, for Scope (2.39:1) presentation 2048x858 pixels of the imager is used + * In 2K, for Flat (1.85:1) presentation 1998x1080 pixels of the imager is used +*/ + +/* ****************************** COPIED FROM image_to_j2k.c */ + +/* ----------------------------------------------------------------------- */ +#define CINEMA_24_CS 1302083 /*Codestream length for 24fps*/ +#define CINEMA_48_CS 651041 /*Codestream length for 48fps*/ +#define COMP_24_CS 1041666 /*Maximum size per color component for 2K & 4K @ 24fps*/ +#define COMP_48_CS 520833 /*Maximum size per color component for 2K @ 48fps*/ + + +static int initialise_4K_poc(opj_poc_t *POC, int numres){ + POC[0].tile = 1; + POC[0].resno0 = 0; + POC[0].compno0 = 0; + POC[0].layno1 = 1; + POC[0].resno1 = numres-1; + POC[0].compno1 = 3; + POC[0].prg1 = CPRL; + POC[1].tile = 1; + POC[1].resno0 = numres-1; + POC[1].compno0 = 0; + POC[1].layno1 = 1; + POC[1].resno1 = numres; + POC[1].compno1 = 3; + POC[1].prg1 = CPRL; + return 2; +} + +void cinema_parameters(opj_cparameters_t *parameters){ + parameters->tile_size_on = false; + parameters->cp_tdx=1; + parameters->cp_tdy=1; + + /*Tile part*/ + parameters->tp_flag = 'C'; + parameters->tp_on = 1; + + /*Tile and Image shall be at (0,0)*/ + parameters->cp_tx0 = 0; + parameters->cp_ty0 = 0; + parameters->image_offset_x0 = 0; + parameters->image_offset_y0 = 0; + + /*Codeblock size= 32*32*/ + parameters->cblockw_init = 32; + parameters->cblockh_init = 32; + parameters->csty |= 0x01; + + /*The progression order shall be CPRL*/ + parameters->prog_order = CPRL; + + /* No ROI */ + parameters->roi_compno = -1; + + parameters->subsampling_dx = 1; parameters->subsampling_dy = 1; + + /* 9-7 transform */ + parameters->irreversible = 1; + +} + +void cinema_setup_encoder(opj_cparameters_t *parameters,opj_image_t *image, img_fol_t *img_fol){ + int i; + float temp_rate; + + switch (parameters->cp_cinema){ + case CINEMA2K_24: + case CINEMA2K_48: + if(parameters->numresolution > 6){ + parameters->numresolution = 6; + } + if (!((image->comps[0].w == 2048) || (image->comps[0].h == 1080))){ + fprintf(stdout,"Image coordinates %d x %d is not 2K compliant.\nJPEG Digital Cinema Profile-3 " + "(2K profile) compliance requires that at least one of coordinates match 2048 x 1080\n", + image->comps[0].w,image->comps[0].h); + parameters->cp_rsiz = STD_RSIZ; + } + break; + + case CINEMA4K_24: + if(parameters->numresolution < 1){ + parameters->numresolution = 1; + }else if(parameters->numresolution > 7){ + parameters->numresolution = 7; + } + if (!((image->comps[0].w == 4096) || (image->comps[0].h == 2160))){ + fprintf(stdout,"Image coordinates %d x %d is not 4K compliant.\nJPEG Digital Cinema Profile-4" + "(4K profile) compliance requires that at least one of coordinates match 4096 x 2160\n", + image->comps[0].w,image->comps[0].h); + parameters->cp_rsiz = STD_RSIZ; + } + parameters->numpocs = initialise_4K_poc(parameters->POC,parameters->numresolution); + break; + case OFF: + /* do nothing */ + break; + } + + switch (parameters->cp_cinema){ + case CINEMA2K_24: + case CINEMA4K_24: + for(i=0 ; i<parameters->tcp_numlayers ; i++){ + temp_rate = 0 ; + if (img_fol->rates[i]== 0){ + parameters->tcp_rates[0]= ((float) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec))/ + (CINEMA_24_CS * 8 * image->comps[0].dx * image->comps[0].dy); + }else{ + temp_rate =((float) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec))/ + (img_fol->rates[i] * 8 * image->comps[0].dx * image->comps[0].dy); + if (temp_rate > CINEMA_24_CS ){ + parameters->tcp_rates[i]= ((float) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec))/ + (CINEMA_24_CS * 8 * image->comps[0].dx * image->comps[0].dy); + }else{ + parameters->tcp_rates[i]= img_fol->rates[i]; + } + } + } + parameters->max_comp_size = COMP_24_CS; + break; + + case CINEMA2K_48: + for(i=0 ; i<parameters->tcp_numlayers ; i++){ + temp_rate = 0 ; + if (img_fol->rates[i]== 0){ + parameters->tcp_rates[0]= ((float) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec))/ + (CINEMA_48_CS * 8 * image->comps[0].dx * image->comps[0].dy); + }else{ + temp_rate =((float) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec))/ + (img_fol->rates[i] * 8 * image->comps[0].dx * image->comps[0].dy); + if (temp_rate > CINEMA_48_CS ){ + parameters->tcp_rates[0]= ((float) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec))/ + (CINEMA_48_CS * 8 * image->comps[0].dx * image->comps[0].dy); + }else{ + parameters->tcp_rates[i]= img_fol->rates[i]; + } + } + } + parameters->max_comp_size = COMP_48_CS; + break; + case OFF: + /* do nothing */ + break; + } + parameters->cp_disto_alloc = 1; +} + + +static opj_image_t* ibuftoimage(ImBuf *ibuf, opj_cparameters_t *parameters) { + + unsigned char *rect; + float *rect_float; + + int subsampling_dx = parameters->subsampling_dx; + int subsampling_dy = parameters->subsampling_dy; + + + int i, numcomps, w, h, prec; + int x,y, y_row; + OPJ_COLOR_SPACE color_space; + opj_image_cmptparm_t cmptparm[4]; /* maximum of 4 components */ + opj_image_t * image = NULL; + + img_fol_t img_fol; /* only needed for cinema presets */ + memset(&img_fol,0,sizeof(img_fol_t)); + + if (ibuf->ftype & JP2_CINE) { + + if (ibuf->x==4096 || ibuf->y==2160) + parameters->cp_cinema= CINEMA4K_24; + else { + if (ibuf->ftype & JP2_CINE_48FPS) { + parameters->cp_cinema= CINEMA2K_48; + } + else { + parameters->cp_cinema= CINEMA2K_24; + } + } + if (parameters->cp_cinema){ + img_fol.rates = (float*)MEM_mallocN(parameters->tcp_numlayers * sizeof(float), "jp2_rates"); + for(i=0; i< parameters->tcp_numlayers; i++){ + img_fol.rates[i] = parameters->tcp_rates[i]; + } + cinema_parameters(parameters); + } + + color_space= CLRSPC_SYCC; + prec= 12; + numcomps= 3; + } + else { + /* Get settings from the imbuf */ + color_space = (ibuf->ftype & JP2_YCC) ? CLRSPC_SYCC : CLRSPC_SRGB; + + if (ibuf->ftype & JP2_16BIT) prec= 16; + else if (ibuf->ftype & JP2_12BIT) prec= 12; + else prec= 8; + + /* 32bit images == alpha channel */ + /* grayscale not supported yet */ + numcomps= (ibuf->depth==32) ? 4 : 3; + } + + w= ibuf->x; + h= ibuf->y; + + + /* initialize image components */ + memset(&cmptparm[0], 0, 4 * sizeof(opj_image_cmptparm_t)); + for(i = 0; i < numcomps; i++) { + cmptparm[i].prec = prec; + cmptparm[i].bpp = prec; + cmptparm[i].sgnd = 0; + cmptparm[i].dx = subsampling_dx; + cmptparm[i].dy = subsampling_dy; + cmptparm[i].w = w; + cmptparm[i].h = h; + } + /* create the image */ + image = opj_image_create(numcomps, &cmptparm[0], color_space); + if(!image) { + printf("Error: opj_image_create() failed\n"); + return NULL; + } + + /* set image offset and reference grid */ + image->x0 = parameters->image_offset_x0; + image->y0 = parameters->image_offset_y0; + image->x1 = parameters->image_offset_x0 + (w - 1) * subsampling_dx + 1; + image->y1 = parameters->image_offset_y0 + (h - 1) * subsampling_dy + 1; + + /* set image data */ + rect = (unsigned char*) ibuf->rect; + rect_float= ibuf->rect_float; + + if (rect_float && rect && prec==8) { + /* No need to use the floating point buffer, just write the 8 bits from the char buffer */ + rect_float= NULL; + } + + + if (rect_float) { + switch (prec) { + case 8: /* Convert blenders float color channels to 8,12 or 16bit ints */ + for(y=h-1; y>=0; y--) { + y_row = y*w; + for(x=0; x<w; x++, rect_float+=4) { + i = y_row + x; + + image->comps[0].data[i] = DOWNSAMPLE_FLOAT_TO_8BIT(rect_float[0]); + image->comps[1].data[i] = DOWNSAMPLE_FLOAT_TO_8BIT(rect_float[1]); + image->comps[2].data[i] = DOWNSAMPLE_FLOAT_TO_8BIT(rect_float[2]); + if (numcomps>3) + image->comps[3].data[i] = DOWNSAMPLE_FLOAT_TO_8BIT(rect_float[3]); + } + } + break; + + case 12: + for(y=h-1; y>=0; y--) { + y_row = y*w; + for(x=0; x<w; x++, rect_float+=4) { + i = y_row + x; + + image->comps[0].data[i] = DOWNSAMPLE_FLOAT_TO_12BIT(rect_float[0]); + image->comps[1].data[i] = DOWNSAMPLE_FLOAT_TO_12BIT(rect_float[1]); + image->comps[2].data[i] = DOWNSAMPLE_FLOAT_TO_12BIT(rect_float[2]); + if (numcomps>3) + image->comps[3].data[i] = DOWNSAMPLE_FLOAT_TO_12BIT(rect_float[3]); + } + } + break; + case 16: + for(y=h-1; y>=0; y--) { + y_row = y*w; + for(x=0; x<w; x++, rect_float+=4) { + i = y_row + x; + + image->comps[0].data[i] = DOWNSAMPLE_FLOAT_TO_16BIT(rect_float[0]); + image->comps[1].data[i] = DOWNSAMPLE_FLOAT_TO_16BIT(rect_float[1]); + image->comps[2].data[i] = DOWNSAMPLE_FLOAT_TO_16BIT(rect_float[2]); + if (numcomps>3) + image->comps[3].data[i] = DOWNSAMPLE_FLOAT_TO_16BIT(rect_float[3]); + } + } + break; + } + } else { + /* just use rect*/ + switch (prec) { + case 8: + for(y=h-1; y>=0; y--) { + y_row = y*w; + for(x=0; x<w; x++, rect+=4) { + i = y_row + x; + + image->comps[0].data[i] = rect[0]; + image->comps[1].data[i] = rect[1]; + image->comps[2].data[i] = rect[2]; + if (numcomps>3) + image->comps[3].data[i] = rect[3]; + } + } + break; + + case 12: /* Up Sampling, a bit pointless but best write the bit depth requested */ + for(y=h-1; y>=0; y--) { + y_row = y*w; + for(x=0; x<w; x++, rect+=4) { + i = y_row + x; + + image->comps[0].data[i]= UPSAMPLE_8_TO_12(rect[0]); + image->comps[1].data[i]= UPSAMPLE_8_TO_12(rect[1]); + image->comps[2].data[i]= UPSAMPLE_8_TO_12(rect[2]); + if (numcomps>3) + image->comps[3].data[i]= UPSAMPLE_8_TO_12(rect[3]); + } + } + break; + case 16: + for(y=h-1; y>=0; y--) { + y_row = y*w; + for(x=0; x<w; x++, rect+=4) { + i = y_row + x; + + image->comps[0].data[i]= UPSAMPLE_8_TO_16(rect[0]); + image->comps[1].data[i]= UPSAMPLE_8_TO_16(rect[1]); + image->comps[2].data[i]= UPSAMPLE_8_TO_16(rect[2]); + if (numcomps>3) + image->comps[3].data[i]= UPSAMPLE_8_TO_16(rect[3]); + } + } + break; + } + } + + /* Decide if MCT should be used */ + parameters->tcp_mct = image->numcomps == 3 ? 1 : 0; + + if(parameters->cp_cinema){ + cinema_setup_encoder(parameters,image,&img_fol); + } + + if (img_fol.rates) + MEM_freeN(img_fol.rates); + + return image; +} + + +/* Found write info at http://users.ece.gatech.edu/~slabaugh/personal/c/bitmapUnix.c */ +short imb_savejp2(struct ImBuf *ibuf, char *name, int flags) { + + int quality = ibuf->ftype & 0xff; + + int bSuccess; + opj_cparameters_t parameters; /* compression parameters */ + opj_event_mgr_t event_mgr; /* event manager */ + opj_image_t *image = NULL; + + /* + configure the event callbacks (not required) + setting of each callback is optionnal + */ + memset(&event_mgr, 0, sizeof(opj_event_mgr_t)); + event_mgr.error_handler = error_callback; + event_mgr.warning_handler = warning_callback; + event_mgr.info_handler = info_callback; + + /* set encoding parameters to default values */ + opj_set_default_encoder_parameters(¶meters); + + /* compression ratio */ + /* invert range, from 10-100, 100-1 + * where jpeg see's 1 and highest quality (lossless) and 100 is very low quality*/ + parameters.tcp_rates[0]= ((100-quality)/90.0f*99.0f) + 1; + + + parameters.tcp_numlayers = 1; // only one resolution + parameters.cp_disto_alloc = 1; + + image= ibuftoimage(ibuf, ¶meters); + + + { /* JP2 format output */ + int codestream_length; + opj_cio_t *cio = NULL; + FILE *f = NULL; + + /* get a JP2 compressor handle */ + opj_cinfo_t* cinfo = opj_create_compress(CODEC_JP2); + + /* catch events using our callbacks and give a local context */ + opj_set_event_mgr((opj_common_ptr)cinfo, &event_mgr, stderr); + + /* setup the encoder parameters using the current image and using user parameters */ + opj_setup_encoder(cinfo, ¶meters, image); + + /* open a byte stream for writing */ + /* allocate memory for all tiles */ + cio = opj_cio_open((opj_common_ptr)cinfo, NULL, 0); + + /* encode the image */ + bSuccess = opj_encode(cinfo, cio, image, NULL); /* last arg used to be parameters.index but this deprecated */ + + if (!bSuccess) { + opj_cio_close(cio); + fprintf(stderr, "failed to encode image\n"); + return 0; + } + codestream_length = cio_tell(cio); + + /* write the buffer to disk */ + f = fopen(name, "wb"); + + if (!f) { + fprintf(stderr, "failed to open %s for writing\n", name); + return 1; + } + fwrite(cio->buffer, 1, codestream_length, f); + fclose(f); + fprintf(stderr,"Generated outfile %s\n",name); + /* close and free the byte stream */ + opj_cio_close(cio); + + /* free remaining compression structures */ + opj_destroy_compress(cinfo); + } + + /* free image data */ + opj_image_destroy(image); + + return 1; +} + +#endif /* WITH_OPENJPEG */ diff --git a/source/blender/imbuf/intern/openexr/CMakeLists.txt b/source/blender/imbuf/intern/openexr/CMakeLists.txt index bb1dad087f3..21792086774 100644 --- a/source/blender/imbuf/intern/openexr/CMakeLists.txt +++ b/source/blender/imbuf/intern/openexr/CMakeLists.txt @@ -38,5 +38,9 @@ SET(INC ${OPENEXR_INC} ) +IF(WITH_OPENEXR) + ADD_DEFINITIONS(-DWITH_OPENEXR) +ENDIF(WITH_OPENEXR) + BLENDERLIB(bf_openexr "${SRC}" "${INC}") #env.BlenderLib ('bf_openexr', source_files, incs, defs, libtype=['core','player'], priority = [90, 200]) diff --git a/source/blender/imbuf/intern/radiance_hdr.c b/source/blender/imbuf/intern/radiance_hdr.c index b4e384ada72..d00e34cfdbe 100644 --- a/source/blender/imbuf/intern/radiance_hdr.c +++ b/source/blender/imbuf/intern/radiance_hdr.c @@ -180,7 +180,6 @@ struct ImBuf *imb_loadhdr(unsigned char *mem, int size, int flags) int width=0, height=0; int x, y; unsigned char* ptr; - unsigned char* rect; char oriY[80], oriX[80]; if (imb_is_a_hdr((void*)mem)) @@ -201,7 +200,7 @@ struct ImBuf *imb_loadhdr(unsigned char *mem, int size, int flags) ptr++; if (flags & IB_test) ibuf = IMB_allocImBuf(width, height, 32, 0, 0); - else ibuf = IMB_allocImBuf(width, height, 32, IB_rect|IB_rectfloat, 0); + else ibuf = IMB_allocImBuf(width, height, 32, (flags & IB_rect)|IB_rectfloat, 0); if (ibuf==NULL) return NULL; ibuf->ftype = RADHDR; @@ -211,7 +210,6 @@ struct ImBuf *imb_loadhdr(unsigned char *mem, int size, int flags) /* read in and decode the actual data */ sline = (RGBE*)MEM_mallocN(sizeof(RGBE)*width, "radhdr_read_tmpscan"); - rect = (unsigned char*)ibuf->rect; rect_float = (float *)ibuf->rect_float; for (y=0;y<height;y++) { @@ -228,19 +226,15 @@ struct ImBuf *imb_loadhdr(unsigned char *mem, int size, int flags) *rect_float++ = fcol[GRN]; *rect_float++ = fcol[BLU]; *rect_float++ = 1.0f; - /* Also old oldstyle for the rest of blender which is not using floats yet */ - // e: changed to simpler tonemapping, previous code was rather slow (is this actually still relevant at all?) - fcol[RED] = fcol[RED]/(1.f + fcol[RED]); - fcol[GRN] = fcol[GRN]/(1.f + fcol[GRN]); - fcol[BLU] = fcol[BLU]/(1.f + fcol[BLU]); - *rect++ = (unsigned char)((fcol[RED] < 0.f) ? 0 : ((fcol[RED] > 1.f) ? 255 : (255.f*fcol[RED]))); - *rect++ = (unsigned char)((fcol[GRN] < 0.f) ? 0 : ((fcol[GRN] > 1.f) ? 255 : (255.f*fcol[GRN]))); - *rect++ = (unsigned char)((fcol[BLU] < 0.f) ? 0 : ((fcol[BLU] > 1.f) ? 255 : (255.f*fcol[BLU]))); - *rect++ = 255; } } MEM_freeN(sline); if (oriY[0]=='-') IMB_flipy(ibuf); + + if (flags & IB_rect) { + IMB_rect_from_float(ibuf); + } + return ibuf; } //else printf("Data not found!\n"); diff --git a/source/blender/imbuf/intern/readimage.c b/source/blender/imbuf/intern/readimage.c index 05e7921665b..6df92f69fff 100644 --- a/source/blender/imbuf/intern/readimage.c +++ b/source/blender/imbuf/intern/readimage.c @@ -58,6 +58,10 @@ #include "IMB_dpxcineon.h" #include "BKE_global.h" +#ifdef WITH_OPENJPEG +#include "IMB_jp2.h" +#endif + #ifdef WITH_OPENEXR #include "openexr/openexr_api.h" #endif @@ -161,11 +165,16 @@ ImBuf *IMB_ibImageFromMemory(int *mem, int size, int flags) { if (ibuf) return (ibuf); #endif +#ifdef WITH_OPENJPEG + ibuf = imb_jp2_decode((uchar *)mem, size, flags); + if (ibuf) return (ibuf); +#endif + #ifdef WITH_DDS ibuf = imb_load_dds((uchar *)mem, size, flags); if (ibuf) return (ibuf); #endif - + #ifdef WITH_QUICKTIME #if defined(_WIN32) || defined (__APPLE__) if(G.have_quicktime) { diff --git a/source/blender/imbuf/intern/util.c b/source/blender/imbuf/intern/util.c index c86f9b017bf..15d1d031dbd 100644 --- a/source/blender/imbuf/intern/util.c +++ b/source/blender/imbuf/intern/util.c @@ -68,10 +68,14 @@ #include "quicktime_import.h" #endif +#ifdef WITH_OPENJPEG +#include "IMB_jp2.h" +#endif + #ifdef WITH_FFMPEG #include <ffmpeg/avcodec.h> #include <ffmpeg/avformat.h> -//#include <ffmpeg/avdevice.h> +#include <ffmpeg/avdevice.h> #include <ffmpeg/log.h> #if LIBAVFORMAT_VERSION_INT < (49 << 16) @@ -140,7 +144,11 @@ static int IMB_ispic_name(char *name) /* if (imb_is_a_bmp(buf)) return(BMP); */ - + +#ifdef WITH_OPENJPEG + if (imb_is_a_jp2(buf)) return(JP2); +#endif + #ifdef WITH_QUICKTIME #if defined(_WIN32) || defined(__APPLE__) if(G.have_quicktime) { @@ -191,6 +199,9 @@ int IMB_ispic(char *filename) #ifdef WITH_BF_OPENEXR || BLI_testextensie(filename, ".exr") #endif +#ifdef WITH_BF_OPENJPEG + || BLI_testextensie(filename, ".jp2") +#endif || BLI_testextensie(filename, ".sgi")) { return IMB_ispic_name(filename); } else { @@ -211,6 +222,9 @@ int IMB_ispic(char *filename) #ifdef WITH_BF_OPENEXR || BLI_testextensie(filename, ".exr") #endif +#ifdef WITH_BF_OPENJPEG + || BLI_testextensie(filename, ".jp2") +#endif || BLI_testextensie(filename, ".iff") || BLI_testextensie(filename, ".lbm") || BLI_testextensie(filename, ".sgi")) { @@ -258,7 +272,7 @@ void do_init_ffmpeg() if (!ffmpeg_init) { ffmpeg_init = 1; av_register_all(); - //avdevice_register_all(); + avdevice_register_all(); if ((G.f & G_DEBUG) == 0) { diff --git a/source/blender/imbuf/intern/writeimage.c b/source/blender/imbuf/intern/writeimage.c index 5a4f83a473b..5df0595d97f 100644 --- a/source/blender/imbuf/intern/writeimage.c +++ b/source/blender/imbuf/intern/writeimage.c @@ -55,6 +55,9 @@ #include "IMB_bmp.h" #include "IMB_tiff.h" #include "IMB_radiance_hdr.h" +#ifdef WITH_OPENJPEG +#include "IMB_jp2.h" +#endif #ifdef WITH_OPENEXR #include "openexr/openexr_api.h" #endif @@ -129,6 +132,11 @@ short IMB_saveiff(struct ImBuf *ibuf, char *name, int flags) if (IS_dpx(ibuf)) { return imb_save_dpx(ibuf, name, flags); } +#ifdef WITH_OPENJPEG + if (IS_jp2(ibuf)) { + return imb_savejp2(ibuf, name, flags); + } +#endif file = open(name, O_BINARY | O_RDWR | O_CREAT | O_TRUNC, 0666); if (file < 0) return (FALSE); diff --git a/source/blender/include/BIF_editparticle.h b/source/blender/include/BIF_editparticle.h index aecaee31d53..2db9aacc96b 100644 --- a/source/blender/include/BIF_editparticle.h +++ b/source/blender/include/BIF_editparticle.h @@ -46,6 +46,7 @@ void PE_create_particle_edit(struct Object *ob, struct ParticleSystem *psys); void PE_free_particle_edit(struct ParticleSystem *psys); void PE_change_act(void *ob_v, void *act_v); +void PE_change_act_psys(struct Object *ob, struct ParticleSystem *psys); int PE_can_edit(struct ParticleSystem *psys); /* access */ diff --git a/source/blender/include/BIF_outliner.h b/source/blender/include/BIF_outliner.h index fcd206bb828..e357f37286c 100644 --- a/source/blender/include/BIF_outliner.h +++ b/source/blender/include/BIF_outliner.h @@ -80,6 +80,7 @@ typedef struct TreeElement { #define TSE_SEQUENCE 26 #define TSE_SEQ_STRIP 27 #define TSE_SEQUENCE_DUP 28 +#define TSE_LINKED_PSYS 29 /* outliner search flags */ #define OL_FIND 0 diff --git a/source/blender/include/BSE_view.h b/source/blender/include/BSE_view.h index f7afce958f5..2a0485e229b 100644 --- a/source/blender/include/BSE_view.h +++ b/source/blender/include/BSE_view.h @@ -80,7 +80,9 @@ void viewmove(int mode); void viewmoveNDOFfly(int mode); void viewmoveNDOF(int mode); void view_zoom_mouseloc(float dfac, short *mouseloc); +int view_mouse_depth( float mouse_worldloc[3], short mval[2], int dist); +int get_view3d_ortho(struct View3D *v3d); int get_view3d_viewplane(int winxi, int winyi, rctf *viewplane, float *clipsta, float *clipend, float *pixsize); void setwinmatrixview3d(int winx, int winy, struct rctf *rect); diff --git a/source/blender/include/blendef.h b/source/blender/include/blendef.h index 60d3a589c51..dc05acc1735 100644 --- a/source/blender/include/blendef.h +++ b/source/blender/include/blendef.h @@ -95,6 +95,10 @@ /* This is a TESTBASELIB that can work without a 3D view */ #define TESTBASELIB_BGMODE(base) ( ((base)->flag & SELECT) && ((base)->lay & (G.vd ? G.vd->lay : G.scene->lay)) && ((base)->object->id.lib==0) && (((base)->object->restrictflag & OB_RESTRICT_VIEW)==0)) +/* Test base for 2D Windows */ +/* This is added so that DNA_view3d_types.h doesn't have to be included */ +#define TESTBASE_2D(base) ( ((base)->flag & SELECT) && ((base)->lay & G.scene->lay) && (((base)->object->restrictflag & OB_RESTRICT_VIEW)==0)) + #define BASE_SELECTABLE(base) ((base->lay & G.vd->lay) && (base->object->restrictflag & (OB_RESTRICT_SELECT|OB_RESTRICT_VIEW))==0) #define FIRSTBASE G.scene->base.first #define LASTBASE G.scene->base.last diff --git a/source/blender/include/butspace.h b/source/blender/include/butspace.h index fd3f6e926b9..868d0c3e6c0 100644 --- a/source/blender/include/butspace.h +++ b/source/blender/include/butspace.h @@ -103,6 +103,13 @@ extern void do_cambuts(unsigned short event); extern void do_armbuts(unsigned short event); extern void do_uvcalculationbuts(unsigned short event); extern void weight_paint_buttons(struct uiBlock *); + +extern void brush_buttons(struct uiBlock *block, short sima, + int evt_nop, int evt_change, + int evt_browse, int evt_local, + int evt_del, int evt_keepdata, + int evt_texbrowse, int evt_texdel); + extern void particle_edit_buttons(struct uiBlock *); extern char *get_vertexgroup_menustr(struct Object *ob); // used in object buttons @@ -446,6 +453,8 @@ void curvemap_buttons(struct uiBlock *block, struct CurveMapping *cumap, char la #define B_GEN_SKELETON 2085 #define B_RETARGET_SKELETON 2086 +#define B_SETTFACE_CLONE 2087 +#define B_SETTFACE_MASK 2088 /* *********************** */ #define B_VGROUPBUTS 2100 diff --git a/source/blender/include/transform.h b/source/blender/include/transform.h index fa7b8fc0a19..c96c5670ae6 100644 --- a/source/blender/include/transform.h +++ b/source/blender/include/transform.h @@ -468,6 +468,7 @@ int validSnappingNormal(TransInfo *t); void initTrans(TransInfo *t); void postTrans (TransInfo *t); +void resetTransRestrictions(TransInfo *t); void drawLine(float *center, float *dir, char axis, short options); diff --git a/source/blender/makesdna/DNA_actuator_types.h b/source/blender/makesdna/DNA_actuator_types.h index 43dada97d0e..48432b8c6e2 100644 --- a/source/blender/makesdna/DNA_actuator_types.h +++ b/source/blender/makesdna/DNA_actuator_types.h @@ -82,7 +82,7 @@ typedef struct bEditObjectActuator { char name[32]; float linVelocity[3]; /* initial lin. velocity on creation */ float angVelocity[3]; /* initial ang. velocity on creation */ - float pad; + float mass; short localflag; /* flag for the lin & ang. vel: apply locally */ short dyn_operation; } bEditObjectActuator; diff --git a/source/blender/makesdna/DNA_customdata_types.h b/source/blender/makesdna/DNA_customdata_types.h index 6c098e220bb..e6b18641d2a 100644 --- a/source/blender/makesdna/DNA_customdata_types.h +++ b/source/blender/makesdna/DNA_customdata_types.h @@ -37,6 +37,8 @@ typedef struct CustomDataLayer { int flag; /* general purpose flag */ int active; /* number of the active layer of this type */ int active_rnd; /* number of the layer to render*/ + int active_clone; /* number of the layer to render*/ + int active_mask; /* number of the layer to render*/ char pad[4]; char name[32]; /* layer name */ void *data; /* layer data */ diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index c6dff387c49..d04d3259c70 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -310,6 +310,10 @@ typedef struct RenderData { /* cineon */ short cineonwhite, cineonblack; float cineongamma; + + /* jpeg2000 */ + short jp2_preset, jp2_depth; + int rpad3; } RenderData; /* control render convert and shading engine */ @@ -345,7 +349,9 @@ typedef struct TimeMarker { typedef struct ImagePaintSettings { struct Brush *brush; short flag, tool; - int pad3; + + /* for projection painting only */ + short seam_bleed,normal_angle; } ImagePaintSettings; typedef struct ParticleBrushData { @@ -698,6 +704,7 @@ typedef struct Scene { #define R_DPX 27 #define R_MULTILAYER 28 #define R_DDS 29 +#define R_JP2 30 /* subimtype, flag options for imtype */ #define R_OPENEXR_HALF 1 @@ -706,6 +713,13 @@ typedef struct Scene { #define R_CINEON_LOG 8 #define R_TIFF_16BIT 16 +#define R_JPEG2K_12BIT 32 /* Jpeg2000 */ +#define R_JPEG2K_16BIT 64 +#define R_JPEG2K_YCC 128 /* when disabled use RGB */ +#define R_JPEG2K_CINE_PRESET 256 +#define R_JPEG2K_CINE_48FPS 512 + + /* bake_mode: same as RE_BAKE_xxx defines */ /* bake_flag: */ #define R_BAKE_CLEAR 1 @@ -808,6 +822,15 @@ typedef struct Scene { #define IMAGEPAINT_DRAW_TOOL 2 #define IMAGEPAINT_DRAW_TOOL_DRAWING 4 +/* projection painting only */ +#define IMAGEPAINT_PROJECT_DISABLE 8 /* Non projection 3D painting */ +#define IMAGEPAINT_PROJECT_XRAY 16 +#define IMAGEPAINT_PROJECT_BACKFACE 32 +#define IMAGEPAINT_PROJECT_FLAT 64 +#define IMAGEPAINT_PROJECT_LAYER_CLONE 128 +#define IMAGEPAINT_PROJECT_LAYER_MASK 256 +#define IMAGEPAINT_PROJECT_LAYER_MASK_INV 512 + /* toolsettings->uvcalc_flag */ #define UVCALC_FILLHOLES 1 #define UVCALC_NO_ASPECT_CORRECT 2 /* would call this UVCALC_ASPECT_CORRECT, except it should be default with old file */ diff --git a/source/blender/makesdna/DNA_scriptlink_types.h b/source/blender/makesdna/DNA_scriptlink_types.h index 95e20dd004d..9b50eb91a20 100644 --- a/source/blender/makesdna/DNA_scriptlink_types.h +++ b/source/blender/makesdna/DNA_scriptlink_types.h @@ -65,10 +65,12 @@ typedef struct ScriptLink { /* these are special scriptlinks that can be assigned to * a given space in a given ScrArea to: * - (EVENT type) handle events sent to that space; - * - (DRAW type) draw on the space after its own drawing function finishes + * - (EVENT_ALL type): handle release events, too; + * - (DRAW type) draw on the space after its own drawing function finishes. */ -#define SPACEHANDLER_VIEW3D_EVENT 1 -#define SPACEHANDLER_VIEW3D_DRAW 2 +#define SPACEHANDLER_VIEW3D_DRAW 1 +#define SPACEHANDLER_VIEW3D_EVENT 2 +#define SPACEHANDLER_VIEW3D_EVENT_ALL 3 #ifdef __cplusplus diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 226a3ecd834..735e1c4f195 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -539,6 +539,7 @@ typedef struct SpaceImaSel { #define SI_SMOOTH_UV 1<<20 #define SI_DRAW_STRETCH 1<<21 #define SI_DISPGP 1<<22 +#define SI_DRAW_OTHER 1<<23 /* SpaceIpo->flag */ #define SIPO_LOCK_VIEW 1<<0 diff --git a/source/blender/nodes/CMP_node.h b/source/blender/nodes/CMP_node.h index 020bbdebfa2..84d311b6173 100644 --- a/source/blender/nodes/CMP_node.h +++ b/source/blender/nodes/CMP_node.h @@ -38,71 +38,71 @@ /* ****************** types array for all composite nodes ****************** */ -extern bNodeType cmp_node_rlayers; -extern bNodeType cmp_node_image; -extern bNodeType cmp_node_texture; -extern bNodeType cmp_node_value; -extern bNodeType cmp_node_rgb; -extern bNodeType cmp_node_curve_time; +bNodeType cmp_node_rlayers; +bNodeType cmp_node_image; +bNodeType cmp_node_texture; +bNodeType cmp_node_value; +bNodeType cmp_node_rgb; +bNodeType cmp_node_curve_time; -extern bNodeType cmp_node_composite; -extern bNodeType cmp_node_viewer; -extern bNodeType cmp_node_splitviewer; -extern bNodeType cmp_node_output_file; +bNodeType cmp_node_composite; +bNodeType cmp_node_viewer; +bNodeType cmp_node_splitviewer; +bNodeType cmp_node_output_file; -extern bNodeType cmp_node_curve_rgb; -extern bNodeType cmp_node_mix_rgb; -extern bNodeType cmp_node_hue_sat; -extern bNodeType cmp_node_brightcontrast; -extern bNodeType cmp_node_gamma; -extern bNodeType cmp_node_invert; -extern bNodeType cmp_node_alphaover; -extern bNodeType cmp_node_zcombine; +bNodeType cmp_node_curve_rgb; +bNodeType cmp_node_mix_rgb; +bNodeType cmp_node_hue_sat; +bNodeType cmp_node_brightcontrast; +bNodeType cmp_node_gamma; +bNodeType cmp_node_invert; +bNodeType cmp_node_alphaover; +bNodeType cmp_node_zcombine; -extern bNodeType cmp_node_normal; -extern bNodeType cmp_node_curve_vec; -extern bNodeType cmp_node_map_value; -extern bNodeType cmp_node_normalize; +bNodeType cmp_node_normal; +bNodeType cmp_node_curve_vec; +bNodeType cmp_node_map_value; +bNodeType cmp_node_normalize; -extern bNodeType cmp_node_filter; -extern bNodeType cmp_node_blur; -extern bNodeType cmp_node_dblur; -extern bNodeType cmp_node_bilateralblur; -extern bNodeType cmp_node_vecblur; -extern bNodeType cmp_node_dilateerode; -extern bNodeType cmp_node_defocus; +bNodeType cmp_node_filter; +bNodeType cmp_node_blur; +bNodeType cmp_node_dblur; +bNodeType cmp_node_bilateralblur; +bNodeType cmp_node_vecblur; +bNodeType cmp_node_dilateerode; +bNodeType cmp_node_defocus; -extern bNodeType cmp_node_valtorgb; -extern bNodeType cmp_node_rgbtobw; -extern bNodeType cmp_node_setalpha; -extern bNodeType cmp_node_idmask; -extern bNodeType cmp_node_math; -extern bNodeType cmp_node_seprgba; -extern bNodeType cmp_node_combrgba; -extern bNodeType cmp_node_sephsva; -extern bNodeType cmp_node_combhsva; -extern bNodeType cmp_node_sepyuva; -extern bNodeType cmp_node_combyuva; -extern bNodeType cmp_node_sepycca; -extern bNodeType cmp_node_combycca; -extern bNodeType cmp_node_premulkey; +bNodeType cmp_node_valtorgb; +bNodeType cmp_node_rgbtobw; +bNodeType cmp_node_setalpha; +bNodeType cmp_node_idmask; +bNodeType cmp_node_math; +bNodeType cmp_node_seprgba; +bNodeType cmp_node_combrgba; +bNodeType cmp_node_sephsva; +bNodeType cmp_node_combhsva; +bNodeType cmp_node_sepyuva; +bNodeType cmp_node_combyuva; +bNodeType cmp_node_sepycca; +bNodeType cmp_node_combycca; +bNodeType cmp_node_premulkey; -extern bNodeType cmp_node_diff_matte; -extern bNodeType cmp_node_chroma; -extern bNodeType cmp_node_channel_matte; -extern bNodeType cmp_node_color_spill; -extern bNodeType cmp_node_luma_matte; +bNodeType cmp_node_diff_matte; +bNodeType cmp_node_chroma; +bNodeType cmp_node_channel_matte; +bNodeType cmp_node_color_spill; +bNodeType cmp_node_luma_matte; -extern bNodeType cmp_node_translate; -extern bNodeType cmp_node_rotate; -extern bNodeType cmp_node_scale; -extern bNodeType cmp_node_flip; -extern bNodeType cmp_node_crop; -extern bNodeType cmp_node_displace; -extern bNodeType cmp_node_mapuv; +bNodeType cmp_node_translate; +bNodeType cmp_node_rotate; +bNodeType cmp_node_scale; +bNodeType cmp_node_flip; +bNodeType cmp_node_crop; +bNodeType cmp_node_displace; +bNodeType cmp_node_mapuv; -extern bNodeType cmp_node_glare; -extern bNodeType cmp_node_tonemap; -extern bNodeType cmp_node_lensdist; +bNodeType cmp_node_glare; +bNodeType cmp_node_tonemap; +bNodeType cmp_node_lensdist; #endif diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index 22e732d046b..4e9e4c2f84f 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -55,8 +55,6 @@ IF(WITH_FFMPEG) ADD_DEFINITIONS(-DWITH_FFMPEG) ENDIF(WITH_FFMPEG) -ADD_DEFINITIONS(-DWITH_CCGSUBSURF) - BLENDERLIB(bf_nodes "${SRC}" "${INC}") IF(WITH_VERSE) diff --git a/source/blender/nodes/SConscript b/source/blender/nodes/SConscript index 91ca6cd8c81..b47eebd0811 100644 --- a/source/blender/nodes/SConscript +++ b/source/blender/nodes/SConscript @@ -2,9 +2,9 @@ Import ('env') sources = env.Glob('intern/*.c') -sources += env.Glob('intern/CMP_nodes/*.c') -sources += env.Glob('intern/SHD_nodes/*.c') -sources += env.Glob('intern/TEX_nodes/*.c') +cmpsources = env.Glob('intern/CMP_nodes/*.c') +shdsources = env.Glob('intern/SHD_nodes/*.c') +texsources = env.Glob('intern/TEX_nodes/*.c') incs = '. ./intern ' incs += '#/intern/guardedalloc ../include ../blenlib ../makesdna' @@ -28,13 +28,6 @@ else: if env['WITH_BF_INTERNATIONAL']: defs += ' WITH_FREETYPE2' -if env['WITH_BF_VERSE']: - defs += ' WITH_VERSE' - incs += ' ' + env['BF_VERSE_INCLUDE'] - -if env['WITH_BF_VERSE']: - defs += ' WITH_VERSE' - if env['WITH_BF_OPENEXR']: defs += ' WITH_OPENEXR' @@ -46,6 +39,7 @@ if env['WITH_BF_QUICKTIME']: defs += ' WITH_QUICKTIME' incs += ' ' + env['BF_QUICKTIME_INC'] -defs += ' WITH_CCGSUBSURF ' - -env.BlenderLib ( libname = 'nodes', sources = sources, includes = Split(incs), defines = Split(defs), libtype=['core','player'], priority = [65, 20] ) +env.BlenderLib ( libname = 'bf_nodes', sources = sources, includes = Split(incs), defines = Split(defs), libtype=['intern', 'core', 'player'], priority = [200, 200, 300] ) +env.BlenderLib ( libname = 'bf_cmpnodes', sources = cmpsources, includes = Split(incs), defines = Split(defs), libtype=['intern', 'core'], priority = [200, 175] ) +env.BlenderLib ( libname = 'bf_shdnodes', sources = shdsources, includes = Split(incs), defines = Split(defs), libtype=['intern', 'core'], priority = [200, 175] ) +env.BlenderLib ( libname = 'bf_texnodes', sources = texsources, includes = Split(incs), defines = Split(defs), libtype=['intern', 'core'], priority = [200, 175] ) diff --git a/source/blender/nodes/SHD_node.h b/source/blender/nodes/SHD_node.h index d75d7c9f568..10af3f162d6 100644 --- a/source/blender/nodes/SHD_node.h +++ b/source/blender/nodes/SHD_node.h @@ -39,29 +39,29 @@ /* the type definitions array */ /* ****************** types array for all shaders ****************** */ -extern bNodeType sh_node_output; -extern bNodeType sh_node_material; -extern bNodeType sh_node_camera; -extern bNodeType sh_node_value; -extern bNodeType sh_node_rgb; -extern bNodeType sh_node_mix_rgb; -extern bNodeType sh_node_valtorgb; -extern bNodeType sh_node_rgbtobw; -extern bNodeType sh_node_texture; -extern bNodeType sh_node_normal; -extern bNodeType sh_node_geom; -extern bNodeType sh_node_mapping; -extern bNodeType sh_node_curve_vec; -extern bNodeType sh_node_curve_rgb; -extern bNodeType sh_node_math; -extern bNodeType sh_node_vect_math; -extern bNodeType sh_node_squeeze; -extern bNodeType node_dynamic_typeinfo; -extern bNodeType sh_node_material_ext; -extern bNodeType sh_node_invert; -extern bNodeType sh_node_seprgb; -extern bNodeType sh_node_combrgb; -extern bNodeType sh_node_hue_sat; +bNodeType sh_node_output; +bNodeType sh_node_material; +bNodeType sh_node_camera; +bNodeType sh_node_value; +bNodeType sh_node_rgb; +bNodeType sh_node_mix_rgb; +bNodeType sh_node_valtorgb; +bNodeType sh_node_rgbtobw; +bNodeType sh_node_texture; +bNodeType sh_node_normal; +bNodeType sh_node_geom; +bNodeType sh_node_mapping; +bNodeType sh_node_curve_vec; +bNodeType sh_node_curve_rgb; +bNodeType sh_node_math; +bNodeType sh_node_vect_math; +bNodeType sh_node_squeeze; +bNodeType node_dynamic_typeinfo; +bNodeType sh_node_material_ext; +bNodeType sh_node_invert; +bNodeType sh_node_seprgb; +bNodeType sh_node_combrgb; +bNodeType sh_node_hue_sat; #endif diff --git a/source/blender/nodes/TEX_node.h b/source/blender/nodes/TEX_node.h index 6be2123b96d..90e171e9cca 100644 --- a/source/blender/nodes/TEX_node.h +++ b/source/blender/nodes/TEX_node.h @@ -38,33 +38,40 @@ /* ****************** types array for all texture nodes ****************** */ -extern bNodeType tex_node_math; -extern bNodeType tex_node_mix_rgb; -extern bNodeType tex_node_valtorgb; -extern bNodeType tex_node_rgbtobw; -extern bNodeType tex_node_output; -extern bNodeType tex_node_viewer; -extern bNodeType tex_node_checker; -extern bNodeType tex_node_texture; -extern bNodeType tex_node_bricks; -extern bNodeType tex_node_image; -extern bNodeType tex_node_curve_rgb; -extern bNodeType tex_node_curve_time; -extern bNodeType tex_node_invert; -extern bNodeType tex_node_hue_sat; +bNodeType tex_node_math; +bNodeType tex_node_mix_rgb; +bNodeType tex_node_valtorgb; +bNodeType tex_node_valtonor; +bNodeType tex_node_rgbtobw; +bNodeType tex_node_output; +bNodeType tex_node_viewer; +bNodeType tex_node_checker; +bNodeType tex_node_texture; +bNodeType tex_node_bricks; +bNodeType tex_node_image; +bNodeType tex_node_curve_rgb; +bNodeType tex_node_curve_time; +bNodeType tex_node_invert; +bNodeType tex_node_hue_sat; +bNodeType tex_node_coord; +bNodeType tex_node_distance; -extern bNodeType tex_node_rotate; -extern bNodeType tex_node_translate; +bNodeType tex_node_rotate; +bNodeType tex_node_translate; +bNodeType tex_node_scale; -extern bNodeType tex_node_proc_voronoi; -extern bNodeType tex_node_proc_blend; -extern bNodeType tex_node_proc_magic; -extern bNodeType tex_node_proc_marble; -extern bNodeType tex_node_proc_clouds; -extern bNodeType tex_node_proc_wood; -extern bNodeType tex_node_proc_musgrave; -extern bNodeType tex_node_proc_noise; -extern bNodeType tex_node_proc_stucci; -extern bNodeType tex_node_proc_distnoise; +bNodeType tex_node_compose; +bNodeType tex_node_decompose; + +bNodeType tex_node_proc_voronoi; +bNodeType tex_node_proc_blend; +bNodeType tex_node_proc_magic; +bNodeType tex_node_proc_marble; +bNodeType tex_node_proc_clouds; +bNodeType tex_node_proc_wood; +bNodeType tex_node_proc_musgrave; +bNodeType tex_node_proc_noise; +bNodeType tex_node_proc_stucci; +bNodeType tex_node_proc_distnoise; #endif diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_blur.c b/source/blender/nodes/intern/CMP_nodes/CMP_blur.c index e7e799b6e76..f9be9533658 100644 --- a/source/blender/nodes/intern/CMP_nodes/CMP_blur.c +++ b/source/blender/nodes/intern/CMP_nodes/CMP_blur.c @@ -567,6 +567,11 @@ static void node_composit_exec_blur(void *data, bNode *node, bNodeStack **in, bN if(out[0]->hasoutput==0) return; + if(nbd->relative) { + nbd->sizex= (int)(nbd->percentx*nbd->image_in_width); + nbd->sizey= (int)(nbd->percenty*nbd->image_in_height); + } + if (((NodeBlurData *)node->storage)->filtertype == R_FILTER_FAST_GAUSS) { CompBuf *new, *img = in[0]->data; /*from eeshlo's original patch, removed to fit in with the existing blur node */ diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_filter.c b/source/blender/nodes/intern/CMP_nodes/CMP_filter.c index 46a9d747ac1..6011ac3b58a 100644 --- a/source/blender/nodes/intern/CMP_nodes/CMP_filter.c +++ b/source/blender/nodes/intern/CMP_nodes/CMP_filter.c @@ -78,6 +78,7 @@ static void do_filter_edge(CompBuf *out, CompBuf *in, float *filter, float fac) QUATCOPY(fp, row2+4); } else if(pix==CB_VAL) { + fp+= pix; for(x=2; x<rowlen; x++) { f1= filter[0]*row1[0] + filter[1]*row1[1] + filter[2]*row1[2] + filter[3]*row2[0] + filter[4]*row2[1] + filter[5]*row2[2] + filter[6]*row3[0] + filter[7]*row3[1] + filter[8]*row3[2]; f2= filter[0]*row1[0] + filter[3]*row1[1] + filter[6]*row1[2] + filter[1]*row2[0] + filter[4]*row2[1] + filter[7]*row2[2] + filter[2]*row3[0] + filter[5]*row3[1] + filter[8]*row3[2]; diff --git a/source/blender/nodes/intern/TEX_nodes/TEX_compose.c b/source/blender/nodes/intern/TEX_nodes/TEX_compose.c new file mode 100644 index 00000000000..26576befa3e --- /dev/null +++ b/source/blender/nodes/intern/TEX_nodes/TEX_compose.c @@ -0,0 +1,71 @@ +/** + * + * ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "../TEX_util.h" + +static bNodeSocketType inputs[]= { + { SOCK_VALUE, 1, "Red", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }, + { SOCK_VALUE, 1, "Green", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }, + { SOCK_VALUE, 1, "Blue", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }, + { SOCK_VALUE, 1, "Alpha", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }, + { -1, 0, "" } +}; +static bNodeSocketType outputs[]= { + { SOCK_RGBA, 0, "Color", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f }, + { -1, 0, "" } +}; + +static void colorfn(float *out, float *coord, bNode *node, bNodeStack **in, short thread) +{ + int i; + for(i = 0; i < 4; i++) + out[i] = tex_input_value(in[i], coord, thread); +} + +static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +{ + tex_output(node, in, out[0], &colorfn); +} + +bNodeType tex_node_compose= { + /* *next,*prev */ NULL, NULL, + /* type code */ TEX_NODE_COMPOSE, + /* name */ "Compose RGBA", + /* width+range */ 100, 60, 150, + /* class+opts */ NODE_CLASS_OP_COLOR, 0, + /* input sock */ inputs, + /* output sock */ outputs, + /* storage */ "", + /* execfunc */ exec, + /* butfunc */ NULL, + /* initfunc */ NULL, + /* freestoragefunc */ NULL, + /* copystoragefunc */ NULL, + /* id */ NULL + +}; diff --git a/source/blender/nodes/intern/TEX_nodes/TEX_coord.c b/source/blender/nodes/intern/TEX_nodes/TEX_coord.c new file mode 100644 index 00000000000..da487c190af --- /dev/null +++ b/source/blender/nodes/intern/TEX_nodes/TEX_coord.c @@ -0,0 +1,66 @@ +/** + * + * ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Mathias Panzenböck (panzi) <grosser.meister.morti@gmx.net>. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "../TEX_util.h" + +static bNodeSocketType outputs[]= { + { SOCK_VECTOR, 0, "Coordinates", 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f }, + { -1, 0, "" } +}; + +static void vectorfn(float *out, float *coord, bNode *node, bNodeStack **in, short thread) +{ + out[0] = coord[0]; + out[1] = coord[1]; + out[2] = coord[2]; +} + +static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +{ + tex_output(node, in, out[0], &vectorfn); + + tex_do_preview(node, out[0], data); +} + +bNodeType tex_node_coord= { + /* *next,*prev */ NULL, NULL, + /* type code */ TEX_NODE_COORD, + /* name */ "Coordinates", + /* width+range */ 120, 110, 160, + /* class+opts */ NODE_CLASS_INPUT, NODE_OPTIONS, + /* input sock */ NULL, + /* output sock */ outputs, + /* storage */ "node_coord", + /* execfunc */ exec, + /* butfunc */ NULL, + /* initfunc */ NULL, + /* freestoragefunc */ NULL, + /* copystoragefunc */ NULL, + /* id */ NULL +}; + diff --git a/source/blender/nodes/intern/TEX_nodes/TEX_decompose.c b/source/blender/nodes/intern/TEX_nodes/TEX_decompose.c new file mode 100644 index 00000000000..c08eb12a18f --- /dev/null +++ b/source/blender/nodes/intern/TEX_nodes/TEX_decompose.c @@ -0,0 +1,92 @@ +/** + * + * ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "../TEX_util.h" +#include <math.h> + +static bNodeSocketType inputs[]= { + { SOCK_RGBA, 1, "Color", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f }, + { -1, 0, "" } +}; +static bNodeSocketType outputs[]= { + { SOCK_VALUE, 0, "Red", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }, + { SOCK_VALUE, 0, "Green", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }, + { SOCK_VALUE, 0, "Blue", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }, + { SOCK_VALUE, 0, "Alpha", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }, + { -1, 0, "" } +}; + +static void valuefn_r(float *out, float *coord, bNode *node, bNodeStack **in, short thread) +{ + tex_input_rgba(out, in[0], coord, thread); + *out = out[0]; +} + +static void valuefn_g(float *out, float *coord, bNode *node, bNodeStack **in, short thread) +{ + tex_input_rgba(out, in[0], coord, thread); + *out = out[1]; +} + +static void valuefn_b(float *out, float *coord, bNode *node, bNodeStack **in, short thread) +{ + tex_input_rgba(out, in[0], coord, thread); + *out = out[2]; +} + +static void valuefn_a(float *out, float *coord, bNode *node, bNodeStack **in, short thread) +{ + tex_input_rgba(out, in[0], coord, thread); + *out = out[3]; +} + +static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +{ + tex_output(node, in, out[0], &valuefn_r); + tex_output(node, in, out[1], &valuefn_g); + tex_output(node, in, out[2], &valuefn_b); + tex_output(node, in, out[3], &valuefn_a); +} + +bNodeType tex_node_decompose= { + /* *next,*prev */ NULL, NULL, + /* type code */ TEX_NODE_DECOMPOSE, + /* name */ "Decompose RGBA", + /* width+range */ 100, 60, 150, + /* class+opts */ NODE_CLASS_OP_COLOR, 0, + /* input sock */ inputs, + /* output sock */ outputs, + /* storage */ "", + /* execfunc */ exec, + /* butfunc */ NULL, + /* initfunc */ NULL, + /* freestoragefunc */ NULL, + /* copystoragefunc */ NULL, + /* id */ NULL + +}; diff --git a/source/blender/nodes/intern/TEX_nodes/TEX_distance.c b/source/blender/nodes/intern/TEX_nodes/TEX_distance.c new file mode 100644 index 00000000000..ff9ec4db76b --- /dev/null +++ b/source/blender/nodes/intern/TEX_nodes/TEX_distance.c @@ -0,0 +1,79 @@ +/** + * + * ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Mathias Panzenböck (panzi) <grosser.meister.morti@gmx.net>. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include <math.h> +#include "BLI_arithb.h" +#include "../TEX_util.h" + +static bNodeSocketType inputs[]= { + { SOCK_VECTOR, 1, "Coordinate 1", 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f }, + { SOCK_VECTOR, 1, "Coordinate 2", 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f }, + { -1, 0, "" } +}; + +static bNodeSocketType outputs[]= { + { SOCK_VALUE, 0, "Value", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f }, + { -1, 0, "" } +}; + +static void valuefn(float *out, float *coord, bNode *node, bNodeStack **in, short thread) +{ + float coord1[3], coord2[3]; + float x, y, z; + + tex_input_vec(coord1, in[0], coord, thread); + tex_input_vec(coord2, in[1], coord, thread); + + *out = VecLenf(coord2, coord1); +} + +static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +{ + tex_output(node, in, out[0], &valuefn); + + tex_do_preview(node, out[0], data); +} + +bNodeType tex_node_distance= { + /* *next,*prev */ NULL, NULL, + /* type code */ TEX_NODE_DISTANCE, + /* name */ "Distance", + /* width+range */ 120, 110, 160, + /* class+opts */ NODE_CLASS_CONVERTOR, NODE_OPTIONS, + /* input sock */ inputs, + /* output sock */ outputs, + /* storage */ "node_distance", + /* execfunc */ exec, + /* butfunc */ NULL, + /* initfunc */ NULL, + /* freestoragefunc */ NULL, + /* copystoragefunc */ NULL, + /* id */ NULL +}; + + diff --git a/source/blender/nodes/intern/TEX_nodes/TEX_hueSatVal.c b/source/blender/nodes/intern/TEX_nodes/TEX_hueSatVal.c index d1a33896fc3..bb1a49fb235 100644 --- a/source/blender/nodes/intern/TEX_nodes/TEX_hueSatVal.c +++ b/source/blender/nodes/intern/TEX_nodes/TEX_hueSatVal.c @@ -30,16 +30,16 @@ static bNodeSocketType inputs[]= { - { SOCK_VALUE, 1, "Hue", 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_VALUE, 1, "Saturation", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.0f}, - { SOCK_VALUE, 1, "Value", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.0f}, - { SOCK_VALUE, 1, "Fac", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 1, "Color", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, - { -1, 0, "" } + { SOCK_VALUE, 1, "Hue", 0.0f, 0.0f, 0.0f, 0.0f, -0.5f, 0.5f }, + { SOCK_VALUE, 1, "Saturation", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.0f }, + { SOCK_VALUE, 1, "Value", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.0f }, + { SOCK_VALUE, 1, "Factor", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }, + { SOCK_RGBA, 1, "Color", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f }, + { -1, 0, "" } }; static bNodeSocketType outputs[]= { - { SOCK_RGBA, 0, "Color", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, - { -1, 0, "" } + { SOCK_RGBA, 0, "Color", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f }, + { -1, 0, "" } }; static void do_hue_sat_fac(bNode *node, float *out, float hue, float sat, float val, float *in, float fac) @@ -67,15 +67,19 @@ static void do_hue_sat_fac(bNode *node, float *out, float hue, float sat, float static void colorfn(float *out, float *coord, bNode *node, bNodeStack **in, short thread) { - float in0 = tex_input_value(in[0], coord, thread); - float in1 = tex_input_value(in[1], coord, thread); - float in2 = tex_input_value(in[2], coord, thread); - float in3 = tex_input_value(in[3], coord, thread); + float hue = tex_input_value(in[0], coord, thread); + float sat = tex_input_value(in[1], coord, thread); + float val = tex_input_value(in[2], coord, thread); + float fac = tex_input_value(in[3], coord, thread); - float in4[4]; - tex_input_rgba(in4, in[4], coord, thread); + float col[4]; + tex_input_rgba(col, in[4], coord, thread); - do_hue_sat_fac(node, out, in0, in1, in2, in4, in3); + hue += 0.5f; /* [-.5, .5] -> [0, 1] */ + + do_hue_sat_fac(node, out, hue, sat, val, col, fac); + + out[3] = col[3]; } static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) diff --git a/source/blender/nodes/intern/TEX_nodes/TEX_math.c b/source/blender/nodes/intern/TEX_nodes/TEX_math.c index a2c66078692..bac91fc0901 100644 --- a/source/blender/nodes/intern/TEX_nodes/TEX_math.c +++ b/source/blender/nodes/intern/TEX_nodes/TEX_math.c @@ -143,6 +143,29 @@ static void valuefn(float *out, float *coord, bNode *node, bNodeStack **in, shor *out= (int)(in0 + 0.5f); } break; + + case 15: /* Less Than */ + { + if( in0 < in1 ) + *out= 1.0f; + else + *out= 0.0f; + } + break; + + case 16: /* Greater Than */ + { + if( in0 > in1 ) + *out= 1.0f; + else + *out= 0.0f; + } + break; + + default: + fprintf(stderr, + "%s:%d: unhandeld value in switch statement: %d\n", + __FILE__, __LINE__, node->custom1); } } diff --git a/source/blender/nodes/intern/TEX_nodes/TEX_proc.c b/source/blender/nodes/intern/TEX_nodes/TEX_proc.c index 9078dd1be21..ec65cf186a8 100644 --- a/source/blender/nodes/intern/TEX_nodes/TEX_proc.c +++ b/source/blender/nodes/intern/TEX_nodes/TEX_proc.c @@ -110,25 +110,25 @@ static int count_outputs(bNode *node) /* Boilerplate generators */ #define ProcNoInputs(name) \ - static void name##_map_inputs(Tex *tex, bNodeStack **in, float *coord, short thread) \ - {} + static void name##_map_inputs(Tex *tex, bNodeStack **in, float *coord, short thread) \ + {} #define ProcDef(name) \ - static void name##_colorfn(float *result, float *coord, bNode *node, bNodeStack **in, short thread) \ - { \ - texfn(result, coord, node, in, 0, &name##_map_inputs, thread); \ - } \ - static void name##_normalfn(float *result, float *coord, bNode *node, bNodeStack **in, short thread) \ - { \ - texfn(result, coord, node, in, 1, &name##_map_inputs, thread); \ - } \ - static void name##_exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) \ - { \ - int outs = count_outputs(node); \ - if(outs >= 1) tex_output(node, in, out[0], &name##_colorfn); \ - if(outs >= 2) tex_output(node, in, out[1], &name##_normalfn); \ - if(outs >= 1) tex_do_preview(node, out[0], data); \ - } + static void name##_colorfn(float *result, float *coord, bNode *node, bNodeStack **in, short thread) \ + { \ + texfn(result, coord, node, in, 0, &name##_map_inputs, thread); \ + } \ + static void name##_normalfn(float *result, float *coord, bNode *node, bNodeStack **in, short thread) \ + { \ + texfn(result, coord, node, in, 1, &name##_map_inputs, thread); \ + } \ + static void name##_exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) \ + { \ + int outs = count_outputs(node); \ + if(outs >= 1) tex_output(node, in, out[0], &name##_colorfn); \ + if(outs >= 2) tex_output(node, in, out[1], &name##_normalfn); \ + if(outs >= 1) tex_do_preview(node, out[0], data); \ + } /* --- VORONOI -- */ diff --git a/source/blender/nodes/intern/TEX_nodes/TEX_rotate.c b/source/blender/nodes/intern/TEX_nodes/TEX_rotate.c index 93bf17d4862..3a2c2b1def1 100644 --- a/source/blender/nodes/intern/TEX_nodes/TEX_rotate.c +++ b/source/blender/nodes/intern/TEX_nodes/TEX_rotate.c @@ -91,8 +91,6 @@ static void colorfn(float *out, float *coord, bNode *node, bNodeStack **in, shor static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) { tex_output(node, in, out[0], &colorfn); - - tex_do_preview(node, out[0], data); } bNodeType tex_node_rotate= { diff --git a/source/blender/nodes/intern/TEX_nodes/TEX_scale.c b/source/blender/nodes/intern/TEX_nodes/TEX_scale.c new file mode 100644 index 00000000000..792c3468e9f --- /dev/null +++ b/source/blender/nodes/intern/TEX_nodes/TEX_scale.c @@ -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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include <math.h> +#include "../TEX_util.h" + +static bNodeSocketType inputs[]= { + { SOCK_RGBA, 1, "Color", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f }, + { SOCK_VECTOR, 1, "Scale", 1.0f, 1.0f, 1.0f, 0.0f, -10.0f, 10.0f }, + { -1, 0, "" } +}; + +static bNodeSocketType outputs[]= { + { SOCK_RGBA, 0, "Color", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; + +static void colorfn(float *out, float *coord, bNode *node, bNodeStack **in, short thread) +{ + float scale[3], new_coord[3]; + + tex_input_vec(scale, in[1], coord, thread); + + new_coord[0] = coord[0] * scale[0]; + new_coord[1] = coord[1] * scale[1]; + new_coord[2] = coord[2] * scale[2]; + + tex_input_rgba(out, in[0], new_coord, thread); +} +static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +{ + tex_output(node, in, out[0], &colorfn); +} + +bNodeType tex_node_scale = { + /* *next,*prev */ NULL, NULL, + /* type code */ TEX_NODE_SCALE, + /* name */ "Scale", + /* width+range */ 90, 80, 100, + /* class+opts */ NODE_CLASS_DISTORT, NODE_OPTIONS, + /* input sock */ inputs, + /* output sock */ outputs, + /* storage */ "", + /* execfunc */ exec, + /* butfunc */ NULL, + /* initfunc */ NULL, + /* freestoragefunc */ NULL, + /* copystoragefunc */ NULL, + /* id */ NULL +}; + diff --git a/source/blender/nodes/intern/TEX_nodes/TEX_translate.c b/source/blender/nodes/intern/TEX_nodes/TEX_translate.c index bd7e61d0ff4..0e903301789 100644 --- a/source/blender/nodes/intern/TEX_nodes/TEX_translate.c +++ b/source/blender/nodes/intern/TEX_nodes/TEX_translate.c @@ -55,8 +55,6 @@ static void colorfn(float *out, float *coord, bNode *node, bNodeStack **in, shor static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) { tex_output(node, in, out[0], &colorfn); - - tex_do_preview(node, out[0], data); } bNodeType tex_node_translate = { diff --git a/source/blender/nodes/intern/TEX_nodes/TEX_valToNor.c b/source/blender/nodes/intern/TEX_nodes/TEX_valToNor.c new file mode 100644 index 00000000000..f63f5682030 --- /dev/null +++ b/source/blender/nodes/intern/TEX_nodes/TEX_valToNor.c @@ -0,0 +1,92 @@ +/** + * + * ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Jucas. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "../TEX_util.h" + +static bNodeSocketType inputs[]= { + { SOCK_VALUE, 1, "Val", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f }, + { SOCK_VALUE, 1, "Nabla", 0.025f, 0.0f, 0.0f, 0.0f, 0.001f, 0.1f }, + { -1, 0, "" } +}; + +static bNodeSocketType outputs[]= { + { SOCK_VECTOR, 0, "Normal", 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f }, + { -1, 0, "" } +}; + +static void normalfn(float *out, float *coord, bNode *node, bNodeStack **in, short thread) +{ + float new_coord[3]; + + float nabla = tex_input_value(in[1], coord, thread); + float val; + float nor[2]; + + val = tex_input_value(in[0], coord, thread); + + new_coord[0] = coord[0] + nabla; + new_coord[1] = coord[1]; + new_coord[2] = coord[2]; + nor[0] = tex_input_value(in[0], new_coord, thread); + + new_coord[0] = coord[0]; + new_coord[1] = coord[1] + nabla; + nor[1] = tex_input_value(in[0], new_coord, thread); + + new_coord[1] = coord[1]; + new_coord[2] = coord[2] + nabla; + nor[2] = tex_input_value(in[0], new_coord, thread); + + out[0] = val-nor[0]; + out[1] = val-nor[1]; + out[2] = val-nor[2]; +} +static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +{ + tex_output(node, in, out[0], &normalfn); + + tex_do_preview(node, out[0], data); +} + +bNodeType tex_node_valtonor = { + /* *next,*prev */ NULL, NULL, + /* type code */ TEX_NODE_VALTONOR, + /* name */ "Value to Normal", + /* width+range */ 90, 80, 100, + /* class+opts */ NODE_CLASS_CONVERTOR, NODE_OPTIONS, + /* input sock */ inputs, + /* output sock */ outputs, + /* storage */ "", + /* execfunc */ exec, + /* butfunc */ NULL, + /* initfunc */ NULL, + /* freestoragefunc */ NULL, + /* copystoragefunc */ NULL, + /* id */ NULL +}; + diff --git a/source/blender/nodes/intern/TEX_util.c b/source/blender/nodes/intern/TEX_util.c index 10fe3bab26c..562072328a8 100644 --- a/source/blender/nodes/intern/TEX_util.c +++ b/source/blender/nodes/intern/TEX_util.c @@ -46,25 +46,32 @@ void tex_call_delegate(TexDelegate *dg, float *out, float *coord, short thread) dg->fn(out, coord, dg->node, dg->in, thread); } -void tex_input_vec(float *out, bNodeStack *in, float *coord, short thread) +void tex_input(float *out, int sz, bNodeStack *in, float *coord, short thread) { TexDelegate *dg = in->data; if(dg) { - tex_call_delegate(dg, out, coord, thread); + tex_call_delegate(dg, in->vec, coord, thread); - if(in->hasoutput && in->sockettype == SOCK_VALUE) { - out[1] = out[2] = out[0]; - out[3] = 1; - } - } - else { - QUATCOPY(out, in->vec); + if(in->hasoutput && in->sockettype == SOCK_VALUE) + in->vec[1] = in->vec[2] = in->vec[0]; } + memcpy(out, in->vec, sz * sizeof(float)); +} + +void tex_input_vec(float *out, bNodeStack *in, float *coord, short thread) +{ + tex_input(out, 3, in, coord, thread); } void tex_input_rgba(float *out, bNodeStack *in, float *coord, short thread) { - tex_input_vec(out, in, coord, thread); + tex_input(out, 4, in, coord, thread); + + if(in->hasoutput && in->sockettype == SOCK_VALUE) + { + out[1] = out[2] = out[0]; + out[3] = 1; + } if(in->hasoutput && in->sockettype == SOCK_VECTOR) { out[0] = out[0] * .5f + .5f; @@ -83,8 +90,8 @@ float tex_input_value(bNodeStack *in, float *coord, short thread) static void init_preview(bNode *node) { - int xsize = node->prvr.xmax - node->prvr.xmin; - int ysize = node->prvr.ymax - node->prvr.ymin; + int xsize = (int)(node->prvr.xmax - node->prvr.xmin); + int ysize = (int)(node->prvr.ymax - node->prvr.ymin); if(xsize == 0) { xsize = PREV_RES; diff --git a/source/blender/python/BPY_interface.c b/source/blender/python/BPY_interface.c index 331f72021f2..ec81de1f5e8 100644 --- a/source/blender/python/BPY_interface.c +++ b/source/blender/python/BPY_interface.c @@ -2403,7 +2403,7 @@ int BPY_is_spacehandler(Text *text, char spacetype) char *line = tline->line; /* Expected format: # SPACEHANDLER.SPACE.TYPE - * Ex: # SPACEHANDLER.VIEW3D.DRAW + * Exs: # SPACEHANDLER.VIEW3D.DRAW * The actual checks are forgiving, so slight variations also work. */ if (line && line[0] == '#' && strstr(line, "HANDLER")) { line++; /* skip '#' */ @@ -2411,11 +2411,19 @@ int BPY_is_spacehandler(Text *text, char spacetype) /* only done for 3D View right now, trivial to add for others: */ switch (spacetype) { case SPACE_VIEW3D: - if (strstr(line, "3D")) { /* VIEW3D, 3DVIEW */ + line = strstr(line, "3D"); /* VIEW3D, 3DVIEW */ + if (line) { if (strstr(line, "DRAW")) type = SPACEHANDLER_VIEW3D_DRAW; - else if (strstr(line, "EVENT")) type = SPACEHANDLER_VIEW3D_EVENT; + else { + line = strstr(line, "EVENT"); + if (line) { + if (strstr(line, "ALL")) { + type = SPACEHANDLER_VIEW3D_EVENT_ALL; + } else { type = SPACEHANDLER_VIEW3D_EVENT; } + } + } } - break; + break; } } } @@ -2464,7 +2472,6 @@ int BPY_add_spacehandler(Text *text, ScrArea *sa, char spacetype) if (handlertype) { ScriptLink *slink = &sa->scriptlink; void *stmp, *ftmp; - unsigned short space_event = SPACEHANDLER_VIEW3D_EVENT; /* extend slink */ @@ -2484,17 +2491,8 @@ int BPY_add_spacehandler(Text *text, ScrArea *sa, char spacetype) MEM_freeN(ftmp); } - switch (spacetype) { - case SPACE_VIEW3D: - if (handlertype == 1) space_event = SPACEHANDLER_VIEW3D_EVENT; - else space_event = SPACEHANDLER_VIEW3D_DRAW; - break; - default: - break; - } - slink->scripts[slink->totscript] = (ID *)text; - slink->flag[slink->totscript]= space_event; + slink->flag[slink->totscript]= handlertype; slink->totscript++; slink->actscript = slink->totscript; @@ -2508,6 +2506,7 @@ int BPY_do_spacehandlers( ScrArea *sa, unsigned short event, { ScriptLink *scriptlink; int retval = 0; + short slink_event, spacehandlers_match; PyGILState_STATE gilstate; if (!sa || !(G.f & G_DOSCRIPTLINKS)) return 0; @@ -2549,7 +2548,16 @@ int BPY_do_spacehandlers( ScrArea *sa, unsigned short event, EXPP_dict_set_item_str(g_blenderdict, "eventValue", PyInt_FromLong(eventValue)); /* now run all assigned space handlers for this space and space_event */ for( index = 0; index < scriptlink->totscript; index++ ) { - + + spacehandlers_match = 0; + + slink_event = scriptlink->flag[index]; + if( slink_event == space_event ) + spacehandlers_match = 1; + else if( ( space_event == SPACEHANDLER_VIEW3D_EVENT ) && + ( slink_event == SPACEHANDLER_VIEW3D_EVENT_ALL ) ) + spacehandlers_match = 1; + /* for DRAW handlers: */ if (event == 0) { glPushAttrib(GL_ALL_ATTRIB_BITS); @@ -2558,8 +2566,8 @@ int BPY_do_spacehandlers( ScrArea *sa, unsigned short event, glMatrixMode(GL_MODELVIEW); glPushMatrix(); } - - if( ( scriptlink->flag[index] == space_event ) && + + if( spacehandlers_match && ( scriptlink->scripts[index] != NULL ) ) { dict = CreateGlobalDictionary(); ret = RunPython( ( Text * ) scriptlink->scripts[index], dict ); diff --git a/source/blender/python/api2_2x/Blender.c b/source/blender/python/api2_2x/Blender.c index 47e7bcb2007..d09506f731b 100644 --- a/source/blender/python/api2_2x/Blender.c +++ b/source/blender/python/api2_2x/Blender.c @@ -1047,8 +1047,11 @@ void M_Blender_Init(void) if (SpaceHandlers) { BPy_constant *d = (BPy_constant *)SpaceHandlers; - PyConstant_Insert(d,"VIEW3D_EVENT",PyInt_FromLong(SPACEHANDLER_VIEW3D_EVENT)); + /* EVENT_ALL are reported as EVENT on key presses + * and EVENT_RELEASE on key releases */ PyConstant_Insert(d,"VIEW3D_DRAW", PyInt_FromLong(SPACEHANDLER_VIEW3D_DRAW)); + PyConstant_Insert(d,"VIEW3D_EVENT",PyInt_FromLong(SPACEHANDLER_VIEW3D_EVENT)); + PyConstant_Insert(d,"VIEW3D_EVENT_RELEASE",PyInt_FromLong(SPACEHANDLER_VIEW3D_EVENT_ALL)); PyModule_AddObject(module, "SpaceHandlers", SpaceHandlers); } diff --git a/source/blender/python/api2_2x/Constraint.c b/source/blender/python/api2_2x/Constraint.c index b0b9aa04a08..9ecec8eb973 100644 --- a/source/blender/python/api2_2x/Constraint.c +++ b/source/blender/python/api2_2x/Constraint.c @@ -1560,7 +1560,7 @@ static int script_setter( BPy_Constraint *self, int type, PyObject *value ) break; case EXPP_CONSTR_SCRIPT: { Text *text = (( BPy_Text * )value)->text; - if( !BPy_Object_Check( value ) ) + if( !BPy_Text_Check( value ) ) return EXPP_ReturnIntError( PyExc_TypeError, "expected BPy text argument" ); con->text = text; @@ -2291,6 +2291,7 @@ static PyObject *ConstraintSeq_remove( BPy_ConstraintSeq *self, BPy_Constraint * { bConstraint *con = locate_constr(self, value); bPoseChannel *active= NULL; + int tmpflag= 0; /* if we can't locate the constraint, return (exception already set) */ if (!con) @@ -2304,6 +2305,11 @@ static PyObject *ConstraintSeq_remove( BPy_ConstraintSeq *self, BPy_Constraint * if (active) active->bone->flag &= ~BONE_ACTIVE; self->pchan->bone->flag |= BONE_ACTIVE; } + + if(!(self->obj->flag & OB_POSEMODE)) { + self->obj->flag |= OB_POSEMODE; + tmpflag= 1; + } } /* del_constr_func() frees constraint + its data */ @@ -2314,6 +2320,8 @@ static PyObject *ConstraintSeq_remove( BPy_ConstraintSeq *self, BPy_Constraint * if (active) active->bone->flag |= BONE_ACTIVE; self->pchan->bone->flag &= ~BONE_ACTIVE; } + if(tmpflag) + self->obj->flag &= ~OB_POSEMODE; /* erase the link to the constraint */ value->con = NULL; diff --git a/source/blender/python/api2_2x/CurNurb.c b/source/blender/python/api2_2x/CurNurb.c index 63a1dccbc50..456f11e4a54 100644 --- a/source/blender/python/api2_2x/CurNurb.c +++ b/source/blender/python/api2_2x/CurNurb.c @@ -467,9 +467,6 @@ PyObject *CurNurb_append( BPy_CurNurb * self, PyObject * value ) PyObject *CurNurb_appendPointToNurb( Nurb * nurb, PyObject * value ) { - - int i; - int size; int npoints = nurb->pntsu; /* @@ -520,81 +517,58 @@ PyObject *CurNurb_appendPointToNurb( Nurb * nurb, PyObject * value ) } else if( PySequence_Check( value ) ) { - size = PySequence_Size( value ); -/* printf("\ndbg: got a sequence of size %d\n", size ); */ - if( size == 4 || size == 5 || size == 6) { - BPoint *tmp; - - tmp = nurb->bp; /* save old pts */ - - nurb->bp = - ( BPoint * ) MEM_mallocN( sizeof( BPoint ) * - ( npoints + 1 ), - "CurNurb_append1" ); - if( !nurb->bp ) - return ( EXPP_ReturnPyObjError - ( PyExc_MemoryError, - "allocation failed" ) ); - - memmove( nurb->bp, tmp, sizeof( BPoint ) * npoints ); - if( tmp ) - MEM_freeN( tmp ); - - ++nurb->pntsu; - /* initialize new BPoint from old */ - memcpy( nurb->bp + npoints, nurb->bp, - sizeof( BPoint ) ); - - for( i = 0; i < 4; ++i ) { - PyObject *item = PySequence_GetItem( value, i ); - - if (item == NULL) - return NULL; - - - nurb->bp[npoints].vec[i] = ( float ) PyFloat_AsDouble( item ); - Py_DECREF( item ); - } - - if (size >= 5) { - PyObject *item = PySequence_GetItem( value, 4 ); - - if (item == NULL) - return NULL; + float xco, yco, zco, wval, tilt=0.0f, radius=1.0f; + PyObject *args; + BPoint *tmp; + + if (PyTuple_Check(value)) { + args= value; + } + else { + args= PySequence_Tuple(value); + } + + if (!PyArg_ParseTuple(args, "ffff|ff", &xco, &yco, &zco, &wval, &tilt, &radius)) { + return EXPP_ReturnPyObjError( PyExc_TypeError, "expected a sequence of 4 to 6 floats" ); + } + + if (args != value) { + Py_DECREF(args); + } + tmp = nurb->bp; /* save old pts */ - nurb->bp[npoints].alfa = ( float ) PyFloat_AsDouble( item ); - Py_DECREF( item ); - } - else { - nurb->bp[npoints].alfa = 0.0f; - } - - if (size == 6) { - PyObject *item = PySequence_GetItem( value, 5 ); + nurb->bp = + ( BPoint * ) MEM_mallocN( sizeof( BPoint ) * + ( npoints + 1 ), + "CurNurb_append1" ); + if( !nurb->bp ) + return ( EXPP_ReturnPyObjError + ( PyExc_MemoryError, + "allocation failed" ) ); - if (item == NULL) - return NULL; + memmove( nurb->bp, tmp, sizeof( BPoint ) * npoints ); + if( tmp ) + MEM_freeN( tmp ); - nurb->bp[npoints].radius = ( float ) PyFloat_AsDouble( item ); - Py_DECREF( item ); - } - else { - nurb->bp[npoints].radius = 1.0f; - } - - nurb->bp[npoints].weight = 0.0; /* softbody weight TODO - add access to this, is zero elsewhere but through blender is 1.0 by default */ - - makeknots( nurb, 1, nurb->flagu >> 1 ); - - } else { - return EXPP_ReturnPyObjError( PyExc_TypeError, - "expected a sequence of 4 or 6 floats" ); - } + ++nurb->pntsu; + /* initialize new BPoint from old */ + memcpy( nurb->bp + npoints, nurb->bp, + sizeof( BPoint ) ); + + tmp= nurb->bp+npoints; + tmp->vec[0] = xco; + tmp->vec[1] = yco; + tmp->vec[2] = zco; + tmp->vec[3] = wval; + tmp->alfa = tilt; + tmp->radius = radius; + tmp->weight = 0.0; /* softbody weight TODO - add access to this, is zero elsewhere but through blender is 1.0 by default */ + + makeknots( nurb, 1, nurb->flagu >> 1 ); } else { /* bail with error */ - return EXPP_ReturnPyObjError( PyExc_TypeError, - "expected a sequence of 4 to 6 floats" ); + return EXPP_ReturnPyObjError( PyExc_TypeError, "expected a sequence of 4 to 6 floats" ); } diff --git a/source/blender/python/api2_2x/Curve.c b/source/blender/python/api2_2x/Curve.c index d1abde19de9..26208e600e6 100644 --- a/source/blender/python/api2_2x/Curve.c +++ b/source/blender/python/api2_2x/Curve.c @@ -822,7 +822,6 @@ static PyObject *Curve_appendNurb( BPy_Curve * self, PyObject * value ) new_nurb->bezt->f2 = SELECT; new_nurb->bezt->f3 = SELECT; new_nurb->bezt->hide = 0; - new_nurb->bezt->radius = 1.0; /* calchandlesNurb( new_nurb ); */ } else { /* set up bp */ new_nurb->pntsv = 1; @@ -832,7 +831,6 @@ static PyObject *Curve_appendNurb( BPy_Curve * self, PyObject * value ) new_nurb->flagv = 0; new_nurb->bp->f1 = 0; new_nurb->bp->hide = 0; - new_nurb->bp->radius = 1.0; new_nurb->knotsu = 0; /*makenots( new_nurb, 1, new_nurb->flagu >> 1); */ } diff --git a/source/blender/python/api2_2x/IDProp.c b/source/blender/python/api2_2x/IDProp.c index 07269e54c7c..6457cd07098 100644 --- a/source/blender/python/api2_2x/IDProp.c +++ b/source/blender/python/api2_2x/IDProp.c @@ -533,21 +533,16 @@ static PyObject *BPy_IDGroup_HasKey(BPy_IDProperty *self, PyObject *value) Py_RETURN_FALSE; } -static PyObject *BPy_IDGroup_Update(BPy_IDProperty *self, PyObject *vars) +static PyObject *BPy_IDGroup_Update(BPy_IDProperty *self, PyObject *value) { - PyObject *pyob, *pkey, *pval; + PyObject *pkey, *pval; Py_ssize_t i=0; - if (PySequence_Size(vars) != 1) - return EXPP_ReturnPyObjError( PyExc_TypeError, - "expected an object derived from dict."); - - pyob = PyTuple_GET_ITEM(vars, 0); - if (!PyDict_Check(pyob)) + if (!PyDict_Check(value)) return EXPP_ReturnPyObjError( PyExc_TypeError, "expected an object derived from dict."); - while (PyDict_Next(pyob, &i, &pkey, &pval)) { + while (PyDict_Next(value, &i, &pkey, &pval)) { BPy_IDGroup_Map_SetItem(self, pkey, pval); if (PyErr_Occurred()) return NULL; } @@ -571,7 +566,7 @@ static struct PyMethodDef BPy_IDGroup_methods[] = { "get the values associated with this group."}, {"has_key", (PyCFunction)BPy_IDGroup_HasKey, METH_O, "returns true if the group contains a key, false if not."}, - {"update", (PyCFunction)BPy_IDGroup_Update, METH_VARARGS, + {"update", (PyCFunction)BPy_IDGroup_Update, METH_O, "updates the values in the group with the values of another or a dict."}, {"convert_to_pyobject", (PyCFunction)BPy_IDGroup_ConvertToPy, METH_NOARGS, "return a purely python version of the group."}, diff --git a/source/blender/python/api2_2x/Mesh.c b/source/blender/python/api2_2x/Mesh.c index 32ddb464c88..42c80728bab 100644 --- a/source/blender/python/api2_2x/Mesh.c +++ b/source/blender/python/api2_2x/Mesh.c @@ -5390,9 +5390,9 @@ static PyObject *MFaceSeq_delete( BPy_MFaceSeq * self, PyObject *args ) /* see how many args we need to parse */ len = PySequence_Size( args ); - if( len < 1 ) - return EXPP_ReturnPyObjError( PyExc_TypeError, - "sequence must contain at least one int or MFace" ); + if( len < 1 ) { + Py_RETURN_NONE; + } face_table = MEM_callocN( len*sizeof( unsigned int ), "face_table" ); diff --git a/source/blender/python/api2_2x/Modifier.c b/source/blender/python/api2_2x/Modifier.c index 3bef0eead09..b43c810b435 100644 --- a/source/blender/python/api2_2x/Modifier.c +++ b/source/blender/python/api2_2x/Modifier.c @@ -909,18 +909,18 @@ static PyObject *displace_getter( BPy_Modifier * self, int type ) switch( type ) { case EXPP_MOD_TEXTURE: - if (md->texture) Texture_CreatePyObject( md->texture ); + if (md->texture) return Texture_CreatePyObject( md->texture ); else Py_RETURN_NONE; case EXPP_MOD_STRENGTH: return PyFloat_FromDouble( (double)md->strength ); case EXPP_MOD_DIRECTION: - PyInt_FromLong( md->direction ); + return PyInt_FromLong( md->direction ); case EXPP_MOD_VERTGROUP: return PyString_FromString( md->defgrp_name ) ; case EXPP_MOD_MID_LEVEL: return PyFloat_FromDouble( (double)md->midlevel ); case EXPP_MOD_MAPPING: - PyInt_FromLong( md->texmapping ); + return PyInt_FromLong( md->texmapping ); case EXPP_MOD_OBJECT: return Object_CreatePyObject( md->map_object ); case EXPP_MOD_UVLAYER: @@ -982,6 +982,41 @@ static int displace_setter( BPy_Modifier *self, int type, PyObject *value ) } } +static PyObject *shrinkwrap_getter( BPy_Modifier * self, int type ) +{ + ShrinkwrapModifierData *md = (ShrinkwrapModifierData *)(self->md); + + switch( type ) { + case EXPP_MOD_OBJECT: + return Object_CreatePyObject( md->target ); + default: + return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" ); + } +} + +static int shrinkwrap_setter( BPy_Modifier *self, int type, PyObject *value ) +{ + ShrinkwrapModifierData *md = (ShrinkwrapModifierData *)(self->md); + + switch( type ) { + case EXPP_MOD_OBJECT: { /* Only object for now */ + Object *ob_new=NULL; + if (value == Py_None) { + md->target = NULL; + } else if (BPy_Object_Check( value )) { + ob_new = ((( BPy_Object * )value)->object); + md->target = ob_new; + } else { + return EXPP_ReturnIntError( PyExc_TypeError, + "Expected an Object or None value" ); + } + return 0; + } + default: + return EXPP_ReturnIntError( PyExc_KeyError, "key not found" ); + } +} + /* static PyObject *uvproject_getter( BPy_Modifier * self, int type ) { @@ -1062,6 +1097,8 @@ static PyObject *Modifier_getData( BPy_Modifier * self, PyObject * key ) return edgesplit_getter( self, setting ); case eModifierType_Displace: return displace_getter( self, setting ); + case eModifierType_Shrinkwrap: + return shrinkwrap_getter( self, setting ); /*case eModifierType_UVProject: return uvproject_getter( self, setting );*/ case eModifierType_Hook: @@ -1132,6 +1169,8 @@ static int Modifier_setData( BPy_Modifier * self, PyObject * key, return edgesplit_setter( self, key_int, arg ); case eModifierType_Displace: return displace_setter( self, key_int, arg ); + case eModifierType_Shrinkwrap: + return shrinkwrap_setter( self, key_int, arg ); /*case eModifierType_UVProject: return uvproject_setter( self, key_int, arg );*/ case eModifierType_Hook: @@ -1550,6 +1589,22 @@ static PyObject *M_Modifier_TypeDict( void ) PyInt_FromLong( eModifierType_Cast ) ); PyConstant_Insert( d, "DISPLACE", PyInt_FromLong( eModifierType_Displace ) ); + PyConstant_Insert( d, "MESHDEFORM", + PyInt_FromLong( eModifierType_MeshDeform ) ); + PyConstant_Insert( d, "PARTICLESYSTEM", + PyInt_FromLong( eModifierType_ParticleSystem ) ); + PyConstant_Insert( d, "PARTICLEINSTANCE", + PyInt_FromLong( eModifierType_ParticleInstance ) ); + PyConstant_Insert( d, "EXPLODE", + PyInt_FromLong( eModifierType_Explode ) ); + PyConstant_Insert( d, "CLOTH", + PyInt_FromLong( eModifierType_Cloth ) ); + PyConstant_Insert( d, "BEVEL", + PyInt_FromLong( eModifierType_Bevel ) ); + PyConstant_Insert( d, "SHRINKWRAP", + PyInt_FromLong( eModifierType_Shrinkwrap ) ); + PyConstant_Insert( d, "SHRINKWRAP", + PyInt_FromLong( eModifierType_Shrinkwrap ) ); } return S; } diff --git a/source/blender/python/api2_2x/NMesh.c b/source/blender/python/api2_2x/NMesh.c index 2e82c55155f..22f619c5f31 100644 --- a/source/blender/python/api2_2x/NMesh.c +++ b/source/blender/python/api2_2x/NMesh.c @@ -1476,7 +1476,7 @@ static PyObject *NMesh_update( PyObject *self, PyObject *a, PyObject *kwd ) static PyObject *NMesh_getVertexInfluences( PyObject * self, PyObject * args ) { int index; - PyObject *influence_list = NULL; + PyObject *influence_list = NULL, *item; Object *object = ( ( BPy_NMesh * ) self )->object; Mesh *me = ( ( BPy_NMesh * ) self )->mesh; @@ -1516,9 +1516,11 @@ static PyObject *NMesh_getVertexInfluences( PyObject * self, PyObject * args ) for( i = 0; i < totinfluences; i++, sweight++ ) { bDeformGroup *defgroup = (bDeformGroup *) BLI_findlink( &object->defbase, sweight->def_nr ); - if( defgroup ) - PyList_Append( influence_list, Py_BuildValue( "[sf]", - defgroup->name, sweight->weight ) ); + if( defgroup ) { + item = Py_BuildValue( "[sf]", defgroup->name, sweight->weight ); + PyList_Append( influence_list, item); + Py_DECREF(item); + } } } diff --git a/source/blender/python/api2_2x/SurfNurb.c b/source/blender/python/api2_2x/SurfNurb.c index 65bd04de14d..deee6c07793 100644 --- a/source/blender/python/api2_2x/SurfNurb.c +++ b/source/blender/python/api2_2x/SurfNurb.c @@ -482,7 +482,7 @@ static int SurfNurb_setCyclicV( BPy_SurfNurb * self, PyObject * value ) self->nurb->flagv |= CU_CYCLIC; else self->nurb->flagv &= ~CU_CYCLIC; - makeknots( self->nurb, 2, self->nurb->flagu >> 1 ); + makeknots( self->nurb, 2, self->nurb->flagv >> 1 ); return 0; } diff --git a/source/blender/python/api2_2x/Sys.c b/source/blender/python/api2_2x/Sys.c index 16d879c3032..936014d87ed 100644 --- a/source/blender/python/api2_2x/Sys.c +++ b/source/blender/python/api2_2x/Sys.c @@ -59,6 +59,7 @@ static PyObject *M_sys_time( PyObject * self ); static PyObject *M_sys_sleep( PyObject * self, PyObject * args ); static PyObject *M_sys_expandpath( PyObject *self, PyObject *value); static PyObject *M_sys_cleanpath( PyObject *self, PyObject *value); +static PyObject *M_sys_relpath( PyObject *self, PyObject *args); /*****************************************************************************/ /* The following string definitions are used for documentation strings. */ @@ -128,6 +129,9 @@ If the special chars are not found in the given path, it is simply returned."; static char M_sys_cleanpath_doc[] = "(path) - Removes parts of a path that are not needed paths such as '../foo/../bar/' and '//./././'"; +static char M_sys_relpath_doc[] = +"(path, start=\"//\") - Returns the path relative to the current blend file or start if spesified"; + /*****************************************************************************/ /* Python method structure definition for Blender.sys module: */ /*****************************************************************************/ @@ -144,6 +148,7 @@ struct PyMethodDef M_sys_methods[] = { {"time", ( PyCFunction ) M_sys_time, METH_NOARGS, M_sys_time_doc}, {"expandpath", M_sys_expandpath, METH_O, M_sys_expandpath_doc}, {"cleanpath", M_sys_cleanpath, METH_O, M_sys_cleanpath_doc}, + {"relpath", M_sys_relpath, METH_VARARGS, M_sys_relpath_doc}, {NULL, NULL, 0, NULL} }; @@ -231,9 +236,8 @@ static PyObject *M_sys_join( PyObject * self, PyObject * args ) char filename[FILE_MAXDIR + FILE_MAXFILE]; int pathlen = 0, namelen = 0; - if( !PyArg_ParseTuple( args, "ss", &path, &name ) ) - return EXPP_ReturnPyObjError( PyExc_TypeError, - "expected string argument" ); + if( !PyArg_ParseTuple( args, "ss:Blender.sys.join", &path, &name ) ) + return NULL; pathlen = strlen( path ) + 1; namelen = strlen( name ) + 1; /* + 1 to account for '\0' for BLI_strncpy */ @@ -300,10 +304,8 @@ static PyObject *M_sys_makename( PyObject * self, PyObject * args, char *dot = NULL, *p = NULL, basename[FILE_MAXDIR + FILE_MAXFILE]; int n, len, lenext = 0; - if( !PyArg_ParseTupleAndKeywords( args, kw, "|ssi", kwlist, - &path, &ext, &strip ) ) - return EXPP_ReturnPyObjError( PyExc_TypeError, - "expected one or two strings and an int (or nothing) as arguments" ); + if( !PyArg_ParseTupleAndKeywords( args, kw, "|ssi:Blender.sys.makename", kwlist, &path, &ext, &strip ) ) + return NULL; len = strlen( path ) + 1; /* + 1 to consider ending '\0' */ if( ext ) @@ -350,13 +352,12 @@ static PyObject *M_sys_sleep( PyObject * self, PyObject * args ) { int millisecs = 10; - if( !PyArg_ParseTuple( args, "|i", &millisecs ) ) - return EXPP_ReturnPyObjError( PyExc_TypeError, - "expected int argument" ); + if( !PyArg_ParseTuple( args, "|i:Blender.sys.sleep", &millisecs ) ) + return NULL; PIL_sleep_ms( millisecs ); - - return EXPP_incr_ret( Py_None ); + + Py_RETURN_NONE; } static PyObject *M_sys_exists( PyObject * self, PyObject * value ) @@ -419,3 +420,19 @@ static PyObject *M_sys_cleanpath( PyObject * self, PyObject * value ) return PyString_FromString(cleaned); } + +static PyObject *M_sys_relpath( PyObject * self, PyObject * args ) +{ + char *base = G.sce; + char *path; + char relpath[FILE_MAXDIR + FILE_MAXFILE]; + + if( !PyArg_ParseTuple( args, "s|s:Blender.sys.relpath", &path, &base ) ) + return NULL; + + strncpy(relpath, path, sizeof(relpath)); + BLI_makestringcode(base, relpath); + + return PyString_FromString(relpath); +} + diff --git a/source/blender/python/api2_2x/doc/API_related.py b/source/blender/python/api2_2x/doc/API_related.py index dcd2bdd1e60..c5b0aafe9f0 100644 --- a/source/blender/python/api2_2x/doc/API_related.py +++ b/source/blender/python/api2_2x/doc/API_related.py @@ -184,11 +184,11 @@ Introduction: Space Handler script links: --------------------------- - This is a new kind of script linked to spaces in a given window. Right now - only the 3D View has the necessary hooks, but the plan is to add access to - other types, too. Just to clarify naming conventions: in Blender, a screen - is partitioned in windows (also called areas) and each window can show any - space. Spaces are: 3D View, Text Editor, Scripts, Buttons, User Preferences, + These are scripts linked to spaces in a given window. Right now + only the 3D View has the necessary hooks. Just to clarify naming + conventions: in Blender, a screen is partitioned in windows (also + called areas) and each window can show any space. + Spaces are: 3D View, Text Editor, Scripts, Buttons, User Preferences, Oops, etc. Space handlers are texts in the Text Editor, like other script links, but they @@ -196,12 +196,16 @@ Introduction: text file}} must inform: 1. that they are space handlers; 2. the space they belong to; - 3. whether they are EVENT or DRAW handlers. + 3. whether they are EVENT, EVENT_RELEASE (EVENT ones reporting key release events) or DRAW handlers. Example header for a 3D View EVENT handler:: # SPACEHANDLER.VIEW3D.EVENT + Example header for a 3D View EVENT handler that also receives release events:: + + # SPACEHANDLER.VIEW3D.EVENT.ALL + Example header for a 3D View DRAW handler:: # SPACEHANDLER.VIEW3D.DRAW @@ -216,6 +220,10 @@ Introduction: - process it (the script must set Blender.event to None then); - ignore it. + EVENT ALL space handlers (header: # SPACEHANDLER.VIEW3D.EVENT.ALL) are executed + both for key presses (Blender.event = Blender.SpaceHandlers.VIEW3D_EVENT) and + for key releases (Blender.event = Blender.SpaceHandlers.VIEW3D_EVENT_RELEASE). + Setting C{Blender.event = None} tells Blender not to go on processing itself the event, because it was grabbed by the script. @@ -248,7 +256,7 @@ Introduction: - B{bylink} is the same: True if the script is running as a script link; - B{link}: integer from the L{Blender}.SpaceHandlers constant dictionary, tells what space this handler belongs to and the handler's type - (EVENT, DRAW); + (EVENT, EVENT_RELEASE, DRAW); - B{event}: - EVENT handlers: an input event (check keys and mouse events in L{Draw}) to be processed or ignored; @@ -258,6 +266,7 @@ Introduction: presses (since we don't pass releases) as 1 and mouse movements (Draw.MOUSE.X and Draw.MOUSE.Y) as the current x or y coordinate, for example; + - EVENT_RELEASE handlers (EVENT handlers executed during key release events): 0; - DRAW handlers: 0 always. B{Guidelines (important)}: diff --git a/source/blender/python/api2_2x/doc/Modifier.py b/source/blender/python/api2_2x/doc/Modifier.py index 47f72e566b2..03b868d3605 100644 --- a/source/blender/python/api2_2x/doc/Modifier.py +++ b/source/blender/python/api2_2x/doc/Modifier.py @@ -129,7 +129,7 @@ Example:: - UVLAYER - Used for Displace only - MID_LEVEL - Used for Displace only (float [0.0, 1.0], default: 0.5) - STRENGTH - Used for Displace only (float [-1000.0, 1000.0, default: 1.0) - - TEXTURE - Used for Displace only (string) + - TEXTURE - Used for Displace only (Texture object) - MAPPING - Used for Displace only - DIRECTION - Used for Displace only diff --git a/source/blender/python/api2_2x/doc/Sys.py b/source/blender/python/api2_2x/doc/Sys.py index d7c62f2cb02..5801913646e 100644 --- a/source/blender/python/api2_2x/doc/Sys.py +++ b/source/blender/python/api2_2x/doc/Sys.py @@ -174,3 +174,15 @@ def cleanpath (path): @rtype: string @return: the cleaned (if necessary) path. """ + +def relpath (path, start="//"): + """ + Returns the path relative to the start, + @note: If the path can be made relative it well start with "//", this is spesific to blender and should be converted to "./" for use as a system path. + @type path: string + @param path: a path name. + @type start: string + @param start: optional argument for the base path, the current blend files base path is used omitted + @rtype: string + @return: The path relative to start + """
\ No newline at end of file diff --git a/source/blender/python/api2_2x/sceneRender.c b/source/blender/python/api2_2x/sceneRender.c index 4e1051176fd..a0087689885 100644 --- a/source/blender/python/api2_2x/sceneRender.c +++ b/source/blender/python/api2_2x/sceneRender.c @@ -1889,10 +1889,10 @@ static PyObject *RenderData_getFloatAttr( BPy_RenderData *self, void *type ) param = self->renderContext->bake_biasdist; break; case EXPP_RENDER_ATTR_ASPECTX: - param = (long)self->renderContext->xasp; + param = self->renderContext->xasp; break; case EXPP_RENDER_ATTR_ASPECTY: - param = (long)self->renderContext->yasp; + param = self->renderContext->yasp; break; default: return EXPP_ReturnPyObjError( PyExc_RuntimeError, diff --git a/source/blender/python/api2_2x/sceneSequence.c b/source/blender/python/api2_2x/sceneSequence.c index c7daea19fe7..afcc8e0588d 100644 --- a/source/blender/python/api2_2x/sceneSequence.c +++ b/source/blender/python/api2_2x/sceneSequence.c @@ -43,6 +43,7 @@ #include "BIF_editsound.h" // RFS: sound_open_hdaudio #include "BLI_blenlib.h" #include "BSE_sequence.h" +#include "BSE_seqeffects.h" #include "Ipo.h" #include "blendef.h" /* CLAMP */ #include "BKE_utildefines.h" @@ -53,7 +54,8 @@ #include "IMB_imbuf_types.h" // RFS: IB_rect #include "IMB_imbuf.h" // RFS: IMB_anim_get_duration -enum seq_consts { +enum seq_consts +{ EXPP_SEQ_ATTR_TYPE = 0, EXPP_SEQ_ATTR_CHAN, EXPP_SEQ_ATTR_LENGTH, @@ -61,7 +63,23 @@ enum seq_consts { EXPP_SEQ_ATTR_STARTOFS, EXPP_SEQ_ATTR_ENDOFS, EXPP_SEQ_ATTR_STARTSTILL, - EXPP_SEQ_ATTR_ENDSTILL + EXPP_SEQ_ATTR_ENDSTILL, + EXPP_SEQ_ATTR_STARTDISP, + EXPP_SEQ_ATTR_ENDDISP +}; + +enum seq_effect_consts +{ + /* speed */ + EXPP_SEQ_ATTR_EFFECT_GLOBAL_SPEED, + EXPP_SEQ_ATTR_EFFECT_IPO_IS_VELOCITY, + EXPP_SEQ_ATTR_EFFECT_FRAME_BLENDING, + EXPP_SEQ_ATTR_EFFECT_NORMALIZE_IPO_0_1, + + /* wipe */ + EXPP_SEQ_ATTR_EFFECT_ANGLE, + EXPP_SEQ_ATTR_EFFECT_BLUR, + EXPP_SEQ_ATTR_EFFECT_WIPE_IN }; @@ -83,36 +101,39 @@ returns None if notfound.\nIf 'name' is not specified, it returns a list of all /*****************************************************************************/ /* Python BPy_Sequence methods table: */ /*****************************************************************************/ -static PyObject *Sequence_copy( BPy_Sequence * self ); -static PyObject *Sequence_new( BPy_Sequence * self, PyObject * args ); -static PyObject *Sequence_remove( BPy_Sequence * self, PyObject * args ); -static PyObject *Sequence_rebuildProxy( BPy_Sequence * self ); +static PyObject *Sequence_copy(BPy_Sequence * self); +static PyObject *Sequence_update(BPy_Sequence * self, PyObject *args); +static PyObject *Sequence_new(BPy_Sequence * self, PyObject * args); +static PyObject *Sequence_remove(BPy_Sequence * self, PyObject * args); +static PyObject *Sequence_rebuildProxy(BPy_Sequence * self); -static PyObject *SceneSeq_new( BPy_SceneSeq * self, PyObject * args ); -static PyObject *SceneSeq_remove( BPy_SceneSeq * self, PyObject * args ); -static void intern_pos_update(Sequence * seq); +static PyObject *SceneSeq_new(BPy_SceneSeq * self, PyObject * args); +static PyObject *SceneSeq_remove(BPy_SceneSeq * self, PyObject * args); +static void intern_pos_update(Sequence * seq); static PyMethodDef BPy_Sequence_methods[] = { /* name, method, flags, doc */ - {"new", ( PyCFunction ) Sequence_new, METH_VARARGS, - "(data) - Return a new sequence."}, - {"remove", ( PyCFunction ) Sequence_remove, METH_VARARGS, - "(data) - Remove a strip."}, - {"__copy__", ( PyCFunction ) Sequence_copy, METH_NOARGS, - "() - Return a copy of the sequence containing the same objects."}, - {"copy", ( PyCFunction ) Sequence_copy, METH_NOARGS, - "() - Return a copy of the sequence containing the same objects."}, - {"rebuildProxy", ( PyCFunction ) Sequence_rebuildProxy, METH_VARARGS, - "() - Rebuild the active strip's Proxy."}, + {"new", (PyCFunction) Sequence_new, METH_VARARGS, + "(data) - Return a new sequence."}, + {"remove", (PyCFunction) Sequence_remove, METH_VARARGS, + "(data) - Remove a strip."}, + {"__copy__", (PyCFunction) Sequence_copy, METH_NOARGS, + "() - Return a copy of the sequence containing the same objects."}, + {"copy", (PyCFunction) Sequence_copy, METH_NOARGS, + "() - Return a copy of the sequence containing the same objects."}, + {"update", (PyCFunction) Sequence_update, METH_VARARGS, + "() - Force and update of the sequence strip"}, + {"rebuildProxy", (PyCFunction) Sequence_rebuildProxy, METH_VARARGS, + "() - Rebuild the active strip's Proxy."}, {NULL, NULL, 0, NULL} }; static PyMethodDef BPy_SceneSeq_methods[] = { /* name, method, flags, doc */ - {"new", ( PyCFunction ) SceneSeq_new, METH_VARARGS, - "(data) - Return a new sequence."}, - {"remove", ( PyCFunction ) SceneSeq_remove, METH_VARARGS, - "(data) - Remove a strip."}, + {"new", (PyCFunction) SceneSeq_new, METH_VARARGS, + "(data) - Return a new sequence."}, + {"remove", (PyCFunction) SceneSeq_remove, METH_VARARGS, + "(data) - Remove a strip."}, {NULL, NULL, 0, NULL} }; @@ -120,76 +141,238 @@ static PyMethodDef BPy_SceneSeq_methods[] = { static PyObject *NewSeq_internal(ListBase *seqbase, PyObject * args, Scene *sce) { PyObject *py_data = NULL; - + Sequence *seq; + PyObject *pyob1 = NULL, *pyob2 = NULL, *pyob3 = NULL; /* for effects */ + int type; + int a; Strip *strip; StripElem *se; int start, machine; - - if( !PyArg_ParseTuple( args, "Oii", &py_data, &start, &machine ) ) - return EXPP_ReturnPyObjError( PyExc_ValueError, - "expect sequence data then 2 ints - (seqdata, start, track)" ); - + + if (!PyArg_ParseTuple(args, "Oii", &py_data, &start, &machine)) + return EXPP_ReturnPyObjError(PyExc_ValueError, + "expect sequence data then 2 ints - (seqdata, start, track)"); + + if (machine < 1 || machine >= MAXSEQ) + { + return EXPP_ReturnPyObjError(PyExc_ValueError, + "track out of range"); + } + seq = alloc_sequence(seqbase, start, machine); /* warning, this sets last */ - - if (PyTuple_Check(py_data) && PyTuple_GET_SIZE(py_data) == 2) { + + + if (PyList_Check(py_data)) /* new metastrip, list of seqs */ + { + /* Warning, no checks for audio which should not be allowed, or a blank metaseq if an empty list */ + int fail= 0; + Sequence *seq_iter; + PyObject *item; + seq->type= SEQ_META; + + + for(a=PyList_GET_SIZE(py_data)-1; a >= 0; a--) { + item= PyList_GET_ITEM(py_data, a); + if (!BPy_Sequence_Check(item)) { /* ignore non seq types */ + fail= 1; + break; + } + + seq_iter = ((BPy_Sequence *) item)->seq; + if (BLI_findindex(seqbase, seq_iter) == -1) { + fail= 2; + break; + } + } + + if (fail) { + BLI_remlink(seqbase, seq); + free_sequence(seq); + + if (fail==1) + return EXPP_ReturnPyObjError(PyExc_ValueError, "One of more of the list items was not a sequence strip"); + else + return EXPP_ReturnPyObjError(PyExc_ValueError, "One of more of the list items sequence strips is not in this meta or scene"); + } + + + for(a=PyList_GET_SIZE(py_data)-1; a >= 0; a--) { + item= PyList_GET_ITEM(py_data, a); + seq_iter = ((BPy_Sequence *) item)->seq; + BLI_remlink(seqbase, seq_iter); + BLI_addtail(&seq->seqbase, seq_iter); + } + + clear_last_seq(); /* just incase */ + calc_sequence(seq); + + seq->strip= MEM_callocN(sizeof(Strip), "metastrip"); + seq->strip->len= seq->len; + seq->strip->us= 1; + } + else if (PyTuple_Check(py_data) && PyTuple_GET_SIZE(py_data) >= 2 && BPy_Sequence_Check(PyTuple_GET_ITEM(py_data, 1))) + { + + struct SeqEffectHandle sh; + Sequence *seq1, *seq2 = NULL, *seq3 = NULL; /* for effects */ + + if (!PyArg_ParseTuple(py_data, "iO!|O!O!", &type, &Sequence_Type, &pyob1, &Sequence_Type, &pyob2, &Sequence_Type, &pyob3)) + { + BLI_remlink(seqbase, seq); + free_sequence(seq); + + return EXPP_ReturnPyObjError(PyExc_ValueError, + "effect stripts expected an effect type int and 1 to 3 sequence strips"); + } + + + seq1 = ((BPy_Sequence *) pyob1)->seq; + if (pyob2) seq2 = ((BPy_Sequence *) pyob2)->seq; + if (pyob3) seq3 = ((BPy_Sequence *) pyob3)->seq; + + if (type <= SEQ_EFFECT || type > SEQ_EFFECT_MAX || type == SEQ_PLUGIN) + { + BLI_remlink(seqbase, seq); + free_sequence(seq); + + return EXPP_ReturnPyObjError(PyExc_ValueError, + "sequencer type out of range, expected a value from 9 to 29, plugins not supported"); + } + + + if (BLI_findindex(seqbase, seq1) == -1 || (seq2 && BLI_findindex(seqbase, seq2) == -1) || (seq3 && BLI_findindex(seqbase, seq3) == -1)) + { + BLI_remlink(seqbase, seq); + free_sequence(seq); + + return EXPP_ReturnPyObjError(PyExc_ValueError, + "one of the given effect sequences wasnt in accessible at the same level as the sequence being added"); + } + + if ((seq2 && seq2 == seq1) || (seq3 && (seq3 == seq1 || seq3 == seq2))) + { + BLI_remlink(seqbase, seq); + free_sequence(seq); + + return EXPP_ReturnPyObjError(PyExc_ValueError, + "2 or more of the sequence arguments were the same"); + + } + + /* allocate and initialize */ + seq->type = type; + + sh = get_sequence_effect(seq); + + seq->seq1 = seq1; + seq->seq2 = seq2; + seq->seq3 = seq3; + + sh.init(seq); + + if (!seq1) + { + seq->len = 1; + seq->startstill = 25; + seq->endstill = 24; + } + + calc_sequence(seq); + + seq->strip = strip = MEM_callocN(sizeof (Strip), "strip"); + strip->len = seq->len; + strip->us = 1; + if (seq->len > 0) + strip->stripdata = MEM_callocN(seq->len * sizeof (StripElem), "stripelem"); + +#if 0 + /* initialize plugin */ + if (newseq->type == SEQ_PLUGIN) + { + sh.init_plugin(seq, str); + + if (newseq->plugin == 0) + { + BLI_remlink(ed->seqbasep, seq); + free_sequence(seq); + return 0; + } + } +#endif + + update_changed_seq_and_deps(seq, 1, 1); + + } + else if (PyTuple_Check(py_data) && PyTuple_GET_SIZE(py_data) == 2) + { /* Image */ PyObject *list; char *name; - - if (!PyArg_ParseTuple( py_data, "sO!", &name, &PyList_Type, &list)) { + + if (!PyArg_ParseTuple(py_data, "sO!", &name, &PyList_Type, &list)) + { BLI_remlink(seqbase, seq); - MEM_freeN(seq); - - return EXPP_ReturnPyObjError( PyExc_ValueError, - "images data needs to be a tuple of a string and a list of images - (path, [filenames...])" ); + free_sequence(seq); + + return EXPP_ReturnPyObjError(PyExc_ValueError, + "images data needs to be a tuple of a string and a list of images - (path, [filenames...])"); } - - seq->type= SEQ_IMAGE; - - seq->len = PyList_Size( list ); - + + seq->type = SEQ_IMAGE; + + seq->len = PyList_Size(list); + /* strip and stripdata */ - seq->strip= strip= MEM_callocN(sizeof(Strip), "strip"); - strip->len= seq->len; - strip->us= 1; - strncpy(strip->dir, name, FILE_MAXDIR-1); - strip->stripdata= se= MEM_callocN(seq->len*sizeof(StripElem), "stripelem"); - - for(a=0; a<seq->len; a++) { - name = PyString_AsString(PyList_GetItem( list, a )); - strncpy(se->name, name, FILE_MAXFILE-1); + seq->strip = strip = MEM_callocN(sizeof (Strip), "strip"); + strip->len = seq->len; + strip->us = 1; + strncpy(strip->dir, name, FILE_MAXDIR - 1); + strip->stripdata = se = MEM_callocN(seq->len * sizeof (StripElem), "stripelem"); + + for (a = 0; a < seq->len; a++) + { + name = PyString_AsString(PyList_GetItem(list, a)); + strncpy(se->name, name, FILE_MAXFILE - 1); se++; - } - } else if (PyTuple_Check(py_data) && PyTuple_GET_SIZE(py_data) == 3) { - float r,g,b; + } + } + else if (PyTuple_Check(py_data) && PyTuple_GET_SIZE(py_data) == 3) + { + float r, g, b; SolidColorVars *colvars; - seq->effectdata = MEM_callocN(sizeof(struct SolidColorVars), "solidcolor"); - colvars = (SolidColorVars *)seq->effectdata; - - if (!PyArg_ParseTuple( py_data, "fff", &r, &g, &b)) { - return EXPP_ReturnPyObjError( PyExc_ValueError, - "color needs to be a tuple of 3 floats - (r,g,b)" ); + + if (!PyArg_ParseTuple(py_data, "fff", &r, &g, &b)) + { + BLI_remlink(seqbase, seq); + free_sequence(seq); + return EXPP_ReturnPyObjError(PyExc_ValueError, + "color needs to be a tuple of 3 floats - (r,g,b)"); } - - seq->type= SEQ_COLOR; - - CLAMP(r,0,1); - CLAMP(g,0,1); - CLAMP(b,0,1); - + + seq->effectdata = MEM_callocN(sizeof (struct SolidColorVars), "solidcolor"); + colvars = (SolidColorVars *) seq->effectdata; + + seq->type = SEQ_COLOR; + + CLAMP(r, 0, 1); + CLAMP(g, 0, 1); + CLAMP(b, 0, 1); + colvars->col[0] = r; colvars->col[1] = b; colvars->col[2] = g; - + /* basic defaults */ - seq->strip= strip= MEM_callocN(sizeof(Strip), "strip"); + seq->strip = strip = MEM_callocN(sizeof (Strip), "strip"); strip->len = seq->len = 1; - strip->us= 1; - strip->stripdata= se= MEM_callocN(seq->len*sizeof(StripElem), "stripelem"); - - } else if (PyTuple_Check(py_data) && PyTuple_GET_SIZE(py_data) == 4) { + strip->us = 1; + strip->stripdata = se = MEM_callocN(seq->len * sizeof (StripElem), "stripelem"); + + } + else if (PyTuple_Check(py_data) && PyTuple_GET_SIZE(py_data) == 4) + { // MOVIE or AUDIO_HD char *filename; char *dir; @@ -197,150 +380,159 @@ static PyObject *NewSeq_internal(ListBase *seqbase, PyObject * args, Scene *sce) char *type; int totframe; - if (!PyArg_ParseTuple( py_data, "ssss", &filename, &dir, &fullpath, &type )) { + if (!PyArg_ParseTuple(py_data, "ssss", &filename, &dir, &fullpath, &type)) + { BLI_remlink(seqbase, seq); - MEM_freeN(seq); - - return EXPP_ReturnPyObjError( PyExc_ValueError, - "movie/audio hd data needs to be a tuple of a string and a list of images - (filename, dir, fullpath, type)" ); + free_sequence(seq); + + return EXPP_ReturnPyObjError(PyExc_ValueError, + "movie/audio hd data needs to be a tuple of a string and a list of images - (filename, dir, fullpath, type)"); } // RFS - Attempting to support Movie and Audio (HD) strips #define RFS #ifdef RFS // Movie strips - if( strcmp( type, "movie" ) == 0 ) + if (strcmp(type, "movie") == 0) { /* open it as an animation */ struct anim * an = openanim(fullpath, IB_rect); - if(an==0) { + if (an == 0) + { BLI_remlink(seqbase, seq); - MEM_freeN(seq); - - return EXPP_ReturnPyObjError( PyExc_ValueError, - "invalid movie strip" ); + free_sequence(seq); + + return EXPP_ReturnPyObjError(PyExc_ValueError, + "invalid movie strip"); } /* get the length in frames */ - totframe = IMB_anim_get_duration( an ); + totframe = IMB_anim_get_duration(an); /* set up sequence */ - seq->type= SEQ_MOVIE; - seq->len= totframe; - seq->anim= an; + seq->type = SEQ_MOVIE; + seq->len = totframe; + seq->anim = an; seq->anim_preseek = IMB_anim_get_preseek(an); calc_sequence(seq); /* strip and stripdata */ - seq->strip= strip= MEM_callocN(sizeof(Strip), "strip"); - strip->len= totframe; - strip->us= 1; - strncpy(strip->dir, dir, FILE_MAXDIR-1); // ???? - strip->stripdata= se= MEM_callocN(sizeof(StripElem), "stripelem"); + seq->strip = strip = MEM_callocN(sizeof (Strip), "strip"); + strip->len = totframe; + strip->us = 1; + strncpy(strip->dir, dir, FILE_MAXDIR - 1); // ???? + strip->stripdata = se = MEM_callocN(sizeof (StripElem), "stripelem"); /* name movie in first strip */ - strncpy(se->name, filename, FILE_MAXFILE-1); // ???? + strncpy(se->name, filename, FILE_MAXFILE - 1); // ???? } // Audio (HD) strips - if( strcmp( type, "audio_hd" ) == 0 ) + if (strcmp(type, "audio_hd") == 0) { struct hdaudio *hdaudio; - totframe= 0; + totframe = 0; /* is it a sound file? */ - hdaudio = sound_open_hdaudio( fullpath ); - if(hdaudio==0) { + hdaudio = sound_open_hdaudio(fullpath); + if (hdaudio == 0) + { BLI_remlink(seqbase, seq); - MEM_freeN(seq); - - return EXPP_ReturnPyObjError( PyExc_ValueError, - fullpath ); + free_sequence(seq); + + return EXPP_ReturnPyObjError(PyExc_ValueError, + fullpath); } - totframe= sound_hdaudio_get_duration(hdaudio, FPS); + totframe = sound_hdaudio_get_duration(hdaudio, FPS); /* set up sequence */ - seq->type= SEQ_HD_SOUND; - seq->len= totframe; - seq->hdaudio= hdaudio; + seq->type = SEQ_HD_SOUND; + seq->len = totframe; + seq->hdaudio = hdaudio; calc_sequence(seq); /* strip and stripdata - same as for MOVIE */ - seq->strip= strip= MEM_callocN(sizeof(Strip), "strip"); - strip->len= totframe; - strip->us= 1; - strncpy(strip->dir, dir, FILE_MAXDIR-1); // ???? - strip->stripdata= se= MEM_callocN(sizeof(StripElem), "stripelem"); + seq->strip = strip = MEM_callocN(sizeof (Strip), "strip"); + strip->len = totframe; + strip->us = 1; + strncpy(strip->dir, dir, FILE_MAXDIR - 1); // ???? + strip->stripdata = se = MEM_callocN(sizeof (StripElem), "stripelem"); /* name movie in first strip */ - strncpy(se->name, filename, FILE_MAXFILE-1); // ???? + strncpy(se->name, filename, FILE_MAXFILE - 1); // ???? } #endif - } else if (BPy_Sound_Check(py_data)) { + } + else if (BPy_Sound_Check(py_data)) + { /* RAM sound */ int totframe; - bSound *sound = (( BPy_Sound * )py_data)->sound; - - seq->type= SEQ_RAM_SOUND; + bSound *sound = ((BPy_Sound *) py_data)->sound; + + seq->type = SEQ_RAM_SOUND; seq->sound = sound; - - totframe= (int) ( ((float)(sound->streamlen-1)/( (float)sce->audio.mixrate*4.0 ))* (float)sce->r.frs_sec / sce->r.frs_sec_base); - + + totframe = (int) (((float) (sound->streamlen - 1) / ((float) sce->audio.mixrate * 4.0))* (float) sce->r.frs_sec / sce->r.frs_sec_base); + sound->flags |= SOUND_FLAGS_SEQUENCE; - + /* strip and stripdata */ - seq->strip= strip= MEM_callocN(sizeof(Strip), "strip"); - strip->len= totframe; - strip->us= 1; - strncpy(strip->dir, sound->name, FILE_MAXDIR-1); - strip->stripdata= se= MEM_callocN(sizeof(StripElem), "stripelem"); + seq->strip = strip = MEM_callocN(sizeof (Strip), "strip"); + strip->len = totframe; + strip->us = 1; + strncpy(strip->dir, sound->name, FILE_MAXDIR - 1); + strip->stripdata = se = MEM_callocN(sizeof (StripElem), "stripelem"); /* name sound in first strip */ - strncpy(se->name, sound->name, FILE_MAXFILE-1); - - } else if (BPy_Scene_Check(py_data)) { + strncpy(se->name, sound->name, FILE_MAXFILE - 1); + + } + else if (BPy_Scene_Check(py_data)) + { /* scene */ - Scene *sceseq = ((BPy_Scene *)py_data)->scene; - - seq->type= SEQ_SCENE; - seq->scene= sceseq; - + Scene *sceseq = ((BPy_Scene *) py_data)->scene; + + seq->type = SEQ_SCENE; + seq->scene = sceseq; + /*seq->sfra= sce->r.sfra;*/ - seq->len= sceseq->r.efra - sceseq->r.sfra + 1; - - seq->strip= strip= MEM_callocN(sizeof(Strip), "strip"); - strncpy(seq->name + 2, sceseq->id.name + 2, - sizeof(seq->name) - 2); - strip->len= seq->len; - strip->us= 1; - } else { + seq->len = sceseq->r.efra - sceseq->r.sfra + 1; + + seq->strip = strip = MEM_callocN(sizeof (Strip), "strip"); + strncpy(seq->name + 2, sceseq->id.name + 2, + sizeof (seq->name) - 2); + strip->len = seq->len; + strip->us = 1; + } + else + { // RFS: REMOVED MOVIE FROM HERE } - strncpy(seq->name+2, "Untitled", 21); + strncpy(seq->name + 2, "Untitled", 21); intern_pos_update(seq); return Sequence_CreatePyObject(seq, NULL, sce); } -static PyObject *Sequence_new( BPy_Sequence * self, PyObject * args ) +static PyObject *Sequence_new(BPy_Sequence * self, PyObject * args) { return NewSeq_internal(&self->seq->seqbase, args, self->scene); } -static PyObject *SceneSeq_new( BPy_SceneSeq * self, PyObject * args ) +static PyObject *SceneSeq_new(BPy_SceneSeq * self, PyObject * args) { - return NewSeq_internal( &((Editing *)self->scene->ed)->seqbase, args, self->scene); + return NewSeq_internal(&((Editing *) self->scene->ed)->seqbase, args, self->scene); } static void del_seq__internal(Sequence *seq) { - if(seq->ipo) seq->ipo->id.us--; - - if(seq->type==SEQ_RAM_SOUND && seq->sound) + if (seq->ipo) seq->ipo->id.us--; + + if (seq->type == SEQ_RAM_SOUND && seq->sound) seq->sound->id.us--; free_sequence(seq); } @@ -349,433 +541,465 @@ static void recurs_del_seq(ListBase *lb) { Sequence *seq, *seqn; - seq= lb->first; - while(seq) { - seqn= seq->next; + seq = lb->first; + while (seq) + { + seqn = seq->next; BLI_remlink(lb, seq); - if(seq->type==SEQ_META) recurs_del_seq(&seq->seqbase); + if (seq->type == SEQ_META) recurs_del_seq(&seq->seqbase); del_seq__internal(seq); - seq= seqn; + seq = seqn; } } static PyObject *RemoveSeq_internal(ListBase *seqbase, PyObject * args, Scene *sce) { BPy_Sequence *bpy_seq = NULL; - - if( !PyArg_ParseTuple( args, "O!", &Sequence_Type, &bpy_seq ) ) - return EXPP_ReturnPyObjError( PyExc_ValueError, - "expects a sequence object" ); - + + if (!PyArg_ParseTuple(args, "O!", &Sequence_Type, &bpy_seq)) + return EXPP_ReturnPyObjError(PyExc_ValueError, + "expects a sequence object"); + /* quick way to tell if we dont have the seq */ if (sce != bpy_seq->scene) - return EXPP_ReturnPyObjError( PyExc_RuntimeError, - "Sequence does not exist here, cannot remove" ); - + return EXPP_ReturnPyObjError(PyExc_RuntimeError, + "Sequence does not exist here, cannot remove"); + recurs_del_seq(&bpy_seq->seq->seqbase); del_seq__internal(bpy_seq->seq); clear_last_seq(); /* just incase */ Py_RETURN_NONE; } -static PyObject *Sequence_remove( BPy_Sequence * self, PyObject * args ) +static PyObject *Sequence_remove(BPy_Sequence * self, PyObject * args) { return RemoveSeq_internal(&self->seq->seqbase, args, self->scene); } -static PyObject *SceneSeq_remove( BPy_SceneSeq * self, PyObject * args ) +static PyObject *SceneSeq_remove(BPy_SceneSeq * self, PyObject * args) { - return RemoveSeq_internal( &((Editing *)self->scene->ed)->seqbase, args, self->scene); + return RemoveSeq_internal(&((Editing *) self->scene->ed)->seqbase, args, self->scene); } - -static PyObject *Sequence_copy( BPy_Sequence * self ) +static PyObject *Sequence_copy(BPy_Sequence * self) { printf("Sequence Copy not implimented yet!\n"); Py_RETURN_NONE; } +static PyObject *Sequence_update(BPy_Sequence * self, PyObject *args) +{ + int data= 0; + if (!PyArg_ParseTuple(args, "|i:update", &data)) + return NULL; + + if (data) { + update_changed_seq_and_deps(self->seq, 1, 1); + new_tstripdata(self->seq); + } + calc_sequence(self->seq); + calc_sequence_disp(self->seq); + Py_RETURN_NONE; +} + /*****************************************************************************/ /* PythonTypeObject callback function prototypes */ /*****************************************************************************/ -static PyObject *Sequence_repr( BPy_Sequence * obj ); -static PyObject *SceneSeq_repr( BPy_SceneSeq * obj ); -static int Sequence_compare( BPy_Sequence * a, BPy_Sequence * b ); -static int SceneSeq_compare( BPy_SceneSeq * a, BPy_SceneSeq * b ); +static PyObject *Sequence_repr(BPy_Sequence * obj); +static PyObject *SceneSeq_repr(BPy_SceneSeq * obj); +static int Sequence_compare(BPy_Sequence * a, BPy_Sequence * b); +static int SceneSeq_compare(BPy_SceneSeq * a, BPy_SceneSeq * b); /*****************************************************************************/ /* Python BPy_Sequence methods: */ + /*****************************************************************************/ -static PyObject *Sequence_getIter( BPy_Sequence * self ) +static PyObject *Sequence_getIter(BPy_Sequence * self) { Sequence *iter = self->seq->seqbase.first; - - if (!self->iter) { + + if (!self->iter) + { self->iter = iter; - return EXPP_incr_ret ( (PyObject *) self ); - } else { + return EXPP_incr_ret((PyObject *) self); + } + else + { return Sequence_CreatePyObject(self->seq, iter, self->scene); } } -static PyObject *SceneSeq_getIter( BPy_SceneSeq * self ) +static PyObject *SceneSeq_getIter(BPy_SceneSeq * self) { - Sequence *iter = ((Editing *)self->scene->ed)->seqbase.first; - - if (!self->iter) { + Sequence *iter = ((Editing *) self->scene->ed)->seqbase.first; + + if (!self->iter) + { self->iter = iter; - return EXPP_incr_ret ( (PyObject *) self ); - } else { + return EXPP_incr_ret((PyObject *) self); + } + else + { return SceneSeq_CreatePyObject(self->scene, iter); } } - /* * Return next Seq */ -static PyObject *Sequence_nextIter( BPy_Sequence * self ) +static PyObject *Sequence_nextIter(BPy_Sequence * self) { PyObject *object; - if( !(self->iter) ) { + if (!(self->iter)) + { self->iter = NULL; /* so we can add objects again */ - return EXPP_ReturnPyObjError( PyExc_StopIteration, - "iterator at end" ); + return EXPP_ReturnPyObjError(PyExc_StopIteration, + "iterator at end"); } - - object= Sequence_CreatePyObject( self->iter, NULL, self->scene ); - self->iter= self->iter->next; + + object = Sequence_CreatePyObject(self->iter, NULL, self->scene); + self->iter = self->iter->next; return object; } - /* * Return next Seq */ -static PyObject *SceneSeq_nextIter( BPy_Sequence * self ) +static PyObject *SceneSeq_nextIter(BPy_Sequence * self) { PyObject *object; - if( !(self->iter) ) { + if (!(self->iter)) + { self->iter = NULL; /* so we can add objects again */ - return EXPP_ReturnPyObjError( PyExc_StopIteration, - "iterator at end" ); + return EXPP_ReturnPyObjError(PyExc_StopIteration, + "iterator at end"); } - - object= Sequence_CreatePyObject( self->iter, NULL, self->scene ); - self->iter= self->iter->next; + + object = Sequence_CreatePyObject(self->iter, NULL, self->scene); + self->iter = self->iter->next; return object; } - -static PyObject *Sequence_getName( BPy_Sequence * self ) +static PyObject *Sequence_getName(BPy_Sequence * self) { - return PyString_FromString( self->seq->name+2 ); + return PyString_FromString(self->seq->name + 2); } -static int Sequence_setName( BPy_Sequence * self, PyObject * value ) +static int Sequence_setName(BPy_Sequence * self, PyObject * value) { char *name = NULL; - - name = PyString_AsString ( value ); - if( !name ) - return EXPP_ReturnIntError( PyExc_TypeError, - "expected string argument" ); - strncpy(self->seq->name+2, name, 21); + name = PyString_AsString(value); + if (!name) + return EXPP_ReturnIntError(PyExc_TypeError, + "expected string argument"); + + strncpy(self->seq->name + 2, name, 21); return 0; } - -static PyObject *Sequence_getProxyDir( BPy_Sequence * self ) +static PyObject *Sequence_getProxyDir(BPy_Sequence * self) { - return PyString_FromString( self->seq->strip->proxy ? self->seq->strip->proxy->dir : "" ); + return PyString_FromString(self->seq->strip->proxy ? self->seq->strip->proxy->dir : ""); } - -static int Sequence_setProxyDir( BPy_Sequence * self, PyObject * value ) +static int Sequence_setProxyDir(BPy_Sequence * self, PyObject * value) { char *name = NULL; - - name = PyString_AsString ( value ); - if( !name ) { - return EXPP_ReturnIntError( PyExc_TypeError, - "expected string argument" ); + + name = PyString_AsString(value); + if (!name) + { + return EXPP_ReturnIntError(PyExc_TypeError, + "expected string argument"); } - - if (strlen(name) == 0) { - if (self->seq->strip->proxy) { - MEM_freeN(self->seq->strip->proxy); + + if (strlen(name) == 0) + { + if (self->seq->strip->proxy) + { + MEM_freeN(self->seq->strip->proxy); } - } else { - self->seq->strip->proxy = MEM_callocN(sizeof(struct StripProxy), "StripProxy"); - strncpy(self->seq->strip->proxy->dir, name, sizeof(struct StripProxy)); + } + else + { + self->seq->strip->proxy = MEM_callocN(sizeof (struct StripProxy), "StripProxy"); + strncpy(self->seq->strip->proxy->dir, name, sizeof (struct StripProxy)); } return 0; } - -static PyObject *Sequence_rebuildProxy( BPy_Sequence * self ) +static PyObject *Sequence_rebuildProxy(BPy_Sequence * self) { if (self->seq->strip->proxy) seq_proxy_rebuild(self->seq); Py_RETURN_NONE; } - -static PyObject *Sequence_getSound( BPy_Sequence * self ) +static PyObject *Sequence_getSound(BPy_Sequence * self) { if (self->seq->type == SEQ_RAM_SOUND && self->seq->sound) return Sound_CreatePyObject(self->seq->sound); Py_RETURN_NONE; } -static PyObject *Sequence_getIpo( BPy_Sequence * self ) +static PyObject *Sequence_getIpo(BPy_Sequence * self) { struct Ipo *ipo; - + ipo = self->seq->ipo; - if( ipo ) - return Ipo_CreatePyObject( ipo ); + if (ipo) + return Ipo_CreatePyObject(ipo); Py_RETURN_NONE; } - -static PyObject *SceneSeq_getActive( BPy_SceneSeq * self ) +static PyObject *SceneSeq_getActive(BPy_SceneSeq * self) { Sequence *last_seq = NULL, *seq; Editing *ed = self->scene->ed; if (!ed) - return EXPP_ReturnPyObjError( PyExc_RuntimeError, - "scene has no sequence data to edit" ); - + return EXPP_ReturnPyObjError(PyExc_RuntimeError, + "scene has no sequence data to edit"); + seq = ed->seqbasep->first; - - while (seq) { + + while (seq) + { if (seq->flag & SELECT) last_seq = seq; - + seq = seq->next; } if (last_seq) - return Sequence_CreatePyObject(last_seq, NULL, self->scene ); - + return Sequence_CreatePyObject(last_seq, NULL, self->scene); + Py_RETURN_NONE; } -static PyObject *SceneSeq_getMetaStrip( BPy_SceneSeq * self ) +static PyObject *SceneSeq_getMetaStrip(BPy_SceneSeq * self) { Sequence *seq = NULL; Editing *ed = self->scene->ed; MetaStack *ms; if (!ed) - return EXPP_ReturnPyObjError( PyExc_RuntimeError, - "scene has no sequence data to edit" ); - + return EXPP_ReturnPyObjError(PyExc_RuntimeError, + "scene has no sequence data to edit"); + ms = ed->metastack.last; if (!ms) Py_RETURN_NONE; - + seq = ms->parseq; return Sequence_CreatePyObject(seq, NULL, self->scene); } - /* * this should accept a Py_None argument and just delete the Ipo link * (as Object_clearIpo() does) */ -static int Sequence_setIpo( BPy_Sequence * self, PyObject * value ) +static int Sequence_setIpo(BPy_Sequence * self, PyObject * value) { Ipo *ipo = NULL; Ipo *oldipo; ID *id; - + oldipo = self->seq->ipo; - + /* if parameter is not None, check for valid Ipo */ - if ( value != Py_None ) { - if ( !BPy_Ipo_Check( value ) ) - return EXPP_ReturnIntError( PyExc_TypeError, - "expected an Ipo object" ); + if (value != Py_None) + { + if (!BPy_Ipo_Check(value)) + return EXPP_ReturnIntError(PyExc_TypeError, + "expected an Ipo object"); - ipo = Ipo_FromPyObject( value ); + ipo = Ipo_FromPyObject(value); - if( !ipo ) - return EXPP_ReturnIntError( PyExc_RuntimeError, - "null ipo!" ); + if (!ipo) + return EXPP_ReturnIntError(PyExc_RuntimeError, + "null ipo!"); - if( ipo->blocktype != ID_SEQ ) - return EXPP_ReturnIntError( PyExc_TypeError, - "Ipo is not a sequence data Ipo" ); + if (ipo->blocktype != ID_SEQ) + return EXPP_ReturnIntError(PyExc_TypeError, + "Ipo is not a sequence data Ipo"); } /* if already linked to Ipo, delete link */ - if ( oldipo ) { + if (oldipo) + { id = &oldipo->id; - if( id->us > 0 ) + if (id->us > 0) id->us--; } /* assign new Ipo and increment user count, or set to NULL if deleting */ self->seq->ipo = ipo; - if ( ipo ) + if (ipo) id_us_plus(&ipo->id); return 0; } -static PyObject *Sequence_getScene( BPy_Sequence * self ) +static PyObject *Sequence_getScene(BPy_Sequence * self) { struct Scene *scene; - + scene = self->seq->scene; - if( scene ) - return Scene_CreatePyObject( scene ); + if (scene) + return Scene_CreatePyObject(scene); Py_RETURN_NONE; } - -static PyObject *Sequence_getImages( BPy_Sequence * self ) +static PyObject *Sequence_getImages(BPy_Sequence * self) { Strip *strip; StripElem *se; int i; PyObject *list, *ret; - - if (self->seq->type != SEQ_IMAGE) { + + if (self->seq->type != SEQ_IMAGE) + { list = PyList_New(0); - ret= Py_BuildValue( "sO", "", list); + ret = Py_BuildValue("sO", "", list); Py_DECREF(list); return ret; } - - /*return EXPP_ReturnPyObjError( PyExc_TypeError, - "Sequence is not an image type" );*/ - - + + /*return EXPP_ReturnPyObjError( PyExc_TypeError, + "Sequence is not an image type" );*/ + + strip = self->seq->strip; se = strip->stripdata; list = PyList_New(strip->len); - - for (i=0; i<strip->len; i++, se++) { - PyList_SetItem( list, i, PyString_FromString(se->name) ); + + for (i = 0; i < strip->len; i++, se++) + { + PyList_SetItem(list, i, PyString_FromString(se->name)); } - - ret= Py_BuildValue( "sO", strip->dir, list); + + ret = Py_BuildValue("sO", strip->dir, list); Py_DECREF(list); return ret; } -static int Sequence_setImages( BPy_Sequence * self, PyObject *value ) +static int Sequence_setImages(BPy_Sequence * self, PyObject *value) { Strip *strip; StripElem *se; int i; PyObject *list; char *basepath, *name; - - if (self->seq->type != SEQ_IMAGE) { - return EXPP_ReturnIntError( PyExc_TypeError, - "Sequence is not an image type" ); + + if (self->seq->type != SEQ_IMAGE) + { + return EXPP_ReturnIntError(PyExc_TypeError, + "Sequence is not an image type"); } - - if( !PyArg_ParseTuple - ( value, "sO!", &basepath, &PyList_Type, &list ) ) - return EXPP_ReturnIntError( PyExc_TypeError, - "expected string and optional list argument" ); - + + if (!PyArg_ParseTuple + (value, "sO!", &basepath, &PyList_Type, &list)) + return EXPP_ReturnIntError(PyExc_TypeError, + "expected string and optional list argument"); + strip = self->seq->strip; se = strip->stripdata; - + /* for now dont support different image list sizes */ - if (PyList_Size(list) != strip->len) { - return EXPP_ReturnIntError( PyExc_TypeError, - "at the moment only image lista with the same number of images as the strip are supported" ); + if (PyList_Size(list) != strip->len) + { + return EXPP_ReturnIntError(PyExc_TypeError, + "at the moment only image lista with the same number of images as the strip are supported"); } - - strncpy(strip->dir, basepath, sizeof(strip->dir)); - - for (i=0; i<strip->len; i++, se++) { + + strncpy(strip->dir, basepath, sizeof (strip->dir)); + + for (i = 0; i < strip->len; i++, se++) + { name = PyString_AsString(PyList_GetItem(list, i)); - if (name) { - strncpy(se->name, name, sizeof(se->name)); - } else { + if (name) + { + strncpy(se->name, name, sizeof (se->name)); + } + else + { PyErr_Clear(); } } - + return 0; } -static PyObject *M_Sequence_BlendModesDict( void ) +static PyObject *M_Sequence_BlendModesDict(void) { - PyObject *M = PyConstant_New( ); - - if( M ) { - BPy_constant *d = ( BPy_constant * ) M; - PyConstant_Insert( d, "CROSS", PyInt_FromLong( SEQ_CROSS ) ); - PyConstant_Insert( d, "ADD", PyInt_FromLong( SEQ_ADD ) ); - PyConstant_Insert( d, "SUBTRACT", PyInt_FromLong( SEQ_SUB ) ); - PyConstant_Insert( d, "ALPHAOVER", PyInt_FromLong( SEQ_ALPHAOVER ) ); - PyConstant_Insert( d, "ALPHAUNDER", PyInt_FromLong( SEQ_ALPHAUNDER ) ); - PyConstant_Insert( d, "GAMMACROSS", PyInt_FromLong( SEQ_GAMCROSS ) ); - PyConstant_Insert( d, "MULTIPLY", PyInt_FromLong( SEQ_MUL ) ); - PyConstant_Insert( d, "OVERDROP", PyInt_FromLong( SEQ_OVERDROP ) ); - PyConstant_Insert( d, "PLUGIN", PyInt_FromLong( SEQ_PLUGIN ) ); - PyConstant_Insert( d, "WIPE", PyInt_FromLong( SEQ_WIPE ) ); - PyConstant_Insert( d, "GLOW", PyInt_FromLong( SEQ_GLOW ) ); - PyConstant_Insert( d, "TRANSFORM", PyInt_FromLong( SEQ_TRANSFORM ) ); - PyConstant_Insert( d, "COLOR", PyInt_FromLong( SEQ_COLOR ) ); - PyConstant_Insert( d, "SPEED", PyInt_FromLong( SEQ_SPEED ) ); + PyObject *M = PyConstant_New(); + + if (M) + { + BPy_constant *d = (BPy_constant *) M; + PyConstant_Insert(d, "CROSS", PyInt_FromLong(SEQ_CROSS)); + PyConstant_Insert(d, "ADD", PyInt_FromLong(SEQ_ADD)); + PyConstant_Insert(d, "SUBTRACT", PyInt_FromLong(SEQ_SUB)); + PyConstant_Insert(d, "ALPHAOVER", PyInt_FromLong(SEQ_ALPHAOVER)); + PyConstant_Insert(d, "ALPHAUNDER", PyInt_FromLong(SEQ_ALPHAUNDER)); + PyConstant_Insert(d, "GAMMACROSS", PyInt_FromLong(SEQ_GAMCROSS)); + PyConstant_Insert(d, "MULTIPLY", PyInt_FromLong(SEQ_MUL)); + PyConstant_Insert(d, "OVERDROP", PyInt_FromLong(SEQ_OVERDROP)); + PyConstant_Insert(d, "PLUGIN", PyInt_FromLong(SEQ_PLUGIN)); + PyConstant_Insert(d, "WIPE", PyInt_FromLong(SEQ_WIPE)); + PyConstant_Insert(d, "GLOW", PyInt_FromLong(SEQ_GLOW)); + PyConstant_Insert(d, "TRANSFORM", PyInt_FromLong(SEQ_TRANSFORM)); + PyConstant_Insert(d, "COLOR", PyInt_FromLong(SEQ_COLOR)); + PyConstant_Insert(d, "SPEED", PyInt_FromLong(SEQ_SPEED)); } return M; } -static PyObject *Sequence_getBlendMode( BPy_Sequence * self ) +static PyObject *Sequence_getBlendMode(BPy_Sequence * self) { - return PyInt_FromLong( self->seq->blend_mode ); + return PyInt_FromLong(self->seq->blend_mode); } -static int Sequence_setBlendMode( BPy_Sequence * self, PyObject * value ) +static int Sequence_setBlendMode(BPy_Sequence * self, PyObject * value) { - struct Sequence *seq= self->seq; - int number = PyInt_AsLong( value ); - - if( number==-1 && PyErr_Occurred() ) - return EXPP_ReturnIntError( PyExc_TypeError, "expected an int value" ); - - if ( !seq_can_blend(seq) ) - return EXPP_ReturnIntError( PyExc_AttributeError, "this sequence type dosnt support blending" ); - - if (number<SEQ_EFFECT || number>SEQ_EFFECT_MAX) - return EXPP_ReturnIntError( PyExc_TypeError, "expected an int value" ); - - seq->blend_mode=number; - + struct Sequence *seq = self->seq; + int number = PyInt_AsLong(value); + + if (number == -1 && PyErr_Occurred()) + return EXPP_ReturnIntError(PyExc_TypeError, "expected an int value"); + + if (!seq_can_blend(seq)) + return EXPP_ReturnIntError(PyExc_AttributeError, "this sequence type dosnt support blending"); + + if (number < SEQ_EFFECT || number > SEQ_EFFECT_MAX) + return EXPP_ReturnIntError(PyExc_TypeError, "expected an int value"); + + seq->blend_mode = number; + return 0; } /* * get floating point attributes */ -static PyObject *getIntAttr( BPy_Sequence *self, void *type ) +static PyObject *getIntAttr(BPy_Sequence *self, void *type) { int param; - struct Sequence *seq= self->seq; - + struct Sequence *seq = self->seq; + /*printf("%i %i %i %i %i %i %i %i %i\n", seq->len, seq->start, seq->startofs, seq->endofs, seq->startstill, seq->endstill, seq->startdisp, seq->enddisp, seq->depth );*/ - switch( GET_INT_FROM_POINTER(type) ) { - case EXPP_SEQ_ATTR_TYPE: + switch (GET_INT_FROM_POINTER(type)) + { + case EXPP_SEQ_ATTR_TYPE: param = seq->type; break; case EXPP_SEQ_ATTR_CHAN: @@ -799,43 +1023,52 @@ static PyObject *getIntAttr( BPy_Sequence *self, void *type ) case EXPP_SEQ_ATTR_ENDSTILL: param = seq->endstill; break; + case EXPP_SEQ_ATTR_STARTDISP: + param = seq->startdisp; + break; + case EXPP_SEQ_ATTR_ENDDISP: + param = seq->enddisp; + break; default: - return EXPP_ReturnPyObjError( PyExc_RuntimeError, - "undefined type in getIntAttr" ); + return EXPP_ReturnPyObjError(PyExc_RuntimeError, + "undefined type in getIntAttr"); } - return PyInt_FromLong( param ); + return PyInt_FromLong(param); } /* internal functions for recursivly updating metastrip locatons */ -static void intern_pos_update(Sequence * seq) { +static void intern_pos_update(Sequence * seq) +{ /* update startdisp and enddisp */ calc_sequence_disp(seq); } -void intern_recursive_pos_update(Sequence * seq, int offset) { +void intern_recursive_pos_update(Sequence * seq, int offset) +{ Sequence *iterseq; intern_pos_update(seq); if (seq->type != SEQ_META) return; - - for (iterseq = seq->seqbase.first; iterseq; iterseq= iterseq->next) { + + for (iterseq = seq->seqbase.first; iterseq; iterseq = iterseq->next) + { iterseq->start -= offset; intern_recursive_pos_update(iterseq, offset); } } - -static int setIntAttrClamp( BPy_Sequence *self, PyObject *value, void *type ) +static int setIntAttrClamp(BPy_Sequence *self, PyObject *value, void *type) { - struct Sequence *seq= self->seq; - int number, origval=0, regen_data; + struct Sequence *seq = self->seq; + int number, origval = 0, regen_data; - if( !PyInt_Check( value ) ) - return EXPP_ReturnIntError( PyExc_TypeError, "expected an int value" ); - - number = PyInt_AS_LONG( value ); - - switch( GET_INT_FROM_POINTER(type) ) { + if (!PyInt_Check(value)) + return EXPP_ReturnIntError(PyExc_TypeError, "expected an int value"); + + number = PyInt_AS_LONG(value); + + switch (GET_INT_FROM_POINTER(type)) + { case EXPP_SEQ_ATTR_CHAN: CLAMP(number, 1, 1024); seq->machine = number; @@ -843,18 +1076,18 @@ static int setIntAttrClamp( BPy_Sequence *self, PyObject *value, void *type ) break; case EXPP_SEQ_ATTR_START: if (self->seq->type == SEQ_EFFECT) - return EXPP_ReturnIntError( PyExc_RuntimeError, - "cannot set the location of an effect directly" ); + return EXPP_ReturnIntError(PyExc_RuntimeError, + "cannot set the location of an effect directly"); CLAMP(number, -MAXFRAME, MAXFRAME); origval = seq->start; seq->start = number; regen_data = 0; break; - + case EXPP_SEQ_ATTR_STARTOFS: if (self->seq->type == SEQ_EFFECT) - return EXPP_ReturnIntError( PyExc_RuntimeError, - "This property dosnt apply to an effect" ); + return EXPP_ReturnIntError(PyExc_RuntimeError, + "This property dosnt apply to an effect"); CLAMP(number, 0, seq->len - seq->endofs); origval = seq->startofs; seq->startofs = number; @@ -862,8 +1095,8 @@ static int setIntAttrClamp( BPy_Sequence *self, PyObject *value, void *type ) break; case EXPP_SEQ_ATTR_ENDOFS: if (self->seq->type == SEQ_EFFECT) - return EXPP_ReturnIntError( PyExc_RuntimeError, - "This property dosnt apply to an effect" ); + return EXPP_ReturnIntError(PyExc_RuntimeError, + "This property dosnt apply to an effect"); CLAMP(number, 0, seq->len - seq->startofs); origval = seq->endofs; seq->endofs = number; @@ -871,8 +1104,8 @@ static int setIntAttrClamp( BPy_Sequence *self, PyObject *value, void *type ) break; case EXPP_SEQ_ATTR_STARTSTILL: if (self->seq->type == SEQ_EFFECT) - return EXPP_ReturnIntError( PyExc_RuntimeError, - "This property dosnt apply to an effect" ); + return EXPP_ReturnIntError(PyExc_RuntimeError, + "This property dosnt apply to an effect"); CLAMP(number, 1, MAXFRAME); origval = seq->startstill; seq->startstill = number; @@ -880,42 +1113,46 @@ static int setIntAttrClamp( BPy_Sequence *self, PyObject *value, void *type ) break; case EXPP_SEQ_ATTR_ENDSTILL: if (self->seq->type == SEQ_EFFECT) - return EXPP_ReturnIntError( PyExc_RuntimeError, - "This property dosnt apply to an effect" ); - CLAMP(number, seq->startstill+1, MAXFRAME); + return EXPP_ReturnIntError(PyExc_RuntimeError, + "This property dosnt apply to an effect"); + CLAMP(number, seq->startstill + 1, MAXFRAME); origval = seq->endstill; seq->endstill = number; regen_data = 1; break; case EXPP_SEQ_ATTR_LENGTH: if (self->seq->type == SEQ_EFFECT) - return EXPP_ReturnIntError( PyExc_RuntimeError, - "cannot set the length of an effect directly" ); + return EXPP_ReturnIntError(PyExc_RuntimeError, + "cannot set the length of an effect directly"); CLAMP(number, 1, MAXFRAME); origval = seq->len; seq->len = number; regen_data = 1; break; default: - return EXPP_ReturnIntError( PyExc_RuntimeError, - "undefined type in setFloatAttrClamp" ); + return EXPP_ReturnIntError(PyExc_RuntimeError, + "undefined type in setFloatAttrClamp"); } - if (number != origval) { + if (number != origval) + { intern_pos_update(seq); - + if (GET_INT_FROM_POINTER(type) == EXPP_SEQ_ATTR_START) intern_recursive_pos_update(seq, origval - seq->start); - - if (regen_data) { + + if (regen_data) + { new_tstripdata(seq); } + + calc_sequence(seq); + calc_sequence_disp(seq); } return 0; } - -static PyObject *getFlagAttr( BPy_Sequence *self, void *type ) +static PyObject *getFlagAttr(BPy_Sequence *self, void *type) { if (self->seq->flag & GET_INT_FROM_POINTER(type)) Py_RETURN_TRUE; @@ -923,155 +1160,424 @@ static PyObject *getFlagAttr( BPy_Sequence *self, void *type ) Py_RETURN_FALSE; } - /* * set floating point attributes which require clamping */ -static int setFlagAttr( BPy_Sequence *self, PyObject *value, void *type ) +static int setFlagAttr(BPy_Sequence *self, PyObject *value, void *type) { int t = GET_INT_FROM_POINTER(type); - int param = PyObject_IsTrue( value ); - - if( param == -1 ) - return EXPP_ReturnIntError( PyExc_TypeError, - "expected True/False or 0/1" ); - + int param = PyObject_IsTrue(value); + + if (param == -1) + return EXPP_ReturnIntError(PyExc_TypeError, + "expected True/False or 0/1"); + if (param) self->seq->flag |= t; - else { + else + { /* dont allow leftsel and rightsel when its not selected */ if (t == SELECT) t = t + SEQ_LEFTSEL + SEQ_RIGHTSEL; - + self->seq->flag &= ~t; } return 0; } +static PyObject *getEffectSeq(BPy_Sequence *self, void *type) +{ + int t = GET_INT_FROM_POINTER(type); + Sequence *seq = NULL; + switch (t) + { + case 1: + seq = self->seq->seq1; + break; + case 2: + seq = self->seq->seq2; + break; + case 3: + seq = self->seq->seq3; + break; + } + + if (seq) + { + return Sequence_CreatePyObject(seq, NULL, self->scene); + } + else + { + Py_RETURN_NONE; + } +} + +/* + * set one of the effect sequences + */ + +static int setEffectSeq(BPy_Sequence *self, PyObject *value, void *type) +{ + int t = GET_INT_FROM_POINTER(type); + Sequence **seq; + if ((value == Py_None || BPy_Sequence_Check(value)) == 0) + return EXPP_ReturnIntError(PyExc_TypeError, + "expected Sequence or None"); + + switch (t) + { + case 1: + seq = &self->seq->seq1; + break; + case 2: + seq = &self->seq->seq2; + break; + case 3: + seq = &self->seq->seq3; + break; + } + + if (value == Py_None) + *seq = NULL; + else + { + Sequence *newseq = ((BPy_Sequence *) value)->seq; + if (newseq == self->seq) + { + return EXPP_ReturnIntError(PyExc_TypeError, "cannot set a sequence as its own effect"); + } + + *seq = ((BPy_Sequence *) value)->seq; + } + + + calc_sequence(self->seq); + update_changed_seq_and_deps(self->seq, 1, 1); + + return 0; +} + + + +static PyObject *getSpeedEffect(BPy_Sequence *self, PyObject *value, void *type) +{ + int t = GET_INT_FROM_POINTER(type); + Sequence *seq= self->seq; + SpeedControlVars * v; + + if (seq->type != SEQ_SPEED) + return EXPP_ReturnPyObjError(PyExc_TypeError, "Not a speed effect strip" ); + + v = (SpeedControlVars *)seq->effectdata; + + switch (t) { + case EXPP_SEQ_ATTR_EFFECT_GLOBAL_SPEED: + return PyFloat_FromDouble(v->globalSpeed); + break; + case EXPP_SEQ_ATTR_EFFECT_IPO_IS_VELOCITY: + return PyBool_FromLong(v->flags & SEQ_SPEED_INTEGRATE); + break; + case EXPP_SEQ_ATTR_EFFECT_FRAME_BLENDING: + return PyBool_FromLong(v->flags & SEQ_SPEED_BLEND); + break; + case EXPP_SEQ_ATTR_EFFECT_NORMALIZE_IPO_0_1: + return PyBool_FromLong(v->flags & SEQ_SPEED_COMPRESS_IPO_Y); + break; + } + + if (PyErr_Occurred()) { + return NULL; + } + + Py_RETURN_NONE; +} + +/* + * set one of the effect sequences + */ + +static int setSpeedEffect(BPy_Sequence *self, PyObject *value, void *type) +{ + int t = GET_INT_FROM_POINTER(type); + Sequence *seq= self->seq; + SpeedControlVars * v; + + if (seq->type != SEQ_SPEED) + return EXPP_ReturnIntError(PyExc_TypeError, "Not a speed effect strip" ); + + v = (SpeedControlVars *)seq->effectdata; + + switch (t) { + case EXPP_SEQ_ATTR_EFFECT_GLOBAL_SPEED: + v->globalSpeed= PyFloat_AsDouble(value); + CLAMP(v->globalSpeed, 0.0f, 100.0f); + break; + case EXPP_SEQ_ATTR_EFFECT_IPO_IS_VELOCITY: + if (PyObject_IsTrue( value )) v->flags |= SEQ_SPEED_INTEGRATE; + else v->flags &= ~SEQ_SPEED_INTEGRATE; + break; + case EXPP_SEQ_ATTR_EFFECT_FRAME_BLENDING: + if (PyObject_IsTrue( value )) v->flags |= SEQ_SPEED_BLEND; + else v->flags &= ~SEQ_SPEED_BLEND; + break; + case EXPP_SEQ_ATTR_EFFECT_NORMALIZE_IPO_0_1: + if (PyObject_IsTrue( value )) v->flags |= SEQ_SPEED_COMPRESS_IPO_Y; + else v->flags &= ~SEQ_SPEED_COMPRESS_IPO_Y; + break; + } + + if (PyErr_Occurred()) { + return -1; + } + + return 0; +} + + + +static PyObject *getWipeEffect(BPy_Sequence *self, PyObject *value, void *type) +{ + int t = GET_INT_FROM_POINTER(type); + Sequence *seq= self->seq; + WipeVars * v; + + if (seq->type != SEQ_WIPE) + return EXPP_ReturnPyObjError(PyExc_TypeError, "Not a wipe effect strip" ); + + v = (WipeVars *)seq->effectdata; + + switch (t) { + case EXPP_SEQ_ATTR_EFFECT_ANGLE: + return PyFloat_FromDouble(v->angle); + break; + case EXPP_SEQ_ATTR_EFFECT_BLUR: + return PyFloat_FromDouble(v->edgeWidth); + break; + case EXPP_SEQ_ATTR_EFFECT_WIPE_IN: + return PyBool_FromLong(v->forward); + break; + } + + if (PyErr_Occurred()) { + return NULL; + } + + Py_RETURN_NONE; +} + +/* + * set one of the effect sequences + */ + +static int setWipeEffect(BPy_Sequence *self, PyObject *value, void *type) +{ + int t = GET_INT_FROM_POINTER(type); + Sequence *seq= self->seq; + WipeVars * v; + + if (seq->type != SEQ_WIPE) + return EXPP_ReturnIntError(PyExc_TypeError, "Not a wipe effect strip" ); + + v = (WipeVars *)seq->effectdata; + + switch (t) { + case EXPP_SEQ_ATTR_EFFECT_ANGLE: + v->angle= PyFloat_AsDouble(value); + CLAMP(v->angle, -90.0f, 90.0f); + break; + case EXPP_SEQ_ATTR_EFFECT_BLUR: + v->edgeWidth= PyFloat_AsDouble(value); + CLAMP(v->edgeWidth, -90.0f, 90.0f); + break; + case EXPP_SEQ_ATTR_EFFECT_WIPE_IN: + if (PyObject_IsTrue( value )) v->forward= 1; + else v->forward= 0; + break; + } + + if (PyErr_Occurred()) { + return -1; + } + + return 0; +} + + /*****************************************************************************/ /* Python attributes get/set structure: */ /*****************************************************************************/ static PyGetSetDef BPy_Sequence_getseters[] = { {"name", - (getter)Sequence_getName, (setter)Sequence_setName, - "Sequence name", - NULL}, + (getter) Sequence_getName, (setter) Sequence_setName, + "Sequence name", + NULL}, {"proxyDir", - (getter)Sequence_getProxyDir, (setter)Sequence_setProxyDir, - "Sequence proxy directory", - NULL}, + (getter) Sequence_getProxyDir, (setter) Sequence_setProxyDir, + "Sequence proxy directory", + NULL}, {"ipo", - (getter)Sequence_getIpo, (setter)Sequence_setIpo, - "Sequence ipo", - NULL}, + (getter) Sequence_getIpo, (setter) Sequence_setIpo, + "Sequence ipo", + NULL}, {"scene", - (getter)Sequence_getScene, (setter)NULL, - "Sequence scene", - NULL}, + (getter) Sequence_getScene, (setter) NULL, + "Sequence scene", + NULL}, {"sound", - (getter)Sequence_getSound, (setter)NULL, - "Sequence name", - NULL}, + (getter) Sequence_getSound, (setter) NULL, + "Sequence name", + NULL}, {"images", - (getter)Sequence_getImages, (setter)Sequence_setImages, - "Sequence scene", - NULL}, + (getter) Sequence_getImages, (setter) Sequence_setImages, + "Sequence scene", + NULL}, {"blendMode", - (getter)Sequence_getBlendMode, (setter)Sequence_setBlendMode, - "Sequence Blend Mode", - NULL}, + (getter) Sequence_getBlendMode, (setter) Sequence_setBlendMode, + "Sequence Blend Mode", + NULL}, {"type", - (getter)getIntAttr, (setter)NULL, - "", - (void *) EXPP_SEQ_ATTR_TYPE}, + (getter) getIntAttr, (setter) NULL, + "", + (void *) EXPP_SEQ_ATTR_TYPE}, {"channel", - (getter)getIntAttr, (setter)setIntAttrClamp, - "", - (void *) EXPP_SEQ_ATTR_CHAN}, - + (getter) getIntAttr, (setter) setIntAttrClamp, + "", + (void *) EXPP_SEQ_ATTR_CHAN}, + {"length", - (getter)getIntAttr, (setter)setIntAttrClamp, - "", - (void *) EXPP_SEQ_ATTR_LENGTH}, + (getter) getIntAttr, (setter) setIntAttrClamp, + "", + (void *) EXPP_SEQ_ATTR_LENGTH}, {"start", - (getter)getIntAttr, (setter)setIntAttrClamp, - "", - (void *) EXPP_SEQ_ATTR_START}, + (getter) getIntAttr, (setter) setIntAttrClamp, + "", + (void *) EXPP_SEQ_ATTR_START}, {"startOffset", - (getter)getIntAttr, (setter)setIntAttrClamp, - "", - (void *) EXPP_SEQ_ATTR_STARTOFS}, + (getter) getIntAttr, (setter) setIntAttrClamp, + "", + (void *) EXPP_SEQ_ATTR_STARTOFS}, {"endOffset", - (getter)getIntAttr, (setter)setIntAttrClamp, - "", - (void *) EXPP_SEQ_ATTR_ENDOFS}, + (getter) getIntAttr, (setter) setIntAttrClamp, + "", + (void *) EXPP_SEQ_ATTR_ENDOFS}, {"startStill", - (getter)getIntAttr, (setter)setIntAttrClamp, - "", - (void *) EXPP_SEQ_ATTR_STARTSTILL}, + (getter) getIntAttr, (setter) setIntAttrClamp, + "", + (void *) EXPP_SEQ_ATTR_STARTSTILL}, {"endStill", - (getter)getIntAttr, (setter)setIntAttrClamp, - "", - (void *) EXPP_SEQ_ATTR_ENDSTILL}, - + (getter) getIntAttr, (setter) setIntAttrClamp, + "", + (void *) EXPP_SEQ_ATTR_ENDSTILL}, + {"startDisp", + (getter) getIntAttr, (setter) NULL, + "", + (void *) EXPP_SEQ_ATTR_STARTDISP}, + {"endDisp", + (getter) getIntAttr, (setter) NULL, + "", + (void *) EXPP_SEQ_ATTR_ENDDISP}, + {"sel", - (getter)getFlagAttr, (setter)setFlagAttr, - "Sequence audio mute option", - (void *)SELECT}, + (getter) getFlagAttr, (setter) setFlagAttr, + "Sequence audio mute option", + (void *) SELECT}, {"selLeft", - (getter)getFlagAttr, (setter)setFlagAttr, - "", - (void *)SEQ_LEFTSEL}, + (getter) getFlagAttr, (setter) setFlagAttr, + "", + (void *) SEQ_LEFTSEL}, {"selRight", - (getter)getFlagAttr, (setter)setFlagAttr, - "", - (void *)SEQ_RIGHTSEL}, + (getter) getFlagAttr, (setter) setFlagAttr, + "", + (void *) SEQ_RIGHTSEL}, {"filtery", - (getter)getFlagAttr, (setter)setFlagAttr, - "", - (void *)SEQ_FILTERY}, + (getter) getFlagAttr, (setter) setFlagAttr, + "", + (void *) SEQ_FILTERY}, {"flipX", - (getter)getFlagAttr, (setter)setFlagAttr, - "", - (void *)SEQ_FLIPX}, + (getter) getFlagAttr, (setter) setFlagAttr, + "", + (void *) SEQ_FLIPX}, {"flipY", - (getter)getFlagAttr, (setter)setFlagAttr, - "", - (void *)SEQ_FLIPY}, + (getter) getFlagAttr, (setter) setFlagAttr, + "", + (void *) SEQ_FLIPY}, {"mute", - (getter)getFlagAttr, (setter)setFlagAttr, - "", - (void *)SEQ_MUTE}, + (getter) getFlagAttr, (setter) setFlagAttr, + "", + (void *) SEQ_MUTE}, {"floatBuffer", - (getter)getFlagAttr, (setter)setFlagAttr, - "", - (void *)SEQ_MAKE_FLOAT}, + (getter) getFlagAttr, (setter) setFlagAttr, + "", + (void *) SEQ_MAKE_FLOAT}, {"lock", - (getter)getFlagAttr, (setter)setFlagAttr, - "", - (void *)SEQ_LOCK}, + (getter) getFlagAttr, (setter) setFlagAttr, + "", + (void *) SEQ_LOCK}, {"useProxy", - (getter)getFlagAttr, (setter)setFlagAttr, - "", - (void *)SEQ_USE_PROXY}, + (getter) getFlagAttr, (setter) setFlagAttr, + "", + (void *) SEQ_USE_PROXY}, {"premul", - (getter)getFlagAttr, (setter)setFlagAttr, - "", - (void *)SEQ_MAKE_PREMUL}, + (getter) getFlagAttr, (setter) setFlagAttr, + "", + (void *) SEQ_MAKE_PREMUL}, {"reversed", - (getter)getFlagAttr, (setter)setFlagAttr, - "", - (void *)SEQ_REVERSE_FRAMES}, + (getter) getFlagAttr, (setter) setFlagAttr, + "", + (void *) SEQ_REVERSE_FRAMES}, {"ipoLocked", - (getter)getFlagAttr, (setter)setFlagAttr, - "", - (void *)SEQ_IPO_FRAME_LOCKED}, - - {NULL,NULL,NULL,NULL,NULL} /* Sentinel */ + (getter) getFlagAttr, (setter) setFlagAttr, + "", + (void *) SEQ_IPO_FRAME_LOCKED}, + {"seq1", + (getter) getEffectSeq, (setter) setEffectSeq, + "", + (void *) 1}, + {"seq2", + (getter) getEffectSeq, (setter) setEffectSeq, + "", + (void *) 2}, + {"seq3", + (getter) getEffectSeq, (setter) setEffectSeq, + "", + (void *) 3}, + + /* effects */ + {"speedEffectGlobalSpeed", + (getter) getSpeedEffect, (setter) setSpeedEffect, + "", + (void *) EXPP_SEQ_ATTR_EFFECT_GLOBAL_SPEED}, + {"speedEffectIpoVelocity", + (getter) getSpeedEffect, (setter) setSpeedEffect, + "", + (void *) EXPP_SEQ_ATTR_EFFECT_IPO_IS_VELOCITY}, + {"speedEffectFrameBlending", + (getter) getSpeedEffect, (setter) setSpeedEffect, + "", + (void *) EXPP_SEQ_ATTR_EFFECT_FRAME_BLENDING}, + {"speedEffectIpoNormalize", + (getter) getSpeedEffect, (setter) setSpeedEffect, + "", + (void *) EXPP_SEQ_ATTR_EFFECT_NORMALIZE_IPO_0_1}, + + {"wipeEffectAngle", + (getter) getWipeEffect, (setter) setWipeEffect, + "", + (void *) EXPP_SEQ_ATTR_EFFECT_ANGLE}, + {"wipeEffectBlur", + (getter) getWipeEffect, (setter) setWipeEffect, + "", + (void *) EXPP_SEQ_ATTR_EFFECT_BLUR}, + {"wipeEffectWipeIn", + (getter) getWipeEffect, (setter) setWipeEffect, + "", + (void *) EXPP_SEQ_ATTR_EFFECT_WIPE_IN}, + + {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ }; /*****************************************************************************/ @@ -1079,98 +1585,98 @@ static PyGetSetDef BPy_Sequence_getseters[] = { /*****************************************************************************/ static PyGetSetDef BPy_SceneSeq_getseters[] = { {"active", - (getter)SceneSeq_getActive, (setter)NULL, - "the active strip", - NULL}, + (getter) SceneSeq_getActive, (setter) NULL, + "the active strip", + NULL}, {"metastrip", - (getter)SceneSeq_getMetaStrip, (setter)NULL, - "The currently active metastrip the user is editing", - NULL}, - {NULL,NULL,NULL,NULL,NULL} /* Sentinel */ + (getter) SceneSeq_getMetaStrip, (setter) NULL, + "The currently active metastrip the user is editing", + NULL}, + {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ }; /*****************************************************************************/ /* Python TypeSequence structure definition: */ /*****************************************************************************/ PyTypeObject Sequence_Type = { - PyObject_HEAD_INIT( NULL ) /* required py macro */ - 0, /* ob_size */ + PyObject_HEAD_INIT(NULL) /* required py macro */ + 0, /* ob_size */ /* For printing, in format "<module>.<name>" */ - "Blender Sequence", /* char *tp_name; */ - sizeof( BPy_Sequence ), /* int tp_basicsize; */ - 0, /* tp_itemsize; For allocation */ + "Blender Sequence", /* char *tp_name; */ + sizeof ( BPy_Sequence), /* int tp_basicsize; */ + 0, /* tp_itemsize; For allocation */ /* Methods to implement standard operations */ - NULL,/* destructor tp_dealloc; */ - NULL, /* printfunc tp_print; */ - NULL, /* getattrfunc tp_getattr; */ - NULL, /* setattrfunc tp_setattr; */ - ( cmpfunc ) Sequence_compare, /* cmpfunc tp_compare; */ - ( reprfunc ) Sequence_repr, /* reprfunc tp_repr; */ + NULL, /* destructor tp_dealloc; */ + NULL, /* printfunc tp_print; */ + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ + (cmpfunc) Sequence_compare, /* cmpfunc tp_compare; */ + (reprfunc) Sequence_repr, /* reprfunc tp_repr; */ /* Method suites for standard classes */ - NULL, /* PyNumberMethods *tp_as_number; */ - NULL, /* PySequenceMethods *tp_as_sequence; */ - NULL, /* PyMappingMethods *tp_as_mapping; */ + NULL, /* PyNumberMethods *tp_as_number; */ + NULL, /* PySequenceMethods *tp_as_sequence; */ + NULL, /* PyMappingMethods *tp_as_mapping; */ /* More standard operations (here for binary compatibility) */ - NULL, /* hashfunc tp_hash; */ - NULL, /* ternaryfunc tp_call; */ - NULL, /* reprfunc tp_str; */ - NULL, /* getattrofunc tp_getattro; */ - NULL, /* setattrofunc tp_setattro; */ + NULL, /* hashfunc tp_hash; */ + NULL, /* ternaryfunc tp_call; */ + NULL, /* reprfunc tp_str; */ + NULL, /* getattrofunc tp_getattro; */ + NULL, /* setattrofunc tp_setattro; */ /* Functions to access object as input/output buffer */ - NULL, /* PyBufferProcs *tp_as_buffer; */ + NULL, /* PyBufferProcs *tp_as_buffer; */ - /*** Flags to define presence of optional/expanded features ***/ - Py_TPFLAGS_DEFAULT, /* long tp_flags; */ + /*** Flags to define presence of optional/expanded features ***/ + Py_TPFLAGS_DEFAULT, /* long tp_flags; */ - NULL, /* char *tp_doc; Documentation string */ - /*** Assigned meaning in release 2.0 ***/ + NULL, /* char *tp_doc; Documentation string */ + /*** Assigned meaning in release 2.0 ***/ /* call function for all accessible objects */ - NULL, /* traverseproc tp_traverse; */ + NULL, /* traverseproc tp_traverse; */ /* delete references to contained objects */ - NULL, /* inquiry tp_clear; */ + NULL, /* inquiry tp_clear; */ - /*** Assigned meaning in release 2.1 ***/ - /*** rich comparisons ***/ - NULL, /* richcmpfunc tp_richcompare; */ + /*** Assigned meaning in release 2.1 ***/ + /*** rich comparisons ***/ + NULL, /* richcmpfunc tp_richcompare; */ - /*** weak reference enabler ***/ - 0, /* long tp_weaklistoffset; */ + /*** weak reference enabler ***/ + 0, /* long tp_weaklistoffset; */ - /*** Added in release 2.2 ***/ + /*** Added in release 2.2 ***/ /* Iterators */ - ( getiterfunc ) Sequence_getIter, /* getiterfunc tp_iter; */ - ( iternextfunc ) Sequence_nextIter, /* iternextfunc tp_iternext; */ - - /*** Attribute descriptor and subclassing stuff ***/ - BPy_Sequence_methods, /* struct PyMethodDef *tp_methods; */ - NULL, /* struct PyMemberDef *tp_members; */ - BPy_Sequence_getseters, /* struct PyGetSetDef *tp_getset; */ - NULL, /* struct _typeobject *tp_base; */ - NULL, /* PyObject *tp_dict; */ - NULL, /* descrgetfunc tp_descr_get; */ - NULL, /* descrsetfunc tp_descr_set; */ - 0, /* long tp_dictoffset; */ - NULL, /* initproc tp_init; */ - NULL, /* allocfunc tp_alloc; */ - NULL, /* newfunc tp_new; */ + (getiterfunc) Sequence_getIter, /* getiterfunc tp_iter; */ + (iternextfunc) Sequence_nextIter, /* iternextfunc tp_iternext; */ + + /*** Attribute descriptor and subclassing stuff ***/ + BPy_Sequence_methods, /* struct PyMethodDef *tp_methods; */ + NULL, /* struct PyMemberDef *tp_members; */ + BPy_Sequence_getseters, /* struct PyGetSetDef *tp_getset; */ + NULL, /* struct _typeobject *tp_base; */ + NULL, /* PyObject *tp_dict; */ + NULL, /* descrgetfunc tp_descr_get; */ + NULL, /* descrsetfunc tp_descr_set; */ + 0, /* long tp_dictoffset; */ + NULL, /* initproc tp_init; */ + NULL, /* allocfunc tp_alloc; */ + NULL, /* newfunc tp_new; */ /* Low-level free-memory routine */ - NULL, /* freefunc tp_free; */ + NULL, /* freefunc tp_free; */ /* For PyObject_IS_GC */ - NULL, /* inquiry tp_is_gc; */ - NULL, /* PyObject *tp_bases; */ + NULL, /* inquiry tp_is_gc; */ + NULL, /* PyObject *tp_bases; */ /* method resolution order */ - NULL, /* PyObject *tp_mro; */ - NULL, /* PyObject *tp_cache; */ - NULL, /* PyObject *tp_subclasses; */ - NULL, /* PyObject *tp_weaklist; */ + NULL, /* PyObject *tp_mro; */ + NULL, /* PyObject *tp_cache; */ + NULL, /* PyObject *tp_subclasses; */ + NULL, /* PyObject *tp_weaklist; */ NULL }; @@ -1180,84 +1686,84 @@ PyTypeObject Sequence_Type = { /* Python TypeSequence structure definition: */ /*****************************************************************************/ PyTypeObject SceneSeq_Type = { - PyObject_HEAD_INIT( NULL ) /* required py macro */ - 0, /* ob_size */ + PyObject_HEAD_INIT(NULL) /* required py macro */ + 0, /* ob_size */ /* For printing, in format "<module>.<name>" */ - "Blender SceneSeq", /* char *tp_name; */ - sizeof( BPy_Sequence ), /* int tp_basicsize; */ - 0, /* tp_itemsize; For allocation */ + "Blender SceneSeq", /* char *tp_name; */ + sizeof ( BPy_Sequence), /* int tp_basicsize; */ + 0, /* tp_itemsize; For allocation */ /* Methods to implement standard operations */ - NULL,/* destructor tp_dealloc; */ - NULL, /* printfunc tp_print; */ - NULL, /* getattrfunc tp_getattr; */ - NULL, /* setattrfunc tp_setattr; */ - ( cmpfunc ) SceneSeq_compare, /* cmpfunc tp_compare; */ - ( reprfunc ) SceneSeq_repr, /* reprfunc tp_repr; */ + NULL, /* destructor tp_dealloc; */ + NULL, /* printfunc tp_print; */ + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ + (cmpfunc) SceneSeq_compare, /* cmpfunc tp_compare; */ + (reprfunc) SceneSeq_repr, /* reprfunc tp_repr; */ /* Method suites for standard classes */ - NULL, /* PyNumberMethods *tp_as_number; */ - NULL, /* PySequenceMethods *tp_as_sequence; */ - NULL, /* PyMappingMethods *tp_as_mapping; */ + NULL, /* PyNumberMethods *tp_as_number; */ + NULL, /* PySequenceMethods *tp_as_sequence; */ + NULL, /* PyMappingMethods *tp_as_mapping; */ /* More standard operations (here for binary compatibility) */ - NULL, /* hashfunc tp_hash; */ - NULL, /* ternaryfunc tp_call; */ - NULL, /* reprfunc tp_str; */ - NULL, /* getattrofunc tp_getattro; */ - NULL, /* setattrofunc tp_setattro; */ + NULL, /* hashfunc tp_hash; */ + NULL, /* ternaryfunc tp_call; */ + NULL, /* reprfunc tp_str; */ + NULL, /* getattrofunc tp_getattro; */ + NULL, /* setattrofunc tp_setattro; */ /* Functions to access object as input/output buffer */ - NULL, /* PyBufferProcs *tp_as_buffer; */ + NULL, /* PyBufferProcs *tp_as_buffer; */ - /*** Flags to define presence of optional/expanded features ***/ - Py_TPFLAGS_DEFAULT, /* long tp_flags; */ + /*** Flags to define presence of optional/expanded features ***/ + Py_TPFLAGS_DEFAULT, /* long tp_flags; */ - NULL, /* char *tp_doc; Documentation string */ - /*** Assigned meaning in release 2.0 ***/ + NULL, /* char *tp_doc; Documentation string */ + /*** Assigned meaning in release 2.0 ***/ /* call function for all accessible objects */ - NULL, /* traverseproc tp_traverse; */ + NULL, /* traverseproc tp_traverse; */ /* delete references to contained objects */ - NULL, /* inquiry tp_clear; */ + NULL, /* inquiry tp_clear; */ - /*** Assigned meaning in release 2.1 ***/ - /*** rich comparisons ***/ - NULL, /* richcmpfunc tp_richcompare; */ + /*** Assigned meaning in release 2.1 ***/ + /*** rich comparisons ***/ + NULL, /* richcmpfunc tp_richcompare; */ - /*** weak reference enabler ***/ - 0, /* long tp_weaklistoffset; */ + /*** weak reference enabler ***/ + 0, /* long tp_weaklistoffset; */ - /*** Added in release 2.2 ***/ + /*** Added in release 2.2 ***/ /* Iterators */ - ( getiterfunc ) SceneSeq_getIter, /* getiterfunc tp_iter; */ - ( iternextfunc ) SceneSeq_nextIter, /* iternextfunc tp_iternext; */ - - /*** Attribute descriptor and subclassing stuff ***/ - BPy_SceneSeq_methods, /* struct PyMethodDef *tp_methods; */ - NULL, /* struct PyMemberDef *tp_members; */ - BPy_SceneSeq_getseters, /* struct PyGetSetDef *tp_getset; */ - NULL, /* struct _typeobject *tp_base; */ - NULL, /* PyObject *tp_dict; */ - NULL, /* descrgetfunc tp_descr_get; */ - NULL, /* descrsetfunc tp_descr_set; */ - 0, /* long tp_dictoffset; */ - NULL, /* initproc tp_init; */ - NULL, /* allocfunc tp_alloc; */ - NULL, /* newfunc tp_new; */ + (getiterfunc) SceneSeq_getIter, /* getiterfunc tp_iter; */ + (iternextfunc) SceneSeq_nextIter, /* iternextfunc tp_iternext; */ + + /*** Attribute descriptor and subclassing stuff ***/ + BPy_SceneSeq_methods, /* struct PyMethodDef *tp_methods; */ + NULL, /* struct PyMemberDef *tp_members; */ + BPy_SceneSeq_getseters, /* struct PyGetSetDef *tp_getset; */ + NULL, /* struct _typeobject *tp_base; */ + NULL, /* PyObject *tp_dict; */ + NULL, /* descrgetfunc tp_descr_get; */ + NULL, /* descrsetfunc tp_descr_set; */ + 0, /* long tp_dictoffset; */ + NULL, /* initproc tp_init; */ + NULL, /* allocfunc tp_alloc; */ + NULL, /* newfunc tp_new; */ /* Low-level free-memory routine */ - NULL, /* freefunc tp_free; */ + NULL, /* freefunc tp_free; */ /* For PyObject_IS_GC */ - NULL, /* inquiry tp_is_gc; */ - NULL, /* PyObject *tp_bases; */ + NULL, /* inquiry tp_is_gc; */ + NULL, /* PyObject *tp_bases; */ /* method resolution order */ - NULL, /* PyObject *tp_mro; */ - NULL, /* PyObject *tp_cache; */ - NULL, /* PyObject *tp_subclasses; */ - NULL, /* PyObject *tp_weaklist; */ + NULL, /* PyObject *tp_mro; */ + NULL, /* PyObject *tp_cache; */ + NULL, /* PyObject *tp_subclasses; */ + NULL, /* PyObject *tp_weaklist; */ NULL }; @@ -1271,27 +1777,28 @@ PyObject *M_Sequence_Get( PyObject * self, PyObject * args ) { return SceneSeq_CreatePyObject( G.scene, NULL ); } -*/ + */ /*****************************************************************************/ /* Function: initObject */ + /*****************************************************************************/ -PyObject *Sequence_Init( void ) +PyObject *Sequence_Init(void) { - PyObject *BlendModesDict = M_Sequence_BlendModesDict( ); + PyObject *BlendModesDict = M_Sequence_BlendModesDict(); PyObject *submodule; - if( PyType_Ready( &Sequence_Type ) < 0 ) + if (PyType_Ready(&Sequence_Type) < 0) return NULL; - if( PyType_Ready( &SceneSeq_Type ) < 0 ) + if (PyType_Ready(&SceneSeq_Type) < 0) return NULL; - + /* NULL was M_Sequence_methods*/ - submodule = Py_InitModule3( "Blender.Scene.Sequence", NULL, -"The Blender Sequence module\n\n\ -This module provides access to **Sequence Data** in Blender.\n" ); + submodule = Py_InitModule3("Blender.Scene.Sequence", NULL, + "The Blender Sequence module\n\n\ +This module provides access to **Sequence Data** in Blender.\n"); - if( BlendModesDict ) - PyModule_AddObject( submodule, "BlendModes", BlendModesDict ); + if (BlendModesDict) + PyModule_AddObject(submodule, "BlendModes", BlendModesDict); /*Add SUBMODULES to the module*/ /*PyDict_SetItemString(dict, "Constraint", Constraint_Init()); //creates a *new* module*/ @@ -1303,68 +1810,74 @@ This module provides access to **Sequence Data** in Blender.\n" ); /* Function: Sequence_CreatePyObject */ /* Description: This function will create a new BlenObject from an existing */ /* Object structure. */ + /*****************************************************************************/ -PyObject *Sequence_CreatePyObject( struct Sequence * seq, struct Sequence * iter, struct Scene *sce) +PyObject *Sequence_CreatePyObject(struct Sequence * seq, struct Sequence * iter, struct Scene *sce) { BPy_Sequence *pyseq; - if( !seq ) + if (!seq) Py_RETURN_NONE; pyseq = - ( BPy_Sequence * ) PyObject_NEW( BPy_Sequence, &Sequence_Type ); + (BPy_Sequence *) PyObject_NEW(BPy_Sequence, &Sequence_Type); - if( pyseq == NULL ) { - return ( NULL ); + if (pyseq == NULL) + { + return ( NULL); } pyseq->seq = seq; pyseq->iter = iter; pyseq->scene = sce; - - return ( ( PyObject * ) pyseq ); + + return ( (PyObject *) pyseq); } /*****************************************************************************/ /* Function: SceneSeq_CreatePyObject */ /* Description: This function will create a new BlenObject from an existing */ /* Object structure. */ + /*****************************************************************************/ -PyObject *SceneSeq_CreatePyObject( struct Scene * scn, struct Sequence * iter) +PyObject *SceneSeq_CreatePyObject(struct Scene * scn, struct Sequence * iter) { BPy_SceneSeq *pysceseq; - if( !scn ) + if (!scn) Py_RETURN_NONE; - if ( !scn->ed ) { + if (!scn->ed) + { Editing *ed; - ed= scn->ed= MEM_callocN( sizeof(Editing), "addseq"); - ed->seqbasep= &ed->seqbase; + ed = scn->ed = MEM_callocN(sizeof (Editing), "addseq"); + ed->seqbasep = &ed->seqbase; } - + pysceseq = - ( BPy_SceneSeq * ) PyObject_NEW( BPy_SceneSeq, &SceneSeq_Type ); + (BPy_SceneSeq *) PyObject_NEW(BPy_SceneSeq, &SceneSeq_Type); - if( pysceseq == NULL ) { - return ( NULL ); + if (pysceseq == NULL) + { + return ( NULL); } pysceseq->scene = scn; pysceseq->iter = iter; - - return ( ( PyObject * ) pysceseq ); + + return ( (PyObject *) pysceseq); } /*****************************************************************************/ /* Function: Sequence_FromPyObject */ /* Description: This function returns the Blender sequence from the given */ /* PyObject. */ + /*****************************************************************************/ -struct Sequence *Sequence_FromPyObject( PyObject * py_seq ) +struct Sequence *Sequence_FromPyObject(PyObject * py_seq) { BPy_Sequence *blen_seq; - blen_seq = ( BPy_Sequence * ) py_seq; - return ( blen_seq->seq ); + blen_seq = (BPy_Sequence *) py_seq; + return ( blen_seq->seq); } /*****************************************************************************/ @@ -1374,33 +1887,36 @@ struct Sequence *Sequence_FromPyObject( PyObject * py_seq ) /* comparisons are meaninful. Returns 0 for equality and -1 if */ /* they don't point to the same Blender Object struct. */ /* In Python it becomes 1 if they are equal, 0 otherwise. */ + /*****************************************************************************/ -static int Sequence_compare( BPy_Sequence * a, BPy_Sequence * b ) +static int Sequence_compare(BPy_Sequence * a, BPy_Sequence * b) { Sequence *pa = a->seq, *pb = b->seq; - return ( pa == pb ) ? 0 : -1; + return ( pa == pb) ? 0 : -1; } -static int SceneSeq_compare( BPy_SceneSeq * a, BPy_SceneSeq * b ) +static int SceneSeq_compare(BPy_SceneSeq * a, BPy_SceneSeq * b) { - + Scene *pa = a->scene, *pb = b->scene; - return ( pa == pb ) ? 0 : -1; + return ( pa == pb) ? 0 : -1; } /*****************************************************************************/ /* Function: Sequence_repr / SceneSeq_repr */ /* Description: This is a callback function for the BPy_Sequence type. It */ /* builds a meaninful string to represent object objects. */ + /*****************************************************************************/ -static PyObject *Sequence_repr( BPy_Sequence * self ) +static PyObject *Sequence_repr(BPy_Sequence * self) { - return PyString_FromFormat( "[Sequence Strip \"%s\"]", - self->seq->name + 2 ); + return PyString_FromFormat("[Sequence Strip \"%s\"]", + self->seq->name + 2); } -static PyObject *SceneSeq_repr( BPy_SceneSeq * self ) + +static PyObject *SceneSeq_repr(BPy_SceneSeq * self) { - return PyString_FromFormat( "[Scene Sequence \"%s\"]", - self->scene->id.name + 2 ); + return PyString_FromFormat("[Scene Sequence \"%s\"]", + self->scene->id.name + 2); } diff --git a/source/blender/quicktime/apple/quicktime_import.c b/source/blender/quicktime/apple/quicktime_import.c index 5a3c76b9d6f..1f3071f114c 100644 --- a/source/blender/quicktime/apple/quicktime_import.c +++ b/source/blender/quicktime/apple/quicktime_import.c @@ -159,6 +159,7 @@ int anim_is_quicktime (char *name) BLI_testextensie(name, ".avi") || // wouldnt be appropriate ;) BLI_testextensie(name, ".tga") || BLI_testextensie(name, ".png") || + BLI_testextensie(name, ".bmp") || BLI_testextensie(name, ".jpg") || BLI_testextensie(name, ".wav") || BLI_testextensie(name, ".zip") || diff --git a/source/blender/radiosity/intern/source/radfactors.c b/source/blender/radiosity/intern/source/radfactors.c index ba4dbf1b793..d5b7c1caef3 100644 --- a/source/blender/radiosity/intern/source/radfactors.c +++ b/source/blender/radiosity/intern/source/radfactors.c @@ -535,10 +535,10 @@ void progressiverad() if(shoot->first->f & RAD_TWOSIDED) { VECCOPY(unshot, shoot->unshot); - VecMulf(shoot->norm, -1.0); + VecNegf(shoot->norm); if(makeformfactors(shoot)) applyformfactors(shoot); - VecMulf(shoot->norm, -1.0); + VecNegf(shoot->norm); VECCOPY(shoot->unshot, unshot); } diff --git a/source/blender/radiosity/intern/source/radrender.c b/source/blender/radiosity/intern/source/radrender.c index 68b5fa81f43..454a7d01688 100644 --- a/source/blender/radiosity/intern/source/radrender.c +++ b/source/blender/radiosity/intern/source/radrender.c @@ -299,10 +299,10 @@ static void progressiverad_rr(Render *re) /* ...unless it's two sided */ if(shootrf->flag & RAD_TWOSIDED) { VECCOPY(unshot, shootrf->unshot); - VecMulf(shootrf->norm, -1.0); + VecNegf(shootrf->norm); makeformfactors_rr(re, shoot, shootrf); applyformfactors_rr(re, shoot, shootrf); - VecMulf(shootrf->norm, -1.0); + VecNegf(shootrf->norm); VECCOPY(shootrf->unshot, unshot); } diff --git a/source/blender/readblenfile/intern/BLO_readblenfile.c b/source/blender/readblenfile/intern/BLO_readblenfile.c index ec71611b31d..aa853e13e48 100644 --- a/source/blender/readblenfile/intern/BLO_readblenfile.c +++ b/source/blender/readblenfile/intern/BLO_readblenfile.c @@ -67,7 +67,7 @@ char *headerMagic = "BLENDFI"; */ void BLO_setversionnumber(char array[4], int version) { - memset(array, 0, sizeof(array)); + memset(array, 0, sizeof(char)*4); array[1] = version / 100; array[2] = version % 100; diff --git a/source/blender/render/intern/source/occlusion.c b/source/blender/render/intern/source/occlusion.c index d2d2cf3fb77..494feb96c18 100644 --- a/source/blender/render/intern/source/occlusion.c +++ b/source/blender/render/intern/source/occlusion.c @@ -181,8 +181,8 @@ static void occ_shade(ShadeSample *ssamp, ObjectInstanceRen *obi, VlakRen *vlr, /* not a pretty solution, but fixes common cases */ if(shi->obr->ob && shi->obr->ob->transflag & OB_NEG_SCALE) { - VecMulf(shi->vn, -1.0f); - VecMulf(shi->vno, -1.0f); + VecNegf(shi->vn); + VecNegf(shi->vno); } /* init material vars */ @@ -1288,7 +1288,7 @@ static void occ_compute_passes(Render *re, OcclusionTree *tree, int totpass) for(pass=0; pass<totpass; pass++) { for(i=0; i<tree->totface; i++) { occ_face(&tree->face[i], co, n, NULL); - VecMulf(n, -1.0f); + VecNegf(n); VECADDFAC(co, co, n, 1e-8f); occ_lookup(tree, 0, &tree->face[i], co, n, &occ[i], NULL); @@ -1321,7 +1321,7 @@ static void sample_occ_tree(Render *re, OcclusionTree *tree, OccFace *exclude, f aocolor= WO_AOPLAIN; VECCOPY(nn, n); - VecMulf(nn, -1.0f); + VecNegf(nn); occ_lookup(tree, thread, exclude, co, nn, &occ, (aocolor)? bn: NULL); @@ -1525,7 +1525,7 @@ static void *exec_strandsurface_sample(void *data) CalcCent3f(co, co1, co2, co3); CalcNormFloat(co1, co2, co3, n); } - VecMulf(n, -1.0f); + VecNegf(n); sample_occ_tree(re, re->occlusiontree, NULL, co, n, othread->thread, 0, col); VECCOPY(othread->facecol[a], col); diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 1dfcbc6e45d..5c3c954aa8e 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -2616,17 +2616,20 @@ void RE_BlenderAnim(Render *re, Scene *scene, int sfra, int efra, int tfra) else nfra+= tfra; - if (scene->r.mode & (R_NO_OVERWRITE | R_TOUCH) ) { - BKE_makepicstring(name, scene->r.pic, scene->r.cfra, scene->r.imtype); - } - - if (scene->r.mode & R_NO_OVERWRITE && BLI_exist(name)) { - printf("skipping existing frame \"%s\"\n", name); - continue; - } - if (scene->r.mode & R_TOUCH && !BLI_exist(name)) { - BLI_make_existing_file(name); /* makes the dir if its not there */ - BLI_touch(name); + /* Touch/NoOverwrite options are only valid for image's */ + if(BKE_imtype_is_movie(scene->r.imtype) == 0) { + if (scene->r.mode & (R_NO_OVERWRITE | R_TOUCH) ) { + BKE_makepicstring(name, scene->r.pic, scene->r.cfra, scene->r.imtype); + } + + if (scene->r.mode & R_NO_OVERWRITE && BLI_exist(name)) { + printf("skipping existing frame \"%s\"\n", name); + continue; + } + if (scene->r.mode & R_TOUCH && !BLI_exist(name)) { + BLI_make_existing_file(name); /* makes the dir if its not there */ + BLI_touch(name); + } } re->r.cfra= scene->r.cfra; /* weak.... */ @@ -2639,8 +2642,10 @@ void RE_BlenderAnim(Render *re, Scene *scene, int sfra, int efra, int tfra) if(G.afbreek==1) { /* remove touched file */ - if (scene->r.mode & R_TOUCH && BLI_exist(name) && BLI_filepathsize(name) == 0) { - BLI_delete(name, 0, 0); + if(BKE_imtype_is_movie(scene->r.imtype) == 0) { + if (scene->r.mode & R_TOUCH && BLI_exist(name) && BLI_filepathsize(name) == 0) { + BLI_delete(name, 0, 0); + } } break; @@ -2705,7 +2710,7 @@ void RE_set_max_threads(int threads) } else if(threads>=1 && threads<=BLENDER_MAX_THREADS) { commandline_threads= threads; } else { - printf("Error, threads has to be in range 1-%d\n", BLENDER_MAX_THREADS); + printf("Error, threads has to be in range 0-%d\n", BLENDER_MAX_THREADS); } } diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index c3b281f2a23..5dfb509939b 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -1505,8 +1505,8 @@ static void shade_sample_sss(ShadeSample *ssamp, Material *mat, ObjectInstanceRe /* not a pretty solution, but fixes common cases */ if(shi->obr->ob && shi->obr->ob->transflag & OB_NEG_SCALE) { - VecMulf(shi->vn, -1.0f); - VecMulf(shi->vno, -1.0f); + VecNegf(shi->vn); + VecNegf(shi->vno); } /* if nodetree, use the material that we are currently preprocessing diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c index 476330152ec..1cd8ec110f9 100644 --- a/source/blender/render/intern/source/shadeinput.c +++ b/source/blender/render/intern/source/shadeinput.c @@ -354,7 +354,7 @@ void shade_input_set_strand(ShadeInput *shi, StrandRen *strand, StrandPoint *spo Normalize(shi->vn); if(INPR(shi->vn, shi->view) < 0.0f) - VecMulf(shi->vn, -1.0f); + VecNegf(shi->vn); } VECCOPY(shi->vno, shi->vn); diff --git a/source/blender/src/SConscript b/source/blender/src/SConscript index c5edd711d0a..384ad1b1bf2 100644 --- a/source/blender/src/SConscript +++ b/source/blender/src/SConscript @@ -53,6 +53,9 @@ if env['WITH_BF_INTERNATIONAL']: if env['WITH_BF_OPENEXR']: defs.append('WITH_OPENEXR') +if env['WITH_BF_OPENJPEG']: + defs.append('WITH_OPENJPEG') + if env['WITH_BF_DDS']: defs.append('WITH_DDS') @@ -94,6 +97,9 @@ if env['WITH_BF_SDL']: else: defs.append('DISABLE_SDL') +if env['WITH_BF_BULLET']: + defs.append('WITH_BULLET') + if env['BF_SPLIT_SRC'] and (env['OURPLATFORM'] == 'win32-mingw'): for i in range(numlibs): env.BlenderLib ( libname = 'src%d' % (i), sources = subsources[i], includes = Split(incs), defines = defs, libtype=['core', 'intern'], priority = [5, 25] ) diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index 50c644ade6f..7b564bdd7a3 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -184,7 +184,7 @@ static float editbutweight= 1.0; float editbutvweight= 1; -static int actmcol= 0, acttface= 0, acttface_rnd = 0, actmcol_rnd = 0; +static int actmcol= 0, acttface= 0, acttface_rnd = 0, acttface_clone = 0, acttface_mask = 0, actmcol_rnd = 0; extern ListBase editNurb; @@ -722,10 +722,10 @@ static void delete_customdata_layer(void *data1, void *data2) Mesh *me= (Mesh*)data1; CustomData *data= (G.obedit)? &G.editMesh->fdata: &me->fdata; CustomDataLayer *layer= (CustomDataLayer*)data2; - void *actlayerdata, *rndlayerdata, *layerdata=layer->data; + void *actlayerdata, *rndlayerdata, *clonelayerdata, *masklayerdata, *layerdata=layer->data; int type= layer->type; int index= CustomData_get_layer_index(data, type); - int i, actindex, rndindex; + int i, actindex, rndindex, cloneindex, maskindex; /*ok, deleting a non-active layer needs to preserve the active layer indices. to do this, we store a pointer to the .data member of both layer and the active layer, @@ -736,6 +736,8 @@ static void delete_customdata_layer(void *data1, void *data2) layer. */ actlayerdata = data->layers[CustomData_get_active_layer_index(data, type)].data; rndlayerdata = data->layers[CustomData_get_render_layer_index(data, type)].data; + clonelayerdata = data->layers[CustomData_get_clone_layer_index(data, type)].data; + masklayerdata = data->layers[CustomData_get_mask_layer_index(data, type)].data; CustomData_set_layer_active(data, type, layer - &data->layers[index]); /* Multires is handled seperately because the display data is separate @@ -787,6 +789,33 @@ static void delete_customdata_layer(void *data1, void *data2) CustomData_set_layer_render(data, type, rndindex); } + if (clonelayerdata != layerdata) { + /*find index. . .*/ + cloneindex = CustomData_get_layer_index(data, type); + for (i=cloneindex; i<data->totlayer; i++) { + if (data->layers[i].data == clonelayerdata) { + cloneindex = i - cloneindex; + break; + } + } + + /*set index. . .*/ + CustomData_set_layer_clone(data, type, cloneindex); + } + + if (masklayerdata != layerdata) { + /*find index. . .*/ + maskindex = CustomData_get_layer_index(data, type); + for (i=maskindex; i<data->totlayer; i++) { + if (data->layers[i].data == masklayerdata) { + maskindex = i - maskindex; + break; + } + } + + /*set index. . .*/ + CustomData_set_layer_mask(data, type, maskindex); + } DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA); @@ -802,9 +831,9 @@ static void delete_customdata_layer(void *data1, void *data2) static int customdata_buttons( uiBlock *block, Mesh *me, CustomData *data, - int type, int *activep, int *renderp, - int setevt, int setevt_rnd, int newevt, - char *label, char *shortlabel, char *browsetip, char *browsetip_rnd, + int type, int *activep, int *renderp, int *clonep, int *maskp, + int setevt, int setevt_rnd, int setevt_clone, int setevt_mask, int newevt, + char *label, char *shortlabel, char *browsetip, char *browsetip_rnd, char *browsetip_clone, char *browsetip_mask, char *newtip, char *deltip, int x, int y) { CustomDataLayer *layer; @@ -828,12 +857,27 @@ static int customdata_buttons( layer= &data->layers[i]; if(layer->type == type) { + int xi = 0; *activep= layer->active + 1; *renderp= layer->active_rnd + 1; + if (clonep) *clonep= layer->active_clone + 1; + if (maskp) *maskp= layer->active_mask + 1; + uiDefIconButI(block, ROW, setevt, ICON_VIEW3D, x,y,25,19, activep, 1.0, count, 0, 0, browsetip); uiDefIconButI(block, ROW, setevt_rnd, ICON_SCENE, x+25,y,25,19, renderp, 1.0, count, 0, 0, browsetip_rnd); - but=uiDefBut(block, TEX, setevt, "", x+50,y,145,19, layer->name, 0.0, 31.0, 0, 0, label); + + if (clonep) { + uiDefIconButI(block, ROW, setevt_clone, ICON_TEXTURE, x+50,y,25,19, clonep, 1.0, count, 0, 0, browsetip_clone); + xi += 25; + } + + if (maskp) { + uiDefIconButI(block, ROW, setevt_mask, ICON_PAINT, x+50+xi,y,25,19, maskp, 1.0, count, 0, 0, browsetip_mask); + xi += 25; + } + + but=uiDefBut(block, TEX, setevt, "", x+50+xi,y,145-xi,19, layer->name, 0.0, 31.0, 0, 0, label); uiButSetFunc(but, verify_customdata_name_func, data, layer); but= uiDefIconBut(block, BUT, B_NOP, VICON_X, x+195,y,25,19, NULL, 0.0, 0.0, 0.0, 0.0, deltip); uiButSetFunc(but, delete_customdata_layer, me, layer); @@ -902,14 +946,14 @@ static void editing_panel_mesh_type(Object *ob, Mesh *me) uiBlockEndAlign(block); fdata= (G.obedit)? &G.editMesh->fdata: &me->fdata; - yco= customdata_buttons(block, me, fdata, CD_MTFACE, &acttface, &acttface_rnd, - B_SETTFACE, B_SETTFACE_RND, B_NEWTFACE, "UV Texture", "UV Texture:", - "Set active UV texture", "Set rendering UV texture", "Creates a new UV texture layer", + yco= customdata_buttons(block, me, fdata, CD_MTFACE, &acttface, &acttface_rnd, (G.f & G_TEXTUREPAINT ? &acttface_clone : NULL), (G.f & G_TEXTUREPAINT ? &acttface_mask : NULL), + B_SETTFACE, B_SETTFACE_RND, B_SETTFACE_CLONE, B_SETTFACE_MASK, B_NEWTFACE, "UV Texture", "UV Texture:", + "Set active UV texture", "Set rendering UV texture", "Set the layer used for texturepaint cloning", "Set the texture paint stencil layer", "Creates a new UV texture layer", "Removes the current UV texture layer", 190, 130); - yco= customdata_buttons(block, me, fdata, CD_MCOL, &actmcol, &actmcol_rnd, - B_SETMCOL, B_SETMCOL_RND, B_NEWMCOL, "Vertex Color", "Vertex Color:", - "Sets active vertex color layer", "Sets rendering vertex color layer", "Creates a new vertex color layer", + yco= customdata_buttons(block, me, fdata, CD_MCOL, &actmcol, &actmcol_rnd, NULL, NULL, + B_SETMCOL, B_SETMCOL_RND, B_NOP, B_NOP, B_NEWMCOL, "Vertex Color", "Vertex Color:", + "Sets active vertex color layer", "Sets rendering vertex color layer", "", "", "Creates a new vertex color layer", "Removes the current vertex color layer", 190, yco-5); if(yco < 0) @@ -1900,13 +1944,14 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco uiButSetFunc(but, modifiers_applyModifier, ob, md); } + uiClearButLock(); + uiSetButLock(ob && ob->id.lib, ERROR_LIBDATA_MESSAGE); + if (md->type!=eModifierType_Fluidsim && md->type!=eModifierType_Softbody && md->type!=eModifierType_ParticleSystem && (md->type!=eModifierType_Cloth)) { but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Copy", lx,(cy-=19),60,19, 0, 0, 0, 0, 0, "Duplicate the current modifier at the same position in the stack"); uiButSetFunc(but, modifiers_copyModifier, ob, md); } uiBlockEndAlign(block); - - uiSetButLock(ob && ob->id.lib, ERROR_LIBDATA_MESSAGE); } lx = x + 10; @@ -4964,7 +5009,22 @@ void do_meshbuts(unsigned short event) allqueue(REDRAWBUTSEDIT, 0); } break; - + case B_SETTFACE_CLONE: + if (G.obedit || me) { + CustomData *fdata= (G.obedit)? &em->fdata: &me->fdata; + CustomData_set_layer_clone(fdata, CD_MTFACE, acttface_clone-1); + BIF_undo_push("Set Clone UV Texture"); + allqueue(REDRAWBUTSEDIT, 0); + } + break; + case B_SETTFACE_MASK: + if (G.obedit || me) { + CustomData *fdata= (G.obedit)? &em->fdata: &me->fdata; + CustomData_set_layer_mask(fdata, CD_MTFACE, acttface_mask-1); + BIF_undo_push("Set Stencil UV Texture"); + allqueue(REDRAWBUTSEDIT, 0); + } + break; case B_FLIPNORM: if(G.obedit) { flip_editnormals(); @@ -5465,7 +5525,6 @@ static void editing_panel_links(Object *ob) uiBlockSetCol(block, TH_AUTO); } if(ob) { - uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE); but = uiDefBut(block, TEX, B_IDNAME, "OB:", xco, 180, 454-xco, YIC, ob->id.name+2, 0.0, 21.0, 0, 0, "Active Object name."); #ifdef WITH_VERSE if(ob->vnode) uiButSetFunc(but, test_and_send_idbutton_cb, ob, ob->id.name); @@ -5474,6 +5533,7 @@ static void editing_panel_links(Object *ob) uiButSetFunc(but, test_idbutton_cb, ob->id.name, NULL); #endif + uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE); } /* empty display handling, note it returns! */ @@ -6269,6 +6329,135 @@ void weight_paint_buttons(uiBlock *block) } } +void brush_buttons(uiBlock *block, short sima, + int evt_nop, int evt_change, + int evt_browse, int evt_local, + int evt_del, int evt_keepdata, + int evt_texbrowse, int evt_texdel) +{ + ToolSettings *settings= G.scene->toolsettings; + Brush *brush= settings->imapaint.brush; + ID *id; + int yco, xco, butw, but_idx; + + short *menupoin = sima ? &(G.sima->menunr) : &(G.buts->menunr); + short do_project = settings->imapaint.flag & IMAGEPAINT_PROJECT_DISABLE ? 0:1; + + yco= 160; + + butw = sima ? 80 : 106; + + uiBlockBeginAlign(block); + but_idx = 0; + uiDefButS(block, ROW, evt_change, "Draw", butw*(but_idx++),yco,butw,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_DRAW, 0, 0, "Draw brush"); + if (sima || do_project==0) + uiDefButS(block, ROW, evt_change, "Soften", butw*(but_idx++), yco,butw,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_SOFTEN, 0, 0, "Soften brush"); + uiDefButS(block, ROW, evt_change, "Smear", butw*(but_idx++), yco,butw,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_SMEAR, 0, 0, "Smear brush"); + if (sima || do_project) + uiDefButS(block, ROW, evt_change, "Clone", butw*(but_idx++), yco,butw,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_CLONE, 0, 0, "Clone brush, use RMB to drag source image"); + + uiBlockEndAlign(block); + yco -= 30; + + uiBlockSetCol(block, TH_BUT_SETTING2); + id= (ID*)settings->imapaint.brush; + xco= std_libbuttons(block, 0, yco, 0, NULL, evt_browse, ID_BR, 0, id, NULL, menupoin, 0, evt_local, evt_del, 0, evt_keepdata); + uiBlockSetCol(block, TH_AUTO); + + if(brush && !brush->id.lib) { + + butw= 320-(xco+10); + + uiDefButS(block, MENU, evt_nop, "Mix %x0|Add %x1|Subtract %x2|Multiply %x3|Lighten %x4|Darken %x5|Erase Alpha %x6|Add Alpha %x7", xco+10,yco,butw,19, &brush->blend, 0, 0, 0, 0, "Blending method for applying brushes"); + + uiBlockBeginAlign(block); + uiDefButBitS(block, TOG|BIT, BRUSH_AIRBRUSH, evt_change, "Airbrush", xco+10,yco-25,butw/2,19, &brush->flag, 0, 0, 0, 0, "Keep applying paint effect while holding mouse (spray)"); + uiDefButF(block, NUM, evt_nop, "", xco+10 + butw/2,yco-25,butw/2,19, &brush->rate, 0.01, 1.0, 0, 0, "Number of paints per second for Airbrush"); + uiBlockEndAlign(block); + + if (sima) { + uiDefButBitS(block, TOG|BIT, BRUSH_TORUS, evt_change, "Wrap", xco+10,yco-45,butw,19, &brush->flag, 0, 0, 0, 0, "Enables torus wrapping"); + yco -= 25; + } + else { + yco -= 25; + uiBlockBeginAlign(block); + uiDefButBitS(block, TOGN|BIT, IMAGEPAINT_PROJECT_DISABLE, B_REDR, "Project Paint", xco+10,yco-25,butw,19, &settings->imapaint.flag, 0, 0, 0, 0, "Use projection painting for improved consistency in the brush strokes"); + + if ((settings->imapaint.flag & IMAGEPAINT_PROJECT_DISABLE)==0) { + + + /* Projection Painting */ + + uiDefButBitS(block, TOGN|BIT, IMAGEPAINT_PROJECT_XRAY, B_NOP, "Occlude", xco+10,yco-45,butw/2,19, &settings->imapaint.flag, 0, 0, 0, 0, "Only paint onto the faces directly under the brush (slower)"); + uiDefButBitS(block, TOGN|BIT, IMAGEPAINT_PROJECT_BACKFACE, B_NOP, "Cull", xco+10+butw/2,yco-45,butw/2,19, &settings->imapaint.flag, 0, 0, 0, 0, "Ignore faces pointing away from the view (faster)"); + + uiDefButBitS(block, TOGN|BIT, IMAGEPAINT_PROJECT_FLAT, B_NOP, "Normal", xco+10,yco-65,butw/2,19, &settings->imapaint.flag, 0, 0, 0, 0, "Paint most on faces pointing towards the view"); + uiDefButS(block, NUM, B_NOP, "", xco+10 +(butw/2),yco-65,butw/2,19, &settings->imapaint.normal_angle, 10.0, 90.0, 0, 0, "Paint most on faces pointing towards the view acording to this angle"); + + uiDefButS(block, NUM, B_NOP, "Bleed: ", xco+10,yco-85,butw,19, &settings->imapaint.seam_bleed, 0.0, 8.0, 0, 0, "Extend paint beyond the faces UVs to reduce seams (in pixels, slower)"); + uiBlockEndAlign(block); + + uiBlockBeginAlign(block); + uiDefButBitS(block, TOG|BIT, IMAGEPAINT_PROJECT_LAYER_MASK, B_NOP, "Stencil Layer", xco+10,yco-110,butw-30,19, &settings->imapaint.flag, 0, 0, 0, 0, "Set the mask layer from the UV layer buttons"); + uiDefButBitS(block, TOG|BIT, IMAGEPAINT_PROJECT_LAYER_MASK_INV, B_NOP, "Inv", xco+10 + butw-30,yco-110,30,19, &settings->imapaint.flag, 0, 0, 0, 0, "Invert the mask"); + uiBlockEndAlign(block); + + } + uiBlockEndAlign(block); + } + + uiBlockBeginAlign(block); + uiDefButF(block, COL, B_VPCOLSLI, "", 0,yco,200,19, brush->rgb, 0, 0, 0, 0, ""); + uiDefButF(block, NUMSLI, evt_nop, "Opacity ", 0,yco-20,180,19, &brush->alpha, 0.0, 1.0, 0, 0, "The amount of pressure on the brush"); + uiDefButBitS(block, TOG|BIT, BRUSH_ALPHA_PRESSURE, evt_nop, "P", 180,yco-20,20,19, &brush->flag, 0, 0, 0, 0, "Enables pressure sensitivity for tablets"); + uiDefButI(block, NUMSLI, evt_nop, "Size ", 0,yco-40,180,19, &brush->size, 1, 200, 0, 0, "The size of the brush"); + uiDefButBitS(block, TOG|BIT, BRUSH_SIZE_PRESSURE, evt_nop, "P", 180,yco-40,20,19, &brush->flag, 0, 0, 0, 0, "Enables pressure sensitivity for tablets"); + uiDefButF(block, NUMSLI, evt_nop, "Falloff ", 0,yco-60,180,19, &brush->innerradius, 0.0, 1.0, 0, 0, "The fall off radius of the brush"); + uiDefButBitS(block, TOG|BIT, BRUSH_RAD_PRESSURE, evt_nop, "P", 180,yco-60,20,19, &brush->flag, 0, 0, 0, 0, "Enables pressure sensitivity for tablets"); + uiDefButF(block, NUMSLI, evt_nop, "Spacing ",0,yco-80,180,19, &brush->spacing, 1.0, 100.0, 0, 0, "Repeating paint on %% of brush diameter"); + uiDefButBitS(block, TOG|BIT, BRUSH_SPACING_PRESSURE, evt_nop, "P", 180,yco-80,20,19, &brush->flag, 0, 0, 0, 0, "Enables pressure sensitivity for tablets"); + uiBlockEndAlign(block); + + yco -= 110; + + if(sima && settings->imapaint.tool == PAINT_TOOL_CLONE) { + id= (ID*)brush->clone.image; + uiBlockSetCol(block, TH_BUT_SETTING2); + xco= std_libbuttons(block, 0, yco, 0, NULL, B_SIMACLONEBROWSE, ID_IM, 0, id, 0, menupoin, 0, 0, B_SIMACLONEDELETE, 0, 0); + uiBlockSetCol(block, TH_AUTO); + if(id) { + butw= 320-(xco+5); + uiDefButF(block, NUMSLI, evt_change, "B ",xco+5,yco,butw,19, &brush->clone.alpha , 0.0, 1.0, 0, 0, "Opacity of clone image display"); + } + } + else { + if ( + (sima==NULL) && /* 3D View */ + (settings->imapaint.flag & IMAGEPAINT_PROJECT_DISABLE)==0 && /* Projection Painting */ + (settings->imapaint.tool == PAINT_TOOL_CLONE) + ) { + butw = 130; + uiDefButBitS(block, TOG|BIT, IMAGEPAINT_PROJECT_LAYER_CLONE, B_REDR, "Clone Layer", 0,yco,butw,20, &settings->imapaint.flag, 0, 0, 0, 0, "Use another UV layer as clone source, otherwise use 3D the cursor as the source"); + } + else { + MTex *mtex= brush->mtex[brush->texact]; + + uiBlockSetCol(block, TH_BUT_SETTING2); + id= (mtex)? (ID*)mtex->tex: NULL; + xco= std_libbuttons(block, 0, yco, 0, NULL, evt_texbrowse, ID_TE, 0, id, NULL, menupoin, 0, 0, evt_texdel, 0, 0); + /*uiDefButBitS(block, TOG|BIT, BRUSH_FIXED_TEX, evt_change, "Fixed", xco+5,yco,butw,19, &brush->flag, 0, 0, 0, 0, "Keep texture origin in fixed position");*/ + uiBlockSetCol(block, TH_AUTO); + } + } + } + +#if 0 + uiDefButBitS(block, TOG|BIT, IMAGEPAINT_DRAW_TOOL_DRAWING, B_SIMABRUSHCHANGE, "TD", 0,1,50,19, &settings->imapaint.flag.flag, 0, 0, 0, 0, "Enables brush shape while drawing"); + uiDefButBitS(block, TOG|BIT, IMAGEPAINT_DRAW_TOOL, B_SIMABRUSHCHANGE, "TP", 50,1,50,19, &settings->imapaint.flag.flag, 0, 0, 0, 0, "Enables brush shape while not drawing"); +#endif +} + static void editing_panel_mesh_paint(void) { uiBlock *block; @@ -6328,61 +6517,7 @@ static void editing_panel_mesh_paint(void) uiBlockEndAlign(block); } else { /* texture paint */ - ToolSettings *settings= G.scene->toolsettings; - Brush *brush= settings->imapaint.brush; - ID *id; - int yco, xco, butw; - - yco= 160; - - uiBlockBeginAlign(block); - uiDefButS(block, ROW, B_BRUSHCHANGE, "Draw", 0 ,yco,108,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_DRAW, 0, 0, "Draw brush"); - uiDefButS(block, ROW, B_BRUSHCHANGE, "Soften", 108 ,yco,106,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_SOFTEN, 0, 0, "Soften brush"); - uiDefButS(block, ROW, B_BRUSHCHANGE, "Smear", 214,yco,106,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_SMEAR, 0, 0, "Smear brush"); - uiBlockEndAlign(block); - yco -= 30; - - uiBlockSetCol(block, TH_BUT_SETTING2); - id= (ID*)settings->imapaint.brush; - xco= std_libbuttons(block, 0, yco, 0, NULL, B_BRUSHBROWSE, ID_BR, 0, id, NULL, &(G.buts->menunr), 0, B_BRUSHLOCAL, B_BRUSHDELETE, 0, B_BRUSHKEEPDATA); - uiBlockSetCol(block, TH_AUTO); - - if(brush && !brush->id.lib) { - MTex *mtex= brush->mtex[brush->texact]; - - butw= 320-(xco+10); - - uiDefButS(block, MENU, B_NOP, "Mix %x0|Add %x1|Subtract %x2|Multiply %x3|Lighten %x4|Darken %x5|Erase Alpha %x6|Add Alpha %x7", xco+10,yco,butw,19, &brush->blend, 0, 0, 0, 0, "Blending method for applying brushes"); - - uiDefButBitS(block, TOG|BIT, BRUSH_TORUS, B_BRUSHCHANGE, "Wrap", xco+10,yco-25,butw,19, &brush->flag, 0, 0, 0, 0, "Enables torus wrapping"); - - uiBlockBeginAlign(block); - uiDefButBitS(block, TOG|BIT, BRUSH_AIRBRUSH, B_BRUSHCHANGE, "Airbrush", xco+10,yco-50,butw,19, &brush->flag, 0, 0, 0, 0, "Keep applying paint effect while holding mouse (spray)"); - uiDefButF(block, NUM, B_NOP, "Rate ", xco+10,yco-70,butw,19, &brush->rate, 0.01, 1.0, 0, 0, "Number of paints per second for Airbrush"); - uiBlockEndAlign(block); - - yco -= 25; - - uiBlockBeginAlign(block); - uiDefButF(block, COL, B_VPCOLSLI, "", 0,yco,200,19, brush->rgb, 0, 0, 0, 0, ""); - uiDefButF(block, NUMSLI, B_NOP, "Opacity ", 0,yco-20,180,19, &brush->alpha, 0.0, 1.0, 0, 0, "The amount of pressure on the brush"); - uiDefButBitS(block, TOG|BIT, BRUSH_ALPHA_PRESSURE, B_NOP, "P", 180,yco-20,20,19, &brush->flag, 0, 0, 0, 0, "Enables pressure sensitivity for tablets"); - uiDefButI(block, NUMSLI, B_NOP, "Size ", 0,yco-40,180,19, &brush->size, 1, 200, 0, 0, "The size of the brush"); - uiDefButBitS(block, TOG|BIT, BRUSH_SIZE_PRESSURE, B_NOP, "P", 180,yco-40,20,19, &brush->flag, 0, 0, 0, 0, "Enables pressure sensitivity for tablets"); - uiDefButF(block, NUMSLI, B_NOP, "Falloff ", 0,yco-60,180,19, &brush->innerradius, 0.0, 1.0, 0, 0, "The fall off radius of the brush"); - uiDefButBitS(block, TOG|BIT, BRUSH_RAD_PRESSURE, B_NOP, "P", 180,yco-60,20,19, &brush->flag, 0, 0, 0, 0, "Enables pressure sensitivity for tablets"); - uiDefButF(block, NUMSLI, B_NOP, "Spacing ",0,yco-80,180,19, &brush->spacing, 1.0, 100.0, 0, 0, "Repeating paint on %% of brush diameter"); - uiDefButBitS(block, TOG|BIT, BRUSH_SPACING_PRESSURE, B_NOP, "P", 180,yco-80,20,19, &brush->flag, 0, 0, 0, 0, "Enables pressure sensitivity for tablets"); - uiBlockEndAlign(block); - - yco -= 110; - - uiBlockSetCol(block, TH_BUT_SETTING2); - id= (mtex)? (ID*)mtex->tex: NULL; - xco= std_libbuttons(block, 0, yco, 0, NULL, B_BTEXBROWSE, ID_TE, 0, id, NULL, &(G.buts->menunr), 0, 0, B_BTEXDELETE, 0, 0); - /*uiDefButBitS(block, TOG|BIT, BRUSH_FIXED_TEX, B_BRUSHCHANGE, "Fixed", xco+5,yco,butw,19, &brush->flag, 0, 0, 0, 0, "Keep texture origin in fixed position");*/ - uiBlockSetCol(block, TH_AUTO); - } + brush_buttons(block, 0, B_NOP, B_BRUSHCHANGE, B_BRUSHBROWSE, B_BRUSHLOCAL, B_BRUSHDELETE, B_BRUSHKEEPDATA, B_BTEXBROWSE, B_BTEXDELETE); } } diff --git a/source/blender/src/buttons_logic.c b/source/blender/src/buttons_logic.c index 8aca111f41f..494dc05d8f9 100644 --- a/source/blender/src/buttons_logic.c +++ b/source/blender/src/buttons_logic.c @@ -2136,12 +2136,17 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh uiDefButS(block, TOG, 0, "3D", xco+width-50, yco-44, 40, 19, &eoa->flag, 0.0, 0.0, 0, 0, "Enable 3D tracking"); } else if(eoa->type==ACT_EDOB_DYNAMICS) { - ysize= 48; + ysize= 69; glRects(xco, yco-ysize, xco+width, yco); uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - str= "Dynamic Operation %t|Restore Dynamics %x0|Suspend Dynamics %x1|Enable Rigid Body %x2|Disable Rigid Body %x3"; + str= "Dynamic Operation %t|Restore Dynamics %x0|Suspend Dynamics %x1|Enable Rigid Body %x2|Disable Rigid Body %x3|Set Mass %x4"; uiDefButS(block, MENU, B_REDR, str, xco+40, yco-44, (width-80), 19, &(eoa->dyn_operation), 0.0, 0.0, 0, 0, ""); + if(eoa->dyn_operation==4) { + uiDefButF(block, NUM, 0, "", xco+40, yco-63, width-80, 19, + &eoa->mass, 0.0, 10000.0, 10, 0, + "Mass for object."); + } } str= "Edit Object %t|Add Object %x0|End Object %x1|Replace Mesh %x2|Track to %x3|Dynamics %x4"; uiDefButS(block, MENU, B_REDR, str, xco+40, yco-24, (width-80), 19, &eoa->type, 0.0, 0.0, 0, 0, ""); diff --git a/source/blender/src/buttons_scene.c b/source/blender/src/buttons_scene.c index 74725b99fea..376a57b11e9 100644 --- a/source/blender/src/buttons_scene.c +++ b/source/blender/src/buttons_scene.c @@ -1388,9 +1388,9 @@ static void run_playanim(char *file) calc_renderwin_rectangle((G.scene->r.xsch*G.scene->r.size)/100, (G.scene->r.ysch*G.scene->r.size)/100, G.winpos, pos, size); #ifdef WIN32 - sprintf(str, "%s -a -s %d -e %d -p %d %d -f %d %g \"%s\"", bprogname, G.scene->r.sfra, G.scene->r.efra, pos[0], pos[1], G.scene->r.frs_sec, G.scene->r.frs_sec_base, file); + sprintf(str, "%s -a -s %d -e %d -p %d %d -f %d %g -j %d \"%s\"", bprogname, G.scene->r.sfra, G.scene->r.efra, pos[0], pos[1], G.scene->r.frs_sec, G.scene->r.frs_sec_base, G.scene->frame_step, file); #else - sprintf(str, "\"%s\" -a -s %d -e %d -p %d %d -f %d %g \"%s\"", bprogname, G.scene->r.sfra, G.scene->r.efra, pos[0], pos[1], G.scene->r.frs_sec, G.scene->r.frs_sec_base, file); + sprintf(str, "\"%s\" -a -s %d -e %d -p %d %d -f %d %g -j %d \"%s\"", bprogname, G.scene->r.sfra, G.scene->r.efra, pos[0], pos[1], G.scene->r.frs_sec, G.scene->r.frs_sec_base, G.scene->frame_step, file); #endif system(str); } @@ -1956,7 +1956,6 @@ static char *imagetype_pup(void) char appendstring[1024]; strcpy(formatstring, "Save image as: %%t|%s %%x%d|%s %%x%d|%s %%x%d|%s %%x%d|%s %%x%d|%s %%x%d|%s %%x%d"); - #ifdef __sgi strcat(formatstring, "|%s %%x%d"); // add space for Movie #endif @@ -1967,6 +1966,10 @@ static char *imagetype_pup(void) strcat(formatstring, "|%s %%x%d"); // add space for DDS #endif */ +#ifdef WITH_OPENJPEG + strcat(formatstring, "|%s %%x%d"); // add space for JP2 +#endif + strcat(formatstring, "|%s %%x%d"); // add space for BMP strcat(formatstring, "|%s %%x%d"); // add space for Radiance HDR strcat(formatstring, "|%s %%x%d"); // add space for Cineon @@ -2008,6 +2011,9 @@ static char *imagetype_pup(void) "DDS", R_DDS, #endif */ +#ifdef WITH_OPENJPEG + "Jpeg 2000", R_JP2, +#endif "BMP", R_BMP, "Jpeg", R_JPEG90, "HamX", R_HAMX, @@ -2015,6 +2021,7 @@ static char *imagetype_pup(void) "Radiance HDR", R_RADHDR, "Cineon", R_CINEON, "DPX", R_DPX + #ifdef __sgi ,"Movie", R_MOVIE #endif @@ -2036,6 +2043,9 @@ static char *imagetype_pup(void) /*#ifdef WITH_DDS "DDS", R_DDS, #endif*/ +#ifdef WITH_OPENJPEG + "Jpeg 2000", R_JP2, +#endif "BMP", R_BMP, "Jpeg", R_JPEG90, "HamX", R_HAMX, @@ -2043,6 +2053,8 @@ static char *imagetype_pup(void) "Radiance HDR", R_RADHDR, "Cineon", R_CINEON, "DPX", R_DPX + + #ifdef __sgi ,"Movie", R_MOVIE #endif @@ -3152,6 +3164,45 @@ static void render_panel_format(void) uiDefButS(block, NUM,B_DIFF, "Q:", 892,yofs,74,20, &G.scene->r.quality, 10.0, 100.0, 0, 0, "Quality setting for JPEG images, AVI Jpeg and SGI movies"); } + +#ifdef WITH_OPENJPEG + if (G.scene->r.imtype == R_JP2) { + + uiDefButS(block, MENU,B_REDR, + "Preset %t|No Preset %x0|" + "Cinema 24fps 2048x1080%x1|" + "Cinema 48fps 2048x1080%x2|" + "Cinema 24fps 4096x2160%x3|" + "Cine-Scope 24fps 2048x858%x4|" + "Cine-Scope 48fps 2048x858%x5|" + "Cine-Flat 24fps 1998x1080%x6|" + "Cine-Flat 48fps 1998x1080%x7", + 892,yofs+44,G.scene->r.jp2_preset?227:110,20, &G.scene->r.jp2_preset, 0, 0, 0, 0, "Use a DCI Standard preset for saving jpeg2000"); + + if (G.scene->r.jp2_preset==0) { + uiBlockBeginAlign(block); + uiDefButS(block, ROW,B_REDR,"8", 1007,yofs+44,20,20, &G.scene->r.jp2_depth,1.0,8.0, 0, 0,""); + uiDefButS(block, ROW,B_REDR,"12",1007+20,yofs+44,25,20, &G.scene->r.jp2_depth,1.0,12.0, 0, 0,""); + uiDefButS(block, ROW,B_REDR,"16", 1007+45,yofs+44,25,20, &G.scene->r.jp2_depth,1.0,16.0, 0, 0,""); + uiDefButBitS(block, TOG, R_JPEG2K_YCC, B_REDR,"YCC",1007+70,yofs+44,42,20, &G.scene->r.subimtype, 0, 0, 0, 0, "Save luminance-chrominance-chrominance instead of RGB color channels "); + uiBlockEndAlign(block); + } + + G.scene->r.subimtype &= ~(R_JPEG2K_12BIT|R_JPEG2K_16BIT | R_JPEG2K_CINE_PRESET|R_JPEG2K_CINE_48FPS); + if (G.scene->r.jp2_depth==12) G.scene->r.subimtype |= R_JPEG2K_12BIT; + if (G.scene->r.jp2_depth==16) G.scene->r.subimtype |= R_JPEG2K_16BIT; + + if (G.scene->r.jp2_preset==1) G.scene->r.subimtype |= R_JPEG2K_CINE_PRESET; + if (G.scene->r.jp2_preset==2) G.scene->r.subimtype |= R_JPEG2K_CINE_PRESET|R_JPEG2K_CINE_48FPS; + if (G.scene->r.jp2_preset==3) G.scene->r.subimtype |= R_JPEG2K_CINE_PRESET; + if (G.scene->r.jp2_preset==4) G.scene->r.subimtype |= R_JPEG2K_CINE_PRESET; + if (G.scene->r.jp2_preset==5) G.scene->r.subimtype |= R_JPEG2K_CINE_PRESET|R_JPEG2K_CINE_48FPS; + if (G.scene->r.jp2_preset==6) G.scene->r.subimtype |= R_JPEG2K_CINE_PRESET; + if (G.scene->r.jp2_preset==7) G.scene->r.subimtype |= R_JPEG2K_CINE_PRESET|R_JPEG2K_CINE_48FPS; + + } +#endif + uiDefButS(block, NUM,B_FRAMEMAP,"FPS:", 968,yofs,75,20, &G.scene->r.frs_sec, 1.0, 120.0, 100.0, 0, "Frames per second"); uiDefButF(block, NUM,B_FRAMEMAP,"/", 1043,yofs,75,20, &G.scene->r.frs_sec_base, 1.0, 120.0, 0.1, 3, "Frames per second base"); diff --git a/source/blender/src/buttons_shading.c b/source/blender/src/buttons_shading.c index 4ca1c13ddb2..98b78d54fff 100644 --- a/source/blender/src/buttons_shading.c +++ b/source/blender/src/buttons_shading.c @@ -1126,9 +1126,10 @@ void uiblock_image_panel(uiBlock *block, Image **ima_pp, ImageUser *iuser, IMAnames_to_pupstring(&strp, NULL, NULL, &(G.main->image), NULL, &iuser->menunr); uiBlockBeginAlign(block); + uiClearButLock(); /* no way to check if the image user is libdata or not, so assume its not, otherwise we cant select linked images - ANNOYING */ but= uiDefButS(block, MENU, imagechanged, strp, 10,155,23,20, &iuser->menunr, 0, 0, 0, 0, "Selects an existing Image or Movie"); uiButSetFunc(but, image_browse_cb, ima_pp, iuser); - + uiSetButLock(ima && (ima->id.lib!=NULL), ERROR_LIBDATA_MESSAGE); MEM_freeN(strp); /* name + options, or only load */ diff --git a/source/blender/src/drawimage.c b/source/blender/src/drawimage.c index 84236a0701a..b8409aff3bd 100644 --- a/source/blender/src/drawimage.c +++ b/source/blender/src/drawimage.c @@ -474,12 +474,13 @@ void draw_uvs_sima(void) MTFace *tface,*activetface = NULL; EditMesh *em = G.editMesh; EditFace *efa, *efa_act; - + Base *base; + char col1[4], col2[4]; float pointsize; int drawface; int lastsel, sel; - + if (!G.obedit || !CustomData_has_layer(&em->fdata, CD_MTFACE)) return; @@ -489,7 +490,47 @@ void draw_uvs_sima(void) myortho2(G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax); glLoadIdentity(); - + if(G.sima->flag & SI_DRAW_OTHER) { + base= FIRSTBASE; + if(base) { + MTFace *activetf; + Image *curimage; + + activetf = get_active_mtface(NULL, NULL, 1); + if (activetf) { + curimage = activetf->tpage; + glColor3ub(96, 96, 96); + while(base) { + if (TESTBASE_2D(base)) { + Object *ob; + ob = base->object; + if ((ob->type==OB_MESH) && (ob!=G.obedit)) { + Mesh *me; + me = ob->data; + if (me->mtface) { + MFace *mface; + int a; + mface= me->mface; + tface= me->mtface; + for (a=me->totface; a>0; a--, tface++, mface++) { + if (tface->tpage == curimage) { + glBegin(GL_LINE_LOOP); + glVertex2fv(tface->uv[0]); + glVertex2fv(tface->uv[1]); + glVertex2fv(tface->uv[2]); + if(mface->v4) glVertex2fv(tface->uv[3]); + glEnd(); + } + } + } + } + } + base= base->next; + } + } + } + } + if(G.sima->flag & SI_DRAWTOOL) { /* draws the grey mesh when painting */ glColor3ub(112, 112, 112); @@ -902,7 +943,7 @@ void draw_uvs_sima(void) } glLineWidth(1); - col2[0] = col2[1] = col2[2] = 128; col2[3] = 255; + col2[0] = col2[1] = col2[2] = 192; col2[3] = 255; glColor4ubv((unsigned char *)col2); if (G.f & G_DRAWEDGES) { @@ -1467,7 +1508,8 @@ static void image_panel_view_properties(short cntrl) // IMAGE_HANDLER_VIEW_PROPE uiDefButBitI(block, TOG, G_DRAWFACES, B_REDR, "Faces", 10,30,60,19, &G.f, 0, 0, 0, 0, "Displays all faces as shades in the 3d view and UV editor"); uiDefButBitI(block, TOG, G_DRAWEDGES, B_REDR, "Edges", 70, 30,60,19, &G.f, 0, 0, 0, 0, "Displays selected edges using hilights in the 3d view and UV editor"); - uiDefButBitI(block, TOG, SI_DRAWSHADOW, B_REDR, "Final Shadow", 130, 30,110,19, &G.sima->flag, 0, 0, 0, 0, "Draw the final result from the objects modifiers"); + uiDefButBitI(block, TOG, SI_DRAWSHADOW, B_REDR, "Final Shadow", 130, 30,100,19, &G.sima->flag, 0, 0, 0, 0, "Draw the final result from the objects modifiers"); + uiDefButBitI(block, TOG, SI_DRAW_OTHER, B_REDR, "Other Objs", 230, 30, 80, 19, &G.sima->flag, 0, 0, 0, 0, "Also draw all 3d view selected mesh objects that use this image"); uiDefButBitI(block, TOG, SI_DRAW_STRETCH, B_REDR, "UV Stretch", 10,0,100,19, &G.sima->flag, 0, 0, 0, 0, "Difference between UV's and the 3D coords (blue for low distortion, red is high)"); if (G.sima->flag & SI_DRAW_STRETCH) { @@ -1483,15 +1525,7 @@ static void image_panel_view_properties(short cntrl) // IMAGE_HANDLER_VIEW_PROPE static void image_panel_paint(short cntrl) // IMAGE_HANDLER_PAINT { - /* B_SIMABRUSHCHANGE only redraws and eats the mouse messages */ - /* so that LEFTMOUSE does not 'punch' through the floating panel */ - /* B_SIMANOTHING */ - ToolSettings *settings= G.scene->toolsettings; - Brush *brush= settings->imapaint.brush; uiBlock *block; - ID *id; - int yco, xco, butw; - if ((G.sima->image && (G.sima->flag & SI_DRAWTOOL))==0) { return; } @@ -1501,75 +1535,8 @@ static void image_panel_paint(short cntrl) // IMAGE_HANDLER_PAINT uiSetPanelHandler(IMAGE_HANDLER_PAINT); // for close and esc if(uiNewPanel(curarea, block, "Image Paint", "Image", 10, 230, 318, 204)==0) return; - - yco= 160; - - uiBlockBeginAlign(block); - uiDefButS(block, ROW, B_SIMABRUSHCHANGE, "Draw", 0 ,yco,80,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_DRAW, 0, 0, "Draw brush"); - uiDefButS(block, ROW, B_SIMABRUSHCHANGE, "Soften", 80 ,yco,80,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_SOFTEN, 0, 0, "Soften brush"); - uiDefButS(block, ROW, B_SIMABRUSHCHANGE, "Smear", 160,yco,80,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_SMEAR, 0, 0, "Smear brush"); - uiDefButS(block, ROW, B_SIMABRUSHCHANGE, "Clone", 240,yco,80,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_CLONE, 0, 0, "Clone brush, use RMB to drag source image"); - uiBlockEndAlign(block); - yco -= 30; - - uiBlockSetCol(block, TH_BUT_SETTING2); - id= (ID*)settings->imapaint.brush; - xco= std_libbuttons(block, 0, yco, 0, NULL, B_SIMABRUSHBROWSE, ID_BR, 0, id, NULL, &(G.sima->menunr), 0, B_SIMABRUSHLOCAL, B_SIMABRUSHDELETE, 0, B_KEEPDATA); - uiBlockSetCol(block, TH_AUTO); - - if(brush && !brush->id.lib) { - butw= 320-(xco+10); - - uiDefButS(block, MENU, B_SIMANOTHING, "Mix %x0|Add %x1|Subtract %x2|Multiply %x3|Lighten %x4|Darken %x5|Erase Alpha %x6|Add Alpha %x7", xco+10,yco,butw,19, &brush->blend, 0, 0, 0, 0, "Blending method for applying brushes"); - - uiDefButBitS(block, TOG|BIT, BRUSH_TORUS, B_SIMABRUSHCHANGE, "Wrap", xco+10,yco-25,butw,19, &brush->flag, 0, 0, 0, 0, "Enables torus wrapping"); - - uiBlockBeginAlign(block); - uiDefButBitS(block, TOG|BIT, BRUSH_AIRBRUSH, B_SIMABRUSHCHANGE, "Airbrush", xco+10,yco-50,butw,19, &brush->flag, 0, 0, 0, 0, "Keep applying paint effect while holding mouse (spray)"); - uiDefButF(block, NUM, B_SIMANOTHING, "Rate ", xco+10,yco-70,butw,19, &brush->rate, 0.01, 1.0, 0, 0, "Number of paints per second for Airbrush"); - uiBlockEndAlign(block); - - yco -= 25; - - uiBlockBeginAlign(block); - uiDefButF(block, COL, B_VPCOLSLI, "", 0,yco,200,19, brush->rgb, 0, 0, 0, 0, ""); - uiDefButF(block, NUMSLI, B_SIMANOTHING, "Opacity ", 0,yco-20,180,19, &brush->alpha, 0.0, 1.0, 0, 0, "The amount of pressure on the brush"); - uiDefButBitS(block, TOG|BIT, BRUSH_ALPHA_PRESSURE, B_SIMANOTHING, "P", 180,yco-20,20,19, &brush->flag, 0, 0, 0, 0, "Enables pressure sensitivity for tablets"); - uiDefButI(block, NUMSLI, B_SIMANOTHING, "Size ", 0,yco-40,180,19, &brush->size, 1, 200, 0, 0, "The size of the brush"); - uiDefButBitS(block, TOG|BIT, BRUSH_SIZE_PRESSURE, B_SIMANOTHING, "P", 180,yco-40,20,19, &brush->flag, 0, 0, 0, 0, "Enables pressure sensitivity for tablets"); - uiDefButF(block, NUMSLI, B_SIMANOTHING, "Falloff ", 0,yco-60,180,19, &brush->innerradius, 0.0, 1.0, 0, 0, "The fall off radius of the brush"); - uiDefButBitS(block, TOG|BIT, BRUSH_RAD_PRESSURE, B_SIMANOTHING, "P", 180,yco-60,20,19, &brush->flag, 0, 0, 0, 0, "Enables pressure sensitivity for tablets"); - uiDefButF(block, NUMSLI, B_SIMANOTHING, "Spacing ",0,yco-80,180,19, &brush->spacing, 1.0, 100.0, 0, 0, "Repeating paint on %% of brush diameter"); - uiDefButBitS(block, TOG|BIT, BRUSH_SPACING_PRESSURE, B_SIMANOTHING, "P", 180,yco-80,20,19, &brush->flag, 0, 0, 0, 0, "Enables pressure sensitivity for tablets"); - uiBlockEndAlign(block); - - yco -= 110; - - if(settings->imapaint.tool == PAINT_TOOL_CLONE) { - id= (ID*)brush->clone.image; - uiBlockSetCol(block, TH_BUT_SETTING2); - xco= std_libbuttons(block, 0, yco, 0, NULL, B_SIMACLONEBROWSE, ID_IM, 0, id, 0, &G.sima->menunr, 0, 0, B_SIMACLONEDELETE, 0, 0); - uiBlockSetCol(block, TH_AUTO); - if(id) { - butw= 320-(xco+5); - uiDefButF(block, NUMSLI, B_SIMABRUSHCHANGE, "B ",xco+5,yco,butw,19, &brush->clone.alpha , 0.0, 1.0, 0, 0, "Opacity of clone image display"); - } - } - else { - MTex *mtex= brush->mtex[brush->texact]; - - uiBlockSetCol(block, TH_BUT_SETTING2); - id= (mtex)? (ID*)mtex->tex: NULL; - xco= std_libbuttons(block, 0, yco, 0, NULL, B_SIMABTEXBROWSE, ID_TE, 0, id, NULL, &(G.sima->menunr), 0, 0, B_SIMABTEXDELETE, 0, 0); - /*uiDefButBitS(block, TOG|BIT, BRUSH_FIXED_TEX, B_SIMABRUSHCHANGE, "Fixed", xco+5,yco,butw,19, &brush->flag, 0, 0, 0, 0, "Keep texture origin in fixed position");*/ - uiBlockSetCol(block, TH_AUTO); - } - } - -#if 0 - uiDefButBitS(block, TOG|BIT, IMAGEPAINT_DRAW_TOOL_DRAWING, B_SIMABRUSHCHANGE, "TD", 0,1,50,19, &settings->imapaint.flag.flag, 0, 0, 0, 0, "Enables brush shape while drawing"); - uiDefButBitS(block, TOG|BIT, IMAGEPAINT_DRAW_TOOL, B_SIMABRUSHCHANGE, "TP", 50,1,50,19, &settings->imapaint.flag.flag, 0, 0, 0, 0, "Enables brush shape while not drawing"); -#endif + + brush_buttons(block, 1, B_SIMANOTHING, B_SIMABRUSHCHANGE, B_SIMABRUSHBROWSE, B_SIMABRUSHLOCAL, B_SIMABRUSHDELETE, B_KEEPDATA, B_SIMABTEXBROWSE, B_SIMABTEXDELETE); } static void image_panel_curves_reset(void *cumap_v, void *ibuf_v) diff --git a/source/blender/src/drawmesh.c b/source/blender/src/drawmesh.c index ba266fa8c29..860bd8cee8f 100644 --- a/source/blender/src/drawmesh.c +++ b/source/blender/src/drawmesh.c @@ -75,6 +75,7 @@ #include "BDR_drawmesh.h" #include "BSE_drawview.h" +#include "BSE_view.h" #include "GPU_extensions.h" #include "GPU_draw.h" @@ -351,9 +352,10 @@ static void draw_textured_begin(Object *ob) solidtex= 1; Gtexdraw.islit= -1; } - else + else { /* draw with lights in the scene otherwise */ - Gtexdraw.islit= GPU_scene_object_lights(G.scene, ob, G.vd->lay, G.vd->viewmat); + Gtexdraw.islit= GPU_scene_object_lights(G.scene, ob, G.vd->lay, G.vd->viewmat, get_view3d_ortho(G.vd)); + } obcol[0]= CLAMPIS(ob->col[0]*255, 0, 255); obcol[1]= CLAMPIS(ob->col[1]*255, 0, 255); diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c index 551ce874db8..43991194658 100644 --- a/source/blender/src/drawobject.c +++ b/source/blender/src/drawobject.c @@ -1096,14 +1096,15 @@ void lattice_foreachScreenVert(void (*func)(void *userData, BPoint *bp, int x, i float *co = dl?dl->verts:NULL; BPoint *bp = editLatt->def; float pmat[4][4], vmat[4][4]; - short s[2]; + short s[2] = {IS_CLIPPED, 0}; view3d_get_object_project_mat(curarea, G.obedit, pmat, vmat); for (i=0; i<N; i++, bp++, co+=3) { if (bp->hide==0) { view3d_project_short_clip(curarea, dl?co:bp->vec, s, pmat, vmat); - func(userData, bp, s[0], s[1]); + if (s[0] != IS_CLIPPED) + func(userData, bp, s[0], s[1]); } } } @@ -1196,15 +1197,18 @@ static void mesh_foreachScreenVert__mapFunc(void *userData, int index, float *co { struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; int clipVerts; float pmat[4][4], vmat[4][4]; } *data = userData; EditVert *eve = EM_get_vert_for_index(index); - short s[2]; if (eve->h==0) { + short s[2]= {IS_CLIPPED, 0}; if (data->clipVerts) { view3d_project_short_clip(curarea, co, s, data->pmat, data->vmat); } else { view3d_project_short_noclip(curarea, co, s, data->pmat); } - + + if (s[0]==IS_CLIPPED) + return; + data->func(data->userData, eve, s[0], s[1], index); } } @@ -1300,7 +1304,7 @@ void mesh_foreachScreenFace(void (*func)(void *userData, EditFace *efa, int x, i void nurbs_foreachScreenVert(void (*func)(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y), void *userData) { float pmat[4][4], vmat[4][4]; - short s[2]; + short s[2] = {IS_CLIPPED, 0}; Nurb *nu; int i; @@ -1336,7 +1340,8 @@ void nurbs_foreachScreenVert(void (*func)(void *userData, Nurb *nu, BPoint *bp, if(bp->hide==0) { view3d_project_short_clip(curarea, bp->vec, s, pmat, vmat); - func(userData, nu, bp, NULL, -1, s[0], s[1]); + if (s[0] != IS_CLIPPED) + func(userData, nu, bp, NULL, -1, s[0], s[1]); } } } diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index 8f38d752719..cb4fa246562 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -977,7 +977,8 @@ void backdrawview3d(int test) int m; #endif - if(G.f & G_VERTEXPAINT || G.f & G_WEIGHTPAINT || G.f & G_TEXTUREPAINT); + if( G.f & G_VERTEXPAINT || G.f & G_WEIGHTPAINT ); + else if ((G.f & G_TEXTUREPAINT) && G.scene->toolsettings && (G.scene->toolsettings->imapaint.flag & IMAGEPAINT_PROJECT_DISABLE)==0); else if(G.obedit && G.vd->drawtype>OB_WIRE && (G.vd->flag & V3D_ZBUF_SELECT)); else { G.vd->flag &= ~V3D_NEEDBACKBUFDRAW; @@ -3451,7 +3452,12 @@ void drawview3dspace(ScrArea *sa, void *spacedata) fdrawXORcirc((float)c[0], (float)c[1], (float)pset->brush[pset->brushtype].size); } } - + if(!G.obedit && OBACT && G.f&G_TEXTUREPAINT && area_is_active_area(v3d->area) && G.scene->toolsettings->imapaint.brush){ + short c[2]; + getmouseco_areawin(c); + fdrawXORcirc((float)c[0], (float)c[1], (float)G.scene->toolsettings->imapaint.brush->size/2); + } + if(v3d->persp>1) drawviewborder(); if(v3d->flag2 & V3D_FLYMODE) drawviewborder_flymode(); diff --git a/source/blender/src/editcurve.c b/source/blender/src/editcurve.c index c26c44103c0..594ff816ec1 100644 --- a/source/blender/src/editcurve.c +++ b/source/blender/src/editcurve.c @@ -3065,8 +3065,8 @@ void makecyclicNurb() Nurb *nu; BezTriple *bezt; BPoint *bp; - float *fp; - int a, b, cyclmode=0; + + int a, cyclmode=0; for(nu= editNurb.first; nu; nu= nu->next) { if( nu->pntsu>1 || nu->pntsv>1) { @@ -3075,8 +3075,7 @@ void makecyclicNurb() bp= nu->bp; while(a--) { if( bp->f1 & SELECT ) { - if(nu->flagu & CU_CYCLIC) nu->flagu &= ~CU_CYCLIC; - else nu->flagu |= CU_CYCLIC; + nu->flagu ^= CU_CYCLIC; break; } bp++; @@ -3087,8 +3086,7 @@ void makecyclicNurb() bezt= nu->bezt; while(a--) { if( BEZSELECTED_HIDDENHANDLES(bezt) ) { - if(nu->flagu & CU_CYCLIC) nu->flagu &= ~CU_CYCLIC; - else nu->flagu |= CU_CYCLIC; + nu->flagu ^= CU_CYCLIC; break; } bezt++; @@ -3101,19 +3099,8 @@ void makecyclicNurb() bp= nu->bp; while(a--) { if( bp->f1 & SELECT ) { - if(nu->flagu & CU_CYCLIC) nu->flagu &= ~CU_CYCLIC; - else { - nu->flagu |= CU_CYCLIC; - nu->flagu &= ~2; /* endpoint flag, fixme */ - fp= MEM_mallocN(sizeof(float)*KNOTSU(nu), "makecyclicN"); - b= (nu->orderu+nu->pntsu); - memcpy(fp, nu->knotsu, sizeof(float)*b); - MEM_freeN(nu->knotsu); - nu->knotsu= fp; - - makeknots(nu, 1, 0); /* 1==u 0==uniform */ - - } + nu->flagu ^= CU_CYCLIC; + makeknots(nu, 1, nu->flagu>>1); /* 1==u type is ignored for cyclic curves */ break; } bp++; @@ -3131,38 +3118,12 @@ void makecyclicNurb() if( bp->f1 & SELECT) { if(cyclmode==1 && nu->pntsu>1) { - if(nu->flagu & CU_CYCLIC) nu->flagu &= ~CU_CYCLIC; - else { - nu->flagu |= CU_CYCLIC; - if (check_valid_nurb_u(nu)) { - fp= MEM_mallocN(sizeof(float)*KNOTSU(nu), "makecyclicN"); - b= (nu->orderu+nu->pntsu); - if (nu->knotsu) { /* null if check_valid_nurb_u failed before but is valid now */ - memcpy(fp, nu->knotsu, sizeof(float)*b); - MEM_freeN(nu->knotsu); - } - nu->knotsu= fp; - - makeknots(nu, 1, 0); /* 1==u 0==uniform */ - } - } + nu->flagu ^= CU_CYCLIC; + makeknots(nu, 1, nu->flagu>>1); /* 1==u type is ignored for cyclic curves */ } if(cyclmode==2 && nu->pntsv>1) { - if(nu->flagv & 1) nu->flagv--; - else { - nu->flagv++; - if (check_valid_nurb_v(nu)) { - fp= MEM_mallocN(sizeof(float)*KNOTSV(nu), "makecyclicN"); - b= (nu->orderv+nu->pntsv); - if (nu->knotsv) { /* null if check_valid_nurb_v failed before but is valid now */ - memcpy(fp, nu->knotsv, sizeof(float)*b); - MEM_freeN(nu->knotsv); - } - nu->knotsv= fp; - - makeknots(nu, 2, 0); /* 2==v 0==uniform */ - } - } + nu->flagv ^= CU_CYCLIC; + makeknots(nu, 2, nu->flagv>>1); /* 2==v type is ignored for cyclic curves */ } break; } diff --git a/source/blender/src/editface.c b/source/blender/src/editface.c index 53fb6dbffb1..f6a0b88cbc8 100644 --- a/source/blender/src/editface.c +++ b/source/blender/src/editface.c @@ -51,6 +51,7 @@ #include "DNA_space_types.h" #include "DNA_screen_types.h" #include "DNA_scene_types.h" +#include "DNA_userdef_types.h" #include "DNA_view3d_types.h" #include "BKE_brush.h" @@ -631,15 +632,15 @@ void default_uv(float uv[][2], float size) dy= 1.0-size; uv[0][0]= 0; - uv[0][1]= size+dy; + uv[0][1]= dy; - uv[1][0]= 0; + uv[1][0]= size; uv[1][1]= dy; uv[2][0]= size; - uv[2][1]= dy; - - uv[3][0]= size; + uv[2][1]= size+dy; + + uv[3][0]= 0; uv[3][1]= size+dy; } @@ -1321,6 +1322,10 @@ void set_texturepaint() /* toggle */ if(G.f & G_TEXTUREPAINT) { G.f &= ~G_TEXTUREPAINT; + + if (U.glreslimit != 0) + GPU_free_images(); + GPU_paint_set_mipmap(1); } else if (me) { @@ -1328,7 +1333,10 @@ void set_texturepaint() /* toggle */ if(me->mtface==NULL) make_tfaces(me); - + + if (U.glreslimit != 0) + GPU_free_images(); + brush_check_exists(&G.scene->toolsettings->imapaint.brush); GPU_paint_set_mipmap(0); } diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c index 4a70e89dd07..2a1d508bf59 100644 --- a/source/blender/src/editobject.c +++ b/source/blender/src/editobject.c @@ -1740,7 +1740,8 @@ void enter_editmode(int wc) if(wc) waitcursor(0); - scrarea_queue_headredraw(curarea); + if (G.background==0) + scrarea_queue_headredraw(curarea); } void exit_editmode(int flag) /* freedata==0 at render, 1= freedata, 2= do undo buffer too */ @@ -1817,8 +1818,9 @@ void exit_editmode(int flag) /* freedata==0 at render, 1= freedata, 2= do undo b allqueue(REDRAWNLA, 0); allqueue(REDRAWIPO, 0); allqueue(REDRAWOOPS, 0); - - scrarea_queue_headredraw(curarea); + + if (G.background==0) + scrarea_queue_headredraw(curarea); if(G.obedit==NULL && (flag & EM_FREEUNDO)) BIF_undo_push("Editmode"); diff --git a/source/blender/src/editparticle.c b/source/blender/src/editparticle.c index 21192d50333..0538bcb98d7 100644 --- a/source/blender/src/editparticle.c +++ b/source/blender/src/editparticle.c @@ -165,6 +165,22 @@ void PE_change_act(void *ob_v, void *act_v) } } +void PE_change_act_psys(Object *ob, ParticleSystem *psys) +{ + ParticleSystem *p; + + if((p=psys_get_current(ob))) + p->flag &= ~PSYS_CURRENT; + + psys->flag |= PSYS_CURRENT; + + if(psys_check_enabled(ob, psys)) { + if(G.f & G_PARTICLEEDIT && !psys->edit) + PE_create_particle_edit(ob, psys); + PE_recalc_world_cos(ob, psys); + } +} + /* always gets atleast the first particlesystem even if PSYS_CURRENT flag is not set */ ParticleSystem *PE_get_current(Object *ob) { diff --git a/source/blender/src/editseq.c b/source/blender/src/editseq.c index d16e3f28671..76e44e5c24f 100644 --- a/source/blender/src/editseq.c +++ b/source/blender/src/editseq.c @@ -183,7 +183,7 @@ Sequence *get_forground_frame_seq(int frame) if(!ed) return NULL; for (seq=ed->seqbasep->first; seq; seq= seq->next) { - if(seq->startdisp > frame || seq->enddisp <= frame) + if(seq->flag & SEQ_MUTE || seq->startdisp > frame || seq->enddisp <= frame) continue; /* only use elements you can see - not */ if (ELEM6(seq->type, SEQ_IMAGE, SEQ_META, SEQ_SCENE, SEQ_MOVIE, SEQ_MOVIE_AND_HD_SOUND, SEQ_COLOR)) { diff --git a/source/blender/src/edittime.c b/source/blender/src/edittime.c index 2c37a0eb20f..bd45a528b8d 100644 --- a/source/blender/src/edittime.c +++ b/source/blender/src/edittime.c @@ -187,6 +187,9 @@ void transform_markers(int mode, int smode) // mode and smode unused here, for c } else markers= &G.scene->markers; + + if (markers == NULL) + return; for (marker= markers->first; marker; marker= marker->next) { if (marker->flag & SELECT) totmark++; @@ -442,6 +445,11 @@ void get_minmax_markers(short sel, float *first, float *last) int selcount = 0; markers= &(G.scene->markers); + if (markers == NULL) { + *first = 0.0f; + *last = 0.0f; + return; + } if (sel) for (marker= markers->first; marker; marker= marker->next) { @@ -494,6 +502,10 @@ TimeMarker *find_nearest_marker(ListBase *markers, int clip_y) getmouseco_areawin (mval); + /* sanity checks */ + if (markers == NULL) + return NULL; + /* first clip selection in Y */ if ((clip_y) && (mval[1] > 30)) return NULL; diff --git a/source/blender/src/filelist.c b/source/blender/src/filelist.c index c2c0f00885f..008bcbe147d 100644 --- a/source/blender/src/filelist.c +++ b/source/blender/src/filelist.c @@ -678,6 +678,9 @@ void BIF_filelist_setfiletypes(struct FileList* filelist, short has_quicktime) if( BLI_testextensie(file->relname, ".int") || BLI_testextensie(file->relname, ".inta") || BLI_testextensie(file->relname, ".jpg") +#ifdef WITH_OPENJPEG + || BLI_testextensie(file->relname, ".jp2") +#endif || BLI_testextensie(file->relname, ".jpeg") || BLI_testextensie(file->relname, ".tga") || BLI_testextensie(file->relname, ".rgb") @@ -721,6 +724,10 @@ void BIF_filelist_setfiletypes(struct FileList* filelist, short has_quicktime) if(BLI_testextensie(file->relname, ".int") || BLI_testextensie(file->relname, ".inta") || BLI_testextensie(file->relname, ".jpg") + || BLI_testextensie(file->relname, ".jpeg") +#ifdef WITH_OPENJPEG + || BLI_testextensie(file->relname, ".jp2") +#endif || BLI_testextensie(file->relname, ".tga") || BLI_testextensie(file->relname, ".rgb") || BLI_testextensie(file->relname, ".rgba") diff --git a/source/blender/src/header_buttonswin.c b/source/blender/src/header_buttonswin.c index 1e2890f4f2b..857fec16a64 100644 --- a/source/blender/src/header_buttonswin.c +++ b/source/blender/src/header_buttonswin.c @@ -77,6 +77,8 @@ #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" +#include "GPU_material.h" + #include "blendef.h" #include "mydevice.h" #include "butspace.h" @@ -168,6 +170,7 @@ void do_buts_buttons(short event) } matcopybuf.nodetree= ntreeCopyTree(ma->nodetree, 0); matcopybuf.preview= NULL; + matcopybuf.gpumaterial.first= matcopybuf.gpumaterial.last= NULL; matcopied= 1; } break; @@ -188,6 +191,8 @@ void do_buts_buttons(short event) ntreeFreeTree(ma->nodetree); MEM_freeN(ma->nodetree); } + + GPU_materials_free(ma); id= (ma->id); memcpy(ma, &matcopybuf, sizeof(Material)); diff --git a/source/blender/src/header_info.c b/source/blender/src/header_info.c index b6bd00d2ad6..6e43b6073eb 100644 --- a/source/blender/src/header_info.c +++ b/source/blender/src/header_info.c @@ -1672,6 +1672,7 @@ static uiBlock *info_game_glslmenu(void *arg_unused) static void do_info_gamemenu(void *arg, int event) { switch (event) { + case G_FILE_IGNORE_DEPRECATION_WARNINGS: case G_FILE_ENABLE_ALL_FRAMES: case G_FILE_DISPLAY_LISTS: case G_FILE_SHOW_FRAMERATE: @@ -1750,6 +1751,12 @@ static uiBlock *info_gamemenu(void *arg_unused) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Show Debug Properties", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_SHOW_DEBUG_PROPS, ""); } + if(G.fileflags & G_FILE_IGNORE_DEPRECATION_WARNINGS) { + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Ignore Deprecation Warnings", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_IGNORE_DEPRECATION_WARNINGS, ""); + } else { + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Ignore Deprecation Warnings", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_IGNORE_DEPRECATION_WARNINGS, ""); + } + uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 1, 0, ""); if(!(G.fileflags & G_FILE_GAME_MAT)) { diff --git a/source/blender/src/header_time.c b/source/blender/src/header_time.c index 574e0b3a9f1..02bdda86b4e 100644 --- a/source/blender/src/header_time.c +++ b/source/blender/src/header_time.c @@ -160,6 +160,9 @@ static void do_time_redrawmenu(void *arg, int event) if(event==1001) { button(&G.scene->r.frs_sec,1,120,"FPS:"); } + else if(event==1002) { + G.scene->audio.flag ^= AUDIO_SYNC; + } } } @@ -202,7 +205,11 @@ static uiBlock *time_redrawmenu(void *arg_unused) uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - sprintf(str, "Set Frames/Sec (%d/%f)", G.scene->r.frs_sec, G.scene->r.frs_sec_base); + if(G.scene->audio.flag & AUDIO_SYNC) icon= ICON_CHECKBOX_HLT; + else icon= ICON_CHECKBOX_DEHLT; + uiDefIconTextBut(block, BUTM, 1, icon, "Sync Playback to Frames/Sec", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1002, ""); + + sprintf(str, "Set Frames/Sec (%d/%2f)", G.scene->r.frs_sec, G.scene->r.frs_sec_base); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, str, 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1001, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); diff --git a/source/blender/src/header_view3d.c b/source/blender/src/header_view3d.c index b51c3e620e5..878213e80a3 100644 --- a/source/blender/src/header_view3d.c +++ b/source/blender/src/header_view3d.c @@ -517,6 +517,8 @@ static uiBlock *view3d_view_spacehandlers(void *arg_unused) if (handlertype == SPACEHANDLER_VIEW3D_EVENT) BLI_strncpy(menustr, "Event: ", 8); + else if (handlertype == SPACEHANDLER_VIEW3D_EVENT_ALL) + BLI_strncpy(menustr, "Event+: ", 8); else BLI_strncpy(menustr, "Draw: ", 8); BLI_strncpy(menustr+7, text->id.name+2, 22); diff --git a/source/blender/src/imagepaint.c b/source/blender/src/imagepaint.c index 149dbf1d026..09666f4819d 100644 --- a/source/blender/src/imagepaint.c +++ b/source/blender/src/imagepaint.c @@ -23,9 +23,9 @@ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. * - * The Original Code is: all of this file. + * The Original Code is: some of this file. * - * Contributor(s): Jens Ole Wund (bjornmose) + * Contributor(s): Jens Ole Wund (bjornmose), Campbell Barton (ideasman42) * * ***** END GPL LICENSE BLOCK ***** */ @@ -46,7 +46,10 @@ #include "BLI_arithb.h" #include "BLI_blenlib.h" #include "BLI_dynstr.h" +#include "BLI_linklist.h" +#include "BLI_memarena.h" #include "PIL_time.h" +#include "BLI_threads.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" @@ -70,6 +73,7 @@ #include "BKE_mesh.h" #include "BKE_node.h" #include "BKE_utildefines.h" +#include "BKE_DerivedMesh.h" #include "BIF_interface.h" #include "BIF_mywindow.h" @@ -77,14 +81,16 @@ #include "BIF_space.h" #include "BIF_toolbox.h" +#include "BIF_editview.h" /* only for mouse_cursor - could remove this later */ + #include "BSE_drawipo.h" #include "BSE_node.h" #include "BSE_trans_types.h" #include "BSE_view.h" +#include "BSE_drawview.h" /* view3d_test_clipping */ #include "BDR_imagepaint.h" #include "BDR_vpaint.h" - #include "GPU_draw.h" #include "GHOST_Types.h" @@ -95,12 +101,13 @@ /* Defines and Structs */ -#define IMAPAINT_CHAR_TO_FLOAT(c) (c/255.0f) +#define IMAPAINT_CHAR_TO_FLOAT(c) ((c)/255.0f) + +#define IMAPAINT_FLOAT_RGB_TO_CHAR(c, f) { (c)[0]=FTOCHAR((f)[0]); (c)[1]=FTOCHAR((f)[1]); (c)[2]=FTOCHAR((f)[2]); } +#define IMAPAINT_FLOAT_RGBA_TO_CHAR(c, f) { (c)[0]=FTOCHAR((f)[0]); (c)[1]=FTOCHAR((f)[1]); (c)[2]=FTOCHAR((f)[2]); (c)[3]=FTOCHAR((f)[3]); } -#define IMAPAINT_FLOAT_RGB_TO_CHAR(c, f) { c[0]=FTOCHAR(f[0]); \ - c[1]=FTOCHAR(f[1]); c[2]=FTOCHAR(f[2]); } -#define IMAPAINT_CHAR_RGB_TO_FLOAT(f, c) { f[0]=IMAPAINT_CHAR_TO_FLOAT(c[0]); \ - f[1]=IMAPAINT_CHAR_TO_FLOAT(c[1]); f[2]=IMAPAINT_CHAR_TO_FLOAT(c[2]); } +#define IMAPAINT_CHAR_RGB_TO_FLOAT(f, c) { (f)[0]=IMAPAINT_CHAR_TO_FLOAT((c)[0]); (f)[1]=IMAPAINT_CHAR_TO_FLOAT((c)[1]); (f)[2]=IMAPAINT_CHAR_TO_FLOAT((c)[2]); } +#define IMAPAINT_CHAR_RGBA_TO_FLOAT(f, c) { (f)[0]=IMAPAINT_CHAR_TO_FLOAT((c)[0]); (f)[1]=IMAPAINT_CHAR_TO_FLOAT((c)[1]); (f)[2]=IMAPAINT_CHAR_TO_FLOAT((c)[2]); (f)[3]=IMAPAINT_CHAR_TO_FLOAT((c)[3]); } #define IMAPAINT_FLOAT_RGB_COPY(a, b) VECCOPY(a, b) #define IMAPAINT_TILE_BITS 6 @@ -109,6 +116,9 @@ #define MAXUNDONAME 64 +static void imapaint_image_update(Image *image, ImBuf *ibuf, short texpaint); + + typedef struct ImagePaintState { Brush *brush; short tool, blend; @@ -126,6 +136,194 @@ typedef struct ImagePaintState { float uv[2]; } ImagePaintState; +typedef struct ImagePaintPartialRedraw { + int x1, y1, x2, y2; + int enabled; +} ImagePaintPartialRedraw; + + +/* ProjectionPaint defines */ + +/* approx the number of buckets to have under the brush, + * used with the brush size to set the ps->buckets_x and ps->buckets_y value. + * + * When 3 - a brush should have ~9 buckets under it at once + * ...this helps for threading while painting as well as + * avoiding initializing pixels that wont touch the brush */ +#define PROJ_BUCKET_BRUSH_DIV 4 + +#define PROJ_BUCKET_RECT_MIN 4 +#define PROJ_BUCKET_RECT_MAX 256 + +#define PROJ_BOUNDBOX_DIV 8 +#define PROJ_BOUNDBOX_SQUARED (PROJ_BOUNDBOX_DIV * PROJ_BOUNDBOX_DIV) + +//#define PROJ_DEBUG_PAINT 1 +//#define PROJ_DEBUG_NOSEAMBLEED 1 +//#define PROJ_DEBUG_PRINT_CLIP 1 +#define PROJ_DEBUG_WINCLIP 1 + +/* projectFaceSeamFlags options */ +//#define PROJ_FACE_IGNORE 1<<0 /* When the face is hidden, backfacing or occluded */ +//#define PROJ_FACE_INIT 1<<1 /* When we have initialized the faces data */ +#define PROJ_FACE_SEAM1 1<<0 /* If this face has a seam on any of its edges */ +#define PROJ_FACE_SEAM2 1<<1 +#define PROJ_FACE_SEAM3 1<<2 +#define PROJ_FACE_SEAM4 1<<3 + +#define PROJ_FACE_NOSEAM1 1<<4 +#define PROJ_FACE_NOSEAM2 1<<5 +#define PROJ_FACE_NOSEAM3 1<<6 +#define PROJ_FACE_NOSEAM4 1<<7 + +/* a slightly scaled down face is used to get fake 3D location for edge pixels in the seams + * as this number approaches 1.0f the likelihood increases of float precision errors where + * it is occluded by an adjacent face */ +#define PROJ_FACE_SCALE_SEAM 0.99f + +#define PROJ_BUCKET_NULL 0 +#define PROJ_BUCKET_INIT 1<<0 +// #define PROJ_BUCKET_CLONE_INIT 1<<1 + +/* used for testing doubles, if a point is on a line etc */ +#define PROJ_GEOM_TOLERANCE 0.0002f + +/* vert flags */ +#define PROJ_VERT_CULL 1 + +#define PI_80_DEG ((M_PI_2 / 9) * 8) + +/* This is mainly a convenience struct used so we can keep an array of images we use + * Thir imbufs, etc, in 1 array, When using threads this array is copied for each thread + * because 'partRedrawRect' and 'touch' values would not be thread safe */ +typedef struct ProjPaintImage { + Image *ima; + ImBuf *ibuf; + ImagePaintPartialRedraw *partRedrawRect; + struct UndoTile **undoRect; /* only used to build undo tiles after painting */ + int touch; +} ProjPaintImage; + +/* Main projection painting struct passed to all projection painting functions */ +typedef struct ProjPaintState { + Brush *brush; + short tool, blend; + Object *ob; + /* end similarities with ImagePaintState */ + + DerivedMesh *dm; + int dm_totface; + int dm_totvert; + + MVert *dm_mvert; + MFace *dm_mface; + MTFace *dm_mtface; + MTFace *dm_mtface_clone; /* other UV layer, use for cloning between layers */ + MTFace *dm_mtface_mask; + + /* projection painting only */ + MemArena *arena_mt[BLENDER_MAX_THREADS];/* for multithreading, the first item is sometimes used for non threaded cases too */ + LinkNode **bucketRect; /* screen sized 2D array, each pixel has a linked list of ProjPixel's */ + LinkNode **bucketFaces; /* bucketRect aligned array linkList of faces overlapping each bucket */ + unsigned char *bucketFlags; /* store if the bucks have been initialized */ +#ifndef PROJ_DEBUG_NOSEAMBLEED + char *faceSeamFlags; /* store info about faces, if they are initialized etc*/ + float (*faceSeamUVs)[4][2]; /* expanded UVs for faces to use as seams */ + LinkNode **vertFaces; /* Only needed for when seam_bleed_px is enabled, use to find UV seams */ + char *vertFlags; /* store options per vert, now only store if the vert is pointing away from the view */ +#endif + int buckets_x; /* The size of the bucket grid, the grid span's screenMin/screenMax so you can paint outsize the screen or with 2 brushes at once */ + int buckets_y; + + ProjPaintImage *projImages; + + int image_tot; /* size of projectImages array */ + + float (*screenCoords)[4]; /* verts projected into floating point screen space */ + + float screenMin[2]; /* 2D bounds for mesh verts on the screen's plane (screenspace) */ + float screenMax[2]; + float screen_width; /* Calculated from screenMin & screenMax */ + float screen_height; + + /* options for projection painting */ + int do_layer_clone; + int do_layer_mask; + int do_layer_mask_inv; + + short do_occlude; /* Use raytraced occlusion? - ortherwise will paint right through to the back*/ + short do_backfacecull; /* ignore faces with normals pointing away, skips a lot of raycasts if your normals are correctly flipped */ + short do_mask_normal; /* mask out pixels based on their normals */ + float normal_angle; /* what angle to mask at*/ + float normal_angle_inner; + float normal_angle_range; /* difference between normal_angle and normal_angle_inner, for easy access */ + + short is_ortho; + short is_airbrush; /* only to avoid using (ps.brush->flag & BRUSH_AIRBRUSH) */ + short is_texbrush; /* only to avoid running */ +#ifndef PROJ_DEBUG_NOSEAMBLEED + float seam_bleed_px; +#endif + /* clone vars */ + float cloneOffset[2]; + + float projectMat[4][4]; /* Projection matrix, use for getting screen coords */ + float viewMat[4][4]; + float viewDir[3]; /* View vector, use for do_backfacecull and for ray casting with an ortho viewport */ + float viewPos[3]; /* View location in object relative 3D space, so can compare to verts */ + float clipsta, clipend; + + /* threads */ + int thread_tot; + int bucketMin[2]; + int bucketMax[2]; + int context_bucket_x, context_bucket_y; /* must lock threads while accessing these */ +} ProjPaintState; + +typedef union pixelPointer +{ + float *f_pt; /* float buffer */ + unsigned int *uint_pt; /* 2 ways to access a char buffer */ + unsigned char *ch_pt; +} PixelPointer; + +typedef union pixelStore +{ + unsigned char ch[4]; + unsigned int uint; + float f[4]; +} PixelStore; + +typedef struct ProjPixel { + float projCoSS[2]; /* the floating point screen projection of this pixel */ + + /* Only used when the airbrush is disabled. + * Store the max mask value to avoid painting over an area with a lower opacity + * with an advantage that we can avoid touching the pixel at all, if the + * new mask value is lower then mask_max */ + unsigned short mask_max; + + /* for various reasons we may want to mask out painting onto this pixel */ + unsigned short mask; + + short x_px, y_px; + + PixelStore origColor; + PixelStore newColor; + PixelPointer pixel; + + short image_index; /* if anyone wants to paint onto more then 32768 images they can bite me */ + unsigned char bb_cell_index; +} ProjPixel; + +typedef struct ProjPixelClone { + struct ProjPixel __pp; + PixelStore clonepx; +} ProjPixelClone; + +/* Finish projection painting structs */ + + typedef struct UndoTile { struct UndoTile *next, *prev; ID id; @@ -142,11 +340,6 @@ typedef struct UndoElem { ListBase tiles; } UndoElem; -typedef struct ImagePaintPartialRedraw { - int x1, y1, x2, y2; - int enabled; -} ImagePaintPartialRedraw; - static ListBase undobase = {NULL, NULL}; static UndoElem *curundo = NULL; static ImagePaintPartialRedraw imapaintpartial = {0, 0, 0, 0, 0}; @@ -161,14 +354,42 @@ static void undo_copy_tile(UndoTile *tile, ImBuf *tmpibuf, ImBuf *ibuf, int rest IMB_rectcpy(tmpibuf, ibuf, 0, 0, tile->x*IMAPAINT_TILE_SIZE, tile->y*IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE); - if(ibuf->rect_float) SWAP(void*, tmpibuf->rect_float, tile->rect) - else SWAP(void*, tmpibuf->rect, tile->rect) + if(ibuf->rect_float) { + SWAP(void*, tmpibuf->rect_float, tile->rect); + } else { + SWAP(void*, tmpibuf->rect, tile->rect); + } if(restore) IMB_rectcpy(ibuf, tmpibuf, tile->x*IMAPAINT_TILE_SIZE, tile->y*IMAPAINT_TILE_SIZE, 0, 0, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE); } +static UndoTile *undo_init_tile(ID *id, ImBuf *ibuf, ImBuf **tmpibuf, int x_tile, int y_tile) +{ + UndoTile *tile; + int allocsize; + + if (*tmpibuf==NULL) + *tmpibuf = IMB_allocImBuf(IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32, IB_rectfloat|IB_rect, 0); + + tile= MEM_callocN(sizeof(UndoTile), "ImaUndoTile"); + tile->id= *id; + tile->x= x_tile; + tile->y= y_tile; + + allocsize= IMAPAINT_TILE_SIZE*IMAPAINT_TILE_SIZE*4; + allocsize *= (ibuf->rect_float)? sizeof(float): sizeof(char); + tile->rect= MEM_mapallocN(allocsize, "ImaUndoRect"); + + undo_copy_tile(tile, *tmpibuf, ibuf, 0); + curundo->undosize += allocsize; + + BLI_addtail(&curundo->tiles, tile); + + return tile; +} + static void undo_restore(UndoElem *undo) { Image *ima = NULL; @@ -281,9 +502,3394 @@ static void undo_imagepaint_push_end() } } -/* external functions */ +/* fast projection bucket array lookup, use the safe version for bound checking */ +static int project_bucket_offset(const ProjPaintState *ps, const float projCoSS[2]) +{ + /* If we were not dealing with screenspace 2D coords we could simple do... + * ps->bucketRect[x + (y*ps->buckets_y)] */ + + /* please explain? + * projCoSS[0] - ps->screenMin[0] : zero origin + * ... / ps->screen_width : range from 0.0 to 1.0 + * ... * ps->buckets_x : use as a bucket index + * + * Second multiplication does similar but for vertical offset + */ + return ( (int)(((projCoSS[0] - ps->screenMin[0]) / ps->screen_width) * ps->buckets_x)) + + ( ( (int)(((projCoSS[1] - ps->screenMin[1]) / ps->screen_height) * ps->buckets_y)) * ps->buckets_x); +} + +static int project_bucket_offset_safe(const ProjPaintState *ps, const float projCoSS[2]) +{ + int bucket_index = project_bucket_offset(ps, projCoSS); + + if (bucket_index < 0 || bucket_index >= ps->buckets_x*ps->buckets_y) { + return -1; + } + else { + return bucket_index; + } +} + +#define SIDE_OF_LINE(pa, pb, pp) ((pa[0]-pp[0])*(pb[1]-pp[1]))-((pb[0]-pp[0])*(pa[1]-pp[1])) + +static float AreaSignedF2Dfl(float *v1, float *v2, float *v3) +{ + return (float)(0.5f*((v1[0]-v2[0])*(v2[1]-v3[1]) + +(v1[1]-v2[1])*(v3[0]-v2[0]))); +} + +static void BarycentricWeights2f(float pt[2], float v1[2], float v2[2], float v3[2], float w[3]) +{ + float wtot_inv, wtot; + + w[0] = AreaSignedF2Dfl(v2, v3, pt); + w[1] = AreaSignedF2Dfl(v3, v1, pt); + w[2] = AreaSignedF2Dfl(v1, v2, pt); + wtot = w[0]+w[1]+w[2]; + + if (wtot != 0.0f) { + wtot_inv = 1.0f/wtot; + + w[0] = w[0]*wtot_inv; + w[1] = w[1]*wtot_inv; + w[2] = w[2]*wtot_inv; + } + else /* dummy values for zero area face */ + w[0] = w[1] = w[2] = 1.0f/3.0f; +} + +/* still use 2D X,Y space but this works for verts transformed by a perspective matrix, using their 4th component as a weight */ +static void BarycentricWeightsPersp2f(float pt[2], float v1[4], float v2[4], float v3[4], float w[3]) +{ + float wtot_inv, wtot; + + w[0] = AreaSignedF2Dfl(v2, v3, pt) / v1[3]; + w[1] = AreaSignedF2Dfl(v3, v1, pt) / v2[3]; + w[2] = AreaSignedF2Dfl(v1, v2, pt) / v3[3]; + wtot = w[0]+w[1]+w[2]; + + if (wtot != 0.0f) { + wtot_inv = 1.0f/wtot; + + w[0] = w[0]*wtot_inv; + w[1] = w[1]*wtot_inv; + w[2] = w[2]*wtot_inv; + } + else /* dummy values for zero area face */ + w[0] = w[1] = w[2] = 1.0f/3.0f; +} + +static void VecWeightf(float p[3], const float v1[3], const float v2[3], const float v3[3], const float w[3]) +{ + p[0] = v1[0]*w[0] + v2[0]*w[1] + v3[0]*w[2]; + p[1] = v1[1]*w[0] + v2[1]*w[1] + v3[1]*w[2]; + p[2] = v1[2]*w[0] + v2[2]*w[1] + v3[2]*w[2]; +} + +static void Vec2Weightf(float p[2], const float v1[2], const float v2[2], const float v3[2], const float w[3]) +{ + p[0] = v1[0]*w[0] + v2[0]*w[1] + v3[0]*w[2]; + p[1] = v1[1]*w[0] + v2[1]*w[1] + v3[1]*w[2]; +} + +static float VecZDepthOrtho(float pt[2], float v1[3], float v2[3], float v3[3], float w[3]) +{ + BarycentricWeights2f(pt, v1, v2, v3, w); + return (v1[2]*w[0]) + (v2[2]*w[1]) + (v3[2]*w[2]); +} + +static float VecZDepthPersp(float pt[2], float v1[3], float v2[3], float v3[3], float w[3]) +{ + BarycentricWeightsPersp2f(pt, v1, v2, v3, w); + return (v1[2]*w[0]) + (v2[2]*w[1]) + (v3[2]*w[2]); +} + + +/* Return the top-most face index that the screen space coord 'pt' touches (or -1) */ +static int project_paint_PickFace(const ProjPaintState *ps, float pt[2], float w[3], int *side) +{ + LinkNode *node; + float w_tmp[3]; + float *v1, *v2, *v3, *v4; + int bucket_index; + int face_index; + int best_side = -1; + int best_face_index = -1; + float z_depth_best = MAXFLOAT, z_depth; + MFace *mf; + + bucket_index = project_bucket_offset_safe(ps, pt); + if (bucket_index==-1) + return -1; + + + + /* we could return 0 for 1 face buckets, as long as this function assumes + * that the point its testing is only every originated from an existing face */ + + for (node= ps->bucketFaces[bucket_index]; node; node= node->next) { + face_index = GET_INT_FROM_POINTER(node->link); + mf= ps->dm_mface + face_index; + + v1= ps->screenCoords[mf->v1]; + v2= ps->screenCoords[mf->v2]; + v3= ps->screenCoords[mf->v3]; + + if (IsectPT2Df(pt, v1, v2, v3)) { + if (ps->is_ortho) z_depth= VecZDepthOrtho(pt, v1, v2, v3, w_tmp); + else z_depth= VecZDepthPersp(pt, v1, v2, v3, w_tmp); + + if (z_depth < z_depth_best) { + best_face_index = face_index; + best_side = 0; + z_depth_best = z_depth; + VECCOPY(w, w_tmp); + } + } + else if (mf->v4) { + v4= ps->screenCoords[mf->v4]; + + if (IsectPT2Df(pt, v1, v3, v4)) { + if (ps->is_ortho) z_depth= VecZDepthOrtho(pt, v1, v3, v4, w_tmp); + else z_depth= VecZDepthPersp(pt, v1, v3, v4, w_tmp); + + if (z_depth < z_depth_best) { + best_face_index = face_index; + best_side= 1; + z_depth_best = z_depth; + VECCOPY(w, w_tmp); + } + } + } + } + + *side = best_side; + return best_face_index; /* will be -1 or a valid face */ +} + +/* Converts a uv coord into a pixel location wrapping if the uv is outside 0-1 range */ +static void uvco_to_wrapped_pxco(float uv[2], int ibuf_x, int ibuf_y, float *x, float *y) +{ + /* use */ + *x = (float)fmod(uv[0], 1.0f); + *y = (float)fmod(uv[1], 1.0f); + + if (*x < 0.0f) *x += 1.0f; + if (*y < 0.0f) *y += 1.0f; + + *x = *x * ibuf_x - 0.5f; + *y = *y * ibuf_y - 0.5f; +} + +/* Set the top-most face color that the screen space coord 'pt' touches (or return 0 if none touch) */ +static int project_paint_PickColor(const ProjPaintState *ps, float pt[2], float *rgba_fp, unsigned char *rgba, const int interp) +{ + float w[3], uv[2]; + int side; + int face_index; + MTFace *tf; + ImBuf *ibuf; + int xi, yi; + + + face_index = project_paint_PickFace(ps, pt, w, &side); + + if (face_index == -1) + return 0; + + tf = ps->dm_mtface + face_index; + + if (side == 0) { + Vec2Weightf(uv, tf->uv[0], tf->uv[1], tf->uv[2], w); + } + else { /* QUAD */ + Vec2Weightf(uv, tf->uv[0], tf->uv[2], tf->uv[3], w); + } + + ibuf = BKE_image_get_ibuf((Image *)tf->tpage, NULL); /* TODO - this may be slow, the only way around it is to have an ibuf index per face */ + + + + if (interp) { + float x, y; + uvco_to_wrapped_pxco(uv, ibuf->x, ibuf->y, &x, &y); + + if (ibuf->rect_float) { + if (rgba_fp) { + bilinear_interpolation_color(ibuf, NULL, rgba_fp, x, y); + } + else { + float rgba_tmp_f[4]; + bilinear_interpolation_color(ibuf, NULL, rgba_tmp_f, x, y); + IMAPAINT_FLOAT_RGBA_TO_CHAR(rgba, rgba_tmp_f); + } + } + else { + if (rgba) { + bilinear_interpolation_color(ibuf, rgba, NULL, x, y); + } + else { + unsigned char rgba_tmp[4]; + bilinear_interpolation_color(ibuf, rgba_tmp, NULL, x, y); + IMAPAINT_CHAR_RGBA_TO_FLOAT(rgba_fp, rgba_tmp); + } + } + } + else { + xi = (uv[0]*ibuf->x) + 0.5f; + yi = (uv[1]*ibuf->y) + 0.5f; + + //if (xi<0 || xi>=ibuf->x || yi<0 || yi>=ibuf->y) return 0; + + /* wrap */ + xi = ((int)(uv[0]*ibuf->x)) % ibuf->x; + if (xi<0) xi += ibuf->x; + yi = ((int)(uv[1]*ibuf->y)) % ibuf->y; + if (yi<0) yi += ibuf->y; + + + if (rgba) { + if (ibuf->rect_float) { + float *rgba_tmp_fp = ibuf->rect_float + (xi + yi * ibuf->x * 4); + IMAPAINT_FLOAT_RGBA_TO_CHAR(rgba, rgba_tmp_fp); + } + else { + *((unsigned int *)rgba) = *(unsigned int *)(((char *)ibuf->rect) + ((xi + yi * ibuf->x) * 4)); + } + } + + if (rgba_fp) { + if (ibuf->rect_float) { + QUATCOPY(rgba_fp, ((float *)ibuf->rect_float + ((xi + yi * ibuf->x) * 4))); + } + else { + char *tmp_ch= ((char *)ibuf->rect) + ((xi + yi * ibuf->x) * 4); + IMAPAINT_CHAR_RGBA_TO_FLOAT(rgba_fp, tmp_ch); + } + } + } + return 1; +} + +/* Check if 'pt' is infront of the 3 verts on the Z axis (used for screenspace occlusuion test) + * return... + * 0 : no occlusion + * -1 : no occlusion but 2D intersection is true (avoid testing the other half of a quad) + * 1 : occluded + 2 : occluded with w[3] weights set (need to know in some cases) */ + +static int project_paint_occlude_ptv(float pt[3], float v1[3], float v2[3], float v3[3], float w[3], int is_ortho) +{ + /* if all are behind us, return false */ + if(v1[2] > pt[2] && v2[2] > pt[2] && v3[2] > pt[2]) + return 0; + + /* do a 2D point in try intersection */ + if (!IsectPT2Df(pt, v1, v2, v3)) + return 0; /* we know there is */ + + + /* From here on we know there IS an intersection */ + /* if ALL of the verts are infront of us then we know it intersects ? */ + if(v1[2] < pt[2] && v2[2] < pt[2] && v3[2] < pt[2]) { + return 1; + } + else { + /* we intersect? - find the exact depth at the point of intersection */ + /* Is this point is occluded by another face? */ + if (is_ortho) { + if (VecZDepthOrtho(pt, v1, v2, v3, w) < pt[2]) return 2; + } + else { + if (VecZDepthPersp(pt, v1, v2, v3, w) < pt[2]) return 2; + } + } + return -1; +} + + +static int project_paint_occlude_ptv_clip( + const ProjPaintState *ps, const MFace *mf, + float pt[3], float v1[3], float v2[3], float v3[3], + const int side ) +{ + float w[3], wco[3]; + int ret = project_paint_occlude_ptv(pt, v1, v2, v3, w, ps->is_ortho); + + if (ret <= 0) + return ret; + + if (ret==1) { /* weights not calculated */ + if (ps->is_ortho) BarycentricWeights2f(pt, v1, v2, v3, w); + else BarycentricWeightsPersp2f(pt, v1, v2, v3, w); + } + + /* Test if we're in the clipped area, */ + if (side) VecWeightf(wco, ps->dm_mvert[mf->v1].co, ps->dm_mvert[mf->v3].co, ps->dm_mvert[mf->v4].co, w); + else VecWeightf(wco, ps->dm_mvert[mf->v1].co, ps->dm_mvert[mf->v2].co, ps->dm_mvert[mf->v3].co, w); + + Mat4MulVecfl(ps->ob->obmat, wco); + if(!view3d_test_clipping(G.vd, wco)) { + return 1; + } + + return -1; +} + + +/* Check if a screenspace location is occluded by any other faces + * check, pixelScreenCo must be in screenspace, its Z-Depth only needs to be used for comparison + * and dosn't need to be correct in relation to X and Y coords (this is the case in perspective view) */ +static int project_bucket_point_occluded(const ProjPaintState *ps, LinkNode *bucketFace, const int orig_face, float pixelScreenCo[4]) +{ + MFace *mf; + int face_index; + int isect_ret; + float w[3]; /* not needed when clipping */ + + /* we could return 0 for 1 face buckets, as long as this function assumes + * that the point its testing is only every originated from an existing face */ + + for (; bucketFace; bucketFace = bucketFace->next) { + face_index = (int)bucketFace->link; + + if (orig_face != face_index) { + mf = ps->dm_mface + face_index; + if(G.vd->flag & V3D_CLIPPING) + isect_ret = project_paint_occlude_ptv_clip(ps, mf, pixelScreenCo, ps->screenCoords[mf->v1], ps->screenCoords[mf->v2], ps->screenCoords[mf->v3], 0); + else + isect_ret = project_paint_occlude_ptv(pixelScreenCo, ps->screenCoords[mf->v1], ps->screenCoords[mf->v2], ps->screenCoords[mf->v3], w, ps->is_ortho); + + /* Note, if isect_ret==-1 then we dont want to test the other side of the quad */ + if (isect_ret==0 && mf->v4) { + if(G.vd->flag & V3D_CLIPPING) + isect_ret = project_paint_occlude_ptv_clip(ps, mf, pixelScreenCo, ps->screenCoords[mf->v1], ps->screenCoords[mf->v3], ps->screenCoords[mf->v4], 1); + else + isect_ret = project_paint_occlude_ptv(pixelScreenCo, ps->screenCoords[mf->v1], ps->screenCoords[mf->v3], ps->screenCoords[mf->v4], w, ps->is_ortho); + } + if (isect_ret==1) { + /* TODO - we may want to cache the first hit, + * it is not possible to swap the face order in the list anymore */ + return 1; + } + } + } + return 0; +} + +/* basic line intersection, could move to arithb.c, 2 points with a horiz line + * 1 for an intersection, 2 if the first point is aligned, 3 if the second point is aligned */ +#define ISECT_TRUE 1 +#define ISECT_TRUE_P1 2 +#define ISECT_TRUE_P2 3 +static int line_isect_y(const float p1[2], const float p2[2], const float y_level, float *x_isect) +{ + float y_diff; + + if (y_level==p1[1]) { /* are we touching the first point? - no interpolation needed */ + *x_isect = p1[0]; + return ISECT_TRUE_P1; + } + if (y_level==p2[1]) { /* are we touching the second point? - no interpolation needed */ + *x_isect = p2[0]; + return ISECT_TRUE_P2; + } + + y_diff= fabs(p1[1]-p2[1]); /* yuck, horizontal line, we cant do much here */ + + if (y_diff < 0.000001f) { + *x_isect = (p1[0]+p2[0]) * 0.5f; + return ISECT_TRUE; + } + + if (p1[1] > y_level && p2[1] < y_level) { + *x_isect = (p2[0]*(p1[1]-y_level) + p1[0]*(y_level-p2[1])) / y_diff; /*(p1[1]-p2[1]);*/ + return ISECT_TRUE; + } + else if (p1[1] < y_level && p2[1] > y_level) { + *x_isect = (p2[0]*(y_level-p1[1]) + p1[0]*(p2[1]-y_level)) / y_diff; /*(p2[1]-p1[1]);*/ + return ISECT_TRUE; + } + else { + return 0; + } +} + +static int line_isect_x(const float p1[2], const float p2[2], const float x_level, float *y_isect) +{ + float x_diff; + + if (x_level==p1[0]) { /* are we touching the first point? - no interpolation needed */ + *y_isect = p1[1]; + return ISECT_TRUE_P1; + } + if (x_level==p2[0]) { /* are we touching the second point? - no interpolation needed */ + *y_isect = p2[1]; + return ISECT_TRUE_P2; + } + + x_diff= fabs(p1[0]-p2[0]); /* yuck, horizontal line, we cant do much here */ + + if (x_diff < 0.000001) { /* yuck, vertical line, we cant do much here */ + *y_isect = (p1[0]+p2[0]) * 0.5f; + return ISECT_TRUE; + } + + if (p1[0] > x_level && p2[0] < x_level) { + *y_isect = (p2[1]*(p1[0]-x_level) + p1[1]*(x_level-p2[0])) / x_diff; /*(p1[0]-p2[0]);*/ + return ISECT_TRUE; + } + else if (p1[0] < x_level && p2[0] > x_level) { + *y_isect = (p2[1]*(x_level-p1[0]) + p1[1]*(p2[0]-x_level)) / x_diff; /*(p2[0]-p1[0]);*/ + return ISECT_TRUE; + } + else { + return 0; + } +} + +/* simple func use for comparing UV locations to check if there are seams. + * Its possible this gives incorrect results, when the UVs for 1 face go into the next + * tile, but do not do this for the adjacent face, it could return a false positive. + * This is so unlikely that Id not worry about it. */ +static int cmp_uv(const float vec2a[2], const float vec2b[2]) +{ + /* if the UV's are not between 0.0 and 1.0 */ + float xa = (float)fmod(vec2a[0], 1.0f); + float ya = (float)fmod(vec2a[1], 1.0f); + + float xb = (float)fmod(vec2b[0], 1.0f); + float yb = (float)fmod(vec2b[1], 1.0f); + + if (xa < 0.0f) xa += 1.0f; + if (ya < 0.0f) ya += 1.0f; + + if (xb < 0.0f) xb += 1.0f; + if (yb < 0.0f) yb += 1.0f; + + return ((fabs(xa-xb) < PROJ_GEOM_TOLERANCE) && (fabs(ya-yb) < PROJ_GEOM_TOLERANCE)) ? 1:0; +} + + +/* set min_px and max_px to the image space bounds of the UV coords + * return zero if there is no area in the returned rectangle */ +static int pixel_bounds_uv( + const float uv1[2], const float uv2[2], const float uv3[2], const float uv4[2], + rcti *bounds_px, + const int ibuf_x, const int ibuf_y, + int is_quad +) { + float min_uv[2], max_uv[2]; /* UV bounds */ + + INIT_MINMAX2(min_uv, max_uv); + + DO_MINMAX2(uv1, min_uv, max_uv); + DO_MINMAX2(uv2, min_uv, max_uv); + DO_MINMAX2(uv3, min_uv, max_uv); + if (is_quad) + DO_MINMAX2(uv4, min_uv, max_uv); + + bounds_px->xmin = (int)(ibuf_x * min_uv[0]); + bounds_px->ymin = (int)(ibuf_y * min_uv[1]); + + bounds_px->xmax = (int)(ibuf_x * max_uv[0]) +1; + bounds_px->ymax = (int)(ibuf_y * max_uv[1]) +1; + + /*printf("%d %d %d %d \n", min_px[0], min_px[1], max_px[0], max_px[1]);*/ + + /* face uses no UV area when quantized to pixels? */ + return (bounds_px->xmin == bounds_px->xmax || bounds_px->ymin == bounds_px->ymax) ? 0 : 1; +} + +static int pixel_bounds_array(float (* uv)[2], rcti *bounds_px, const int ibuf_x, const int ibuf_y, int tot) +{ + float min_uv[2], max_uv[2]; /* UV bounds */ + + if (tot==0) { + return 0; + } + + INIT_MINMAX2(min_uv, max_uv); + + while (tot--) { + DO_MINMAX2((*uv), min_uv, max_uv); + uv++; + } + + bounds_px->xmin = (int)(ibuf_x * min_uv[0]); + bounds_px->ymin = (int)(ibuf_y * min_uv[1]); + + bounds_px->xmax = (int)(ibuf_x * max_uv[0]) +1; + bounds_px->ymax = (int)(ibuf_y * max_uv[1]) +1; + + /*printf("%d %d %d %d \n", min_px[0], min_px[1], max_px[0], max_px[1]);*/ + + /* face uses no UV area when quantized to pixels? */ + return (bounds_px->xmin == bounds_px->xmax || bounds_px->ymin == bounds_px->ymax) ? 0 : 1; +} + +#ifndef PROJ_DEBUG_NOSEAMBLEED + +/* This function returns 1 if this face has a seam along the 2 face-vert indicies + * 'orig_i1_fidx' and 'orig_i2_fidx' */ +static int check_seam(const ProjPaintState *ps, const int orig_face, const int orig_i1_fidx, const int orig_i2_fidx, int *other_face, int *orig_fidx) +{ + LinkNode *node; + int face_index; + int i1, i2; + int i1_fidx = -1, i2_fidx = -1; /* index in face */ + MFace *mf; + MTFace *tf; + const MFace *orig_mf = ps->dm_mface + orig_face; + const MTFace *orig_tf = ps->dm_mtface + orig_face; + + /* vert indicies from face vert order indicies */ + i1 = (*(&orig_mf->v1 + orig_i1_fidx)); + i2 = (*(&orig_mf->v1 + orig_i2_fidx)); + + for (node = ps->vertFaces[i1]; node; node = node->next) { + face_index = (int)node->link; + if (face_index != orig_face) { + mf = ps->dm_mface + face_index; + /* could check if the 2 faces images match here, + * but then there wouldn't be a way to return the opposite face's info */ + + + /* We need to know the order of the verts in the adjacent face + * set the i1_fidx and i2_fidx to (0,1,2,3) */ + if (mf->v1==i1) i1_fidx = 0; + else if (mf->v2==i1) i1_fidx = 1; + else if (mf->v3==i1) i1_fidx = 2; + else if (mf->v4 && mf->v4==i1) i1_fidx = 3; + + if (mf->v1==i2) i2_fidx = 0; + else if (mf->v2==i2) i2_fidx = 1; + else if (mf->v3==i2) i2_fidx = 2; + else if (mf->v4 && mf->v4==i2) i2_fidx = 3; + + /* Only need to check if 'i2_fidx' is valid because we know i1_fidx is the same vert on both faces */ + if (i2_fidx != -1) { + /* This IS an adjacent face!, now lets check if the UVs are ok */ + tf = ps->dm_mtface + face_index; + + /* set up the other face */ + *other_face = face_index; + *orig_fidx = (i1_fidx < i2_fidx) ? i1_fidx : i2_fidx; + + /* first test if they have the same image */ + if ( (orig_tf->tpage == tf->tpage) && + cmp_uv(orig_tf->uv[orig_i1_fidx], tf->uv[i1_fidx]) && + cmp_uv(orig_tf->uv[orig_i2_fidx], tf->uv[i2_fidx]) ) + { + // printf("SEAM (NONE)\n"); + return 0; + + } + else { + // printf("SEAM (UV GAP)\n"); + return 1; + } + } + } + } + // printf("SEAM (NO FACE)\n"); + *other_face = -1; + return 1; +} + +/* TODO - move to arithb.c */ +/* Converts an angle to a length that can be used for maintaining an even margin around UV's */ +static float angleToLength(float angle) +{ + // already accounted for + if (angle < 0.000001f) { + return 1.0f; + } + else { + return fabs(1.0f / cos(angle * (M_PI/180.0f))); + } +} + +/* Calculate outset UV's, this is not the same as simply scaling the UVs, + * since the outset coords are a margin that keep an even distance from the original UV's, + * note that the image aspect is taken into account */ +static void uv_image_outset(float (*orig_uv)[2], float (*outset_uv)[2], const float scaler, const int ibuf_x, const int ibuf_y, const int is_quad) +{ + float a1, a2, a3, a4=0.0f; + float puv[4][2]; /* pixelspace uv's */ + float no1[2], no2[2], no3[2], no4[2]; /* normals */ + float dir1[2], dir2[2], dir3[2], dir4[2]; + float ibuf_x_inv = 1.0f / (float)ibuf_x; + float ibuf_y_inv = 1.0f / (float)ibuf_y; + + /* make UV's in pixel space so we can */ + puv[0][0] = orig_uv[0][0] * ibuf_x; + puv[0][1] = orig_uv[0][1] * ibuf_y; + + puv[1][0] = orig_uv[1][0] * ibuf_x; + puv[1][1] = orig_uv[1][1] * ibuf_y; + + puv[2][0] = orig_uv[2][0] * ibuf_x; + puv[2][1] = orig_uv[2][1] * ibuf_y; + + if (is_quad) { + puv[3][0] = orig_uv[3][0] * ibuf_x; + puv[3][1] = orig_uv[3][1] * ibuf_y; + } + + /* face edge directions */ + Vec2Subf(dir1, puv[1], puv[0]); + Vec2Subf(dir2, puv[2], puv[1]); + Normalize2(dir1); + Normalize2(dir2); + + if (is_quad) { + Vec2Subf(dir3, puv[3], puv[2]); + Vec2Subf(dir4, puv[0], puv[3]); + Normalize2(dir3); + Normalize2(dir4); + } + else { + Vec2Subf(dir3, puv[0], puv[2]); + Normalize2(dir3); + } + + if (is_quad) { + a1 = angleToLength(NormalizedVecAngle2_2D(dir4, dir1)); + a2 = angleToLength(NormalizedVecAngle2_2D(dir1, dir2)); + a3 = angleToLength(NormalizedVecAngle2_2D(dir2, dir3)); + a4 = angleToLength(NormalizedVecAngle2_2D(dir3, dir4)); + } + else { + a1 = angleToLength(NormalizedVecAngle2_2D(dir3, dir1)); + a2 = angleToLength(NormalizedVecAngle2_2D(dir1, dir2)); + a3 = angleToLength(NormalizedVecAngle2_2D(dir2, dir3)); + } + + if (is_quad) { + Vec2Subf(no1, dir4, dir1); + Vec2Subf(no2, dir1, dir2); + Vec2Subf(no3, dir2, dir3); + Vec2Subf(no4, dir3, dir4); + Normalize2(no1); + Normalize2(no2); + Normalize2(no3); + Normalize2(no4); + Vec2Mulf(no1, a1*scaler); + Vec2Mulf(no2, a2*scaler); + Vec2Mulf(no3, a3*scaler); + Vec2Mulf(no4, a4*scaler); + Vec2Addf(outset_uv[0], puv[0], no1); + Vec2Addf(outset_uv[1], puv[1], no2); + Vec2Addf(outset_uv[2], puv[2], no3); + Vec2Addf(outset_uv[3], puv[3], no4); + outset_uv[0][0] *= ibuf_x_inv; + outset_uv[0][1] *= ibuf_y_inv; + + outset_uv[1][0] *= ibuf_x_inv; + outset_uv[1][1] *= ibuf_y_inv; + + outset_uv[2][0] *= ibuf_x_inv; + outset_uv[2][1] *= ibuf_y_inv; + + outset_uv[3][0] *= ibuf_x_inv; + outset_uv[3][1] *= ibuf_y_inv; + } + else { + Vec2Subf(no1, dir3, dir1); + Vec2Subf(no2, dir1, dir2); + Vec2Subf(no3, dir2, dir3); + Normalize2(no1); + Normalize2(no2); + Normalize2(no3); + Vec2Mulf(no1, a1*scaler); + Vec2Mulf(no2, a2*scaler); + Vec2Mulf(no3, a3*scaler); + Vec2Addf(outset_uv[0], puv[0], no1); + Vec2Addf(outset_uv[1], puv[1], no2); + Vec2Addf(outset_uv[2], puv[2], no3); + outset_uv[0][0] *= ibuf_x_inv; + outset_uv[0][1] *= ibuf_y_inv; + + outset_uv[1][0] *= ibuf_x_inv; + outset_uv[1][1] *= ibuf_y_inv; + + outset_uv[2][0] *= ibuf_x_inv; + outset_uv[2][1] *= ibuf_y_inv; + } +} + +/* + * Be tricky with flags, first 4 bits are PROJ_FACE_SEAM1 to 4, last 4 bits are PROJ_FACE_NOSEAM1 to 4 + * 1<<i - where i is (0-3) + * + * If we're multithreadng, make sure threads are locked when this is called + */ +static void project_face_seams_init(const ProjPaintState *ps, const int face_index, const int is_quad) +{ + int other_face, other_fidx; /* vars for the other face, we also set its flag */ + int fidx1 = is_quad ? 3 : 2; + int fidx2 = 0; /* next fidx in the face (0,1,2,3) -> (1,2,3,0) or (0,1,2) -> (1,2,0) for a tri */ + + do { + if ((ps->faceSeamFlags[face_index] & (1<<fidx1|16<<fidx1)) == 0) { + if (check_seam(ps, face_index, fidx1, fidx2, &other_face, &other_fidx)) { + ps->faceSeamFlags[face_index] |= 1<<fidx1; + if (other_face != -1) + ps->faceSeamFlags[other_face] |= 1<<other_fidx; + } + else { + ps->faceSeamFlags[face_index] |= 16<<fidx1; + if (other_face != -1) + ps->faceSeamFlags[other_face] |= 16<<other_fidx; /* second 4 bits for disabled */ + } + } + + fidx2 = fidx1; + } while (fidx1--); +} +#endif // PROJ_DEBUG_NOSEAMBLEED + + +/* TODO - move to arithb.c */ + +/* little sister we only need to know lambda */ +static float lambda_cp_line2(const float p[2], const float l1[2], const float l2[2]) +{ + float h[2], u[2]; + + u[0] = l2[0] - l1[0]; + u[1] = l2[1] - l1[1]; + + h[0] = p[0] - l1[0]; + h[1] = p[1] - l1[1]; + + return(Inp2f(u, h)/Inp2f(u, u)); +} + + +/* Converts a UV location to a 3D screenspace location + * Takes a 'uv' and 3 UV coords, and sets the values of pixelScreenCo + * + * This is used for finding a pixels location in screenspace for painting */ +static void screen_px_from_ortho( + float uv[2], + float v1co[3], float v2co[3], float v3co[3], /* Screenspace coords */ + float uv1co[2], float uv2co[2], float uv3co[2], + float pixelScreenCo[4], + float w[3]) +{ + BarycentricWeights2f(uv, uv1co, uv2co, uv3co, w); + VecWeightf(pixelScreenCo, v1co, v2co, v3co, w); +} + +/* same as screen_px_from_ortho except we need to take into account + * the perspective W coord for each vert */ +static void screen_px_from_persp( + float uv[2], + float v1co[3], float v2co[3], float v3co[3], /* screenspace coords */ + float uv1co[2], float uv2co[2], float uv3co[2], + float pixelScreenCo[4], + float w[3]) +{ + + float wtot_inv, wtot; + BarycentricWeights2f(uv, uv1co, uv2co, uv3co, w); + + /* re-weight from the 4th coord of each screen vert */ + w[0] *= v1co[3]; + w[1] *= v2co[3]; + w[2] *= v3co[3]; + + wtot = w[0]+w[1]+w[2]; + + if (wtot > 0.0f) { + wtot_inv = 1.0f / wtot; + w[0] *= wtot_inv; + w[1] *= wtot_inv; + w[2] *= wtot_inv; + } + else { + w[0] = w[1] = w[2] = 1.0/3.0; /* dummy values for zero area face */ + } + /* done re-weighting */ + + VecWeightf(pixelScreenCo, v1co, v2co, v3co, w); +} + +static void project_face_pixel(const MTFace *tf_other, ImBuf *ibuf_other, const float w[3], int side, unsigned char rgba_ub[4], float rgba_f[4]) +{ + float *uvCo1, *uvCo2, *uvCo3; + float uv_other[2], x, y; + + uvCo1 = (float *)tf_other->uv[0]; + if (side==1) { + uvCo2 = (float *)tf_other->uv[2]; + uvCo3 = (float *)tf_other->uv[3]; + } + else { + uvCo2 = (float *)tf_other->uv[1]; + uvCo3 = (float *)tf_other->uv[2]; + } + + Vec2Weightf(uv_other, uvCo1, uvCo2, uvCo3, w); + + /* use */ + uvco_to_wrapped_pxco(uv_other, ibuf_other->x, ibuf_other->y, &x, &y); + + + if (ibuf_other->rect_float) { /* from float to float */ + bilinear_interpolation_color(ibuf_other, NULL, rgba_f, x, y); + } + else { /* from char to float */ + bilinear_interpolation_color(ibuf_other, rgba_ub, NULL, x, y); + } + +} + +/* run this outside project_paint_uvpixel_init since pixels with mask 0 dont need init */ +float project_paint_uvpixel_mask( + const ProjPaintState *ps, + const int face_index, + const int side, + const float w[3]) +{ + float mask; + + /* Image Mask */ + if (ps->do_layer_mask) { + /* another UV layers image is masking this one's */ + ImBuf *ibuf_other; + const MTFace *tf_other = ps->dm_mtface_mask + face_index; + + if (tf_other->tpage && (ibuf_other = BKE_image_get_ibuf((Image *)tf_other->tpage, NULL))) { + /* BKE_image_get_ibuf - TODO - this may be slow */ + unsigned char rgba_ub[4]; + float rgba_f[4]; + + project_face_pixel(tf_other, ibuf_other, w, side, rgba_ub, rgba_f); + + if (ibuf_other->rect_float) { /* from float to float */ + mask = ((rgba_f[0]+rgba_f[1]+rgba_f[2])/3.0f) * rgba_f[3]; + } + else { /* from char to float */ + mask = ((rgba_ub[0]+rgba_ub[1]+rgba_ub[2])/(256*3.0f)) * (rgba_ub[3]/256.0f); + } + + if (!ps->do_layer_mask_inv) /* matching the gimps layer mask black/white rules, white==full opacity */ + mask = (1.0f - mask); + + if (mask == 0.0f) { + return 0.0f; + } + } + else { + return 0.0f; + } + } else { + mask = 1.0f; + } + + /* calculate mask */ + if (ps->do_mask_normal) { + MFace *mf = ps->dm_mface + face_index; + short *no1, *no2, *no3; + float no[3], angle; + no1 = ps->dm_mvert[mf->v1].no; + if (side==1) { + no2 = ps->dm_mvert[mf->v3].no; + no3 = ps->dm_mvert[mf->v4].no; + } + else { + no2 = ps->dm_mvert[mf->v2].no; + no3 = ps->dm_mvert[mf->v3].no; + } + + no[0] = w[0]*no1[0] + w[1]*no2[0] + w[2]*no3[0]; + no[1] = w[0]*no1[1] + w[1]*no2[1] + w[2]*no3[1]; + no[2] = w[0]*no1[2] + w[1]*no2[2] + w[2]*no3[2]; + Normalize(no); + + /* now we can use the normal as a mask */ + if (ps->is_ortho) { + angle = NormalizedVecAngle2((float *)ps->viewDir, no); + } + else { + /* Annoying but for the perspective view we need to get the pixels location in 3D space :/ */ + float viewDirPersp[3]; + float *co1, *co2, *co3; + co1 = ps->dm_mvert[mf->v1].co; + if (side==1) { + co2 = ps->dm_mvert[mf->v3].co; + co3 = ps->dm_mvert[mf->v4].co; + } + else { + co2 = ps->dm_mvert[mf->v2].co; + co3 = ps->dm_mvert[mf->v3].co; + } + + /* Get the direction from the viewPoint to the pixel and normalize */ + viewDirPersp[0] = (ps->viewPos[0] - (w[0]*co1[0] + w[1]*co2[0] + w[2]*co3[0])); + viewDirPersp[1] = (ps->viewPos[1] - (w[0]*co1[1] + w[1]*co2[1] + w[2]*co3[1])); + viewDirPersp[2] = (ps->viewPos[2] - (w[0]*co1[2] + w[1]*co2[2] + w[2]*co3[2])); + Normalize(viewDirPersp); + + angle = NormalizedVecAngle2(viewDirPersp, no); + } + + if (angle >= ps->normal_angle) { + return 0.0f; /* outsize the normal limit*/ + } + else if (angle > ps->normal_angle_inner) { + mask *= (ps->normal_angle - angle) / ps->normal_angle_range; + } /* otherwise no mask normal is needed, were within the limit */ + } + + // This only works when the opacity dosnt change while painting, stylus pressure messes with this + // so dont use it. + // if (ps->is_airbrush==0) mask *= ps->brush->alpha; + + return mask; +} + +/* run this function when we know a bucket's, face's pixel can be initialized, + * return the ProjPixel which is added to 'ps->bucketRect[bucket_index]' */ +static ProjPixel *project_paint_uvpixel_init( + const ProjPaintState *ps, + MemArena *arena, + const ImBuf *ibuf, + short x_px, short y_px, + const float mask, + const int face_index, + const int image_index, + const float pixelScreenCo[4], + const int side, + const float w[3]) +{ + ProjPixel *projPixel; + short size; + + /* wrap pixel location */ + x_px = x_px % ibuf->x; + if (x_px<0) x_px += ibuf->x; + y_px = y_px % ibuf->y; + if (y_px<0) y_px += ibuf->y; + + if (ps->tool==PAINT_TOOL_CLONE) { + size = sizeof(ProjPixelClone); + } + else if (ps->tool==PAINT_TOOL_SMEAR) { + size = sizeof(ProjPixelClone); + } + else { + size = sizeof(ProjPixel); + } + + projPixel = (ProjPixel *)BLI_memarena_alloc(arena, size); + //memset(projPixel, 0, size); + + if (ibuf->rect_float) { + projPixel->pixel.f_pt = (float *)ibuf->rect_float + ((x_px + y_px * ibuf->x) * 4); + projPixel->origColor.f[0] = projPixel->newColor.f[0] = projPixel->pixel.f_pt[0]; + projPixel->origColor.f[1] = projPixel->newColor.f[1] = projPixel->pixel.f_pt[1]; + projPixel->origColor.f[2] = projPixel->newColor.f[2] = projPixel->pixel.f_pt[2]; + projPixel->origColor.f[3] = projPixel->newColor.f[3] = projPixel->pixel.f_pt[3]; + } + else { + projPixel->pixel.ch_pt = ((unsigned char *)ibuf->rect + ((x_px + y_px * ibuf->x) * 4)); + projPixel->origColor.uint = projPixel->newColor.uint = *projPixel->pixel.uint_pt; + } + + /* screenspace unclamped, we could keep its z and w values but dont need them at the moment */ + VECCOPY2D(projPixel->projCoSS, pixelScreenCo); + + projPixel->x_px = x_px; + projPixel->y_px = y_px; + + projPixel->mask = (unsigned short)(mask * 65535); + projPixel->mask_max = 0; + + /* which bounding box cell are we in?, needed for undo */ + projPixel->bb_cell_index = ((int)(((float)x_px/(float)ibuf->x) * PROJ_BOUNDBOX_DIV)) + ((int)(((float)y_px/(float)ibuf->y) * PROJ_BOUNDBOX_DIV)) * PROJ_BOUNDBOX_DIV ; + + /* done with view3d_project_float inline */ + if (ps->tool==PAINT_TOOL_CLONE) { + if (ps->dm_mtface_clone) { + ImBuf *ibuf_other; + const MTFace *tf_other = ps->dm_mtface_clone + face_index; + + if (tf_other->tpage && (ibuf_other = BKE_image_get_ibuf((Image *)tf_other->tpage, NULL))) { + /* BKE_image_get_ibuf - TODO - this may be slow */ + + if (ibuf->rect_float) { + if (ibuf_other->rect_float) { /* from float to float */ + project_face_pixel(tf_other, ibuf_other, w, side, NULL, ((ProjPixelClone *)projPixel)->clonepx.f); + } + else { /* from char to float */ + unsigned char rgba_ub[4]; + project_face_pixel(tf_other, ibuf_other, w, side, rgba_ub, NULL); + IMAPAINT_CHAR_RGBA_TO_FLOAT(((ProjPixelClone *)projPixel)->clonepx.f, rgba_ub); + } + } + else { + if (ibuf_other->rect_float) { /* float to char */ + float rgba[4]; + project_face_pixel(tf_other, ibuf_other, w, side, NULL, rgba); + IMAPAINT_FLOAT_RGBA_TO_CHAR(((ProjPixelClone *)projPixel)->clonepx.ch, rgba) + } + else { /* char to char */ + project_face_pixel(tf_other, ibuf_other, w, side, ((ProjPixelClone *)projPixel)->clonepx.ch, NULL); + } + } + } + else { + if (ibuf->rect_float) { + ((ProjPixelClone *)projPixel)->clonepx.f[3] = 0; + } + else { + ((ProjPixelClone *)projPixel)->clonepx.ch[3] = 0; + } + } + + } + else { + float co[2]; + Vec2Subf(co, projPixel->projCoSS, (float *)ps->cloneOffset); + + /* no need to initialize the bucket, we're only checking buckets faces and for this + * the faces are alredy initialized in project_paint_delayed_face_init(...) */ + if (ibuf->rect_float) { + if (!project_paint_PickColor(ps, co, ((ProjPixelClone *)projPixel)->clonepx.f, NULL, 1)) { + ((ProjPixelClone *)projPixel)->clonepx.f[3] = 0; /* zero alpha - ignore */ + } + } + else { + if (!project_paint_PickColor(ps, co, NULL, ((ProjPixelClone *)projPixel)->clonepx.ch, 1)) { + ((ProjPixelClone *)projPixel)->clonepx.ch[3] = 0; /* zero alpha - ignore */ + } + } + } + } + +#ifdef PROJ_DEBUG_PAINT + if (ibuf->rect_float) projPixel->pixel.f_pt[0] = 0; + else projPixel->pixel.ch_pt[0] = 0; +#endif + projPixel->image_index = image_index; + + return projPixel; +} + +static int line_clip_rect2f( + rctf *rect, + const float l1[2], const float l2[2], + float l1_clip[2], float l2_clip[2]) +{ + /* first account for horizontal, then vertical lines */ + /* horiz */ + if (fabs(l1[1]-l2[1]) < PROJ_GEOM_TOLERANCE) { + /* is the line out of range on its Y axis? */ + if (l1[1] < rect->ymin || l1[1] > rect->ymax) { + return 0; + } + /* line is out of range on its X axis */ + if ((l1[0] < rect->xmin && l2[0] < rect->xmin) || (l1[0] > rect->xmax && l2[0] > rect->xmax)) { + return 0; + } + + + if (fabs(l1[0]-l2[0]) < PROJ_GEOM_TOLERANCE) { /* this is a single point (or close to)*/ + if (BLI_in_rctf(rect, l1[0], l1[1])) { + VECCOPY2D(l1_clip, l1); + VECCOPY2D(l2_clip, l2); + return 1; + } + else { + return 0; + } + } + + VECCOPY2D(l1_clip, l1); + VECCOPY2D(l2_clip, l2); + CLAMP(l1_clip[0], rect->xmin, rect->xmax); + CLAMP(l2_clip[0], rect->xmin, rect->xmax); + return 1; + } + else if (fabs(l1[0]-l2[0]) < PROJ_GEOM_TOLERANCE) { + /* is the line out of range on its X axis? */ + if (l1[0] < rect->xmin || l1[0] > rect->xmax) { + return 0; + } + + /* line is out of range on its Y axis */ + if ((l1[1] < rect->ymin && l2[1] < rect->ymin) || (l1[1] > rect->ymax && l2[1] > rect->ymax)) { + return 0; + } + + if (fabs(l1[1]-l2[1]) < PROJ_GEOM_TOLERANCE) { /* this is a single point (or close to)*/ + if (BLI_in_rctf(rect, l1[0], l1[1])) { + VECCOPY2D(l1_clip, l1); + VECCOPY2D(l2_clip, l2); + return 1; + } + else { + return 0; + } + } + + VECCOPY2D(l1_clip, l1); + VECCOPY2D(l2_clip, l2); + CLAMP(l1_clip[1], rect->ymin, rect->ymax); + CLAMP(l2_clip[1], rect->ymin, rect->ymax); + return 1; + } + else { + float isect; + short ok1 = 0; + short ok2 = 0; + + /* Done with vertical lines */ + + /* are either of the points inside the rectangle ? */ + if (BLI_in_rctf(rect, l1[0], l1[1])) { + VECCOPY2D(l1_clip, l1); + ok1 = 1; + } + + if (BLI_in_rctf(rect, l2[0], l2[1])) { + VECCOPY2D(l2_clip, l2); + ok2 = 1; + } + + /* line inside rect */ + if (ok1 && ok2) return 1; + + /* top/bottom */ + if (line_isect_y(l1, l2, rect->ymin, &isect) && (isect >= rect->xmin) && (isect <= rect->xmax)) { + if (l1[1] < l2[1]) { /* line 1 is outside */ + l1_clip[0] = isect; + l1_clip[1] = rect->ymin; + ok1 = 1; + } + else { + l2_clip[0] = isect; + l2_clip[1] = rect->ymin; + ok2 = 2; + } + } + + if (ok1 && ok2) return 1; + + if (line_isect_y(l1, l2, rect->ymax, &isect) && (isect >= rect->xmin) && (isect <= rect->xmax)) { + if (l1[1] > l2[1]) { /* line 1 is outside */ + l1_clip[0] = isect; + l1_clip[1] = rect->ymax; + ok1 = 1; + } + else { + l2_clip[0] = isect; + l2_clip[1] = rect->ymax; + ok2 = 2; + } + } + + if (ok1 && ok2) return 1; + + /* left/right */ + if (line_isect_x(l1, l2, rect->xmin, &isect) && (isect >= rect->ymin) && (isect <= rect->ymax)) { + if (l1[0] < l2[0]) { /* line 1 is outside */ + l1_clip[0] = rect->xmin; + l1_clip[1] = isect; + ok1 = 1; + } + else { + l2_clip[0] = rect->xmin; + l2_clip[1] = isect; + ok2 = 2; + } + } + + if (ok1 && ok2) return 1; + + if (line_isect_x(l1, l2, rect->xmax, &isect) && (isect >= rect->ymin) && (isect <= rect->ymax)) { + if (l1[0] > l2[0]) { /* line 1 is outside */ + l1_clip[0] = rect->xmax; + l1_clip[1] = isect; + ok1 = 1; + } + else { + l2_clip[0] = rect->xmax; + l2_clip[1] = isect; + ok2 = 2; + } + } + + if (ok1 && ok2) { + return 1; + } + else { + return 0; + } + } +} + + + +/* scale the quad & tri about its center + * scaling by PROJ_FACE_SCALE_SEAM (0.99x) is used for getting fake UV pixel coords that are on the + * edge of the face but slightly inside it occlusion tests dont return hits on adjacent faces */ +static void scale_quad(float insetCos[4][3], float *origCos[4], const float inset) +{ + float cent[3]; + cent[0] = (origCos[0][0] + origCos[1][0] + origCos[2][0] + origCos[3][0]) / 4.0f; + cent[1] = (origCos[0][1] + origCos[1][1] + origCos[2][1] + origCos[3][1]) / 4.0f; + cent[2] = (origCos[0][2] + origCos[1][2] + origCos[2][2] + origCos[3][2]) / 4.0f; + + VecSubf(insetCos[0], origCos[0], cent); + VecSubf(insetCos[1], origCos[1], cent); + VecSubf(insetCos[2], origCos[2], cent); + VecSubf(insetCos[3], origCos[3], cent); + + VecMulf(insetCos[0], inset); + VecMulf(insetCos[1], inset); + VecMulf(insetCos[2], inset); + VecMulf(insetCos[3], inset); + + VecAddf(insetCos[0], insetCos[0], cent); + VecAddf(insetCos[1], insetCos[1], cent); + VecAddf(insetCos[2], insetCos[2], cent); + VecAddf(insetCos[3], insetCos[3], cent); +} + + +static void scale_tri(float insetCos[4][3], float *origCos[4], const float inset) +{ + float cent[3]; + cent[0] = (origCos[0][0] + origCos[1][0] + origCos[2][0]) / 3.0f; + cent[1] = (origCos[0][1] + origCos[1][1] + origCos[2][1]) / 3.0f; + cent[2] = (origCos[0][2] + origCos[1][2] + origCos[2][2]) / 3.0f; + + VecSubf(insetCos[0], origCos[0], cent); + VecSubf(insetCos[1], origCos[1], cent); + VecSubf(insetCos[2], origCos[2], cent); + + VecMulf(insetCos[0], inset); + VecMulf(insetCos[1], inset); + VecMulf(insetCos[2], inset); + + VecAddf(insetCos[0], insetCos[0], cent); + VecAddf(insetCos[1], insetCos[1], cent); + VecAddf(insetCos[2], insetCos[2], cent); +} + + +static float Vec2Lenf_nosqrt(const float *v1, const float *v2) +{ + float x, y; + + x = v1[0]-v2[0]; + y = v1[1]-v2[1]; + return x*x+y*y; +} + +static float Vec2Lenf_nosqrt_other(const float *v1, const float v2_1, const float v2_2) +{ + float x, y; + + x = v1[0]-v2_1; + y = v1[1]-v2_2; + return x*x+y*y; +} + +/* note, use a squared value so we can use Vec2Lenf_nosqrt + * be sure that you have done a bounds check first or this may fail */ +/* only give bucket_bounds as an arg because we need it elsewhere */ +static int project_bucket_isect_circle(const int bucket_x, const int bucket_y, const float cent[2], const float radius_squared, rctf *bucket_bounds) +{ + + /* Would normally to a simple intersection test, however we know the bounds of these 2 alredy intersect + * so we only need to test if the center is inside the vertical or horizontal bounds on either axis, + * this is even less work then an intersection test + * + if (BLI_in_rctf(bucket_bounds, cent[0], cent[1])) + return 1; + */ + + if((bucket_bounds->xmin <= cent[0] && bucket_bounds->xmax >= cent[0]) || (bucket_bounds->ymin <= cent[1] && bucket_bounds->ymax >= cent[1]) ) { + return 1; + } + + /* out of bounds left */ + if (cent[0] < bucket_bounds->xmin) { + /* lower left out of radius test */ + if (cent[1] < bucket_bounds->ymin) { + return (Vec2Lenf_nosqrt_other(cent, bucket_bounds->xmin, bucket_bounds->ymin) < radius_squared) ? 1 : 0; + } + /* top left test */ + else if (cent[1] > bucket_bounds->ymax) { + return (Vec2Lenf_nosqrt_other(cent, bucket_bounds->xmin, bucket_bounds->ymax) < radius_squared) ? 1 : 0; + } + } + else if (cent[0] > bucket_bounds->xmax) { + /* lower right out of radius test */ + if (cent[1] < bucket_bounds->ymin) { + return (Vec2Lenf_nosqrt_other(cent, bucket_bounds->xmax, bucket_bounds->ymin) < radius_squared) ? 1 : 0; + } + /* top right test */ + else if (cent[1] > bucket_bounds->ymax) { + return (Vec2Lenf_nosqrt_other(cent, bucket_bounds->xmax, bucket_bounds->ymax) < radius_squared) ? 1 : 0; + } + } + + return 0; +} + + + +/* Note for rect_to_uvspace_ortho() and rect_to_uvspace_persp() + * in ortho view this function gives good results when bucket_bounds are outside the triangle + * however in some cases, perspective view will mess up with faces that have minimal screenspace area (viewed from the side) + * + * for this reason its not relyable in this case so we'll use the Simple Barycentric' funcs that only account for points inside the triangle. + * however switching back to this for ortho is always an option */ + +static void rect_to_uvspace_ortho( + rctf *bucket_bounds, + float *v1coSS, float *v2coSS, float *v3coSS, + float *uv1co, float *uv2co, float *uv3co, + float bucket_bounds_uv[4][2], + const int flip) +{ + float uv[2]; + float w[3]; + + /* get the UV space bounding box */ + uv[0] = bucket_bounds->xmax; + uv[1] = bucket_bounds->ymin; + BarycentricWeights2f(uv, v1coSS, v2coSS, v3coSS, w); + Vec2Weightf(bucket_bounds_uv[flip?3:0], uv1co, uv2co, uv3co, w); + + //uv[0] = bucket_bounds->xmax; // set above + uv[1] = bucket_bounds->ymax; + BarycentricWeights2f(uv, v1coSS, v2coSS, v3coSS, w); + Vec2Weightf(bucket_bounds_uv[flip?2:1], uv1co, uv2co, uv3co, w); + + uv[0] = bucket_bounds->xmin; + //uv[1] = bucket_bounds->ymax; // set above + BarycentricWeights2f(uv, v1coSS, v2coSS, v3coSS, w); + Vec2Weightf(bucket_bounds_uv[flip?1:2], uv1co, uv2co, uv3co, w); + + //uv[0] = bucket_bounds->xmin; // set above + uv[1] = bucket_bounds->ymin; + BarycentricWeights2f(uv, v1coSS, v2coSS, v3coSS, w); + Vec2Weightf(bucket_bounds_uv[flip?0:3], uv1co, uv2co, uv3co, w); +} + +/* same as above but use BarycentricWeightsPersp2f */ +static void rect_to_uvspace_persp( + rctf *bucket_bounds, + float *v1coSS, float *v2coSS, float *v3coSS, + float *uv1co, float *uv2co, float *uv3co, + float bucket_bounds_uv[4][2], + const int flip + ) +{ + float uv[2]; + float w[3]; + + /* get the UV space bounding box */ + uv[0] = bucket_bounds->xmax; + uv[1] = bucket_bounds->ymin; + BarycentricWeightsPersp2f(uv, v1coSS, v2coSS, v3coSS, w); + Vec2Weightf(bucket_bounds_uv[flip?3:0], uv1co, uv2co, uv3co, w); + + //uv[0] = bucket_bounds->xmax; // set above + uv[1] = bucket_bounds->ymax; + BarycentricWeightsPersp2f(uv, v1coSS, v2coSS, v3coSS, w); + Vec2Weightf(bucket_bounds_uv[flip?2:1], uv1co, uv2co, uv3co, w); + + uv[0] = bucket_bounds->xmin; + //uv[1] = bucket_bounds->ymax; // set above + BarycentricWeightsPersp2f(uv, v1coSS, v2coSS, v3coSS, w); + Vec2Weightf(bucket_bounds_uv[flip?1:2], uv1co, uv2co, uv3co, w); + + //uv[0] = bucket_bounds->xmin; // set above + uv[1] = bucket_bounds->ymin; + BarycentricWeightsPersp2f(uv, v1coSS, v2coSS, v3coSS, w); + Vec2Weightf(bucket_bounds_uv[flip?0:3], uv1co, uv2co, uv3co, w); +} + +/* This works as we need it to but we can save a few steps and not use it */ + +static float angle_2d_clockwise(const float p1[2], const float p2[2], const float p3[2]) +{ + float v1[2], v2[2]; + + v1[0] = p1[0]-p2[0]; v1[1] = p1[1]-p2[1]; + v2[0] = p3[0]-p2[0]; v2[1] = p3[1]-p2[1]; + + return -atan2(v1[0]*v2[1] - v1[1]*v2[0], v1[0]*v2[0]+v1[1]*v2[1]); +} + +#define ISECT_1 (1) +#define ISECT_2 (1<<1) +#define ISECT_3 (1<<2) +#define ISECT_4 (1<<3) +#define ISECT_ALL3 ((1<<3)-1) +#define ISECT_ALL4 ((1<<4)-1) + +/* limit must be a fraction over 1.0f */ +static int IsectPT2Df_limit(float pt[2], float v1[2], float v2[2], float v3[2], float limit) +{ + return ((AreaF2Dfl(pt,v1,v2) + AreaF2Dfl(pt,v2,v3) + AreaF2Dfl(pt,v3,v1)) / (AreaF2Dfl(v1,v2,v3))) < limit; +} + +/* Clip the face by a bucket and set the uv-space bucket_bounds_uv + * so we have the clipped UV's to do pixel intersection tests with + * */ +static int float_z_sort_flip(const void *p1, const void *p2) { + return (((float *)p1)[2] < ((float *)p2)[2] ? 1:-1); +} + +static int float_z_sort(const void *p1, const void *p2) { + return (((float *)p1)[2] < ((float *)p2)[2] ?-1:1); +} + +static void project_bucket_clip_face( + const int is_ortho, + rctf *bucket_bounds, + float *v1coSS, float *v2coSS, float *v3coSS, + float *uv1co, float *uv2co, float *uv3co, + float bucket_bounds_uv[8][2], + int *tot) +{ + int inside_bucket_flag = 0; + int inside_face_flag = 0; + const int flip = ((SIDE_OF_LINE(v1coSS, v2coSS, v3coSS) > 0.0f) != (SIDE_OF_LINE(uv1co, uv2co, uv3co) > 0.0f)); + + float bucket_bounds_ss[4][2]; + float w[3]; + + /* get the UV space bounding box */ + inside_bucket_flag |= BLI_in_rctf(bucket_bounds, v1coSS[0], v1coSS[1]); + inside_bucket_flag |= BLI_in_rctf(bucket_bounds, v2coSS[0], v2coSS[1]) << 1; + inside_bucket_flag |= BLI_in_rctf(bucket_bounds, v3coSS[0], v3coSS[1]) << 2; + + if (inside_bucket_flag == ISECT_ALL3) { + /* all screenspace points are inside the bucket bounding box, this means we dont need to clip and can simply return the UVs */ + if (flip) { /* facing the back? */ + VECCOPY2D(bucket_bounds_uv[0], uv3co); + VECCOPY2D(bucket_bounds_uv[1], uv2co); + VECCOPY2D(bucket_bounds_uv[2], uv1co); + } + else { + VECCOPY2D(bucket_bounds_uv[0], uv1co); + VECCOPY2D(bucket_bounds_uv[1], uv2co); + VECCOPY2D(bucket_bounds_uv[2], uv3co); + } + + *tot = 3; + return; + } + + /* get the UV space bounding box */ + /* use IsectPT2Df_limit here so we catch points are are touching the tri edge (or a small fraction over) */ + bucket_bounds_ss[0][0] = bucket_bounds->xmax; + bucket_bounds_ss[0][1] = bucket_bounds->ymin; + inside_face_flag |= (IsectPT2Df_limit(bucket_bounds_ss[0], v1coSS, v2coSS, v3coSS, 1+PROJ_GEOM_TOLERANCE) ? ISECT_1 : 0); + + bucket_bounds_ss[1][0] = bucket_bounds->xmax; + bucket_bounds_ss[1][1] = bucket_bounds->ymax; + inside_face_flag |= (IsectPT2Df_limit(bucket_bounds_ss[1], v1coSS, v2coSS, v3coSS, 1+PROJ_GEOM_TOLERANCE) ? ISECT_2 : 0); + + bucket_bounds_ss[2][0] = bucket_bounds->xmin; + bucket_bounds_ss[2][1] = bucket_bounds->ymax; + inside_face_flag |= (IsectPT2Df_limit(bucket_bounds_ss[2], v1coSS, v2coSS, v3coSS, 1+PROJ_GEOM_TOLERANCE) ? ISECT_3 : 0); + + bucket_bounds_ss[3][0] = bucket_bounds->xmin; + bucket_bounds_ss[3][1] = bucket_bounds->ymin; + inside_face_flag |= (IsectPT2Df_limit(bucket_bounds_ss[3], v1coSS, v2coSS, v3coSS, 1+PROJ_GEOM_TOLERANCE) ? ISECT_4 : 0); + + if (inside_face_flag == ISECT_ALL4) { + /* bucket is totally inside the screenspace face, we can safely use weights */ + + if (is_ortho) rect_to_uvspace_ortho(bucket_bounds, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, bucket_bounds_uv, flip); + else rect_to_uvspace_persp(bucket_bounds, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, bucket_bounds_uv, flip); + + *tot = 4; + return; + } + else { + /* The Complicated Case! + * + * The 2 cases above are where the face is inside the bucket or the bucket is inside the face. + * + * we need to make a convex polyline from the intersection between the screenspace face + * and the bucket bounds. + * + * There are a number of ways this could be done, currently it just collects all intersecting verts, + * and line intersections, then sorts them clockwise, this is a lot easier then evaluating the geometry to + * do a correct clipping on both shapes. */ + + + /* add a bunch of points, we know must make up the convex hull which is the clipped rect and triangle */ + + + + /* Maximum possible 6 intersections when using a rectangle and triangle */ + float isectVCosSS[8][3]; /* The 3rd float is used to store angle for qsort(), NOT as a Z location */ + float v1_clipSS[2], v2_clipSS[2]; + + /* calc center*/ + float cent[2] = {0.0f, 0.0f}; + /*float up[2] = {0.0f, 1.0f};*/ + int i; + short doubles; + + (*tot) = 0; + + if (inside_face_flag & ISECT_1) { VECCOPY2D(isectVCosSS[*tot], bucket_bounds_ss[0]); (*tot)++; } + if (inside_face_flag & ISECT_2) { VECCOPY2D(isectVCosSS[*tot], bucket_bounds_ss[1]); (*tot)++; } + if (inside_face_flag & ISECT_3) { VECCOPY2D(isectVCosSS[*tot], bucket_bounds_ss[2]); (*tot)++; } + if (inside_face_flag & ISECT_4) { VECCOPY2D(isectVCosSS[*tot], bucket_bounds_ss[3]); (*tot)++; } + + if (inside_bucket_flag & ISECT_1) { VECCOPY2D(isectVCosSS[*tot], v1coSS); (*tot)++; } + if (inside_bucket_flag & ISECT_2) { VECCOPY2D(isectVCosSS[*tot], v2coSS); (*tot)++; } + if (inside_bucket_flag & ISECT_3) { VECCOPY2D(isectVCosSS[*tot], v3coSS); (*tot)++; } + + if ((inside_bucket_flag & (ISECT_1|ISECT_2)) != (ISECT_1|ISECT_2)) { + if (line_clip_rect2f(bucket_bounds, v1coSS, v2coSS, v1_clipSS, v2_clipSS)) { + if ((inside_bucket_flag & ISECT_1)==0) { VECCOPY2D(isectVCosSS[*tot], v1_clipSS); (*tot)++; } + if ((inside_bucket_flag & ISECT_2)==0) { VECCOPY2D(isectVCosSS[*tot], v2_clipSS); (*tot)++; } + } + } + + if ((inside_bucket_flag & (ISECT_2|ISECT_3)) != (ISECT_2|ISECT_3)) { + if (line_clip_rect2f(bucket_bounds, v2coSS, v3coSS, v1_clipSS, v2_clipSS)) { + if ((inside_bucket_flag & ISECT_2)==0) { VECCOPY2D(isectVCosSS[*tot], v1_clipSS); (*tot)++; } + if ((inside_bucket_flag & ISECT_3)==0) { VECCOPY2D(isectVCosSS[*tot], v2_clipSS); (*tot)++; } + } + } + + if ((inside_bucket_flag & (ISECT_3|ISECT_1)) != (ISECT_3|ISECT_1)) { + if (line_clip_rect2f(bucket_bounds, v3coSS, v1coSS, v1_clipSS, v2_clipSS)) { + if ((inside_bucket_flag & ISECT_3)==0) { VECCOPY2D(isectVCosSS[*tot], v1_clipSS); (*tot)++; } + if ((inside_bucket_flag & ISECT_1)==0) { VECCOPY2D(isectVCosSS[*tot], v2_clipSS); (*tot)++; } + } + } + + + if ((*tot) < 3) { /* no intersections to speak of */ + *tot = 0; + } + + /* now we have all points we need, collect their angles and sort them clockwise */ + + for(i=0; i<(*tot); i++) { + cent[0] += isectVCosSS[i][0]; + cent[1] += isectVCosSS[i][1]; + } + cent[0] = cent[0] / (float)(*tot); + cent[1] = cent[1] / (float)(*tot); + + + + /* Collect angles for every point around the center point */ + + +#if 0 /* uses a few more cycles then the above loop */ + for(i=0; i<(*tot); i++) { + isectVCosSS[i][2] = angle_2d_clockwise(up, cent, isectVCosSS[i]); + } +#endif + + v1_clipSS[0] = cent[0]; /* Abuse this var for the loop below */ + v1_clipSS[1] = cent[1] + 1.0f; + + for(i=0; i<(*tot); i++) { + v2_clipSS[0] = isectVCosSS[i][0] - cent[0]; + v2_clipSS[1] = isectVCosSS[i][1] - cent[1]; + isectVCosSS[i][2] = atan2(v1_clipSS[0]*v2_clipSS[1] - v1_clipSS[1]*v2_clipSS[0], v1_clipSS[0]*v2_clipSS[0]+v1_clipSS[1]*v2_clipSS[1]); + } + + if (flip) qsort(isectVCosSS, *tot, sizeof(float)*3, float_z_sort_flip); + else qsort(isectVCosSS, *tot, sizeof(float)*3, float_z_sort); + + + /* remove doubles */ + /* first/last check */ + if (fabs(isectVCosSS[0][0]-isectVCosSS[(*tot)-1][0]) < PROJ_GEOM_TOLERANCE && fabs(isectVCosSS[0][1]-isectVCosSS[(*tot)-1][1]) < PROJ_GEOM_TOLERANCE) { + (*tot)--; + } + + /* its possible there is only a few left after remove doubles */ + if ((*tot) < 3) { + // printf("removed too many doubles A\n"); + *tot = 0; + return; + } + + doubles = TRUE; + while (doubles==TRUE) { + doubles = FALSE; + for(i=1; i<(*tot); i++) { + if (fabs(isectVCosSS[i-1][0]-isectVCosSS[i][0]) < PROJ_GEOM_TOLERANCE && + fabs(isectVCosSS[i-1][1]-isectVCosSS[i][1]) < PROJ_GEOM_TOLERANCE) + { + int j; + for(j=i+1; j<(*tot); j++) { + isectVCosSS[j-1][0] = isectVCosSS[j][0]; + isectVCosSS[j-1][1] = isectVCosSS[j][1]; + } + doubles = TRUE; /* keep looking for more doubles */ + (*tot)--; + } + } + } + + /* its possible there is only a few left after remove doubles */ + if ((*tot) < 3) { + // printf("removed too many doubles B\n"); + *tot = 0; + return; + } + + + if (is_ortho) { + for(i=0; i<(*tot); i++) { + BarycentricWeights2f(isectVCosSS[i], v1coSS, v2coSS, v3coSS, w); + Vec2Weightf(bucket_bounds_uv[i], uv1co, uv2co, uv3co, w); + } + } + else { + for(i=0; i<(*tot); i++) { + BarycentricWeightsPersp2f(isectVCosSS[i], v1coSS, v2coSS, v3coSS, w); + Vec2Weightf(bucket_bounds_uv[i], uv1co, uv2co, uv3co, w); + } + } + } + +#ifdef PROJ_DEBUG_PRINT_CLIP + /* include this at the bottom of the above function to debug the output */ + + { + /* If there are ever any problems, */ + float test_uv[4][2]; + int i; + if (is_ortho) rect_to_uvspace_ortho(bucket_bounds, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, test_uv, flip); + else rect_to_uvspace_persp(bucket_bounds, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, test_uv, flip); + printf("( [(%f,%f), (%f,%f), (%f,%f), (%f,%f)], ", test_uv[0][0], test_uv[0][1], test_uv[1][0], test_uv[1][1], test_uv[2][0], test_uv[2][1], test_uv[3][0], test_uv[3][1]); + + printf(" [(%f,%f), (%f,%f), (%f,%f)], ", uv1co[0], uv1co[1], uv2co[0], uv2co[1], uv3co[0], uv3co[1]); + + printf("["); + for (i=0; i < (*tot); i++) { + printf("(%f, %f),", bucket_bounds_uv[i][0], bucket_bounds_uv[i][1]); + } + printf("]),\\\n"); + } +#endif +} + + /* +# This script creates faces in a blender scene from printed data above. + +project_ls = [ +...(output from above block)... +] + +from Blender import Scene, Mesh, Window, sys, Mathutils + +import bpy + +V = Mathutils.Vector + +def main(): + sce = bpy.data.scenes.active + + for item in project_ls: + bb = item[0] + uv = item[1] + poly = item[2] + + me = bpy.data.meshes.new() + ob = sce.objects.new(me) + + me.verts.extend([V(bb[0]).resize3D(), V(bb[1]).resize3D(), V(bb[2]).resize3D(), V(bb[3]).resize3D()]) + me.faces.extend([(0,1,2,3),]) + me.verts.extend([V(uv[0]).resize3D(), V(uv[1]).resize3D(), V(uv[2]).resize3D()]) + me.faces.extend([(4,5,6),]) + + vs = [V(p).resize3D() for p in poly] + print len(vs) + l = len(me.verts) + me.verts.extend(vs) + + i = l + while i < len(me.verts): + ii = i+1 + if ii==len(me.verts): + ii = l + me.edges.extend([i, ii]) + i+=1 + +if __name__ == '__main__': + main() + */ + + +#undef ISECT_1 +#undef ISECT_2 +#undef ISECT_3 +#undef ISECT_4 +#undef ISECT_ALL3 +#undef ISECT_ALL4 + + +/* checks if pt is inside a convex 2D polyline, the polyline must be ordered rotating clockwise + * otherwise it would have to test for mixed (SIDE_OF_LINE > 0.0f) cases */ +int IsectPoly2Df(const float pt[2], float uv[][2], const int tot) +{ + int i; + if (SIDE_OF_LINE(uv[tot-1], uv[0], pt) < 0.0f) + return 0; + + for (i=1; i<tot; i++) { + if (SIDE_OF_LINE(uv[i-1], uv[i], pt) < 0.0f) + return 0; + + } + + return 1; +} + +/* One of the most important function for projectiopn painting, since it selects the pixels to be added into each bucket. + * initialize pixels from this face where it intersects with the bucket_index, optionally initialize pixels for removing seams */ +static void project_paint_face_init(const ProjPaintState *ps, const int thread_index, const int bucket_index, const int face_index, const int image_index, rctf *bucket_bounds, const ImBuf *ibuf) +{ + /* Projection vars, to get the 3D locations into screen space */ + MemArena *arena = ps->arena_mt[thread_index]; + LinkNode **bucketPixelNodes = ps->bucketRect + bucket_index; + LinkNode *bucketFaceNodes = ps->bucketFaces[bucket_index]; + + const MFace *mf = ps->dm_mface + face_index; + const MTFace *tf = ps->dm_mtface + face_index; + + /* UV/pixel seeking data */ + int x; /* Image X-Pixel */ + int y;/* Image Y-Pixel */ + float mask; + float uv[2]; /* Image floating point UV - same as x, y but from 0.0-1.0 */ + + int side; + float *v1coSS, *v2coSS, *v3coSS; /* vert co screen-space, these will be assigned to mf->v1,2,3 or mf->v1,3,4 */ + + float *vCo[4]; /* vertex screenspace coords */ + + float w[3], wco[3]; + + float *uv1co, *uv2co, *uv3co; /* for convenience only, these will be assigned to tf->uv[0],1,2 or tf->uv[0],2,3 */ + float pixelScreenCo[4]; + + rcti bounds_px; /* ispace bounds */ + /* vars for getting uvspace bounds */ + + float tf_uv_pxoffset[4][2]; /* bucket bounds in UV space so we can init pixels only for this face, */ + float xhalfpx, yhalfpx; + const float ibuf_xf = ibuf->x, ibuf_yf = ibuf->y; + + int has_x_isect = 0, has_isect = 0; /* for early loop exit */ + + int i1, i2, i3; + + float uv_clip[8][2]; + int uv_clip_tot; + const short is_ortho = ps->is_ortho; + + vCo[0] = ps->dm_mvert[mf->v1].co; + vCo[1] = ps->dm_mvert[mf->v2].co; + vCo[2] = ps->dm_mvert[mf->v3].co; + + + /* Use tf_uv_pxoffset instead of tf->uv so we can offset the UV half a pixel + * this is done so we can avoid offseting all the pixels by 0.5 which causes + * problems when wrapping negative coords */ + xhalfpx = 0.5f / ibuf_xf; + yhalfpx = 0.5f / ibuf_yf; + + tf_uv_pxoffset[0][0] = tf->uv[0][0] - xhalfpx; + tf_uv_pxoffset[0][1] = tf->uv[0][1] - yhalfpx; + + tf_uv_pxoffset[1][0] = tf->uv[1][0] - xhalfpx; + tf_uv_pxoffset[1][1] = tf->uv[1][1] - yhalfpx; + + tf_uv_pxoffset[2][0] = tf->uv[2][0] - xhalfpx; + tf_uv_pxoffset[2][1] = tf->uv[2][1] - yhalfpx; + + if (mf->v4) { + vCo[3] = ps->dm_mvert[ mf->v4 ].co; + + tf_uv_pxoffset[3][0] = tf->uv[3][0] - xhalfpx; + tf_uv_pxoffset[3][1] = tf->uv[3][1] - yhalfpx; + side = 1; + } + else { + side = 0; + } + + do { + if (side==1) { + i1=0; i2=2; i3=3; + } + else { + i1=0; i2=1; i3=2; + } + + uv1co = tf_uv_pxoffset[i1]; // was tf->uv[i1]; + uv2co = tf_uv_pxoffset[i2]; // was tf->uv[i2]; + uv3co = tf_uv_pxoffset[i3]; // was tf->uv[i3]; + + v1coSS = ps->screenCoords[ (*(&mf->v1 + i1)) ]; + v2coSS = ps->screenCoords[ (*(&mf->v1 + i2)) ]; + v3coSS = ps->screenCoords[ (*(&mf->v1 + i3)) ]; + + + /* This funtion gives is a concave polyline in UV space from the clipped quad and tri*/ + project_bucket_clip_face( + is_ortho, bucket_bounds, + v1coSS, v2coSS, v3coSS, + uv1co, uv2co, uv3co, + uv_clip, &uv_clip_tot + ); + + + /* sometimes this happens, better just allow for 8 intersectiosn even though there should be max 6 */ + /* + if (uv_clip_tot>6) { + printf("this should never happen! %d\n", uv_clip_tot); + }*/ + + + if (pixel_bounds_array(uv_clip, &bounds_px, ibuf->x, ibuf->y, uv_clip_tot)) { + + /* clip face and */ + + has_isect = 0; + for (y = bounds_px.ymin; y < bounds_px.ymax; y++) { + //uv[1] = (((float)y) + 0.5f) / (float)ibuf->y; + uv[1] = (float)y / ibuf_yf; /* use pixel offset UV coords instead */ + + has_x_isect = 0; + for (x = bounds_px.xmin; x < bounds_px.xmax; x++) { + //uv[0] = (((float)x) + 0.5f) / ibuf->x; + uv[0] = (float)x / ibuf_xf; /* use pixel offset UV coords instead */ + + if (IsectPoly2Df(uv, uv_clip, uv_clip_tot)) { + + has_x_isect = has_isect = 1; + + if (is_ortho) screen_px_from_ortho(uv, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, pixelScreenCo, w); + else screen_px_from_persp(uv, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, pixelScreenCo, w); + + /* a pitty we need to get the worldspace pixel location here */ + if(G.vd->flag & V3D_CLIPPING) { + VecWeightf(wco, ps->dm_mvert[ (*(&mf->v1 + i1)) ].co, ps->dm_mvert[ (*(&mf->v1 + i2)) ].co, ps->dm_mvert[ (*(&mf->v1 + i3)) ].co, w); + Mat4MulVecfl(ps->ob->obmat, wco); + if(view3d_test_clipping(G.vd, wco)) { + continue; /* Watch out that no code below this needs to run */ + } + } + + /* Is this UV visible from the view? - raytrace */ + /* project_paint_PickFace is less complex, use for testing */ + //if (project_paint_PickFace(ps, pixelScreenCo, w, &side) == face_index) { + if (ps->do_occlude==0 || !project_bucket_point_occluded(ps, bucketFaceNodes, face_index, pixelScreenCo)) { + + mask = project_paint_uvpixel_mask(ps, face_index, side, w); + + if (mask > 0.0f) { + BLI_linklist_prepend_arena( + bucketPixelNodes, + project_paint_uvpixel_init(ps, arena, ibuf, x, y, mask, face_index, image_index, pixelScreenCo, side, w), + arena + ); + } + } + + } +//#if 0 + else if (has_x_isect) { + /* assuming the face is not a bow-tie - we know we cant intersect again on the X */ + break; + } +//#endif + } + + +#if 0 /* TODO - investigate why this dosnt work sometimes! it should! */ + /* no intersection for this entire row, after some intersection above means we can quit now */ + if (has_x_isect==0 && has_isect) { + break; + } +#endif + } + } + } while(side--); + + + +#ifndef PROJ_DEBUG_NOSEAMBLEED + if (ps->seam_bleed_px > 0.0f) { + int face_seam_flag; + + if (ps->thread_tot > 1) + BLI_lock_thread(LOCK_CUSTOM1); /* Other threads could be modifying these vars */ + + face_seam_flag = ps->faceSeamFlags[face_index]; + + /* are any of our edges un-initialized? */ + if ((face_seam_flag & (PROJ_FACE_SEAM1|PROJ_FACE_NOSEAM1))==0 || + (face_seam_flag & (PROJ_FACE_SEAM2|PROJ_FACE_NOSEAM2))==0 || + (face_seam_flag & (PROJ_FACE_SEAM3|PROJ_FACE_NOSEAM3))==0 || + (face_seam_flag & (PROJ_FACE_SEAM4|PROJ_FACE_NOSEAM4))==0 + ) { + project_face_seams_init(ps, face_index, mf->v4); + face_seam_flag = ps->faceSeamFlags[face_index]; + //printf("seams - %d %d %d %d\n", flag&PROJ_FACE_SEAM1, flag&PROJ_FACE_SEAM2, flag&PROJ_FACE_SEAM3, flag&PROJ_FACE_SEAM4); + } + + if ((face_seam_flag & (PROJ_FACE_SEAM1|PROJ_FACE_SEAM2|PROJ_FACE_SEAM3|PROJ_FACE_SEAM4))==0) { + + if (ps->thread_tot > 1) + BLI_unlock_thread(LOCK_CUSTOM1); /* Other threads could be modifying these vars */ + + } + else { + /* we have a seam - deal with it! */ + + /* Now create new UV's for the seam face */ + float (*outset_uv)[2] = ps->faceSeamUVs[face_index]; + float insetCos[4][3]; /* inset face coords. NOTE!!! ScreenSace for ortho, Worldspace in prespective view */ + + float *uv_seam_quad[4]; + float fac; + float *vCoSS[4]; /* vertex screenspace coords */ + + float bucket_clip_edges[2][2]; /* store the screenspace coords of the face, clipped by the bucket's screen aligned rectangle */ + float edge_verts_inset_clip[2][3]; + int fidx1, fidx2; /* face edge pairs - loop throuh these ((0,1), (1,2), (2,3), (3,0)) or ((0,1), (1,2), (2,0)) for a tri */ + + float seam_subsection[4][2]; + float fac1, fac2, ftot; + + + if (outset_uv[0][0]==MAXFLOAT) /* first time initialize */ + uv_image_outset(tf_uv_pxoffset, outset_uv, ps->seam_bleed_px, ibuf->x, ibuf->y, mf->v4); + + /* ps->faceSeamUVs cant be modified when threading, now this is done we can unlock */ + if (ps->thread_tot > 1) + BLI_unlock_thread(LOCK_CUSTOM1); /* Other threads could be modifying these vars */ + + vCoSS[0] = ps->screenCoords[mf->v1]; + vCoSS[1] = ps->screenCoords[mf->v2]; + vCoSS[2] = ps->screenCoords[mf->v3]; + if (mf->v4) + vCoSS[3] = ps->screenCoords[ mf->v4 ]; + + /* PROJ_FACE_SCALE_SEAM must be slightly less then 1.0f */ + if (is_ortho) { + if (mf->v4) scale_quad(insetCos, vCoSS, PROJ_FACE_SCALE_SEAM); + else scale_tri(insetCos, vCoSS, PROJ_FACE_SCALE_SEAM); + } + else { + if (mf->v4) scale_quad(insetCos, vCo, PROJ_FACE_SCALE_SEAM); + else scale_tri(insetCos, vCo, PROJ_FACE_SCALE_SEAM); + } + + side = 0; /* for triangles this wont need to change */ + + for (fidx1 = 0; fidx1 < (mf->v4 ? 4 : 3); fidx1++) { + if (mf->v4) fidx2 = (fidx1==3) ? 0 : fidx1+1; /* next fidx in the face (0,1,2,3) -> (1,2,3,0) */ + else fidx2 = (fidx1==2) ? 0 : fidx1+1; /* next fidx in the face (0,1,2) -> (1,2,0) */ + + if ( (face_seam_flag & (1<<fidx1)) && /* 1<<fidx1 -> PROJ_FACE_SEAM# */ + line_clip_rect2f(bucket_bounds, vCoSS[fidx1], vCoSS[fidx2], bucket_clip_edges[0], bucket_clip_edges[1]) + ) { + + ftot = Vec2Lenf(vCoSS[fidx1], vCoSS[fidx2]); /* screenspace edge length */ + + if (ftot > 0.0f) { /* avoid div by zero */ + if (mf->v4) { + if (fidx1==2 || fidx2==2) side= 1; + else side= 0; + } + + fac1 = Vec2Lenf(vCoSS[fidx1], bucket_clip_edges[0]) / ftot; + fac2 = Vec2Lenf(vCoSS[fidx1], bucket_clip_edges[1]) / ftot; + + uv_seam_quad[0] = tf_uv_pxoffset[fidx1]; + uv_seam_quad[1] = tf_uv_pxoffset[fidx2]; + uv_seam_quad[2] = outset_uv[fidx2]; + uv_seam_quad[3] = outset_uv[fidx1]; + + Vec2Lerpf(seam_subsection[0], uv_seam_quad[0], uv_seam_quad[1], fac1); + Vec2Lerpf(seam_subsection[1], uv_seam_quad[0], uv_seam_quad[1], fac2); + + Vec2Lerpf(seam_subsection[2], uv_seam_quad[3], uv_seam_quad[2], fac2); + Vec2Lerpf(seam_subsection[3], uv_seam_quad[3], uv_seam_quad[2], fac1); + + /* if the bucket_clip_edges values Z values was kept we could avoid this + * Inset needs to be added so occlusion tests wont hit adjacent faces */ + VecLerpf(edge_verts_inset_clip[0], insetCos[fidx1], insetCos[fidx2], fac1); + VecLerpf(edge_verts_inset_clip[1], insetCos[fidx1], insetCos[fidx2], fac2); + + + if (pixel_bounds_uv(seam_subsection[0], seam_subsection[1], seam_subsection[2], seam_subsection[3], &bounds_px, ibuf->x, ibuf->y, 1)) { + /* bounds between the seam rect and the uvspace bucket pixels */ + + has_isect = 0; + for (y = bounds_px.ymin; y < bounds_px.ymax; y++) { + // uv[1] = (((float)y) + 0.5f) / (float)ibuf->y; + uv[1] = (float)y / ibuf_yf; /* use offset uvs instead */ + + has_x_isect = 0; + for (x = bounds_px.xmin; x < bounds_px.xmax; x++) { + //uv[0] = (((float)x) + 0.5f) / (float)ibuf->x; + uv[0] = (float)x / ibuf_xf; /* use offset uvs instead */ + + /* test we're inside uvspace bucket and triangle bounds */ + if (IsectPQ2Df(uv, seam_subsection[0], seam_subsection[1], seam_subsection[2], seam_subsection[3])) { + + /* We need to find the closest point along the face edge, + * getting the screen_px_from_*** wont work because our actual location + * is not relevent, since we are outside the face, Use VecLerpf to find + * our location on the side of the face's UV */ + /* + if (is_ortho) screen_px_from_ortho(ps, uv, v1co, v2co, v3co, uv1co, uv2co, uv3co, pixelScreenCo); + else screen_px_from_persp(ps, uv, v1co, v2co, v3co, uv1co, uv2co, uv3co, pixelScreenCo); + */ + + /* Since this is a seam we need to work out where on the line this pixel is */ + //fac = lambda_cp_line2(uv, uv_seam_quad[0], uv_seam_quad[1]); + + fac = lambda_cp_line2(uv, seam_subsection[0], seam_subsection[1]); + if (fac < 0.0f) { VECCOPY(pixelScreenCo, edge_verts_inset_clip[0]); } + else if (fac > 1.0f) { VECCOPY(pixelScreenCo, edge_verts_inset_clip[1]); } + else { VecLerpf(pixelScreenCo, edge_verts_inset_clip[0], edge_verts_inset_clip[1], fac); } + + if (!is_ortho) { + pixelScreenCo[3] = 1.0f; + Mat4MulVec4fl(ps->projectMat, pixelScreenCo); + pixelScreenCo[0] = (float)(curarea->winx/2.0f)+(curarea->winx/2.0f)*pixelScreenCo[0]/pixelScreenCo[3]; + pixelScreenCo[1] = (float)(curarea->winy/2.0f)+(curarea->winy/2.0f)*pixelScreenCo[1]/pixelScreenCo[3]; + pixelScreenCo[2] = pixelScreenCo[2]/pixelScreenCo[3]; /* Use the depth for bucket point occlusion */ + } + + if (ps->do_occlude==0 || !project_bucket_point_occluded(ps, bucketFaceNodes, face_index, pixelScreenCo)) { + + /* Only bother calculating the weights if we intersect */ + if (ps->do_mask_normal || ps->dm_mtface_clone) { + /* TODO, this is not QUITE correct since UV is not inside the UV's but good enough for seams */ + if (side) { + BarycentricWeights2f(uv, tf_uv_pxoffset[0], tf_uv_pxoffset[2], tf_uv_pxoffset[3], w); + } + else { + BarycentricWeights2f(uv, tf_uv_pxoffset[0], tf_uv_pxoffset[1], tf_uv_pxoffset[2], w); + } + + } + + /* a pitty we need to get the worldspace pixel location here */ + if(G.vd->flag & V3D_CLIPPING) { + if (side) VecWeightf(wco, ps->dm_mvert[mf->v1].co, ps->dm_mvert[mf->v3].co, ps->dm_mvert[mf->v4].co, w); + else VecWeightf(wco, ps->dm_mvert[mf->v1].co, ps->dm_mvert[mf->v2].co, ps->dm_mvert[mf->v3].co, w); + + Mat4MulVecfl(ps->ob->obmat, wco); + if(view3d_test_clipping(G.vd, wco)) { + continue; /* Watch out that no code below this needs to run */ + } + } + + mask = project_paint_uvpixel_mask(ps, face_index, side, w); + + if (mask > 0.0f) { + BLI_linklist_prepend_arena( + bucketPixelNodes, + project_paint_uvpixel_init(ps, arena, ibuf, x, y, mask, face_index, image_index, pixelScreenCo, side, w), + arena + ); + } + + } + } + else if (has_x_isect) { + /* assuming the face is not a bow-tie - we know we cant intersect again on the X */ + break; + } + } + +#if 0 /* TODO - investigate why this dosnt work sometimes! it should! */ + /* no intersection for this entire row, after some intersection above means we can quit now */ + if (has_x_isect==0 && has_isect) { + break; + } +#endif + } + } + } + } + } + } + } +#endif // PROJ_DEBUG_NOSEAMBLEED +} + + +/* takes floating point screenspace min/max and returns int min/max to be used as indicies for ps->bucketRect, ps->bucketFlags */ +static void project_paint_bucket_bounds(const ProjPaintState *ps, const float min[2], const float max[2], int bucketMin[2], int bucketMax[2]) +{ + /* divide by bucketWidth & bucketHeight so the bounds are offset in bucket grid units */ + bucketMin[0] = (int)(((float)(min[0] - ps->screenMin[0]) / ps->screen_width) * ps->buckets_x) + 0.5f; /* these offsets of 0.5 and 1.5 seem odd but they are correct */ + bucketMin[1] = (int)(((float)(min[1] - ps->screenMin[1]) / ps->screen_height) * ps->buckets_y) + 0.5f; + + bucketMax[0] = (int)(((float)(max[0] - ps->screenMin[0]) / ps->screen_width) * ps->buckets_x) + 1.5f; + bucketMax[1] = (int)(((float)(max[1] - ps->screenMin[1]) / ps->screen_height) * ps->buckets_y) + 1.5f; + + /* incase the rect is outside the mesh 2d bounds */ + CLAMP(bucketMin[0], 0, ps->buckets_x); + CLAMP(bucketMin[1], 0, ps->buckets_y); + + CLAMP(bucketMax[0], 0, ps->buckets_x); + CLAMP(bucketMax[1], 0, ps->buckets_y); +} + +/* set bucket_bounds to a screen space-aligned floating point bound-box */ +static void project_bucket_bounds(const ProjPaintState *ps, const int bucket_x, const int bucket_y, rctf *bucket_bounds) +{ + bucket_bounds->xmin = ps->screenMin[0]+((bucket_x)*(ps->screen_width / ps->buckets_x)); /* left */ + bucket_bounds->xmax = ps->screenMin[0]+((bucket_x+1)*(ps->screen_width / ps->buckets_x)); /* right */ + + bucket_bounds->ymin = ps->screenMin[1]+((bucket_y)*(ps->screen_height / ps->buckets_y)); /* bottom */ + bucket_bounds->ymax = ps->screenMin[1]+((bucket_y+1)*(ps->screen_height / ps->buckets_y)); /* top */ +} + +/* Fill this bucket with pixels from the faces that intersect it. + * + * have bucket_bounds as an argument so we don;t need to give bucket_x/y the rect function needs */ +static void project_bucket_init(const ProjPaintState *ps, const int thread_index, const int bucket_index, rctf *bucket_bounds) +{ + LinkNode *node; + int face_index, image_index; + ImBuf *ibuf = NULL; + MTFace *tf; + + Image *tpage_last = NULL; + + + if (ps->image_tot==1) { + /* Simple loop, no context switching */ + ibuf = ps->projImages[0].ibuf; + + for (node = ps->bucketFaces[bucket_index]; node; node= node->next) { + project_paint_face_init(ps, thread_index, bucket_index, (int)node->link, 0, bucket_bounds, ibuf); + } + } + else { + + /* More complicated loop, switch between images */ + for (node = ps->bucketFaces[bucket_index]; node; node= node->next) { + face_index = (int)node->link; + + /* Image context switching */ + tf = ps->dm_mtface+face_index; + if (tpage_last != tf->tpage) { + tpage_last = tf->tpage; + + image_index = -1; /* sanity check */ + + for (image_index=0; image_index < ps->image_tot; image_index++) { + if (ps->projImages[image_index].ima == tpage_last) { + ibuf = ps->projImages[image_index].ibuf; + break; + } + } + } + /* context switching done */ + + project_paint_face_init(ps, thread_index, bucket_index, face_index, image_index, bucket_bounds, ibuf); + + } + } + + ps->bucketFlags[bucket_index] |= PROJ_BUCKET_INIT; +} + + +/* We want to know if a bucket and a face overlap in screen-space + * + * Note, if this ever returns false positives its not that bad, since a face in the bounding area will have its pixels + * calculated when it might not be needed later, (at the moment at least) + * obviously it shouldn't have bugs though */ + +static int project_bucket_face_isect(ProjPaintState *ps, float min[2], float max[2], int bucket_x, int bucket_y, int bucket_index, const MFace *mf) +{ + /* TODO - replace this with a tricker method that uses sideofline for all screenCoords's edges against the closest bucket corner */ + rctf bucket_bounds; + float p1[2], p2[2], p3[2], p4[2]; + float *v, *v1,*v2,*v3,*v4; + int fidx; + + project_bucket_bounds(ps, bucket_x, bucket_y, &bucket_bounds); + + /* Is one of the faces verts in the bucket bounds? */ + + fidx = mf->v4 ? 3:2; + do { + v = ps->screenCoords[ (*(&mf->v1 + fidx)) ]; + if (BLI_in_rctf(&bucket_bounds, v[0], v[1])) { + return 1; + } + } while (fidx--); + + v1 = ps->screenCoords[mf->v1]; + v2 = ps->screenCoords[mf->v2]; + v3 = ps->screenCoords[mf->v3]; + if (mf->v4) { + v4 = ps->screenCoords[mf->v4]; + } + + p1[0] = bucket_bounds.xmin; p1[1] = bucket_bounds.ymin; + p2[0] = bucket_bounds.xmin; p2[1] = bucket_bounds.ymax; + p3[0] = bucket_bounds.xmax; p3[1] = bucket_bounds.ymax; + p4[0] = bucket_bounds.xmax; p4[1] = bucket_bounds.ymin; + + if (mf->v4) { + if( IsectPQ2Df(p1, v1, v2, v3, v4) || IsectPQ2Df(p2, v1, v2, v3, v4) || IsectPQ2Df(p3, v1, v2, v3, v4) || IsectPQ2Df(p4, v1, v2, v3, v4) || + /* we can avoid testing v3,v1 because another intersection MUST exist if this intersects */ + (IsectLL2Df(p1, p2, v1, v2) || IsectLL2Df(p1, p2, v2, v3) || IsectLL2Df(p1, p2, v3, v4)) || + (IsectLL2Df(p2, p3, v1, v2) || IsectLL2Df(p2, p3, v2, v3) || IsectLL2Df(p2, p3, v3, v4)) || + (IsectLL2Df(p3, p4, v1, v2) || IsectLL2Df(p3, p4, v2, v3) || IsectLL2Df(p3, p4, v3, v4)) || + (IsectLL2Df(p4, p1, v1, v2) || IsectLL2Df(p4, p1, v2, v3) || IsectLL2Df(p4, p1, v3, v4)) + ) { + return 1; + } + } + else { + if( IsectPT2Df(p1, v1, v2, v3) || IsectPT2Df(p2, v1, v2, v3) || IsectPT2Df(p3, v1, v2, v3) || IsectPT2Df(p4, v1, v2, v3) || + /* we can avoid testing v3,v1 because another intersection MUST exist if this intersects */ + (IsectLL2Df(p1, p2, v1, v2) || IsectLL2Df(p1, p2, v2, v3)) || + (IsectLL2Df(p2, p3, v1, v2) || IsectLL2Df(p2, p3, v2, v3)) || + (IsectLL2Df(p3, p4, v1, v2) || IsectLL2Df(p3, p4, v2, v3)) || + (IsectLL2Df(p4, p1, v1, v2) || IsectLL2Df(p4, p1, v2, v3)) + ) { + return 1; + } + } + + return 0; +} + +/* Add faces to the bucket but dont initialize its pixels + * TODO - when painting occluded, sort the faces on their min-Z and only add faces that faces that are not occluded */ +static void project_paint_delayed_face_init(ProjPaintState *ps, const MFace *mf, const MTFace *tf, const int face_index) +{ + float min[2], max[2], *vCoSS; + int bucketMin[2], bucketMax[2]; /* for ps->bucketRect indexing */ + int fidx, bucket_x, bucket_y, bucket_index; + int has_x_isect = -1, has_isect = 0; /* for early loop exit */ + MemArena *arena = ps->arena_mt[0]; /* just use the first thread arena since threading has not started yet */ + + INIT_MINMAX2(min, max); + + fidx = mf->v4 ? 3:2; + do { + vCoSS = ps->screenCoords[ *(&mf->v1 + fidx) ]; + DO_MINMAX2(vCoSS, min, max); + } while (fidx--); + + project_paint_bucket_bounds(ps, min, max, bucketMin, bucketMax); + + for (bucket_y = bucketMin[1]; bucket_y < bucketMax[1]; bucket_y++) { + has_x_isect = 0; + for (bucket_x = bucketMin[0]; bucket_x < bucketMax[0]; bucket_x++) { + + bucket_index = bucket_x + (bucket_y * ps->buckets_x); + + if (project_bucket_face_isect(ps, min, max, bucket_x, bucket_y, bucket_index, mf)) { + BLI_linklist_prepend_arena( + &ps->bucketFaces[ bucket_index ], + SET_INT_IN_POINTER(face_index), /* cast to a pointer to shut up the compiler */ + arena + ); + + has_x_isect = has_isect = 1; + } + else if (has_x_isect) { + /* assuming the face is not a bow-tie - we know we cant intersect again on the X */ + break; + } + } + + /* no intersection for this entire row, after some intersection above means we can quit now */ + if (has_x_isect==0 && has_isect) { + break; + } + } + +#ifndef PROJ_DEBUG_NOSEAMBLEED + if (ps->seam_bleed_px > 0.0f) { + if (!mf->v4) { + ps->faceSeamFlags[face_index] |= PROJ_FACE_NOSEAM4; /* so this wont show up as an untagged edge */ + } + **ps->faceSeamUVs[face_index] = MAXFLOAT; /* set as uninitialized */ + } +#endif +} + +/* run once per stroke before projection painting */ +static void project_paint_begin(ProjPaintState *ps, short mval[2]) +{ + /* Viewport vars */ + float mat[3][3]; + + float no[3]; + + float (*projScreenCo)[4]; /* Note, we could have 4D vectors are only needed for */ + float projMargin; + /* Image Vars - keep track of images we have used */ + LinkNode *image_LinkList = NULL; + LinkNode *node; + + ProjPaintImage *projIma; + Image *tpage_last = NULL; + + /* Face vars */ + MFace *mf; + MTFace *tf; + + int a, i; /* generic looping vars */ + int image_index = -1, face_index; + + MemArena *arena; /* at the moment this is just ps->arena_mt[0], but use this to show were not multithreading */ + + /* ---- end defines ---- */ + + /* paint onto the derived mesh */ + ps->dm = mesh_get_derived_final(ps->ob, get_viewedit_datamask()); + + if ( !CustomData_has_layer( &ps->dm->faceData, CD_MTFACE) ) { + ps->dm = NULL; + return; + } + ps->dm_mvert = ps->dm->getVertArray(ps->dm); + ps->dm_mface = ps->dm->getFaceArray(ps->dm); + ps->dm_mtface= ps->dm->getFaceDataArray(ps->dm, CD_MTFACE); + + ps->dm_totvert = ps->dm->getNumVerts(ps->dm); + ps->dm_totface = ps->dm->getNumFaces(ps->dm); + + /* use clone mtface? */ + + + /* Note, use the original mesh for getting the clone and mask layer index + * this avoids re-generating the derived mesh just to get the new index */ + if (ps->do_layer_clone) { + //int layer_num = CustomData_get_clone_layer(&ps->dm->faceData, CD_MTFACE); + int layer_num = CustomData_get_clone_layer(&((Mesh *)ps->ob->data)->fdata, CD_MTFACE); + if (layer_num != -1) + ps->dm_mtface_clone = CustomData_get_layer_n(&ps->dm->faceData, CD_MTFACE, layer_num); + + if (ps->dm_mtface_clone==NULL || ps->dm_mtface_clone==ps->dm_mtface) { + ps->do_layer_clone = 0; + ps->dm_mtface_clone= NULL; + } + } + + if (ps->do_layer_mask) { + //int layer_num = CustomData_get_mask_layer(&ps->dm->faceData, CD_MTFACE); + int layer_num = CustomData_get_mask_layer(&((Mesh *)ps->ob->data)->fdata, CD_MTFACE); + if (layer_num != -1) + ps->dm_mtface_mask = CustomData_get_layer_n(&ps->dm->faceData, CD_MTFACE, layer_num); + + if (ps->dm_mtface_mask==NULL || ps->dm_mtface_mask==ps->dm_mtface) { + ps->do_layer_mask = 0; + ps->dm_mtface_mask = NULL; + } + } + + + + ps->viewDir[0] = 0.0f; + ps->viewDir[1] = 0.0f; + ps->viewDir[2] = 1.0f; + + view3d_get_object_project_mat(curarea, ps->ob, ps->projectMat, ps->viewMat); + + /* viewDir - object relative */ + Mat4Invert(ps->ob->imat, ps->ob->obmat); + Mat3CpyMat4(mat, G.vd->viewinv); + Mat3MulVecfl(mat, ps->viewDir); + Mat3CpyMat4(mat, ps->ob->imat); + Mat3MulVecfl(mat, ps->viewDir); + Normalize(ps->viewDir); + + /* viewPos - object relative */ + VECCOPY(ps->viewPos, G.vd->viewinv[3]); + Mat3CpyMat4(mat, ps->ob->imat); + Mat3MulVecfl(mat, ps->viewPos); + VecAddf(ps->viewPos, ps->viewPos, ps->ob->imat[3]); + + { /* only use these for running 'get_view3d_viewplane' */ + rctf viewplane; + + ps->is_ortho = get_view3d_viewplane(curarea->winx, curarea->winy, &viewplane, &ps->clipsta, &ps->clipend, NULL); + + //printf("%f %f\n", ps->clipsta, ps->clipend); + if (ps->is_ortho) { /* only needed for ortho */ + float fac = 2.0f / (ps->clipend - ps->clipsta); + ps->clipsta *= fac; + ps->clipend *= fac; + } + else { + /* TODO - can we even adjust for clip start/end? */ + } + + } + + ps->is_airbrush = (ps->brush->flag & BRUSH_AIRBRUSH) ? 1 : 0; + + ps->is_texbrush = (ps->brush->mtex[ps->brush->texact] && ps->brush->mtex[ps->brush->texact]->tex) ? 1 : 0; + + + /* calculate vert screen coords + * run this early so we can calculate the x/y resolution of our bucket rect */ + INIT_MINMAX2(ps->screenMin, ps->screenMax); + + ps->screenCoords = MEM_mallocN(sizeof(float) * ps->dm_totvert * 4, "ProjectPaint ScreenVerts"); + projScreenCo = ps->screenCoords; + + if (ps->is_ortho) { + for(a=0; a < ps->dm_totvert; a++, projScreenCo++) { + VECCOPY((*projScreenCo), ps->dm_mvert[a].co); + Mat4MulVecfl(ps->projectMat, (*projScreenCo)); + + /* screen space, not clamped */ + (*projScreenCo)[0] = (float)(curarea->winx/2.0f)+(curarea->winx/2.0f)*(*projScreenCo)[0]; + (*projScreenCo)[1] = (float)(curarea->winy/2.0f)+(curarea->winy/2.0f)*(*projScreenCo)[1]; + DO_MINMAX2((*projScreenCo), ps->screenMin, ps->screenMax); + } + } + else { + for(a=0; a < ps->dm_totvert; a++, projScreenCo++) { + VECCOPY((*projScreenCo), ps->dm_mvert[a].co); + (*projScreenCo)[3] = 1.0f; + + Mat4MulVec4fl(ps->projectMat, (*projScreenCo)); + + + if ((*projScreenCo)[3] > ps->clipsta) { + /* screen space, not clamped */ + (*projScreenCo)[0] = (float)(curarea->winx/2.0f)+(curarea->winx/2.0f)*(*projScreenCo)[0]/(*projScreenCo)[3]; + (*projScreenCo)[1] = (float)(curarea->winy/2.0f)+(curarea->winy/2.0f)*(*projScreenCo)[1]/(*projScreenCo)[3]; + (*projScreenCo)[2] = (*projScreenCo)[2]/(*projScreenCo)[3]; /* Use the depth for bucket point occlusion */ + DO_MINMAX2((*projScreenCo), ps->screenMin, ps->screenMax); + } + else { + /* TODO - deal with cases where 1 side of a face goes behind the view ? + * + * After some research this is actually very tricky, only option is to + * clip the derived mesh before painting, which is a Pain */ + (*projScreenCo)[0] = MAXFLOAT; + } + } + } + + /* If this border is not added we get artifacts for faces that + * have a parallel edge and at the bounds of the the 2D projected verts eg + * - a single screen aligned quad */ + projMargin = (ps->screenMax[0] - ps->screenMin[0]) * 0.000001f; + ps->screenMax[0] += projMargin; + ps->screenMin[0] -= projMargin; + projMargin = (ps->screenMax[1] - ps->screenMin[1]) * 0.000001f; + ps->screenMax[1] += projMargin; + ps->screenMin[1] -= projMargin; + +#ifdef PROJ_DEBUG_WINCLIP + CLAMP(ps->screenMin[0], -ps->brush->size, curarea->winx + ps->brush->size); + CLAMP(ps->screenMax[0], -ps->brush->size, curarea->winx + ps->brush->size); + + CLAMP(ps->screenMin[1], -ps->brush->size, curarea->winy + ps->brush->size); + CLAMP(ps->screenMax[1], -ps->brush->size, curarea->winy + ps->brush->size); +#endif + + /* only for convenience */ + ps->screen_width = ps->screenMax[0] - ps->screenMin[0]; + ps->screen_height = ps->screenMax[1] - ps->screenMin[1]; + + ps->buckets_x = (int)(ps->screen_width / (((float)ps->brush->size) / PROJ_BUCKET_BRUSH_DIV)); + ps->buckets_y = (int)(ps->screen_height / (((float)ps->brush->size) / PROJ_BUCKET_BRUSH_DIV)); + + printf("\tscreenspace bucket division x:%d y:%d\n", ps->buckets_x, ps->buckets_y); + + /* really high values could cause problems since it has to allocate a few + * (ps->buckets_x*ps->buckets_y) sized arrays */ + CLAMP(ps->buckets_x, PROJ_BUCKET_RECT_MIN, PROJ_BUCKET_RECT_MAX); + CLAMP(ps->buckets_y, PROJ_BUCKET_RECT_MIN, PROJ_BUCKET_RECT_MAX); + + ps->bucketRect = (LinkNode **)MEM_callocN(sizeof(LinkNode *) * ps->buckets_x * ps->buckets_y, "paint-bucketRect"); + ps->bucketFaces= (LinkNode **)MEM_callocN(sizeof(LinkNode *) * ps->buckets_x * ps->buckets_y, "paint-bucketFaces"); + + ps->bucketFlags= (unsigned char *)MEM_callocN(sizeof(char) * ps->buckets_x * ps->buckets_y, "paint-bucketFaces"); +#ifndef PROJ_DEBUG_NOSEAMBLEED + if (ps->seam_bleed_px > 0.0f) { + ps->vertFaces= (LinkNode **)MEM_callocN(sizeof(LinkNode *) * ps->dm_totvert, "paint-vertFaces"); + ps->faceSeamFlags = (char *)MEM_callocN(sizeof(char) * ps->dm_totface, "paint-faceSeamFlags"); + ps->faceSeamUVs= MEM_mallocN(sizeof(float) * ps->dm_totface * 8, "paint-faceSeamUVs"); + } +#endif + + /* Thread stuff + * + * very small brushes run a lot slower multithreaded since the advantage with + * threads is being able to fill in multiple buckets at once. + * Only use threads for bigger brushes. */ + + if (G.scene->r.mode & R_FIXED_THREADS) { + ps->thread_tot = G.scene->r.threads; + } + else { + ps->thread_tot = BLI_system_thread_count(); + } + for (a=0; a<ps->thread_tot; a++) { + ps->arena_mt[a] = BLI_memarena_new(1<<16); + } + + arena = ps->arena_mt[0]; + + if (ps->do_backfacecull && ps->do_mask_normal) { + MVert *v = ps->dm_mvert; + float viewDirPersp[3]; + + ps->vertFlags = MEM_callocN(sizeof(char) * ps->dm_totvert, "paint-vertFlags"); + + for(a=0; a < ps->dm_totvert; a++, v++) { + no[0] = (float)(v->no[0] / 32767.0f); + no[1] = (float)(v->no[1] / 32767.0f); + no[2] = (float)(v->no[2] / 32767.0f); + + if (ps->is_ortho) { + if (NormalizedVecAngle2(ps->viewDir, no) >= ps->normal_angle) { /* 1 vert of this face is towards us */ + ps->vertFlags[a] |= PROJ_VERT_CULL; + } + } + else { + VecSubf(viewDirPersp, ps->viewPos, v->co); + Normalize(viewDirPersp); + if (NormalizedVecAngle2(viewDirPersp, no) >= ps->normal_angle) { /* 1 vert of this face is towards us */ + ps->vertFlags[a] |= PROJ_VERT_CULL; + } + } + } + } + + /* setup clone offset */ + if (ps->tool == PAINT_TOOL_CLONE) { + float projCo[4]; + float *curs= give_cursor(); + VECCOPY(projCo, curs); + Mat4MulVecfl(ps->ob->imat, projCo); + + projCo[3] = 1.0f; + Mat4MulVec4fl(ps->projectMat, projCo); + ps->cloneOffset[0] = mval[0] - ((float)(curarea->winx/2.0f)+(curarea->winx/2.0f)*projCo[0]/projCo[3]); + ps->cloneOffset[1] = mval[1] - ((float)(curarea->winy/2.0f)+(curarea->winy/2.0f)*projCo[1]/projCo[3]); + + // printf("%f %f %f %f %f\n", ps->cloneOffset[0], ps->cloneOffset[1], curs[0], curs[1], curs[2]); + + } + + + + for(face_index = 0, tf = ps->dm_mtface, mf = ps->dm_mface; face_index < ps->dm_totface; mf++, tf++, face_index++) { + +#ifndef PROJ_DEBUG_NOSEAMBLEED + /* add face user if we have bleed enabled, set the UV seam flags later */ + /* annoying but we need to add all faces even ones we never use elsewhere */ + if (ps->seam_bleed_px > 0.0f) { + BLI_linklist_prepend_arena(&ps->vertFaces[mf->v1], (void *)face_index, arena); + BLI_linklist_prepend_arena(&ps->vertFaces[mf->v2], (void *)face_index, arena); + BLI_linklist_prepend_arena(&ps->vertFaces[mf->v3], (void *)face_index, arena); + if (mf->v4) { + BLI_linklist_prepend_arena(&ps->vertFaces[ mf->v4 ], (void *)face_index, arena); + } + } +#endif + + if (tf->tpage && ((G.f & G_FACESELECT)==0 || mf->flag & ME_FACE_SEL)) { + + float *v1coSS, *v2coSS, *v3coSS, *v4coSS; + + v1coSS = ps->screenCoords[mf->v1]; + v2coSS = ps->screenCoords[mf->v2]; + v3coSS = ps->screenCoords[mf->v3]; + if (mf->v4) { + v4coSS = ps->screenCoords[mf->v4]; + } + + + if (!ps->is_ortho) { + if ( v1coSS[0]==MAXFLOAT || + v2coSS[0]==MAXFLOAT || + v3coSS[0]==MAXFLOAT || + (mf->v4 && v4coSS[0]==MAXFLOAT) + ) { + continue; + } + } + +#ifdef PROJ_DEBUG_WINCLIP + /* ignore faces outside the view */ + if ( + (v1coSS[0] < ps->screenMin[0] && + v2coSS[0] < ps->screenMin[0] && + v3coSS[0] < ps->screenMin[0] && + (mf->v4 && v4coSS[0] < ps->screenMin[0])) || + + (v1coSS[0] > ps->screenMax[0] && + v2coSS[0] > ps->screenMax[0] && + v3coSS[0] > ps->screenMax[0] && + (mf->v4 && v4coSS[0] > ps->screenMax[0])) || + + (v1coSS[1] < ps->screenMin[1] && + v2coSS[1] < ps->screenMin[1] && + v3coSS[1] < ps->screenMin[1] && + (mf->v4 && v4coSS[1] < ps->screenMin[1])) || + + (v1coSS[1] > ps->screenMax[1] && + v2coSS[1] > ps->screenMax[1] && + v3coSS[1] > ps->screenMax[1] && + (mf->v4 && v4coSS[1] > ps->screenMax[1])) + ) { + continue; + } + +#endif //PROJ_DEBUG_WINCLIP + + + if (ps->do_backfacecull) { + if (ps->do_mask_normal) { + /* Since we are interpolating the normals of faces, we want to make + * sure all the verts are pointing away from the view, + * not just the face */ + if ( (ps->vertFlags[mf->v1] & PROJ_VERT_CULL) && + (ps->vertFlags[mf->v2] & PROJ_VERT_CULL) && + (ps->vertFlags[mf->v3] & PROJ_VERT_CULL) && + (mf->v4==0 || ps->vertFlags[mf->v4] & PROJ_VERT_CULL) + + ) { + continue; + } + } + else { + if (SIDE_OF_LINE(v1coSS, v2coSS, v3coSS) < 0.0f) { + continue; + } + + } + } + + if (tpage_last != tf->tpage) { + + image_index = BLI_linklist_index(image_LinkList, tf->tpage); + + if (image_index==-1 && BKE_image_get_ibuf((Image *)tf->tpage, NULL)) { /* MemArena dosnt have an append func */ + BLI_linklist_append(&image_LinkList, tf->tpage); + image_index = ps->image_tot; + ps->image_tot++; + } + + tpage_last = tf->tpage; + } + + if (image_index != -1) { + /* Initialize the faces screen pixels */ + /* Add this to a list to initialize later */ + project_paint_delayed_face_init(ps, mf, tf, face_index); + } + } + } + + /* build an array of images we use*/ + projIma = ps->projImages = (ProjPaintImage *)BLI_memarena_alloc(arena, sizeof(ProjPaintImage) * ps->image_tot); + + for (node= image_LinkList, i=0; node; node= node->next, i++, projIma++) { + projIma->ima = node->link; + // calloced - projIma->touch = 0; + projIma->ibuf = BKE_image_get_ibuf(projIma->ima, NULL); + projIma->partRedrawRect = BLI_memarena_alloc(arena, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED); + // calloced - memset(projIma->partRedrawRect, 0, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED); + } + + /* we have built the array, discard the linked list */ + BLI_linklist_free(image_LinkList, NULL); +} + +static void project_paint_end(ProjPaintState *ps) +{ + int a; + + /* build undo data from original pixel colors */ + if(U.uiflag & USER_GLOBALUNDO) { + ProjPixel *projPixel; + ImBuf *tmpibuf = NULL, *tmpibuf_float = NULL; + LinkNode *pixel_node; + UndoTile *tile; + MemArena *arena = ps->arena_mt[0]; /* threaded arena re-used for non threaded case */ + + int bucket_tot = (ps->buckets_x * ps->buckets_y); /* we could get an X/Y but easier to loop through all possible buckets */ + int bucket_index; + int tile_index; + int x_round, y_round; + int x_tile, y_tile; + int is_float = -1; + + /* context */ + ProjPaintImage *last_projIma; + int last_image_index = -1; + int last_tile_width; + + for(a=0, last_projIma=ps->projImages; a < ps->image_tot; a++, last_projIma++) { + int size = sizeof(UndoTile **) * IMAPAINT_TILE_NUMBER(last_projIma->ibuf->x) * IMAPAINT_TILE_NUMBER(last_projIma->ibuf->y); + last_projIma->undoRect = (UndoTile **) BLI_memarena_alloc(arena, size); + memset(last_projIma->undoRect, 0, size); + } + + for (bucket_index = 0; bucket_index < bucket_tot; bucket_index++) { + /* loop through all pixels */ + for(pixel_node= ps->bucketRect[bucket_index]; pixel_node; pixel_node= pixel_node->next) { + + /* ok we have a pixel, was it modified? */ + projPixel = (ProjPixel *)pixel_node->link; + + if (last_image_index != projPixel->image_index) { + /* set the context */ + last_image_index = projPixel->image_index; + last_projIma = ps->projImages + last_image_index; + last_tile_width = IMAPAINT_TILE_NUMBER(last_projIma->ibuf->x); + is_float = last_projIma->ibuf->rect_float ? 1 : 0; + } + + + if ( (is_float == 0 && projPixel->origColor.uint != *projPixel->pixel.uint_pt) || + + (is_float == 1 && + ( projPixel->origColor.f[0] != projPixel->pixel.f_pt[0] || + projPixel->origColor.f[1] != projPixel->pixel.f_pt[1] || + projPixel->origColor.f[2] != projPixel->pixel.f_pt[2] || + projPixel->origColor.f[3] != projPixel->pixel.f_pt[3] )) + ) { + + x_tile = projPixel->x_px >> IMAPAINT_TILE_BITS; + y_tile = projPixel->y_px >> IMAPAINT_TILE_BITS; + + x_round = x_tile * IMAPAINT_TILE_SIZE; + y_round = y_tile * IMAPAINT_TILE_SIZE; + + tile_index = x_tile + y_tile * last_tile_width; + + if (last_projIma->undoRect[tile_index]==NULL) { + /* add the undo tile from the modified image, then write the original colors back into it */ + tile = last_projIma->undoRect[tile_index] = undo_init_tile(&last_projIma->ima->id, last_projIma->ibuf, is_float ? (&tmpibuf_float):(&tmpibuf) , x_tile, y_tile); + } + else { + tile = last_projIma->undoRect[tile_index]; + } + + /* This is a BIT ODD, but overwrite the undo tiles image info with this pixels original color + * because allocating the tiles allong the way slows down painting */ + + if (is_float) { + float *rgba_fp = (float *)tile->rect + (((projPixel->x_px - x_round) + (projPixel->y_px - y_round) * IMAPAINT_TILE_SIZE)) * 4; + QUATCOPY(rgba_fp, projPixel->origColor.f); + } + else { + ((unsigned int *)tile->rect)[ (projPixel->x_px - x_round) + (projPixel->y_px - y_round) * IMAPAINT_TILE_SIZE ] = projPixel->origColor.uint; + } + } + } + } + + if (tmpibuf) IMB_freeImBuf(tmpibuf); + if (tmpibuf_float) IMB_freeImBuf(tmpibuf_float); + } + /* done calculating undo data */ + + MEM_freeN(ps->screenCoords); + MEM_freeN(ps->bucketRect); + MEM_freeN(ps->bucketFaces); + MEM_freeN(ps->bucketFlags); + + if (ps->seam_bleed_px > 0.0f) { + MEM_freeN(ps->vertFaces); + MEM_freeN(ps->faceSeamFlags); + MEM_freeN(ps->faceSeamUVs); + } + + if (ps->vertFlags) MEM_freeN(ps->vertFlags); + + + for (a=0; a<ps->thread_tot; a++) { + BLI_memarena_free(ps->arena_mt[a]); + } + + ps->dm->release(ps->dm); +} + +/* Use this rather then mouse_cursor() + * so rotating the view leaves the 3D Cursor on the clone source surface. + */ +static void project_paint_setCursor(void) { + float *curs = give_cursor(); + short mval[2]; + + mouse_cursor(); /* set the cursor location on the view X/Y */ + getmouseco_areawin(mval); + view_mouse_depth(curs, mval, 1); +} /* 1= an undo, -1 is a redo. */ +static void partial_redraw_array_init(ImagePaintPartialRedraw *pr) +{ + int tot = PROJ_BOUNDBOX_SQUARED; + while (tot--) { + pr->x1 = 10000000; + pr->y1 = 10000000; + + pr->x2 = -1; + pr->y2 = -1; + + pr->enabled = 1; + + pr++; + } +} + + +static int partial_redraw_array_merge(ImagePaintPartialRedraw *pr, ImagePaintPartialRedraw *pr_other, int tot) +{ + int touch; + while (tot--) { + pr->x1 = MIN2(pr->x1, pr_other->x1); + pr->y1 = MIN2(pr->y1, pr_other->y1); + + pr->x2 = MAX2(pr->x2, pr_other->x2); + pr->y2 = MAX2(pr->y2, pr_other->y2); + + if (pr->x2 != -1) + touch = 1; + + pr++; pr_other++; + } + + return touch; +} + +/* Loop over all images on this mesh and update any we have touched */ +static int project_image_refresh_tagged(ProjPaintState *ps) +{ + ImagePaintPartialRedraw *pr; + ProjPaintImage *projIma; + int a,i; + int redraw = 0; + + + for (a=0, projIma=ps->projImages; a < ps->image_tot; a++, projIma++) { + if (projIma->touch) { + /* look over each bound cell */ + for (i=0; i<PROJ_BOUNDBOX_SQUARED; i++) { + pr = &(projIma->partRedrawRect[i]); + if (pr->x2 != -1) { /* TODO - use 'enabled' ? */ + imapaintpartial = *pr; + imapaint_image_update(projIma->ima, projIma->ibuf, 1); /*last 1 is for texpaint*/ + redraw = 1; + } + } + + projIma->touch = 0; /* clear for reuse */ + } + } + + return redraw; +} + +/* run this per painting onto each mouse location */ +static int project_bucket_iter_init(ProjPaintState *ps, const float mval_f[2]) +{ + float min_brush[2], max_brush[2]; + float size_half = ((float)ps->brush->size) * 0.5f; + + /* so we dont have a bucket bounds that is way too small to paint into */ + // if (size_half < 1.0f) size_half = 1.0f; // this dosnt work yet :/ + + min_brush[0] = mval_f[0] - size_half; + min_brush[1] = mval_f[1] - size_half; + + max_brush[0] = mval_f[0] + size_half; + max_brush[1] = mval_f[1] + size_half; + + /* offset to make this a valid bucket index */ + project_paint_bucket_bounds(ps, min_brush, max_brush, ps->bucketMin, ps->bucketMax); + + /* mouse outside the model areas? */ + if (ps->bucketMin[0]==ps->bucketMax[0] || ps->bucketMin[1]==ps->bucketMax[1]) { + return 0; + } + + ps->context_bucket_x = ps->bucketMin[0]; + ps->context_bucket_y = ps->bucketMin[1]; + return 1; +} + +static int project_bucket_iter_next(ProjPaintState *ps, int *bucket_index, rctf *bucket_bounds, const float mval[2]) +{ + if (ps->thread_tot > 1) + BLI_lock_thread(LOCK_CUSTOM1); + + //printf("%d %d \n", ps->context_bucket_x, ps->context_bucket_y); + + for ( ; ps->context_bucket_y < ps->bucketMax[1]; ps->context_bucket_y++) { + for ( ; ps->context_bucket_x < ps->bucketMax[0]; ps->context_bucket_x++) { + + /* use bucket_bounds for project_bucket_isect_circle and project_bucket_init*/ + project_bucket_bounds(ps, ps->context_bucket_x, ps->context_bucket_y, bucket_bounds); + + if (project_bucket_isect_circle(ps->context_bucket_x, ps->context_bucket_y, mval, ps->brush->size * ps->brush->size, bucket_bounds)) { + *bucket_index = ps->context_bucket_x + (ps->context_bucket_y * ps->buckets_x); + ps->context_bucket_x++; + + if (ps->thread_tot > 1) + BLI_unlock_thread(LOCK_CUSTOM1); + + return 1; + } + } + ps->context_bucket_x = ps->bucketMin[0]; + } + + if (ps->thread_tot > 1) + BLI_unlock_thread(LOCK_CUSTOM1); + return 0; +} + +/* Each thread gets one of these, also used as an argument to pass to project_paint_op */ +typedef struct ProjectHandle { + /* args */ + ProjPaintState *ps; + float prevmval[2]; + float mval[2]; + + /* annoying but we need to have image bounds per thread, then merge into ps->projectPartialRedraws */ + ProjPaintImage *projImages; /* array of partial redraws */ + + /* thread settings */ + int thread_index; +} ProjectHandle; + +static void blend_color_mix(unsigned char *cp, const unsigned char *cp1, const unsigned char *cp2, const int fac) +{ + /* this and other blending modes previously used >>8 instead of /255. both + are not equivalent (>>8 is /256), and the former results in rounding + errors that can turn colors black fast after repeated blending */ + const int mfac= 255-fac; + + cp[0]= (mfac*cp1[0]+fac*cp2[0])/255; + cp[1]= (mfac*cp1[1]+fac*cp2[1])/255; + cp[2]= (mfac*cp1[2]+fac*cp2[2])/255; +} + +static void blend_color_mix_float(float *cp, const float *cp1, const float *cp2, const float fac) +{ + const float mfac= 1.0-fac; + cp[0]= mfac*cp1[0] + fac*cp2[0]; + cp[1]= mfac*cp1[1] + fac*cp2[1]; + cp[2]= mfac*cp1[2] + fac*cp2[2]; +} + +static void do_projectpaint_clone(ProjPaintState *ps, ProjPixel *projPixel, float *rgba, float alpha, float mask) +{ + if (ps->is_airbrush==0 && mask < 1.0f) { + projPixel->newColor.uint = IMB_blend_color(projPixel->newColor.uint, ((ProjPixelClone*)projPixel)->clonepx.uint, (int)(alpha*255), ps->blend); + blend_color_mix(projPixel->pixel.ch_pt, projPixel->origColor.ch, projPixel->newColor.ch, (int)(mask*255)); + } + else { + *projPixel->pixel.uint_pt = IMB_blend_color(*projPixel->pixel.uint_pt, ((ProjPixelClone*)projPixel)->clonepx.uint, (int)(alpha*mask*255), ps->blend); + } +} + +static void do_projectpaint_clone_f(ProjPaintState *ps, ProjPixel *projPixel, float *rgba, float alpha, float mask) +{ + if (ps->is_airbrush==0 && mask < 1.0f) { + IMB_blend_color_float(projPixel->newColor.f, projPixel->newColor.f, ((ProjPixelClone *)projPixel)->clonepx.f, alpha, ps->blend); + blend_color_mix_float(projPixel->pixel.f_pt, projPixel->origColor.f, projPixel->newColor.f, mask); + } + else { + IMB_blend_color_float(projPixel->pixel.f_pt, projPixel->pixel.f_pt, ((ProjPixelClone *)projPixel)->clonepx.f, alpha*mask, ps->blend); + } +} + +/* do_projectpaint_smear* + * + * note, mask is used to modify the alpha here, this is not correct since it allows + * accumulation of color greater then 'projPixel->mask' however in the case of smear its not + * really that important to be correct as it is with clone and painting + */ +static void do_projectpaint_smear(ProjPaintState *ps, ProjPixel *projPixel, float *rgba, float alpha, float mask, MemArena *smearArena, LinkNode **smearPixels, float co[2]) +{ + unsigned char rgba_ub[4]; + + if (project_paint_PickColor(ps, co, NULL, rgba_ub, 1)==0) + return; + + ((ProjPixelClone *)projPixel)->clonepx.uint = IMB_blend_color(*projPixel->pixel.uint_pt, *((unsigned int *)rgba_ub), (int)(alpha*mask*255), ps->blend); + BLI_linklist_prepend_arena(smearPixels, (void *)projPixel, smearArena); +} + +static void do_projectpaint_smear_f(ProjPaintState *ps, ProjPixel *projPixel, float *rgba, float alpha, float mask, MemArena *smearArena, LinkNode **smearPixels_f, float co[2]) +{ + unsigned char rgba_ub[4]; + unsigned char rgba_smear[4]; + + if (project_paint_PickColor(ps, co, NULL, rgba_ub, 1)==0) + return; + + IMAPAINT_FLOAT_RGBA_TO_CHAR(rgba_smear, projPixel->pixel.f_pt); + ((ProjPixelClone *)projPixel)->clonepx.uint = IMB_blend_color(*((unsigned int *)rgba_smear), *((unsigned int *)rgba_ub), (int)(alpha*mask*255), ps->blend); + BLI_linklist_prepend_arena(smearPixels_f, (void *)projPixel, smearArena); +} + +static void do_projectpaint_draw(ProjPaintState *ps, ProjPixel *projPixel, float *rgba, float alpha, float mask) +{ + unsigned char rgba_ub[4]; + + if (ps->is_texbrush) { + rgba_ub[0] = FTOCHAR(rgba[0] * ps->brush->rgb[0]); + rgba_ub[1] = FTOCHAR(rgba[1] * ps->brush->rgb[1]); + rgba_ub[2] = FTOCHAR(rgba[2] * ps->brush->rgb[2]); + rgba_ub[3] = FTOCHAR(rgba[3]); + } + else { + IMAPAINT_FLOAT_RGB_TO_CHAR(rgba_ub, ps->brush->rgb); + rgba_ub[3] = 255; + } + + if (ps->is_airbrush==0 && mask < 1.0f) { + projPixel->newColor.uint = IMB_blend_color(projPixel->newColor.uint, *((unsigned int *)rgba_ub), (int)(alpha*255), ps->blend); + blend_color_mix(projPixel->pixel.ch_pt, projPixel->origColor.ch, projPixel->newColor.ch, (int)(mask*255)); + } + else { + *projPixel->pixel.uint_pt = IMB_blend_color(*projPixel->pixel.uint_pt, *((unsigned int *)rgba_ub), (int)(alpha*mask*255), ps->blend); + } +} + +static void do_projectpaint_draw_f(ProjPaintState *ps, ProjPixel *projPixel, float *rgba, float alpha, float mask) { + if (ps->is_texbrush) { + rgba[0] *= ps->brush->rgb[0]; + rgba[1] *= ps->brush->rgb[1]; + rgba[2] *= ps->brush->rgb[2]; + } + else { + VECCOPY(rgba, ps->brush->rgb); + } + + if (ps->is_airbrush==0 && mask < 1.0f) { + IMB_blend_color_float(projPixel->newColor.f, projPixel->newColor.f, rgba, alpha, ps->blend); + blend_color_mix_float(projPixel->pixel.f_pt, projPixel->origColor.f, projPixel->newColor.f, mask); + } + else { + IMB_blend_color_float(projPixel->pixel.f_pt, projPixel->pixel.f_pt, rgba, alpha*mask, ps->blend); + } +} + + + +/* run this for single and multithreaded painting */ +static void *do_projectpaint_thread(void *ph_v) +{ + /* First unpack args from the struct */ + ProjPaintState *ps = ((ProjectHandle *)ph_v)->ps; + ProjPaintImage *projImages = ((ProjectHandle *)ph_v)->projImages; + const float *lastpos = ((ProjectHandle *)ph_v)->prevmval; + const float *pos = ((ProjectHandle *)ph_v)->mval; + const int thread_index = ((ProjectHandle *)ph_v)->thread_index; + /* Done with args from ProjectHandle */ + + LinkNode *node; + ProjPixel *projPixel; + + int last_index = -1; + ProjPaintImage *last_projIma; + ImagePaintPartialRedraw *last_partial_redraw_cell; + + float rgba[4], alpha, dist_nosqrt; + + float brush_size_sqared; + float falloff; + int bucket_index; + int is_floatbuf = 0; + const short tool = ps->tool; + rctf bucket_bounds; + + /* for smear only */ + float pos_ofs[2]; + float co[2]; + float mask = 1.0f; /* airbrush wont use mask */ + unsigned short mask_short; + + LinkNode *smearPixels = NULL; + LinkNode *smearPixels_f = NULL; + MemArena *smearArena = NULL; /* mem arena for this brush projection only */ + + + if (tool==PAINT_TOOL_SMEAR) { + pos_ofs[0] = pos[0] - lastpos[0]; + pos_ofs[1] = pos[1] - lastpos[1]; + + smearArena = BLI_memarena_new(1<<16); + } + + /* avoid a square root with every dist comparison */ + brush_size_sqared = ps->brush->size * ps->brush->size; + + /* printf("brush bounds %d %d %d %d\n", bucketMin[0], bucketMin[1], bucketMax[0], bucketMax[1]); */ + + while (project_bucket_iter_next(ps, &bucket_index, &bucket_bounds, pos)) { + + /* Check this bucket and its faces are initialized */ + if (ps->bucketFlags[bucket_index] == PROJ_BUCKET_NULL) { + /* No pixels initialized */ + project_bucket_init(ps, thread_index, bucket_index, &bucket_bounds); + } + + for (node = ps->bucketRect[bucket_index]; node; node = node->next) { + + projPixel = (ProjPixel *)node->link; + + /*dist = Vec2Lenf(projPixel->projCoSS, pos);*/ /* correct but uses a sqrt */ + dist_nosqrt = Vec2Lenf_nosqrt(projPixel->projCoSS, pos); + + /*if (dist < s->brush->size) {*/ /* correct but uses a sqrt */ + if (dist_nosqrt < brush_size_sqared) { + falloff = brush_sample_falloff_noalpha(ps->brush, sqrt(dist_nosqrt)); + if (falloff > 0.0f) { + if (ps->is_texbrush) { + brush_sample_tex(ps->brush, projPixel->projCoSS, rgba); + alpha = rgba[3]; + } else { + alpha = 1.0f; + } + + if (ps->is_airbrush) { + /* for an aurbrush there is no real mask, so just multiply the alpha by it */ + alpha *= falloff * ps->brush->alpha; + mask = ((float)projPixel->mask)/65535.0f; + } + else { + /* This brush dosnt accumulate so add some curve to the brushes falloff */ + falloff = 1.0f - falloff; + falloff = 1.0f - (falloff * falloff); + + mask_short = projPixel->mask * (ps->brush->alpha * falloff); + if (mask_short > projPixel->mask_max) { + mask = ((float)mask_short)/65535.0f; + projPixel->mask_max = mask_short; + } + else { + /*mask = ((float)projPixel->mask_max)/65535.0f;*/ + + /* Go onto the next pixel */ + continue; + } + } + + if (alpha > 0.0f) { + + if (last_index != projPixel->image_index) { + last_index = projPixel->image_index; + last_projIma = projImages + last_index; + + last_projIma->touch = 1; + is_floatbuf = last_projIma->ibuf->rect_float ? 1 : 0; + } + + last_partial_redraw_cell = last_projIma->partRedrawRect + projPixel->bb_cell_index; + last_partial_redraw_cell->x1 = MIN2(last_partial_redraw_cell->x1, projPixel->x_px); + last_partial_redraw_cell->y1 = MIN2(last_partial_redraw_cell->y1, projPixel->y_px); + + last_partial_redraw_cell->x2 = MAX2(last_partial_redraw_cell->x2, projPixel->x_px+1); + last_partial_redraw_cell->y2 = MAX2(last_partial_redraw_cell->y2, projPixel->y_px+1); + + + switch(tool) { + case PAINT_TOOL_CLONE: + if (is_floatbuf) { + if (((ProjPixelClone *)projPixel)->clonepx.f[3]) { + do_projectpaint_clone_f(ps, projPixel, rgba, alpha, mask); + } + } + else { + if (((ProjPixelClone*)projPixel)->clonepx.ch[3]) { + do_projectpaint_clone(ps, projPixel, rgba, alpha, mask); + } + } + break; + case PAINT_TOOL_SMEAR: + Vec2Subf(co, projPixel->projCoSS, pos_ofs); + + if (is_floatbuf) do_projectpaint_smear_f(ps, projPixel, rgba, alpha, mask, smearArena, &smearPixels_f, co); + else do_projectpaint_smear(ps, projPixel, rgba, alpha, mask, smearArena, &smearPixels, co); + break; + default: + if (is_floatbuf) do_projectpaint_draw_f(ps, projPixel, rgba, alpha, mask); + else do_projectpaint_draw(ps, projPixel, rgba, alpha, mask); + break; + } + } + /* done painting */ + } + } + } + } + + + if (tool==PAINT_TOOL_SMEAR) { + + for (node= smearPixels; node; node= node->next) { /* this wont run for a float image */ + projPixel = node->link; + *projPixel->pixel.uint_pt = ((ProjPixelClone *)projPixel)->clonepx.uint; + } + + for (node= smearPixels_f; node; node= node->next) { /* this wont run for a float image */ + projPixel = node->link; + IMAPAINT_CHAR_RGBA_TO_FLOAT(projPixel->pixel.f_pt, ((ProjPixelClone *)projPixel)->clonepx.ch); + node = node->next; + } + + BLI_memarena_free(smearArena); + } + + return NULL; +} + +static int project_paint_op(void *state, ImBuf *ibufb, float *lastpos, float *pos) +{ + /* First unpack args from the struct */ + ProjPaintState *ps = (ProjPaintState *)state; + int touch_any = 0; + + ProjectHandle handles[BLENDER_MAX_THREADS]; + ListBase threads; + int a,i; + + if (!project_bucket_iter_init(ps, pos)) { + return 0; + } + + if (ps->thread_tot > 1) + BLI_init_threads(&threads, do_projectpaint_thread, ps->thread_tot); + + /* get the threads running */ + for(a=0; a < ps->thread_tot; a++) { + + /* set defaults in handles */ + //memset(&handles[a], 0, sizeof(BakeShade)); + + handles[a].ps = ps; + VECCOPY2D(handles[a].mval, pos); + VECCOPY2D(handles[a].prevmval, lastpos); + + /* thread spesific */ + handles[a].thread_index = a; + + handles[a].projImages = (ProjPaintImage *)BLI_memarena_alloc(ps->arena_mt[a], ps->image_tot * sizeof(ProjPaintImage)); + + memcpy(handles[a].projImages, ps->projImages, ps->image_tot * sizeof(ProjPaintImage)); + + /* image bounds */ + for (i=0; i< ps->image_tot; i++) { + handles[a].projImages[i].partRedrawRect = (ImagePaintPartialRedraw *)BLI_memarena_alloc(ps->arena_mt[a], sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED); + memcpy(handles[a].projImages[i].partRedrawRect, ps->projImages[i].partRedrawRect, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED); + } + + if (ps->thread_tot > 1) + BLI_insert_thread(&threads, &handles[a]); + } + + if (ps->thread_tot > 1) /* wait for everything to be done */ + BLI_end_threads(&threads); + else + do_projectpaint_thread(&handles[0]); + + + /* move threaded bounds back into ps->projectPartialRedraws */ + for(i=0; i < ps->image_tot; i++) { + int touch = 0; + for(a=0; a < ps->thread_tot; a++) { + touch |= partial_redraw_array_merge(ps->projImages[i].partRedrawRect, handles[a].projImages[i].partRedrawRect, PROJ_BOUNDBOX_SQUARED); + } + + if (touch) { + ps->projImages[i].touch = 1; + touch_any = 1; + } + } + + return touch_any; +} + + +static int project_paint_sub_stroke(ProjPaintState *ps, BrushPainter *painter, short *prevmval_i, short *mval_i, double time, float pressure) +{ + + /* Use mouse coords as floats for projection painting */ + float pos[2]; + + pos[0] = mval_i[0]; + pos[1] = mval_i[1]; + + // we may want to use this later + // brush_painter_require_imbuf(painter, ((ibuf->rect_float)? 1: 0), 0, 0); + + if (brush_painter_paint(painter, project_paint_op, pos, time, pressure, ps)) { + return 1; + } + else return 0; +} + + +static int project_paint_stroke(ProjPaintState *ps, BrushPainter *painter, short *prevmval_i, short *mval_i, double time, int update, float pressure) +{ + int a, redraw = 0; + + for (a=0; a < ps->image_tot; a++) { + partial_redraw_array_init(ps->projImages[a].partRedrawRect); + } + + redraw |= project_paint_sub_stroke(ps, painter, prevmval_i, mval_i, time, pressure); + + if (update) { + if (project_image_refresh_tagged(ps)) { + if (redraw) { + force_draw(0); /* imapaint_redraw just calls this in viewport paint anyway */ + /* imapaint_redraw(0, 1, NULL); */ + /* imapaint_clear_partial_redraw(); */ /* not needed since we use our own array */ + } + } + } + + return redraw; +} + void undo_imagepaint_step(int step) { UndoElem *undo; @@ -333,9 +3939,9 @@ static void imapaint_clear_partial_redraw() static void imapaint_dirty_region(Image *ima, ImBuf *ibuf, int x, int y, int w, int h) { - ImBuf *tmpibuf; + ImBuf *tmpibuf = NULL; UndoTile *tile; - int srcx= 0, srcy= 0, origx, allocsize; + int srcx= 0, srcy= 0, origx; IMB_rectclip(ibuf, NULL, &x, &y, &srcx, &srcy, &w, &h); @@ -360,9 +3966,6 @@ static void imapaint_dirty_region(Image *ima, ImBuf *ibuf, int x, int y, int w, h = ((y + h - 1) >> IMAPAINT_TILE_BITS); origx = (x >> IMAPAINT_TILE_BITS); y = (y >> IMAPAINT_TILE_BITS); - - tmpibuf= IMB_allocImBuf(IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32, - IB_rectfloat|IB_rect, 0); for (; y <= h; y++) { for (x=origx; x <= w; x++) { @@ -371,32 +3974,21 @@ static void imapaint_dirty_region(Image *ima, ImBuf *ibuf, int x, int y, int w, break; if(!tile) { - tile= MEM_callocN(sizeof(UndoTile), "ImaUndoTile"); - tile->id= ima->id; - tile->x= x; - tile->y= y; - - allocsize= IMAPAINT_TILE_SIZE*IMAPAINT_TILE_SIZE*4; - allocsize *= (ibuf->rect_float)? sizeof(float): sizeof(char); - tile->rect= MEM_mapallocN(allocsize, "ImaUndoRect"); - - undo_copy_tile(tile, tmpibuf, ibuf, 0); - curundo->undosize += allocsize; - - BLI_addtail(&curundo->tiles, tile); + undo_init_tile(&ima->id, ibuf, &tmpibuf, x, y); } } } ibuf->userflags |= IB_BITMAPDIRTY; - - IMB_freeImBuf(tmpibuf); + + if (tmpibuf) + IMB_freeImBuf(tmpibuf); } static void imapaint_image_update(Image *image, ImBuf *ibuf, short texpaint) { if(ibuf->rect_float) - imb_freerectImBuf(ibuf); /* force recreate of char rect */ + imb_freerectImBuf(ibuf); /* force recreate of char rect */ /* TODO - should just update a portion from imapaintpartial! */ if(ibuf->mipmap[0]) imb_freemipmapImBuf(ibuf); @@ -404,6 +3996,7 @@ static void imapaint_image_update(Image *image, ImBuf *ibuf, short texpaint) if(texpaint || G.sima->lock) { int w = imapaintpartial.x2 - imapaintpartial.x1; int h = imapaintpartial.y2 - imapaintpartial.y1; + // printf("%d, %d, \n", w, h); GPU_paint_update_image(image, imapaintpartial.x1, imapaintpartial.y1, w, h); } } @@ -461,14 +4054,20 @@ static void imapaint_ibuf_get_set_rgb(ImBuf *ibuf, int x, int y, short torus, sh if (ibuf->rect_float) { float *rrgbf = ibuf->rect_float + (ibuf->x*y + x)*4; - if (set) IMAPAINT_FLOAT_RGB_COPY(rrgbf, rgb) - else IMAPAINT_FLOAT_RGB_COPY(rgb, rrgbf) + if (set) { + IMAPAINT_FLOAT_RGB_COPY(rrgbf, rgb); + } else { + IMAPAINT_FLOAT_RGB_COPY(rgb, rrgbf); + } } else { char *rrgb = (char*)ibuf->rect + (ibuf->x*y + x)*4; - if (set) IMAPAINT_FLOAT_RGB_TO_CHAR(rrgb, rgb) - else IMAPAINT_CHAR_RGB_TO_FLOAT(rgb, rrgb) + if (set) { + IMAPAINT_FLOAT_RGB_TO_CHAR(rrgb, rgb) + } else { + IMAPAINT_CHAR_RGB_TO_FLOAT(rgb, rrgb) + } } } @@ -569,6 +4168,8 @@ static void imapaint_convert_brushco(ImBuf *ibufb, float *pos, int *ipos) ipos[1]= (int)(pos[1] - ibufb->y/2); } +/* dosnt run for projection painting + * only the old style painting in the 3d view */ static int imapaint_paint_op(void *state, ImBuf *ibufb, float *lastpos, float *pos) { ImagePaintState *s= ((ImagePaintState*)state); @@ -793,30 +4394,53 @@ static void imapaint_paint_stroke(ImagePaintState *s, BrushPainter *painter, sho void imagepaint_paint(short mousebutton, short texpaint) { ImagePaintState s; + ProjPaintState ps; BrushPainter *painter; ToolSettings *settings= G.scene->toolsettings; - short prevmval[2], mval[2]; + short prevmval[2], mval[2], project = 0; double time; float pressure; - + int init = 1; + if(!settings->imapaint.brush) return; - + + if (texpaint) { /* are we painting in the 3D view ? */ + if ((settings->imapaint.flag & IMAGEPAINT_PROJECT_DISABLE)==0) { + project= 1; + } + } + + if (G.qual & LR_CTRLKEY) { + persp(PERSP_VIEW); + project_paint_setCursor(); + persp(PERSP_WIN); + return; + } + /* initialize state */ memset(&s, 0, sizeof(s)); + memset(&ps, 0, sizeof(ps)); + s.brush = settings->imapaint.brush; s.tool = settings->imapaint.tool; - if(texpaint && (s.tool == PAINT_TOOL_CLONE)) + if(texpaint && (project==0) && (s.tool == PAINT_TOOL_CLONE)) s.tool = PAINT_TOOL_DRAW; s.blend = s.brush->blend; - + + if (project) { + ps.brush = s.brush; + ps.tool = s.tool; + ps.blend = s.blend; + } + if(texpaint) { - s.ob = OBACT; + ps.ob = s.ob = OBACT; if (!s.ob || !(s.ob->lay & G.vd->lay)) return; s.me = get_mesh(s.ob); if (!s.me) return; - persp(PERSP_VIEW); + persp(PERSP_VIEW); /* set back to PERSP_WIN before returning */ } else { s.image = G.sima->image; @@ -829,28 +4453,76 @@ void imagepaint_paint(short mousebutton, short texpaint) return; } } + + getmouseco_areawin(mval); /* make sure this runs before project_paint_begin() */ + + /* note, if we have no UVs on the derived mesh, then we must return here */ + if (project) { + /* setup projection painting data */ + ps.do_backfacecull = (settings->imapaint.flag & IMAGEPAINT_PROJECT_BACKFACE) ? 0 : 1; + ps.do_occlude = (settings->imapaint.flag & IMAGEPAINT_PROJECT_XRAY) ? 0 : 1; + ps.do_mask_normal = (settings->imapaint.flag & IMAGEPAINT_PROJECT_FLAT) ? 0 : 1;; + + if (ps.tool == PAINT_TOOL_CLONE) + ps.do_layer_clone = (settings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_CLONE); + + ps.do_layer_mask = (settings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_MASK) ? 1 : 0; + ps.do_layer_mask_inv = (settings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_MASK_INV) ? 1 : 0; + + +#ifndef PROJ_DEBUG_NOSEAMBLEED + ps.seam_bleed_px = settings->imapaint.seam_bleed; /* pixel num to bleed */ +#endif + if (ps.do_mask_normal) { + ps.normal_angle_inner = settings->imapaint.normal_angle; + ps.normal_angle = (ps.normal_angle_inner + 90.0f) * 0.5f; + } + else { + ps.normal_angle_inner= ps.normal_angle= settings->imapaint.normal_angle; + } + + ps.normal_angle_inner *= M_PI_2 / 90; + ps.normal_angle *= M_PI_2 / 90; + ps.normal_angle_range = ps.normal_angle - ps.normal_angle_inner; + + if (ps.normal_angle_range <= 0.0f) + ps.do_mask_normal = 0; /* no need to do blending */ + + project_paint_begin(&ps, mval); + + if (ps.dm==NULL) { + persp(PERSP_WIN); + return; + } + } + settings->imapaint.flag |= IMAGEPAINT_DRAWING; undo_imagepaint_push_begin("Image Paint"); /* create painter and paint once */ painter= brush_painter_new(s.brush); - getmouseco_areawin(mval); - pressure = get_pressure(); s.blend = (get_activedevice() == 2)? BRUSH_BLEND_ERASE_ALPHA: s.brush->blend; time= PIL_check_seconds_timer(); prevmval[0]= mval[0]; prevmval[1]= mval[1]; - + /* special exception here for too high pressure values on first touch in - windows for some tablets */ - if (!((s.brush->flag & (BRUSH_ALPHA_PRESSURE|BRUSH_SIZE_PRESSURE| + windows for some tablets */ + if (!((s.brush->flag & (BRUSH_ALPHA_PRESSURE|BRUSH_SIZE_PRESSURE| BRUSH_SPACING_PRESSURE|BRUSH_RAD_PRESSURE)) && (get_activedevice() != 0) && (pressure >= 0.99f))) - imapaint_paint_stroke(&s, painter, texpaint, prevmval, mval, time, pressure); - + { + if (project) { + project_paint_stroke(&ps, painter, prevmval, mval, time, 1, pressure); + } + else { + imapaint_paint_stroke(&s, painter, texpaint, prevmval, mval, time, pressure); + } + } + /* paint loop */ do { getmouseco_areawin(mval); @@ -860,16 +4532,37 @@ void imagepaint_paint(short mousebutton, short texpaint) time= PIL_check_seconds_timer(); - if((mval[0] != prevmval[0]) || (mval[1] != prevmval[1])) { - imapaint_paint_stroke(&s, painter, texpaint, prevmval, mval, time, pressure); - prevmval[0]= mval[0]; - prevmval[1]= mval[1]; - } - else if (s.brush->flag & BRUSH_AIRBRUSH) - imapaint_paint_stroke(&s, painter, texpaint, prevmval, mval, time, pressure); - else - BIF_wait_for_statechange(); + if (project) { /* Projection Painting */ + int redraw = 1; + + if (((s.brush->flag & BRUSH_AIRBRUSH) || init) || ((mval[0] != prevmval[0]) || (mval[1] != prevmval[1]))) { + redraw = project_paint_stroke(&ps, painter, prevmval, mval, time, 1, pressure); + prevmval[0]= mval[0]; + prevmval[1]= mval[1]; + } + else { + BIF_wait_for_statechange(); + if (redraw==0) { + /* Only so the brush outline is redrawn, pitty we need to do this + * however it wont run when the mouse is still so not too bad */ + force_draw(0); + } + } + + init = 0; + } + else { + if((mval[0] != prevmval[0]) || (mval[1] != prevmval[1])) { + imapaint_paint_stroke(&s, painter, texpaint, prevmval, mval, time, pressure); + prevmval[0]= mval[0]; + prevmval[1]= mval[1]; + } + else if (s.brush->flag & BRUSH_AIRBRUSH) + imapaint_paint_stroke(&s, painter, texpaint, prevmval, mval, time, pressure); + else + BIF_wait_for_statechange(); + } /* do mouse checking at the end, so don't check twice, and potentially miss a short tap */ } while(get_mbut() & mousebutton); @@ -879,6 +4572,10 @@ void imagepaint_paint(short mousebutton, short texpaint) imapaint_canvas_free(&s); brush_painter_free(painter); + if (project) { + project_paint_end(&ps); + } + imapaint_redraw(1, texpaint, s.image); undo_imagepaint_push_end(); diff --git a/source/blender/src/interface.c b/source/blender/src/interface.c index 7417218f253..40640c01998 100644 --- a/source/blender/src/interface.c +++ b/source/blender/src/interface.c @@ -6083,12 +6083,13 @@ void autocomplete_do_name(AutoComplete *autocpl, const char *name) } void autocomplete_end(AutoComplete *autocpl, char *autoname) -{ +{ if(autocpl->truncate[0]) BLI_strncpy(autoname, autocpl->truncate, autocpl->maxlen); - else - BLI_strncpy(autoname, autocpl->startname, autocpl->maxlen); - + else { + if (autoname != autocpl->startname) /* dont copy a string over its self */ + BLI_strncpy(autoname, autocpl->startname, autocpl->maxlen); + } MEM_freeN(autocpl->truncate); MEM_freeN(autocpl); } diff --git a/source/blender/src/outliner.c b/source/blender/src/outliner.c index 8e3e44c06de..e6ffa128310 100644 --- a/source/blender/src/outliner.c +++ b/source/blender/src/outliner.c @@ -50,6 +50,7 @@ #include "DNA_nla_types.h" #include "DNA_object_types.h" #include "DNA_oops_types.h" +#include "DNA_particle_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_space_types.h" @@ -87,6 +88,7 @@ #include "BIF_editarmature.h" #include "BIF_editdeform.h" #include "BIF_editnla.h" +#include "BIF_editparticle.h" #include "BIF_editview.h" #include "BIF_editconstraint.h" #include "BIF_gl.h" @@ -715,6 +717,13 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i outliner_add_element(soops, &te->subtree, ((ArmatureModifierData*) md)->object, te, TSE_LINKED_OB, 0); } else if (md->type==eModifierType_Hook) { outliner_add_element(soops, &te->subtree, ((HookModifierData*) md)->object, te, TSE_LINKED_OB, 0); + } else if (md->type==eModifierType_ParticleSystem) { + TreeElement *ten; + ParticleSystem *psys= ((ParticleSystemModifierData*) md)->psys; + + ten = outliner_add_element(soops, &te->subtree, ob, te, TSE_LINKED_PSYS, 0); + ten->directdata = psys; + ten->name = psys->part->id.name+2; } } } @@ -1965,6 +1974,19 @@ static int tree_element_active_modifier(TreeElement *te, TreeStoreElem *tselem, return 0; } +static int tree_element_active_psys(TreeElement *te, TreeStoreElem *tselem, int set) +{ + if(set) { + Object *ob= (Object *)tselem->id; + ParticleSystem *psys= te->directdata; + + PE_change_act_psys(ob, psys); + extern_set_butspace(F7KEY, 0); + } + + return 0; +} + static int tree_element_active_constraint(TreeElement *te, TreeStoreElem *tselem, int set) { if(set) { @@ -2094,6 +2116,9 @@ static int tree_element_type_active(SpaceOops *soops, TreeElement *te, TreeStore if(set) tree_element_active_object(soops, te); else if(tselem->id==(ID *)OBACT) return 1; break; + case TSE_LINKED_PSYS: + return tree_element_active_psys(te, tselem, set); + break; case TSE_POSE_BASE: return tree_element_active_pose(te, tselem, set); break; @@ -3203,6 +3228,8 @@ static void tselem_draw_icon(float x, float y, TreeStoreElem *tselem, TreeElemen BIF_icon_draw(x, y, ICON_MODIFIER); break; case TSE_LINKED_OB: BIF_icon_draw(x, y, ICON_OBJECT); break; + case TSE_LINKED_PSYS: + BIF_icon_draw(x, y, ICON_PARTICLES); break; case TSE_MODIFIER: { Object *ob= (Object *)tselem->id; @@ -3230,6 +3257,9 @@ static void tselem_draw_icon(float x, float y, TreeStoreElem *tselem, TreeElemen BIF_icon_draw(x, y, ICON_MOD_SOFT); break; case eModifierType_Boolean: BIF_icon_draw(x, y, ICON_MOD_BOOLEAN); break; + case eModifierType_ParticleSystem: + case eModifierType_ParticleInstance: + BIF_icon_draw(x, y, ICON_PARTICLES); break; default: BIF_icon_draw(x, y, ICON_DOT); break; } diff --git a/source/blender/src/playanim.c b/source/blender/src/playanim.c index 8880380700d..b2851342cac 100644 --- a/source/blender/src/playanim.c +++ b/source/blender/src/playanim.c @@ -169,6 +169,7 @@ typedef struct pict{ static struct ListBase _picsbase = {0,0}; static struct ListBase *picsbase = &_picsbase; static int fromdisk = FALSE; +static int fstep = 1; static float zoomx = 1.0 , zoomy = 1.0; static double ptottime = 0.0, swaptime = 0.04; @@ -208,14 +209,14 @@ static void toscreen(Pict *picture, struct ImBuf *ibuf) char str[512]; cpack(-1); glRasterPos2f(0.02f, 0.03f); - sprintf(str, "%s | %.2f frames/s\n", picture->name, 1.0 / swaptime); + sprintf(str, "%s | %.2f frames/s\n", picture->name, fstep / swaptime); BMF_DrawString(G.fonts, str); } window_swap_buffers(g_window); } -static void build_pict_list(char * first, int totframes) +static void build_pict_list(char * first, int totframes, int fstep) { int size,pic,file; char *mem, name[512]; @@ -322,7 +323,7 @@ static void build_pict_list(char * first, int totframes) ptottime = 0.0; } - BLI_newname(name, +1); + BLI_newname(name, +fstep); while(qtest()){ switch(qreadN(&val)){ @@ -396,6 +397,12 @@ void playanim(int argc, char **argv) argc--; argv++; break; + case 'j': + fstep= MIN2(MAXFRAME, MAX2(1, atoi(argv[2]))); + swaptime*= fstep; + argc--; + argv++; + break; default: printf("unknown option '%c': skipping\n", argv[1][1]); break; @@ -486,11 +493,11 @@ void playanim(int argc, char **argv) efra = MAXFRAME; } - build_pict_list(name, (efra - sfra) + 1); + build_pict_list(name, (efra - sfra) + 1, fstep); for (i = 2; i < argc; i++){ strcpy(name, argv[i]); - build_pict_list(name, (efra - sfra) + 1); + build_pict_list(name, (efra - sfra) + 1, fstep); } IMB_freeImBuf(ibuf); @@ -571,9 +578,9 @@ void playanim(int argc, char **argv) if (val) { if (qualN & SHIFT) { if (ibuf) - printf(" Name: %s | Speed: %.2f frames/s\n", ibuf->name, 1.0 / swaptime); + printf(" Name: %s | Speed: %.2f frames/s\n", ibuf->name, fstep / swaptime); } else { - swaptime = 1.0 / 5.0; + swaptime = fstep / 5.0; } } break; @@ -688,34 +695,34 @@ void playanim(int argc, char **argv) } break; case PAD1: - swaptime = 1.0 / 60.0; + swaptime = fstep / 60.0; break; case PAD2: - swaptime = 1.0 / 50.0; + swaptime = fstep / 50.0; break; case PAD3: - swaptime = 1.0 / 30.0; + swaptime = fstep / 30.0; break; case PAD4: if (qualN & SHIFT) - swaptime = 1.0 / 24.0; + swaptime = fstep / 24.0; else - swaptime = 1.0 / 25.0; + swaptime = fstep / 25.0; break; case PAD5: - swaptime = 1.0 / 20.0; + swaptime = fstep / 20.0; break; case PAD6: - swaptime = 1.0 / 15.0; + swaptime = fstep / 15.0; break; case PAD7: - swaptime = 1.0 / 12.0; + swaptime = fstep / 12.0; break; case PAD8: - swaptime = 1.0 / 10.0; + swaptime = fstep / 10.0; break; case PAD9: - swaptime = 1.0 / 6.0; + swaptime = fstep / 6.0; break; case PADPLUSKEY: if (val == 0) break; diff --git a/source/blender/src/seqeffects.c b/source/blender/src/seqeffects.c index 58554fbfeba..6b25499fe6b 100644 --- a/source/blender/src/seqeffects.c +++ b/source/blender/src/seqeffects.c @@ -924,18 +924,18 @@ static void free_gammacross(Sequence * seq) static void do_gammacross_effect_byte(float facf0, float facf1, int x, int y, - char *rect1, - char *rect2, - char *out) + unsigned char *rect1, + unsigned char *rect2, + unsigned char *out) { int fac1, fac2, col; int xo; - char *rt1, *rt2, *rt; + unsigned char *rt1, *rt2, *rt; xo= x; - rt1= (char *)rect1; - rt2= (char *)rect2; - rt= (char *)out; + rt1= (unsigned char *)rect1; + rt2= (unsigned char *)rect2; + rt= (unsigned char *)out; fac2= (int)(256.0*facf0); fac1= 256-fac2; @@ -1994,6 +1994,9 @@ static void do_transform(Sequence * seq,float facf0, int x, int y, float xs,ys,factxScale,factyScale,tx,ty,rad,s,c,xaux,yaux,factRot,px,py; TransformVars *scale; + struct RenderData *rd = &G.scene->r; + + scale = (TransformVars *)seq->effectdata; xo = x; yo = y; @@ -2004,8 +2007,10 @@ static void do_transform(Sequence * seq,float facf0, int x, int y, //Factor translate if(!scale->percent){ - tx = scale->xIni+(xo / 2.0f) + (scale->xFin-(xo / 2.0f) - scale->xIni+(xo / 2.0f)) * facf0; - ty = scale->yIni+(yo / 2.0f) + (scale->yFin-(yo / 2.0f) - scale->yIni+(yo / 2.0f)) * facf0; + float rd_s = (rd->size / 100.0f); + + tx = scale->xIni * rd_s+(xo / 2.0f) + (scale->xFin * rd_s -(xo / 2.0f) - scale->xIni * rd_s +(xo / 2.0f)) * facf0; + ty = scale->yIni * rd_s+(yo / 2.0f) + (scale->yFin * rd_s -(yo / 2.0f) - scale->yIni * rd_s +(yo / 2.0f)) * facf0; }else{ tx = xo*(scale->xIni/100.0f)+(xo / 2.0f) + (xo*(scale->xFin/100.0f)-(xo / 2.0f) - xo*(scale->xIni/100.0f)+(xo / 2.0f)) * facf0; ty = yo*(scale->yIni/100.0f)+(yo / 2.0f) + (yo*(scale->yFin/100.0f)-(yo / 2.0f) - yo*(scale->yIni/100.0f)+(yo / 2.0f)) * facf0; @@ -2017,6 +2022,7 @@ static void do_transform(Sequence * seq,float facf0, int x, int y, s= sin(rad); c= cos(rad); + for (yi = 0; yi < yo; yi++) { for (xi = 0; xi < xo; xi++) { //tranlate point diff --git a/source/blender/src/sequence.c b/source/blender/src/sequence.c index 219768b2776..3c3c7c7b30a 100644 --- a/source/blender/src/sequence.c +++ b/source/blender/src/sequence.c @@ -2111,6 +2111,14 @@ static TStripElem* do_build_seq_recursively(Sequence * seq, int cfra) } } +/* Bug: 18209 + * when dragging the mouse over a metastrip, on mouse-up for some unknown + * reason in some cases the metastrips TStripElem->ibuf->rect is NULL, + * This should be fixed but I had a look and couldnt work out why its + * happening so for now workaround with a NULL check - campbell */ + +#define SEQ_SPECIAL_SEQ_UPDATE_WORKAROUND + static TStripElem* do_build_seq_array_recursively( ListBase *seqbasep, int cfra, int chanshown) { @@ -2277,7 +2285,14 @@ static TStripElem* do_build_seq_array_recursively( !se2->ibuf_comp->rect_float) { IMB_rect_from_float(se2->ibuf); } - + +#ifdef SEQ_SPECIAL_SEQ_UPDATE_WORKAROUND + if (se2->ibuf->rect==NULL && se2->ibuf->rect_float==NULL) { + printf("ERROR: sequencer se2->ibuf missing buffer\n"); + } else if (se1->ibuf->rect==NULL && se1->ibuf->rect_float==NULL) { + printf("ERROR: sequencer se1->ibuf missing buffer\n"); + } else { +#endif /* bad hack, to fix crazy input ordering of those two effects */ @@ -2299,6 +2314,10 @@ static TStripElem* do_build_seq_array_recursively( se2->ibuf_comp); } +#ifdef SEQ_SPECIAL_SEQ_UPDATE_WORKAROUND + } +#endif + IMB_cache_limiter_insert(se2->ibuf_comp); IMB_cache_limiter_ref(se2->ibuf_comp); IMB_cache_limiter_touch(se2->ibuf_comp); diff --git a/source/blender/src/space.c b/source/blender/src/space.c index ede33374ac8..c6510b780d8 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -426,6 +426,9 @@ void space_set_commmandline_options(void) { a= (G.fileflags & G_FILE_GAME_TO_IPO); SYS_WriteCommandLineInt(syshandle, "game2ipo", a); + a= (G.fileflags & G_FILE_IGNORE_DEPRECATION_WARNINGS); + SYS_WriteCommandLineInt(syshandle, "ignore_deprecation_warnings", a); + a=(G.fileflags & G_FILE_GAME_MAT); SYS_WriteCommandLineInt(syshandle, "blender_material", a); a=(G.fileflags & G_FILE_GAME_MAT_GLSL); @@ -1249,18 +1252,19 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) if( uiDoBlocks(&curarea->uiblocks, event, 1)!=UI_NOTHING ) event= 0; if(event==UI_BUT_EVENT) do_butspace(val); /* temporal, view3d deserves own queue? */ - + +#ifndef DISABLE_PYTHON + /* run any view3d event handler script links */ + if(sa->scriptlink.totscript) { + if(BPY_do_spacehandlers(sa, event, val, SPACEHANDLER_VIEW3D_EVENT)) + return; /* return if event was processed (swallowed) by handler(s) */ + } +#endif + /* - we consider manipulator a button, defaulting to leftmouse * - grease-pencil also defaults to leftmouse */ if(event==LEFTMOUSE) { -#ifndef DISABLE_PYTHON - /* run any view3d event handler script links */ - if (sa->scriptlink.totscript) { - if (BPY_do_spacehandlers(sa, event, val, SPACEHANDLER_VIEW3D_EVENT)) - return; /* return if event was processed (swallowed) by handler(s) */ - } -#endif if(BIF_paintSketch(LEFTMOUSE)) return; if(gpencil_do_paint(sa, L_MOUSE)) return; if(BIF_do_manipulator(sa)) return; @@ -1310,6 +1314,13 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) } } } + else if (!G.obedit && OBACT && G.f&G_TEXTUREPAINT){ + if(G.scene->toolsettings->imapaint.brush && + event!=LEFTMOUSE && event!=RIGHTMOUSE && event!=MIDDLEMOUSE && + (event==MOUSEY || event==MOUSEX) && bwin_qtest(sa->win)==0) { + allqueue(REDRAWVIEW3D, 0); + } + } BDR_queueDrawSketch(); @@ -1320,13 +1331,6 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) } } -#ifndef DISABLE_PYTHON - /* run any view3d event handler script links */ - if (event && sa->scriptlink.totscript) - if (BPY_do_spacehandlers(sa, event, val, SPACEHANDLER_VIEW3D_EVENT)) - return; /* return if event was processed (swallowed) by handler(s) */ -#endif - /* TEXTEDITING?? */ if((G.obedit) && G.obedit->type==OB_FONT) { switch(event) { @@ -2981,7 +2985,17 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) } } } - + +#ifndef DISABLE_PYTHON + else { /* val= 0 */ + /* run any view3d release event handler script links */ + if(sa->scriptlink.totscript) { + if(BPY_do_spacehandlers(sa, event, 0, SPACEHANDLER_VIEW3D_EVENT_ALL)) + return; /* return if event was processed (swallowed) by handler(s) */ + } + } +#endif + if(doredraw) { scrarea_queue_winredraw(curarea); scrarea_queue_headredraw(curarea); diff --git a/source/blender/src/transform.c b/source/blender/src/transform.c index 7a13943d0e0..a1abc5ea6bb 100644 --- a/source/blender/src/transform.c +++ b/source/blender/src/transform.c @@ -737,6 +737,7 @@ static void transformEvent(unsigned short event, short val) { case GKEY: /* only switch when... */ if( ELEM3(Trans.mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL) ) { + resetTransRestrictions(&Trans); restoreTransObjects(&Trans); initTranslation(&Trans); Trans.redraw = 1; @@ -745,6 +746,7 @@ static void transformEvent(unsigned short event, short val) { case SKEY: /* only switch when... */ if( ELEM3(Trans.mode, TFM_ROTATION, TFM_TRANSLATION, TFM_TRACKBALL) ) { + resetTransRestrictions(&Trans); restoreTransObjects(&Trans); initResize(&Trans); Trans.redraw = 1; @@ -752,7 +754,9 @@ static void transformEvent(unsigned short event, short val) { break; case RKEY: /* only switch when... */ - if( ELEM4(Trans.mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_TRANSLATION) ) { + if( ELEM4(Trans.mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_TRANSLATION) ) { + + resetTransRestrictions(&Trans); if (Trans.mode == TFM_ROTATION) { restoreTransObjects(&Trans); diff --git a/source/blender/src/transform_constraints.c b/source/blender/src/transform_constraints.c index 796b013cb88..438066fcfe2 100644 --- a/source/blender/src/transform_constraints.c +++ b/source/blender/src/transform_constraints.c @@ -685,6 +685,8 @@ void BIF_drawConstraint(void) return; if (t->flag & T_USES_MANIPULATOR) return; + if (t->flag & T_NO_CONSTRAINT) + return; /* nasty exception for Z constraint in camera view */ if((t->flag & T_OBJECT) && G.vd->camera==OBACT && G.vd->persp==V3D_CAMOB) diff --git a/source/blender/src/transform_conversions.c b/source/blender/src/transform_conversions.c index f58eaefc628..dadeb71f73e 100644 --- a/source/blender/src/transform_conversions.c +++ b/source/blender/src/transform_conversions.c @@ -780,7 +780,7 @@ static void pose_grab_with_ik_clear(Object *ob) { bKinematicConstraint *data; bPoseChannel *pchan; - bConstraint *con; + bConstraint *con, *next; for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { /* clear all temporary lock flags */ @@ -788,7 +788,8 @@ static void pose_grab_with_ik_clear(Object *ob) pchan->constflag &= ~(PCHAN_HAS_IK|PCHAN_HAS_TARGET); /* remove all temporary IK-constraints added */ - for (con= pchan->constraints.first; con; con= con->next) { + for (con= pchan->constraints.first; con; con= next) { + next= con->next; if (con->type==CONSTRAINT_TYPE_KINEMATIC) { data= con->data; if (data->flag & CONSTRAINT_IK_TEMP) { diff --git a/source/blender/src/transform_generics.c b/source/blender/src/transform_generics.c index 229889d15ff..f2e90818f9d 100644 --- a/source/blender/src/transform_generics.c +++ b/source/blender/src/transform_generics.c @@ -649,6 +649,11 @@ void drawLine(float *center, float *dir, char axis, short options) myloadmatrix(G.vd->viewmat); } +void resetTransRestrictions(TransInfo *t) +{ + t->flag &= ~T_ALL_RESTRICTIONS; +} + void initTrans (TransInfo *t) { diff --git a/source/blender/src/transform_snap.c b/source/blender/src/transform_snap.c index e7937e72c2b..eeb5eaeec10 100644 --- a/source/blender/src/transform_snap.c +++ b/source/blender/src/transform_snap.c @@ -1186,10 +1186,21 @@ int snapObjects(int *dist, float *loc, float *no, int mode) { Object *ob = dupli_ob->ob; if (ob->type == OB_MESH) { - DerivedMesh *dm = mesh_get_derived_final(ob, CD_MASK_BAREMESH); + DerivedMesh *dm; + int editmesh = 0; int val; - val = snapDerivedMesh(ob, dm, dupli_ob->mat, ray_start, ray_normal, mval, loc, no, dist, &depth, 0); + if (ob == G.obedit) + { + dm = editmesh_get_derived_cage(CD_MASK_BAREMESH); + editmesh = 1; + } + else + { + dm = mesh_get_derived_final(ob, CD_MASK_BAREMESH); + } + + val = snapDerivedMesh(ob, dm, dupli_ob->mat, ray_start, ray_normal, mval, loc, no, dist, &depth, editmesh); retval = retval || val; diff --git a/source/blender/src/usiblender.c b/source/blender/src/usiblender.c index e3f153a64b6..da331ea2df2 100644 --- a/source/blender/src/usiblender.c +++ b/source/blender/src/usiblender.c @@ -668,6 +668,12 @@ int BIF_read_homefile(int from_memory) success = BKE_read_file_from_memory(datatoc_B_blend, datatoc_B_blend_size, NULL); /* outliner patch for 2.42 .b.blend */ outliner_242_patch(); + + /* When loading factory settings, the reset solid OpenGL lights need to be applied. */ + U.light[0].flag=0; + U.light[1].flag=0; + U.light[2].flag=0; + GPU_default_lights(); } BLI_clean(scestr); diff --git a/source/blender/src/view.c b/source/blender/src/view.c index 0908a75c6a3..768bc715aca 100644 --- a/source/blender/src/view.c +++ b/source/blender/src/view.c @@ -798,12 +798,15 @@ void viewmoveNDOFfly(int mode) BIF_view3d_previewrender_signal(curarea, PR_DBASE|PR_DISPRECT); } -int view_autodist( float mouse_worldloc[3] ) //, float *autodist ) +/* Be sure to run persp(PERSP_VIEW) if this isnt set, + * + * mouse_worldloc - worldspace vector that is set + * mval - screenspace location, or from getmouseco_areawin(mval) + * dist - the size of the square to use when averaging the Z depth. + */ +int view_mouse_depth( float mouse_worldloc[3], short mval[2], int dist) { View3D *v3d = G.vd; - - /* Zooms in on a border drawn by the user */ - short mval[2]; rcti rect; /* ZBuffer depth vars */ @@ -815,13 +818,13 @@ int view_autodist( float mouse_worldloc[3] ) //, float *autodist ) getmouseco_areawin(mval); - persp(PERSP_VIEW); + /* persp(PERSP_VIEW); */ - rect.xmax = mval[0] + 4; - rect.ymax = mval[1] + 4; + rect.xmax = mval[0] + dist; + rect.ymax = mval[1] + dist; - rect.xmin = mval[0] - 4; - rect.ymin = mval[1] - 4; + rect.xmin = mval[0] - dist; + rect.ymin = mval[1] - dist; /* Get Z Depths, needed for perspective, nice for ortho */ bgl_get_mats(&mats); @@ -945,7 +948,8 @@ void viewmove(int mode) VecMulf(obofs, -1.0f); } else if (U.uiflag & USER_ORBIT_ZBUF) { - if ((use_sel=view_autodist(obofs))) { + persp(PERSP_VIEW); + if ((use_sel=view_mouse_depth(obofs, mval_area, 4))) { if (G.vd->persp==V3D_PERSP) { float my_origin[3]; /* original G.vd->ofs */ float my_pivot[3]; /* view */ @@ -976,6 +980,8 @@ void viewmove(int mode) } else { ofs[0] = ofs[1] = ofs[2] = 0.0f; } + + persp(PERSP_WIN); } else ofs[0] = ofs[1] = ofs[2] = 0.0f; @@ -1575,6 +1581,28 @@ void object_view_settings(Object *ob, float *lens, float *clipsta, float *clipen } } +int get_view3d_ortho(View3D *v3d) +{ + Camera *cam; + + if(v3d->persp==V3D_CAMOB) { + if(v3d->camera && v3d->camera->type==OB_CAMERA) { + cam= v3d->camera->data; + + if(cam && cam->type==CAM_ORTHO) + return 1; + else + return 0; + } + else + return 0; + } + + if(v3d->persp==V3D_ORTHO) + return 1; + + return 0; +} int get_view3d_viewplane(int winxi, int winyi, rctf *viewplane, float *clipsta, float *clipend, float *pixsize) { diff --git a/source/blender/src/writeimage.c b/source/blender/src/writeimage.c index b21c14bed35..a611353026e 100644 --- a/source/blender/src/writeimage.c +++ b/source/blender/src/writeimage.c @@ -190,6 +190,11 @@ void save_image_filesel_str(char *str) case R_MULTILAYER: strcpy(str, "Save Multi Layer EXR"); break; +#ifdef WITH_OPENJPEG + case R_JP2: + strcpy(str, "Save JPEG2000"); + break; +#endif /* default we save jpeg, also for all movie formats */ case R_JPEG90: case R_MOVIE: diff --git a/source/creator/creator.c b/source/creator/creator.c index 872a5f4d497..5c0ca9e07ff 100644 --- a/source/creator/creator.c +++ b/source/creator/creator.c @@ -29,6 +29,13 @@ #include <stdlib.h> #include <string.h> + +/* for setuid / getuid */ +#ifdef __sgi +#include <sys/types.h> +#include <unistd.h> +#endif + /* This little block needed for linking to Blender... */ #include "MEM_guardedalloc.h" @@ -201,7 +208,7 @@ static void print_help(void) printf (" -t <threads>\tUse amount of <threads> for rendering (background mode only).\n"); printf (" [1-8], 0 for systems processor count.\n"); printf ("\nAnimation playback options:\n"); - printf (" -a <file(s)>\tPlayback <file(s)>, only operates this way when -b is not used.\n"); + printf (" -a <options> <file(s)>\tPlayback <file(s)>, only operates this way when -b is not used.\n"); printf (" -p <sx> <sy>\tOpen with lower left corner at <sx>, <sy>\n"); printf (" -m\t\tRead from disk (Don't buffer)\n"); printf (" -f <fps> <fps-base>\t\tSpecify FPS to start with\n"); @@ -769,6 +776,9 @@ int main(int argc, char **argv) else if (!strcmp(argv[a],"FRAMESERVER")) G.scene->r.imtype = R_FRAMESERVER; else if (!strcmp(argv[a],"CINEON")) G.scene->r.imtype = R_CINEON; else if (!strcmp(argv[a],"DPX")) G.scene->r.imtype = R_DPX; +#if WITH_OPENJPEG + else if (!strcmp(argv[a],"JP2")) G.scene->r.imtype = R_JP2; +#endif else printf("\nError: Format from '-F' not known or not compiled in this release.\n"); } } else { @@ -778,10 +788,14 @@ int main(int argc, char **argv) case 't': a++; - if(G.background) { - RE_set_max_threads(atoi(argv[a])); + if (a < argc) { + if(G.background) { + RE_set_max_threads(atoi(argv[a])); + } else { + printf("Warning: threads can only be set in background mode\n"); + } } else { - printf("Warning: threads can only be set in background mode\n"); + printf("\nError: you must specify a number of threads between 0 and 8 '-t '.\n"); } break; case 'x': /* extension */ diff --git a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp index 4410763ec53..67bec97ea32 100644 --- a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp +++ b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp @@ -81,6 +81,7 @@ /***/ #include "GPU_extensions.h" +#include "Value.h" #ifdef __cplusplus extern "C" { @@ -139,6 +140,7 @@ extern "C" void StartKetsjiShell(struct ScrArea *area, bool frameRate = (SYS_GetCommandLineInt(syshandle, "show_framerate", 0) != 0); bool game2ipo = (SYS_GetCommandLineInt(syshandle, "game2ipo", 0) != 0); bool displaylists = (SYS_GetCommandLineInt(syshandle, "displaylists", 0) != 0); + bool nodepwarnings = (SYS_GetCommandLineInt(syshandle, "ignore_deprecation_warnings", 0) != 0); // create the canvas, rasterizer and rendertools RAS_ICanvas* canvas = new KX_BlenderCanvas(area); @@ -195,6 +197,8 @@ extern "C" void StartKetsjiShell(struct ScrArea *area, ketsjiengine->SetUseFixedTime(usefixed); ketsjiengine->SetTimingDisplay(frameRate, profile, properties); + CValue::SetDeprecationWarnings(nodepwarnings); + //lock frame and camera enabled - storing global values int tmp_lay= G.scene->lay; @@ -364,7 +368,9 @@ extern "C" void StartKetsjiShell(struct ScrArea *area, initGameKeys(); initPythonConstraintBinding(); initMathutils(); +#ifdef WITH_FFMPEG initVideoTexture(); +#endif if (sceneconverter) { @@ -656,7 +662,9 @@ extern "C" void StartKetsjiShellSimulation(struct ScrArea *area, initGameKeys(); initPythonConstraintBinding(); initMathutils(); - initVideoTexture(); +#ifdef WITH_FFMPEG + initVideoTexture(); +#endif if (sceneconverter) { diff --git a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp index 1797d6c1a0f..42ad7769cbd 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp +++ b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp @@ -80,7 +80,7 @@ void KX_BlenderRenderTools::EndFrame(RAS_IRasterizer* rasty) * has a maximum of 8 lights (simultaneous), so 20 * 8 lights are possible in * a scene. */ -void KX_BlenderRenderTools::ProcessLighting(int layer, const MT_Transform& viewmat) +void KX_BlenderRenderTools::ProcessLighting(RAS_IRasterizer *rasty, int layer, const MT_Transform& viewmat) { if(m_lastlightlayer == layer) return; @@ -101,12 +101,12 @@ void KX_BlenderRenderTools::ProcessLighting(int layer, const MT_Transform& viewm } if(enable) - EnableOpenGLLights(); + EnableOpenGLLights(rasty); else DisableOpenGLLights(); } -void KX_BlenderRenderTools::EnableOpenGLLights() +void KX_BlenderRenderTools::EnableOpenGLLights(RAS_IRasterizer *rasty) { if(m_lastlighting == true) return; @@ -115,7 +115,8 @@ void KX_BlenderRenderTools::EnableOpenGLLights() glEnable(GL_COLOR_MATERIAL); glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); - glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, true); + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); + glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, (rasty->GetCameraOrtho())? GL_FALSE: GL_TRUE); if (GLEW_EXT_separate_specular_color || GLEW_VERSION_1_2) glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); diff --git a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h index a7618462c9b..ebf7562503f 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h +++ b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h @@ -60,9 +60,9 @@ public: void EndFrame(RAS_IRasterizer* rasty); void BeginFrame(RAS_IRasterizer* rasty); - void EnableOpenGLLights(); + void EnableOpenGLLights(RAS_IRasterizer *rasty); void DisableOpenGLLights(); - void ProcessLighting(int layer, const MT_Transform& viewmat); + void ProcessLighting(RAS_IRasterizer *rasty, int layer, const MT_Transform& viewmat); void RenderText2D(RAS_TEXT_RENDER_MODE mode, const char* text, diff --git a/source/gameengine/BlenderRoutines/Makefile b/source/gameengine/BlenderRoutines/Makefile index 4b9a2a3af17..c2f19ae1d8a 100644 --- a/source/gameengine/BlenderRoutines/Makefile +++ b/source/gameengine/BlenderRoutines/Makefile @@ -35,6 +35,7 @@ include nan_compile.mk CCFLAGS += $(LEVEL_1_CPP_WARNINGS) +CPPFLAGS += -I$(NAN_GLEW)/include CPPFLAGS += -I$(NAN_SUMO)/include -I$(NAN_SOLID)/include CPPFLAGS += -I$(NAN_SOLID) CPPFLAGS += -I$(NAN_STRING)/include diff --git a/source/gameengine/BlenderRoutines/SConscript b/source/gameengine/BlenderRoutines/SConscript index 78adbc83d9b..7a1bf4d9ad6 100644 --- a/source/gameengine/BlenderRoutines/SConscript +++ b/source/gameengine/BlenderRoutines/SConscript @@ -25,5 +25,6 @@ incs += ' ' + env['BF_OPENGL_INC'] cxxflags = [] if env['OURPLATFORM']=='win32-vc': cxxflags.append ('/GR') + cxxflags.append ('/O2') -env.BlenderLib ( 'bf_bloutines', sources, Split(incs), [], libtype=['game', 'game2', 'player'], priority=[0, 0, 55] , compileflags=cxxflags) +env.BlenderLib ( 'bf_bloutines', sources, Split(incs), [], libtype=['game', 'game2', 'player'], priority=[0, 0, 55] , cxx_compileflags=cxxflags) diff --git a/source/gameengine/Converter/BL_ActionActuator.cpp b/source/gameengine/Converter/BL_ActionActuator.cpp index 4d748948c27..22c6c95b158 100644 --- a/source/gameengine/Converter/BL_ActionActuator.cpp +++ b/source/gameengine/Converter/BL_ActionActuator.cpp @@ -39,10 +39,9 @@ #include "BL_SkinDeformer.h" #include "KX_GameObject.h" #include "STR_HashedString.h" -#include "DNA_action_types.h" #include "DNA_nla_types.h" -#include "DNA_actuator_types.h" #include "BKE_action.h" +#include "DNA_action_types.h" #include "DNA_armature_types.h" #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" @@ -51,6 +50,7 @@ #include "BKE_utildefines.h" #include "FloatValue.h" #include "PyObjectPlus.h" +#include "blendef.h" #ifdef HAVE_CONFIG_H #include <config.h> @@ -418,67 +418,6 @@ bool BL_ActionActuator::Update(double curtime, bool frame) /* Python functions */ /* ------------------------------------------------------------------------- */ -/* Integration hooks ------------------------------------------------------- */ - -PyTypeObject BL_ActionActuator::Type = { - PyObject_HEAD_INIT(&PyType_Type) - 0, - "BL_ActionActuator", - sizeof(BL_ActionActuator), - 0, - PyDestructor, - 0, - __getattr, - __setattr, - 0, //&MyPyCompare, - __repr, - 0, //&cvalue_as_number, - 0, - 0, - 0, - 0 -}; - -PyParentObject BL_ActionActuator::Parents[] = { - &BL_ActionActuator::Type, - &SCA_IActuator::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL -}; - -PyMethodDef BL_ActionActuator::Methods[] = { - {"setAction", (PyCFunction) BL_ActionActuator::sPySetAction, METH_VARARGS, (PY_METHODCHAR)SetAction_doc}, - {"setStart", (PyCFunction) BL_ActionActuator::sPySetStart, METH_VARARGS, (PY_METHODCHAR)SetStart_doc}, - {"setEnd", (PyCFunction) BL_ActionActuator::sPySetEnd, METH_VARARGS, (PY_METHODCHAR)SetEnd_doc}, - {"setBlendin", (PyCFunction) BL_ActionActuator::sPySetBlendin, METH_VARARGS, (PY_METHODCHAR)SetBlendin_doc}, - {"setPriority", (PyCFunction) BL_ActionActuator::sPySetPriority, METH_VARARGS, (PY_METHODCHAR)SetPriority_doc}, - {"setFrame", (PyCFunction) BL_ActionActuator::sPySetFrame, METH_VARARGS, (PY_METHODCHAR)SetFrame_doc}, - {"setProperty", (PyCFunction) BL_ActionActuator::sPySetProperty, METH_VARARGS, (PY_METHODCHAR)SetProperty_doc}, - {"setFrameProperty", (PyCFunction) BL_ActionActuator::sPySetFrameProperty, METH_VARARGS, (PY_METHODCHAR)SetFrameProperty_doc}, - {"setBlendtime", (PyCFunction) BL_ActionActuator::sPySetBlendtime, METH_VARARGS, (PY_METHODCHAR)SetBlendtime_doc}, - - {"getAction", (PyCFunction) BL_ActionActuator::sPyGetAction, METH_VARARGS, (PY_METHODCHAR)GetAction_doc}, - {"getStart", (PyCFunction) BL_ActionActuator::sPyGetStart, METH_VARARGS, (PY_METHODCHAR)GetStart_doc}, - {"getEnd", (PyCFunction) BL_ActionActuator::sPyGetEnd, METH_VARARGS, (PY_METHODCHAR)GetEnd_doc}, - {"getBlendin", (PyCFunction) BL_ActionActuator::sPyGetBlendin, METH_VARARGS, (PY_METHODCHAR)GetBlendin_doc}, - {"getPriority", (PyCFunction) BL_ActionActuator::sPyGetPriority, METH_VARARGS, (PY_METHODCHAR)GetPriority_doc}, - {"getFrame", (PyCFunction) BL_ActionActuator::sPyGetFrame, METH_VARARGS, (PY_METHODCHAR)GetFrame_doc}, - {"getProperty", (PyCFunction) BL_ActionActuator::sPyGetProperty, METH_VARARGS, (PY_METHODCHAR)GetProperty_doc}, - {"getFrameProperty", (PyCFunction) BL_ActionActuator::sPyGetFrameProperty, METH_VARARGS, (PY_METHODCHAR)GetFrameProperty_doc}, - {"setChannel", (PyCFunction) BL_ActionActuator::sPySetChannel, METH_VARARGS, (PY_METHODCHAR)SetChannel_doc}, -// {"getChannel", (PyCFunction) BL_ActionActuator::sPyGetChannel, METH_VARARGS}, - {"getType", (PyCFunction) BL_ActionActuator::sPyGetType, METH_VARARGS, (PY_METHODCHAR)GetType_doc}, - {"setType", (PyCFunction) BL_ActionActuator::sPySetType, METH_VARARGS, (PY_METHODCHAR)SetType_doc}, - {"getContinue", (PyCFunction) BL_ActionActuator::sPyGetContinue, METH_NOARGS, 0}, - {"setContinue", (PyCFunction) BL_ActionActuator::sPySetContinue, METH_O, 0}, - {NULL,NULL} //Sentinel -}; - -PyObject* BL_ActionActuator::_getattr(const STR_String& attr) { - _getattr_up(SCA_IActuator); -} - /* setStart */ const char BL_ActionActuator::GetAction_doc[] = "getAction()\n" @@ -487,6 +426,8 @@ const char BL_ActionActuator::GetAction_doc[] = PyObject* BL_ActionActuator::PyGetAction(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getAction()", "the action property"); + if (m_action){ return PyString_FromString(m_action->id.name+2); } @@ -501,6 +442,8 @@ const char BL_ActionActuator::GetProperty_doc[] = PyObject* BL_ActionActuator::PyGetProperty(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getProperty()", "the property property"); + PyObject *result; result = Py_BuildValue("s", (const char *)m_propname); @@ -516,6 +459,8 @@ const char BL_ActionActuator::GetFrameProperty_doc[] = PyObject* BL_ActionActuator::PyGetFrameProperty(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getFrameProperty()", "the frameProperty property"); + PyObject *result; result = Py_BuildValue("s", (const char *)m_framepropname); @@ -531,6 +476,8 @@ const char BL_ActionActuator::GetFrame_doc[] = PyObject* BL_ActionActuator::PyGetFrame(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getFrame()", "the frame property"); + PyObject *result; result = Py_BuildValue("f", m_localtime); @@ -546,6 +493,8 @@ const char BL_ActionActuator::GetEnd_doc[] = PyObject* BL_ActionActuator::PyGetEnd(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getEnd()", "the end property"); + PyObject *result; result = Py_BuildValue("f", m_endframe); @@ -561,6 +510,8 @@ const char BL_ActionActuator::GetStart_doc[] = PyObject* BL_ActionActuator::PyGetStart(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getStart()", "the start property"); + PyObject *result; result = Py_BuildValue("f", m_startframe); @@ -577,6 +528,8 @@ const char BL_ActionActuator::GetBlendin_doc[] = PyObject* BL_ActionActuator::PyGetBlendin(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getBlendin()", "the blendin property"); + PyObject *result; result = Py_BuildValue("f", m_blendin); @@ -593,6 +546,8 @@ const char BL_ActionActuator::GetPriority_doc[] = PyObject* BL_ActionActuator::PyGetPriority(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getPriority()", "the priority property"); + PyObject *result; result = Py_BuildValue("i", m_priority); @@ -613,6 +568,8 @@ const char BL_ActionActuator::SetAction_doc[] = PyObject* BL_ActionActuator::PySetAction(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setAction()", "the action property"); + char *string; int reset = 1; @@ -647,6 +604,8 @@ const char BL_ActionActuator::SetStart_doc[] = PyObject* BL_ActionActuator::PySetStart(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setStart()", "the start property"); + float start; if (PyArg_ParseTuple(args,"f",&start)) @@ -668,6 +627,8 @@ const char BL_ActionActuator::SetEnd_doc[] = PyObject* BL_ActionActuator::PySetEnd(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setEnd()", "the end property"); + float end; if (PyArg_ParseTuple(args,"f",&end)) @@ -690,6 +651,8 @@ const char BL_ActionActuator::SetBlendin_doc[] = PyObject* BL_ActionActuator::PySetBlendin(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setBlendin()", "the blendin property"); + float blendin; if (PyArg_ParseTuple(args,"f",&blendin)) @@ -713,6 +676,8 @@ const char BL_ActionActuator::SetBlendtime_doc[] = PyObject* BL_ActionActuator::PySetBlendtime(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setBlendtime()", "the blendtime property"); + float blendframe; if (PyArg_ParseTuple(args,"f",&blendframe)) @@ -740,6 +705,8 @@ const char BL_ActionActuator::SetPriority_doc[] = PyObject* BL_ActionActuator::PySetPriority(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setPriority()", "the priority property"); + int priority; if (PyArg_ParseTuple(args,"i",&priority)) @@ -761,6 +728,8 @@ const char BL_ActionActuator::SetFrame_doc[] = PyObject* BL_ActionActuator::PySetFrame(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setFrame()", "the frame property"); + float frame; if (PyArg_ParseTuple(args,"f",&frame)) @@ -787,6 +756,8 @@ const char BL_ActionActuator::SetProperty_doc[] = PyObject* BL_ActionActuator::PySetProperty(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setProperty()", "the property property"); + char *string; if (PyArg_ParseTuple(args,"s",&string)) @@ -808,6 +779,8 @@ const char BL_ActionActuator::SetFrameProperty_doc[] = PyObject* BL_ActionActuator::PySetFrameProperty(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setFrameProperty()", "the frameProperty property"); + char *string; if (PyArg_ParseTuple(args,"s",&string)) @@ -839,16 +812,80 @@ PyObject* BL_ActionActuator::PyGetChannel(PyObject* self, } */ -/* setChannel */ -const char BL_ActionActuator::SetChannel_doc[] = +/* getType */ +const char BL_ActionActuator::GetType_doc[] = +"getType()\n" +"\tReturns the operation mode of the actuator.\n"; +PyObject* BL_ActionActuator::PyGetType(PyObject* self, + PyObject* args, + PyObject* kwds) { + ShowDeprecationWarning("getType()", "the type property"); + + return Py_BuildValue("h", m_playtype); +} + +/* setType */ +const char BL_ActionActuator::SetType_doc[] = +"setType(mode)\n" +"\t - mode: Play (0), Flipper (2), LoopStop (3), LoopEnd (4) or Property (6)\n" +"\tSet the operation mode of the actuator.\n"; +PyObject* BL_ActionActuator::PySetType(PyObject* self, + PyObject* args, + PyObject* kwds) { + ShowDeprecationWarning("setType()", "the type property"); + + short typeArg; + + if (!PyArg_ParseTuple(args, "h", &typeArg)) { + return NULL; + } + + switch (typeArg) { + case ACT_ACTION_PLAY: + case ACT_ACTION_FLIPPER: + case ACT_ACTION_LOOP_STOP: + case ACT_ACTION_LOOP_END: + case ACT_ACTION_FROM_PROP: + m_playtype = typeArg; + break; + default: + printf("Invalid type for action actuator: %d\n", typeArg); /* error */ + } + Py_RETURN_NONE; +} + +PyObject* BL_ActionActuator::PyGetContinue(PyObject* self) { + ShowDeprecationWarning("getContinue()", "the continue property"); + + return PyInt_FromLong((long)(m_end_reset==0)); +} + +PyObject* BL_ActionActuator::PySetContinue(PyObject* self, PyObject* value) { + ShowDeprecationWarning("setContinue()", "the continue property"); + + int param = PyObject_IsTrue( value ); + + if( param == -1 ) { + PyErr_SetString( PyExc_TypeError, "expected True/False or 0/1" ); + return NULL; + } + + if (param) { + m_end_reset = 0; + } else { + m_end_reset = 1; + } + Py_RETURN_NONE; +} + +//<-----Deprecated + +/* setChannel */ +KX_PYMETHODDEF_DOC(BL_ActionActuator, setChannel, "setChannel(channel, matrix)\n" "\t - channel : A string specifying the name of the bone channel.\n" "\t - matrix : A 4x4 matrix specifying the overriding transformation\n" -"\t as an offset from the bone's rest position.\n"; - -PyObject* BL_ActionActuator::PySetChannel(PyObject* self, - PyObject* args, - PyObject* kwds) +"\t as an offset from the bone's rest position.\n") { float matrix[4][4]; char *string; @@ -923,61 +960,123 @@ PyObject* BL_ActionActuator::PySetChannel(PyObject* self, Py_RETURN_NONE; } -/* getType */ -const char BL_ActionActuator::GetType_doc[] = -"getType()\n" -"\tReturns the operation mode of the actuator.\n"; -PyObject* BL_ActionActuator::PyGetType(PyObject* self, - PyObject* args, - PyObject* kwds) { - return Py_BuildValue("h", m_playtype); -} +/* ------------------------------------------------------------------------- */ +/* Python Integration Hooks */ +/* ------------------------------------------------------------------------- */ -/* setType */ -const char BL_ActionActuator::SetType_doc[] = -"setType(mode)\n" -"\t - mode: Play (0), Flipper (2), LoopStop (3), LoopEnd (4) or Property (6)\n" -"\tSet the operation mode of the actuator.\n"; -PyObject* BL_ActionActuator::PySetType(PyObject* self, - PyObject* args, - PyObject* kwds) { - short typeArg; - - if (!PyArg_ParseTuple(args, "h", &typeArg)) { - return NULL; - } +PyTypeObject BL_ActionActuator::Type = { + PyObject_HEAD_INIT(&PyType_Type) + 0, + "BL_ActionActuator", + sizeof(BL_ActionActuator), + 0, + PyDestructor, + 0, + __getattr, + __setattr, + 0, //&MyPyCompare, + __repr, + 0, //&cvalue_as_number, + 0, + 0, + 0, + 0 +}; - switch (typeArg) { - case KX_ACT_ACTION_PLAY: - case KX_ACT_ACTION_FLIPPER: - case KX_ACT_ACTION_LOOPSTOP: - case KX_ACT_ACTION_LOOPEND: - case KX_ACT_ACTION_PROPERTY: - m_playtype = typeArg; - break; - default: - printf("Invalid type for action actuator: %d\n", typeArg); /* error */ - } - Py_RETURN_NONE; -} +PyParentObject BL_ActionActuator::Parents[] = { + &BL_ActionActuator::Type, + &SCA_IActuator::Type, + &SCA_ILogicBrick::Type, + &CValue::Type, + NULL +}; -PyObject* BL_ActionActuator::PyGetContinue(PyObject* self) { - return PyInt_FromLong((long)(m_end_reset==0)); -} +PyMethodDef BL_ActionActuator::Methods[] = { + //Deprecated -----> + {"setAction", (PyCFunction) BL_ActionActuator::sPySetAction, METH_VARARGS, (PY_METHODCHAR)SetAction_doc}, + {"setStart", (PyCFunction) BL_ActionActuator::sPySetStart, METH_VARARGS, (PY_METHODCHAR)SetStart_doc}, + {"setEnd", (PyCFunction) BL_ActionActuator::sPySetEnd, METH_VARARGS, (PY_METHODCHAR)SetEnd_doc}, + {"setBlendin", (PyCFunction) BL_ActionActuator::sPySetBlendin, METH_VARARGS, (PY_METHODCHAR)SetBlendin_doc}, + {"setPriority", (PyCFunction) BL_ActionActuator::sPySetPriority, METH_VARARGS, (PY_METHODCHAR)SetPriority_doc}, + {"setFrame", (PyCFunction) BL_ActionActuator::sPySetFrame, METH_VARARGS, (PY_METHODCHAR)SetFrame_doc}, + {"setProperty", (PyCFunction) BL_ActionActuator::sPySetProperty, METH_VARARGS, (PY_METHODCHAR)SetProperty_doc}, + {"setFrameProperty", (PyCFunction) BL_ActionActuator::sPySetFrameProperty, METH_VARARGS, (PY_METHODCHAR)SetFrameProperty_doc}, + {"setBlendtime", (PyCFunction) BL_ActionActuator::sPySetBlendtime, METH_VARARGS, (PY_METHODCHAR)SetBlendtime_doc}, -PyObject* BL_ActionActuator::PySetContinue(PyObject* self, PyObject* value) { - int param = PyObject_IsTrue( value ); - - if( param == -1 ) { - PyErr_SetString( PyExc_TypeError, "expected True/False or 0/1" ); - return NULL; - } + {"getAction", (PyCFunction) BL_ActionActuator::sPyGetAction, METH_VARARGS, (PY_METHODCHAR)GetAction_doc}, + {"getStart", (PyCFunction) BL_ActionActuator::sPyGetStart, METH_VARARGS, (PY_METHODCHAR)GetStart_doc}, + {"getEnd", (PyCFunction) BL_ActionActuator::sPyGetEnd, METH_VARARGS, (PY_METHODCHAR)GetEnd_doc}, + {"getBlendin", (PyCFunction) BL_ActionActuator::sPyGetBlendin, METH_VARARGS, (PY_METHODCHAR)GetBlendin_doc}, + {"getPriority", (PyCFunction) BL_ActionActuator::sPyGetPriority, METH_VARARGS, (PY_METHODCHAR)GetPriority_doc}, + {"getFrame", (PyCFunction) BL_ActionActuator::sPyGetFrame, METH_VARARGS, (PY_METHODCHAR)GetFrame_doc}, + {"getProperty", (PyCFunction) BL_ActionActuator::sPyGetProperty, METH_VARARGS, (PY_METHODCHAR)GetProperty_doc}, + {"getFrameProperty", (PyCFunction) BL_ActionActuator::sPyGetFrameProperty, METH_VARARGS, (PY_METHODCHAR)GetFrameProperty_doc}, +// {"getChannel", (PyCFunction) BL_ActionActuator::sPyGetChannel, METH_VARARGS}, + {"getType", (PyCFunction) BL_ActionActuator::sPyGetType, METH_VARARGS, (PY_METHODCHAR)GetType_doc}, + {"setType", (PyCFunction) BL_ActionActuator::sPySetType, METH_VARARGS, (PY_METHODCHAR)SetType_doc}, + {"getContinue", (PyCFunction) BL_ActionActuator::sPyGetContinue, METH_NOARGS, 0}, + {"setContinue", (PyCFunction) BL_ActionActuator::sPySetContinue, METH_O, 0}, + //<------ + KX_PYMETHODTABLE(BL_ActionActuator, setChannel), + {NULL,NULL} //Sentinel +}; - if (param) { - m_end_reset = 0; - } else { - m_end_reset = 1; - } - Py_RETURN_NONE; +PyAttributeDef BL_ActionActuator::Attributes[] = { + KX_PYATTRIBUTE_FLOAT_RW("start", 0, MAXFRAMEF, BL_ActionActuator, m_startframe), + KX_PYATTRIBUTE_FLOAT_RW("end", 0, MAXFRAMEF, BL_ActionActuator, m_endframe), + KX_PYATTRIBUTE_FLOAT_RW("blendin", 0, MAXFRAMEF, BL_ActionActuator, m_blendin), + KX_PYATTRIBUTE_SHORT_RW("priority", 0, 100, false, BL_ActionActuator, m_priority), + KX_PYATTRIBUTE_FLOAT_RW_CHECK("frame", 0, MAXFRAMEF, BL_ActionActuator, m_localtime, CheckFrame), + KX_PYATTRIBUTE_STRING_RW("property", 0, 31, false, BL_ActionActuator, m_propname), + KX_PYATTRIBUTE_STRING_RW("frameProperty", 0, 31, false, BL_ActionActuator, m_framepropname), + KX_PYATTRIBUTE_BOOL_RW("continue", BL_ActionActuator, m_end_reset), + KX_PYATTRIBUTE_FLOAT_RW_CHECK("blendTime", 0, MAXFRAMEF, BL_ActionActuator, m_blendframe, CheckBlendTime), + KX_PYATTRIBUTE_SHORT_RW_CHECK("type",0,100,false,BL_ActionActuator,m_playtype,CheckType), + { NULL } //Sentinel +}; + +PyObject* BL_ActionActuator::_getattr(const char *attr) { + if (!strcmp(attr, "action")) + return PyString_FromString(m_action->id.name+2); + PyObject* object = _getattr_self(Attributes, this, attr); + if (object != NULL) + return object; + _getattr_up(SCA_IActuator); } +int BL_ActionActuator::_setattr(const char *attr, PyObject* value) { + if (!strcmp(attr, "action")) + { + if (!PyString_Check(value)) + { + PyErr_SetString(PyExc_ValueError, "expected a string"); + return 1; + } + + STR_String val = PyString_AsString(value); + + if (val == "") + { + m_action = NULL; + return 0; + } + + bAction *action; + + action = (bAction*)SCA_ILogicBrick::m_sCurrentLogicManager->GetActionByName(val); + + + if (!action) + { + PyErr_SetString(PyExc_ValueError, "action not found!"); + return 1; + } + + m_action = action; + return 0; + } + int ret = _setattr_self(Attributes, this, attr, value); + if (ret >= 0) + return ret; + return SCA_IActuator::_setattr(attr, value); +}
\ No newline at end of file diff --git a/source/gameengine/Converter/BL_ActionActuator.h b/source/gameengine/Converter/BL_ActionActuator.h index a67b6d29b74..6161048afb8 100644 --- a/source/gameengine/Converter/BL_ActionActuator.h +++ b/source/gameengine/Converter/BL_ActionActuator.h @@ -32,6 +32,7 @@ #include "GEN_HashedPtr.h" #include "SCA_IActuator.h" +#include "DNA_actuator_types.h" #include "MT_Point3.h" class BL_ActionActuator : public SCA_IActuator @@ -81,6 +82,7 @@ public: void SetBlendTime (float newtime); + //Deprecated -----> KX_PYMETHOD_DOC(BL_ActionActuator,SetAction); KX_PYMETHOD_DOC(BL_ActionActuator,SetBlendin); KX_PYMETHOD_DOC(BL_ActionActuator,SetPriority); @@ -90,7 +92,6 @@ public: KX_PYMETHOD_DOC(BL_ActionActuator,SetProperty); KX_PYMETHOD_DOC(BL_ActionActuator,SetFrameProperty); KX_PYMETHOD_DOC(BL_ActionActuator,SetBlendtime); - KX_PYMETHOD_DOC(BL_ActionActuator,SetChannel); KX_PYMETHOD_DOC(BL_ActionActuator,GetAction); KX_PYMETHOD_DOC(BL_ActionActuator,GetBlendin); @@ -105,18 +106,53 @@ public: KX_PYMETHOD_DOC(BL_ActionActuator,SetType); KX_PYMETHOD_NOARGS(BL_ActionActuator,GetContinue); KX_PYMETHOD_O(BL_ActionActuator,SetContinue); + //<----- - virtual PyObject* _getattr(const STR_String& attr); + KX_PYMETHOD_DOC(BL_ActionActuator,setChannel); - enum ActionActType + virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject* value); + + /* attribute check */ + static int CheckFrame(void *self, const PyAttributeDef*) { - KX_ACT_ACTION_PLAY = 0, - KX_ACT_ACTION_FLIPPER = 2, - KX_ACT_ACTION_LOOPSTOP, - KX_ACT_ACTION_LOOPEND, - KX_ACT_ACTION_PROPERTY = 6 - }; + BL_ActionActuator* act = reinterpret_cast<BL_ActionActuator*>(self); + + if (act->m_localtime < act->m_startframe) + act->m_localtime = act->m_startframe; + else if (act->m_localtime > act->m_endframe) + act->m_localtime = act->m_endframe; + + return 0; + } + + static int CheckBlendTime(void *self, const PyAttributeDef*) + { + BL_ActionActuator* act = reinterpret_cast<BL_ActionActuator*>(self); + + if (act->m_blendframe > act->m_blendin) + act->m_blendframe = act->m_blendin; + + return 0; + } + + static int CheckType(void *self, const PyAttributeDef*) + { + BL_ActionActuator* act = reinterpret_cast<BL_ActionActuator*>(self); + + switch (act->m_playtype) { + case ACT_ACTION_PLAY: + case ACT_ACTION_FLIPPER: + case ACT_ACTION_LOOP_STOP: + case ACT_ACTION_LOOP_END: + case ACT_ACTION_FROM_PROP: + return 0; + default: + PyErr_SetString(PyExc_ValueError, "invalid type supplied"); + return 1; + } + } protected: void SetStartTime(float curtime); @@ -141,7 +177,7 @@ protected: float m_stridelength; short m_playtype; short m_priority; - short m_end_reset; + bool m_end_reset; struct bPose* m_pose; struct bPose* m_blendpose; struct bPose* m_userpose; diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index 9c699b67b28..2fa3e192179 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -361,7 +361,7 @@ BL_Material* ConvertMaterial( facetex = true; if(validface && mat->mtex[0]) { MTex *tmp = mat->mtex[0]; - if(!tmp->tex || tmp->tex && !tmp->tex->ima ) + if(!tmp->tex || (tmp->tex && !tmp->tex->ima)) facetex = true; } numchan = numchan>MAXTEX?MAXTEX:numchan; diff --git a/source/gameengine/Converter/BL_ShapeActionActuator.cpp b/source/gameengine/Converter/BL_ShapeActionActuator.cpp index 46f3141be29..2e02ee9b941 100644 --- a/source/gameengine/Converter/BL_ShapeActionActuator.cpp +++ b/source/gameengine/Converter/BL_ShapeActionActuator.cpp @@ -35,13 +35,11 @@ #include "SCA_LogicManager.h" #include "BL_ShapeActionActuator.h" -#include "BL_ActionActuator.h" #include "BL_ShapeDeformer.h" #include "KX_GameObject.h" #include "STR_HashedString.h" -#include "DNA_action_types.h" #include "DNA_nla_types.h" -#include "DNA_actuator_types.h" +#include "DNA_action_types.h" #include "BKE_action.h" #include "DNA_armature_types.h" #include "MEM_guardedalloc.h" @@ -51,6 +49,7 @@ #include "BKE_utildefines.h" #include "FloatValue.h" #include "PyObjectPlus.h" +#include "blendef.h" #ifdef HAVE_CONFIG_H #include <config.h> @@ -471,16 +470,73 @@ PyMethodDef BL_ShapeActionActuator::Methods[] = { {NULL,NULL} //Sentinel }; -PyObject* BL_ShapeActionActuator::_getattr(const STR_String& attr) { +PyAttributeDef BL_ShapeActionActuator::Attributes[] = { + KX_PYATTRIBUTE_FLOAT_RW("start", 0, MAXFRAMEF, BL_ShapeActionActuator, m_startframe), + KX_PYATTRIBUTE_FLOAT_RW("end", 0, MAXFRAMEF, BL_ShapeActionActuator, m_endframe), + KX_PYATTRIBUTE_FLOAT_RW("blendin", 0, MAXFRAMEF, BL_ShapeActionActuator, m_blendin), + KX_PYATTRIBUTE_SHORT_RW("priority", 0, 100, false, BL_ShapeActionActuator, m_priority), + KX_PYATTRIBUTE_FLOAT_RW_CHECK("frame", 0, MAXFRAMEF, BL_ShapeActionActuator, m_localtime, CheckFrame), + KX_PYATTRIBUTE_STRING_RW("property", 0, 31, false, BL_ShapeActionActuator, m_propname), + KX_PYATTRIBUTE_STRING_RW("frameProperty", 0, 31, false, BL_ShapeActionActuator, m_framepropname), + KX_PYATTRIBUTE_FLOAT_RW_CHECK("blendTime", 0, MAXFRAMEF, BL_ShapeActionActuator, m_blendframe, CheckBlendTime), + KX_PYATTRIBUTE_SHORT_RW_CHECK("type",0,100,false,BL_ShapeActionActuator,m_playtype,CheckType), + { NULL } //Sentinel +}; + + +PyObject* BL_ShapeActionActuator::_getattr(const char *attr) { + if (!strcmp(attr, "action")) + return PyString_FromString(m_action->id.name+2); + PyObject* object = _getattr_self(Attributes, this, attr); + if (object != NULL) + return object; _getattr_up(SCA_IActuator); } +int BL_ShapeActionActuator::_setattr(const char *attr, PyObject* value) { + if (!strcmp(attr, "action")) + { + if (!PyString_Check(value)) + { + PyErr_SetString(PyExc_ValueError, "expected a string"); + return 1; + } + + STR_String val = PyString_AsString(value); + + if (val == "") + { + m_action = NULL; + return 0; + } + + bAction *action; + + action = (bAction*)SCA_ILogicBrick::m_sCurrentLogicManager->GetActionByName(val); + + + if (!action) + { + PyErr_SetString(PyExc_ValueError, "action not found!"); + return 1; + } + + m_action = action; + return 0; + } + int ret = _setattr_self(Attributes, this, attr, value); + if (ret >= 0) + return ret; + return SCA_IActuator::_setattr(attr, value); +} + /* setStart */ const char BL_ShapeActionActuator::GetAction_doc[] = "getAction()\n" "\tReturns a string containing the name of the current action.\n"; PyObject* BL_ShapeActionActuator::PyGetAction(PyObject* self) { + ShowDeprecationWarning("getAction()", "the action property"); if (m_action){ return PyString_FromString(m_action->id.name+2); } @@ -493,6 +549,7 @@ const char BL_ShapeActionActuator::GetProperty_doc[] = "\tReturns the name of the property to be used in FromProp mode.\n"; PyObject* BL_ShapeActionActuator::PyGetProperty(PyObject* self) { + ShowDeprecationWarning("getProperty()", "the property property"); PyObject *result; result = Py_BuildValue("s", (const char *)m_propname); @@ -506,6 +563,7 @@ const char BL_ShapeActionActuator::GetFrame_doc[] = "\tReturns the current frame number.\n"; PyObject* BL_ShapeActionActuator::PyGetFrame(PyObject* self) { + ShowDeprecationWarning("getFrame()", "the frame property"); PyObject *result; result = Py_BuildValue("f", m_localtime); @@ -519,6 +577,7 @@ const char BL_ShapeActionActuator::GetEnd_doc[] = "\tReturns the last frame of the action.\n"; PyObject* BL_ShapeActionActuator::PyGetEnd(PyObject* self) { + ShowDeprecationWarning("getEnd()", "the end property"); PyObject *result; result = Py_BuildValue("f", m_endframe); @@ -532,6 +591,7 @@ const char BL_ShapeActionActuator::GetStart_doc[] = "\tReturns the starting frame of the action.\n"; PyObject* BL_ShapeActionActuator::PyGetStart(PyObject* self) { + ShowDeprecationWarning("getStart()", "the start property"); PyObject *result; result = Py_BuildValue("f", m_startframe); @@ -546,6 +606,7 @@ const char BL_ShapeActionActuator::GetBlendin_doc[] = "\tgenerated when this actuator is triggered.\n"; PyObject* BL_ShapeActionActuator::PyGetBlendin(PyObject* self) { + ShowDeprecationWarning("getBlendin()", "the blendin property"); PyObject *result; result = Py_BuildValue("f", m_blendin); @@ -560,6 +621,7 @@ const char BL_ShapeActionActuator::GetPriority_doc[] = "\tPriority numbers will override actuators with higher numbers.\n"; PyObject* BL_ShapeActionActuator::PyGetPriority(PyObject* self) { + ShowDeprecationWarning("getPriority()", "the priority property"); PyObject *result; result = Py_BuildValue("i", m_priority); @@ -581,6 +643,7 @@ const char BL_ShapeActionActuator::SetAction_doc[] = PyObject* BL_ShapeActionActuator::PySetAction(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setAction()", "the action property"); char *string; int reset = 1; @@ -615,6 +678,7 @@ const char BL_ShapeActionActuator::SetStart_doc[] = PyObject* BL_ShapeActionActuator::PySetStart(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setStart()", "the start property"); float start; if (PyArg_ParseTuple(args,"f",&start)) @@ -636,6 +700,7 @@ const char BL_ShapeActionActuator::SetEnd_doc[] = PyObject* BL_ShapeActionActuator::PySetEnd(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setEnd()", "the end property"); float end; if (PyArg_ParseTuple(args,"f",&end)) @@ -658,6 +723,7 @@ const char BL_ShapeActionActuator::SetBlendin_doc[] = PyObject* BL_ShapeActionActuator::PySetBlendin(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setBlendin()", "the blendin property"); float blendin; if (PyArg_ParseTuple(args,"f",&blendin)) @@ -681,6 +747,7 @@ const char BL_ShapeActionActuator::SetBlendtime_doc[] = PyObject* BL_ShapeActionActuator::PySetBlendtime(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setBlendtime()", "the blendTime property"); float blendframe; if (PyArg_ParseTuple(args,"f",&blendframe)) @@ -708,6 +775,7 @@ const char BL_ShapeActionActuator::SetPriority_doc[] = PyObject* BL_ShapeActionActuator::PySetPriority(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setPriority()", "the priority property"); int priority; if (PyArg_ParseTuple(args,"i",&priority)) @@ -727,6 +795,7 @@ const char BL_ShapeActionActuator::GetFrameProperty_doc[] = "\tReturns the name of the property, that is set to the current frame number.\n"; PyObject* BL_ShapeActionActuator::PyGetFrameProperty(PyObject* self) { + ShowDeprecationWarning("getFrameProperty()", "the frameProperty property"); PyObject *result; result = Py_BuildValue("s", (const char *)m_framepropname); @@ -743,6 +812,7 @@ const char BL_ShapeActionActuator::SetFrame_doc[] = PyObject* BL_ShapeActionActuator::PySetFrame(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setFrame()", "the frame property"); float frame; if (PyArg_ParseTuple(args,"f",&frame)) @@ -769,6 +839,7 @@ const char BL_ShapeActionActuator::SetProperty_doc[] = PyObject* BL_ShapeActionActuator::PySetProperty(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setProperty()", "the property property"); char *string; if (PyArg_ParseTuple(args,"s",&string)) @@ -790,6 +861,7 @@ const char BL_ShapeActionActuator::SetFrameProperty_doc[] = PyObject* BL_ShapeActionActuator::PySetFrameProperty(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setFrameProperty()", "the frameProperty property"); char *string; if (PyArg_ParseTuple(args,"s",&string)) @@ -808,6 +880,7 @@ const char BL_ShapeActionActuator::GetType_doc[] = "getType()\n" "\tReturns the operation mode of the actuator.\n"; PyObject* BL_ShapeActionActuator::PyGetType(PyObject* self) { + ShowDeprecationWarning("getType()", "the type property"); return Py_BuildValue("h", m_playtype); } @@ -819,6 +892,7 @@ const char BL_ShapeActionActuator::SetType_doc[] = PyObject* BL_ShapeActionActuator::PySetType(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setType()", "the type property"); short typeArg; if (!PyArg_ParseTuple(args, "h", &typeArg)) { @@ -837,6 +911,6 @@ PyObject* BL_ShapeActionActuator::PySetType(PyObject* self, printf("Invalid type for action actuator: %d\n", typeArg); /* error */ } - Py_Return; + Py_RETURN_NONE; } diff --git a/source/gameengine/Converter/BL_ShapeActionActuator.h b/source/gameengine/Converter/BL_ShapeActionActuator.h index 30b2d41fc67..7f2431bcfa5 100644 --- a/source/gameengine/Converter/BL_ShapeActionActuator.h +++ b/source/gameengine/Converter/BL_ShapeActionActuator.h @@ -32,6 +32,7 @@ #include "GEN_HashedPtr.h" #include "SCA_IActuator.h" +#include "BL_ActionActuator.h" #include "MT_Point3.h" #include <vector> @@ -102,7 +103,46 @@ public: KX_PYMETHOD_DOC_NOARGS(BL_ShapeActionActuator,GetType); KX_PYMETHOD_DOC(BL_ShapeActionActuator,SetType); - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject* value); + + static int CheckBlendTime(void *self, const PyAttributeDef*) + { + BL_ShapeActionActuator* act = reinterpret_cast<BL_ShapeActionActuator*>(self); + + if (act->m_blendframe > act->m_blendin) + act->m_blendframe = act->m_blendin; + + return 0; + } + static int CheckFrame(void *self, const PyAttributeDef*) + { + BL_ShapeActionActuator* act = reinterpret_cast<BL_ShapeActionActuator*>(self); + + if (act->m_localtime < act->m_startframe) + act->m_localtime = act->m_startframe; + else if (act->m_localtime > act->m_endframe) + act->m_localtime = act->m_endframe; + + return 0; + } + static int CheckType(void *self, const PyAttributeDef*) + { + BL_ShapeActionActuator* act = reinterpret_cast<BL_ShapeActionActuator*>(self); + + switch (act->m_playtype) { + case ACT_ACTION_PLAY: + case ACT_ACTION_FLIPPER: + case ACT_ACTION_LOOP_STOP: + case ACT_ACTION_LOOP_END: + case ACT_ACTION_FROM_PROP: + return 0; + default: + PyErr_SetString(PyExc_ValueError, "invalid type supplied"); + return 1; + } + + } protected: @@ -129,8 +169,8 @@ protected: short m_playtype; short m_priority; struct bAction *m_action; - STR_String m_propname; STR_String m_framepropname; + STR_String m_propname; vector<float> m_blendshape; }; diff --git a/source/gameengine/Converter/KX_ConvertActuators.cpp b/source/gameengine/Converter/KX_ConvertActuators.cpp index 4f152acc918..3a6122e6608 100644 --- a/source/gameengine/Converter/KX_ConvertActuators.cpp +++ b/source/gameengine/Converter/KX_ConvertActuators.cpp @@ -661,7 +661,8 @@ void BL_ConvertActuators(char* maggiename, { KX_SCA_DynamicActuator* tmpdynact = new KX_SCA_DynamicActuator(gameobj, - editobact->dyn_operation + editobact->dyn_operation, + editobact->mass ); baseact = tmpdynact; } diff --git a/source/gameengine/Expressions/InputParser.cpp b/source/gameengine/Expressions/InputParser.cpp index 32a9de32e21..a60e1ee59dc 100644 --- a/source/gameengine/Expressions/InputParser.cpp +++ b/source/gameengine/Expressions/InputParser.cpp @@ -38,6 +38,9 @@ // cool things like (IF(LOD==1,CCurvedValue,IF(LOD==2,CCurvedValue2)) etc... #include "IfExpr.h" +#if defined(WIN32) || defined(WIN64) +#define strcasecmp _stricmp +#endif /* Def WIN32 or Def WIN64 */ #define NUM_PRIORITY 6 ////////////////////////////////////////////////////////////////////// @@ -272,32 +275,29 @@ void CParser::NextSym() || ((ch >= 'A') && (ch <= 'Z'))) { // reserved word? int start; - STR_String funstr; start = chcount; CharRep(); GrabString(start); - funstr = const_as_string; - funstr.Upper(); - if (funstr == STR_String("SUM")) { + if (!strcasecmp(const_as_string, "SUM")) { sym = sumsym; } - else if (funstr == STR_String("NOT")) { + else if (!strcasecmp(const_as_string, "NOT")) { sym = opsym; opkind = OPnot; } - else if (funstr == STR_String("AND")) { + else if (!strcasecmp(const_as_string, "AND")) { sym = opsym; opkind = OPand; } - else if (funstr == STR_String("OR")) { + else if (!strcasecmp(const_as_string, "OR")) { sym = opsym; opkind = OPor; } - else if (funstr == STR_String("IF")) { + else if (!strcasecmp(const_as_string, "IF")) sym = ifsym; - } else if (funstr == STR_String("WHOMADE")) { + else if (!strcasecmp(const_as_string, "WHOMADE")) sym = whocodedsym; - } else if (funstr == STR_String("FALSE")) { + else if (!strcasecmp(const_as_string, "FALSE")) { sym = constsym; constkind = booltype; boolvalue = false; - } else if (funstr == STR_String("TRUE")) { + } else if (!strcasecmp(const_as_string, "TRUE")) { sym = constsym; constkind = booltype; boolvalue = true; } else { sym = idsym; diff --git a/source/gameengine/Expressions/ListValue.cpp b/source/gameengine/Expressions/ListValue.cpp index 9ffdbb1223c..9acc6ad2cde 100644 --- a/source/gameengine/Expressions/ListValue.cpp +++ b/source/gameengine/Expressions/ListValue.cpp @@ -34,7 +34,12 @@ Py_ssize_t listvalue_bufferlen(PyObject* list) PyObject* listvalue_buffer_item(PyObject* list,Py_ssize_t index) { - if (index >= 0 && index < ((CListValue*) list)->GetCount()) + int count = ((CListValue*) list)->GetCount(); + + if (index < 0) + index = count+index; + + if (index >= 0 && index < count) { PyObject* pyobj = ((CListValue*) list)->GetValue(index)->ConvertValueToPython(); if (pyobj) @@ -64,8 +69,7 @@ PyObject* listvalue_mapping_subscript(PyObject* list,PyObject* pyindex) } PyObject *pyindex_str = PyObject_Repr(pyindex); /* new ref */ - STR_String index_str(PyString_AsString(pyindex_str)); - PyErr_Format(PyExc_KeyError, "'%s' not in list", index_str.Ptr()); + PyErr_Format(PyExc_KeyError, "'%s' not in list", PyString_AsString(pyindex_str)); Py_DECREF(pyindex_str); return NULL; } @@ -220,17 +224,17 @@ PyParentObject CListValue::Parents[] = { PyMethodDef CListValue::Methods[] = { - {"append", (PyCFunction)CListValue::sPyappend,METH_VARARGS}, - {"reverse", (PyCFunction)CListValue::sPyreverse,METH_VARARGS}, - {"index", (PyCFunction)CListValue::sPyindex,METH_VARARGS}, - {"count", (PyCFunction)CListValue::sPycount,METH_VARARGS}, + {"append", (PyCFunction)CListValue::sPyappend,METH_O}, + {"reverse", (PyCFunction)CListValue::sPyreverse,METH_NOARGS}, + {"index", (PyCFunction)CListValue::sPyindex,METH_O}, + {"count", (PyCFunction)CListValue::sPycount,METH_O}, {NULL,NULL} //Sentinel }; -PyObject* CListValue::_getattr(const STR_String& attr) { +PyObject* CListValue::_getattr(const char *attr) { _getattr_up(CValue); } @@ -399,34 +403,17 @@ void CListValue::MergeList(CListValue *otherlist) -PyObject* CListValue::Pyappend(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* CListValue::Pyappend(PyObject* self, PyObject* value) { - - PyObject* pyobj = NULL; - if (PyArg_ParseTuple(args,"O",&pyobj)) - { - return listvalue_buffer_concat(self,pyobj); - } - else - { - return NULL; - } - - + return listvalue_buffer_concat(self, value); } -PyObject* CListValue::Pyreverse(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* CListValue::Pyreverse(PyObject* self) { std::reverse(m_pValueArray.begin(),m_pValueArray.end()); - - Py_Return; - + Py_RETURN_NONE; } @@ -448,58 +435,56 @@ bool CListValue::CheckEqual(CValue* first,CValue* second) -PyObject* CListValue::Pyindex(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* CListValue::Pyindex(PyObject* self, PyObject *value) { PyObject* result = NULL; - PyObject* pyobj = NULL; - if (PyArg_ParseTuple(args,"O",&pyobj)) + CValue* checkobj = ConvertPythonToValue(value); + if (checkobj==NULL) + return NULL; /* ConvertPythonToValue sets the error */ + + int numelem = GetCount(); + for (int i=0;i<numelem;i++) { - - CValue* checkobj = ConvertPythonToValue(pyobj); - int numelem = GetCount(); - for (int i=0;i<numelem;i++) + CValue* elem = GetValue(i); + if (CheckEqual(checkobj,elem)) { - CValue* elem = GetValue(i); - if (CheckEqual(checkobj,elem)) - { - result = PyInt_FromLong(i); - break; - } + result = PyInt_FromLong(i); + break; } - checkobj->Release(); } + checkobj->Release(); + if (result==NULL) { + PyErr_SetString(PyExc_ValueError, "ValueError: list.index(x): x not in CListValue"); + } return result; } -PyObject* CListValue::Pycount(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* CListValue::Pycount(PyObject* self, PyObject* value) { - int numfound = 0; - PyObject* pyobj = NULL; - if (PyArg_ParseTuple(args,"O",&pyobj)) + CValue* checkobj = ConvertPythonToValue(value); + + if (checkobj==NULL) { /* in this case just return that there are no items in the list */ + PyErr_Clear(); + PyInt_FromLong(0); + } + + int numelem = GetCount(); + for (int i=0;i<numelem;i++) { - CValue* checkobj = ConvertPythonToValue(pyobj); - int numelem = GetCount(); - for (int i=0;i<numelem;i++) + CValue* elem = GetValue(i); + if (CheckEqual(checkobj,elem)) { - CValue* elem = GetValue(i); - if (CheckEqual(checkobj,elem)) - { - numfound ++; - } + numfound ++; } - checkobj->Release(); } + checkobj->Release(); return PyInt_FromLong(numfound); } diff --git a/source/gameengine/Expressions/ListValue.h b/source/gameengine/Expressions/ListValue.h index 431f8f558a9..104e3e63283 100644 --- a/source/gameengine/Expressions/ListValue.h +++ b/source/gameengine/Expressions/ListValue.h @@ -59,12 +59,12 @@ public: bool CheckEqual(CValue* first,CValue* second); - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); - KX_PYMETHOD(CListValue,append); - KX_PYMETHOD(CListValue,reverse); - KX_PYMETHOD(CListValue,index); - KX_PYMETHOD(CListValue,count); + KX_PYMETHOD_O(CListValue,append); + KX_PYMETHOD_NOARGS(CListValue,reverse); + KX_PYMETHOD_O(CListValue,index); + KX_PYMETHOD_O(CListValue,count); private: diff --git a/source/gameengine/Expressions/PyObjectPlus.cpp b/source/gameengine/Expressions/PyObjectPlus.cpp index 1eca527151a..2c4fbd5a867 100644 --- a/source/gameengine/Expressions/PyObjectPlus.cpp +++ b/source/gameengine/Expressions/PyObjectPlus.cpp @@ -94,7 +94,7 @@ PyObjectPlus::PyObjectPlus(PyTypeObject *T) // constructor * PyObjectPlus Methods -- Every class, even the abstract one should have a Methods ------------------------------*/ PyMethodDef PyObjectPlus::Methods[] = { - {"isA", (PyCFunction) sPy_isA, METH_VARARGS}, + {"isA", (PyCFunction) sPy_isA, METH_O}, {NULL, NULL} /* Sentinel */ }; @@ -106,24 +106,24 @@ PyParentObject PyObjectPlus::Parents[] = {&PyObjectPlus::Type, NULL}; /*------------------------------ * PyObjectPlus attributes -- attributes ------------------------------*/ -PyObject *PyObjectPlus::_getattr(const STR_String& attr) +PyObject *PyObjectPlus::_getattr(const char *attr) { - if (attr == "__doc__" && GetType()->tp_doc) + if (!strcmp(attr, "__doc__") && GetType()->tp_doc) return PyString_FromString(GetType()->tp_doc); //if (streq(attr, "type")) // return Py_BuildValue("s", (*(GetParents()))->tp_name); - return Py_FindMethod(Methods, this, const_cast<char *>(attr.ReadPtr())); + return Py_FindMethod(Methods, this, attr); } -int PyObjectPlus::_delattr(const STR_String& attr) +int PyObjectPlus::_delattr(const char *attr) { PyErr_SetString(PyExc_AttributeError, "attribute cant be deleted"); return 1; } -int PyObjectPlus::_setattr(const STR_String& attr, PyObject *value) +int PyObjectPlus::_setattr(const char *attr, PyObject *value) { //return PyObject::_setattr(attr,value); //cerr << "Unknown attribute" << endl; @@ -131,6 +131,537 @@ int PyObjectPlus::_setattr(const STR_String& attr, PyObject *value) return 1; } +PyObject *PyObjectPlus::_getattr_self(const PyAttributeDef attrlist[], void *self, const char *attr) +{ + const PyAttributeDef *attrdef; + for (attrdef=attrlist; attrdef->m_name != NULL; attrdef++) + { + if (!strcmp(attr, attrdef->m_name)) + { + if (attrdef->m_type == KX_PYATTRIBUTE_TYPE_DUMMY) + { + // fake attribute, ignore + return NULL; + } + char *ptr = reinterpret_cast<char*>(self)+attrdef->m_offset; + if (attrdef->m_length > 1) + { + PyObject* resultlist = PyList_New(attrdef->m_length); + for (int i=0; i<attrdef->m_length; i++) + { + switch (attrdef->m_type) { + case KX_PYATTRIBUTE_TYPE_BOOL: + { + bool *val = reinterpret_cast<bool*>(ptr); + ptr += sizeof(bool); + PyList_SetItem(resultlist,i,PyInt_FromLong(*val)); + break; + } + case KX_PYATTRIBUTE_TYPE_SHORT: + { + short int *val = reinterpret_cast<short int*>(ptr); + ptr += sizeof(short int); + PyList_SetItem(resultlist,i,PyInt_FromLong(*val)); + break; + } + case KX_PYATTRIBUTE_TYPE_ENUM: + // enum are like int, just make sure the field size is the same + if (sizeof(int) != attrdef->m_size) + { + Py_DECREF(resultlist); + return NULL; + } + // walkthrough + case KX_PYATTRIBUTE_TYPE_INT: + { + int *val = reinterpret_cast<int*>(ptr); + ptr += sizeof(int); + PyList_SetItem(resultlist,i,PyInt_FromLong(*val)); + break; + } + case KX_PYATTRIBUTE_TYPE_FLOAT: + { + float *val = reinterpret_cast<float*>(ptr); + ptr += sizeof(float); + PyList_SetItem(resultlist,i,PyFloat_FromDouble(*val)); + break; + } + default: + // no support for array of complex data + Py_DECREF(resultlist); + return NULL; + } + } + return resultlist; + } + else + { + switch (attrdef->m_type) { + case KX_PYATTRIBUTE_TYPE_BOOL: + { + bool *val = reinterpret_cast<bool*>(ptr); + return PyInt_FromLong(*val); + } + case KX_PYATTRIBUTE_TYPE_SHORT: + { + short int *val = reinterpret_cast<short int*>(ptr); + return PyInt_FromLong(*val); + } + case KX_PYATTRIBUTE_TYPE_ENUM: + // enum are like int, just make sure the field size is the same + if (sizeof(int) != attrdef->m_size) + { + return NULL; + } + // walkthrough + case KX_PYATTRIBUTE_TYPE_INT: + { + int *val = reinterpret_cast<int*>(ptr); + return PyInt_FromLong(*val); + } + case KX_PYATTRIBUTE_TYPE_FLOAT: + { + float *val = reinterpret_cast<float*>(ptr); + return PyFloat_FromDouble(*val); + } + case KX_PYATTRIBUTE_TYPE_STRING: + { + STR_String *val = reinterpret_cast<STR_String*>(ptr); + return PyString_FromString(*val); + } + default: + return NULL; + } + } + } + } + return NULL; +} + +int PyObjectPlus::_setattr_self(const PyAttributeDef attrlist[], void *self, const char *attr, PyObject *value) +{ + const PyAttributeDef *attrdef; + void *undoBuffer = NULL; + void *sourceBuffer = NULL; + size_t bufferSize = 0; + + for (attrdef=attrlist; attrdef->m_name != NULL; attrdef++) + { + if (!strcmp(attr, attrdef->m_name)) + { + if (attrdef->m_access == KX_PYATTRIBUTE_RO || + attrdef->m_type == KX_PYATTRIBUTE_TYPE_DUMMY) + { + PyErr_SetString(PyExc_AttributeError, "property is read-only"); + return 1; + } + char *ptr = reinterpret_cast<char*>(self)+attrdef->m_offset; + if (attrdef->m_length > 1) + { + if (!PySequence_Check(value)) + { + PyErr_SetString(PyExc_TypeError, "expected a sequence"); + return 1; + } + if (PySequence_Size(value) != attrdef->m_length) + { + PyErr_SetString(PyExc_TypeError, "incorrect number of elements in sequence"); + return 1; + } + switch (attrdef->m_type) + { + case KX_PYATTRIBUTE_TYPE_BOOL: + bufferSize = sizeof(bool); + break; + case KX_PYATTRIBUTE_TYPE_SHORT: + bufferSize = sizeof(short int); + break; + case KX_PYATTRIBUTE_TYPE_ENUM: + case KX_PYATTRIBUTE_TYPE_INT: + bufferSize = sizeof(int); + break; + case KX_PYATTRIBUTE_TYPE_FLOAT: + bufferSize = sizeof(float); + break; + default: + // should not happen + PyErr_SetString(PyExc_AttributeError, "Unsupported attribute type, report to blender.org"); + return 1; + } + // let's implement a smart undo method + bufferSize *= attrdef->m_length; + undoBuffer = malloc(bufferSize); + sourceBuffer = ptr; + if (undoBuffer) + { + memcpy(undoBuffer, sourceBuffer, bufferSize); + } + for (int i=0; i<attrdef->m_length; i++) + { + PyObject *item = PySequence_GetItem(value, i); /* new ref */ + // we can decrement the reference immediately, the reference count + // is at least 1 because the item is part of an array + Py_DECREF(item); + switch (attrdef->m_type) + { + case KX_PYATTRIBUTE_TYPE_BOOL: + { + bool *var = reinterpret_cast<bool*>(ptr); + ptr += sizeof(bool); + if (PyInt_Check(item)) + { + *var = (PyInt_AsLong(item) != 0); + } + else if (PyBool_Check(item)) + { + *var = (item == Py_True); + } + else + { + PyErr_SetString(PyExc_TypeError, "expected an integer or a bool"); + goto UNDO_AND_ERROR; + } + break; + } + case KX_PYATTRIBUTE_TYPE_SHORT: + { + short int *var = reinterpret_cast<short int*>(ptr); + ptr += sizeof(short int); + if (PyInt_Check(item)) + { + long val = PyInt_AsLong(item); + if (attrdef->m_clamp) + { + if (val < attrdef->m_imin) + val = attrdef->m_imin; + else if (val > attrdef->m_imax) + val = attrdef->m_imax; + } + else if (val < attrdef->m_imin || val > attrdef->m_imax) + { + PyErr_SetString(PyExc_ValueError, "item value out of range"); + goto UNDO_AND_ERROR; + } + *var = (short int)val; + } + else + { + PyErr_SetString(PyExc_TypeError, "expected an integer"); + goto UNDO_AND_ERROR; + } + break; + } + case KX_PYATTRIBUTE_TYPE_ENUM: + // enum are equivalent to int, just make sure that the field size matches: + if (sizeof(int) != attrdef->m_size) + { + PyErr_SetString(PyExc_AttributeError, "attribute size check error, report to blender.org"); + goto UNDO_AND_ERROR; + } + // walkthrough + case KX_PYATTRIBUTE_TYPE_INT: + { + int *var = reinterpret_cast<int*>(ptr); + ptr += sizeof(int); + if (PyInt_Check(item)) + { + long val = PyInt_AsLong(item); + if (attrdef->m_clamp) + { + if (val < attrdef->m_imin) + val = attrdef->m_imin; + else if (val > attrdef->m_imax) + val = attrdef->m_imax; + } + else if (val < attrdef->m_imin || val > attrdef->m_imax) + { + PyErr_SetString(PyExc_ValueError, "item value out of range"); + goto UNDO_AND_ERROR; + } + *var = (int)val; + } + else + { + PyErr_SetString(PyExc_TypeError, "expected an integer"); + goto UNDO_AND_ERROR; + } + break; + } + case KX_PYATTRIBUTE_TYPE_FLOAT: + { + float *var = reinterpret_cast<float*>(ptr); + ptr += sizeof(float); + double val = PyFloat_AsDouble(item); + if (val == -1.0 && PyErr_Occurred()) + { + PyErr_SetString(PyExc_TypeError, "expected a float"); + goto UNDO_AND_ERROR; + } + else if (attrdef->m_clamp) + { + if (val < attrdef->m_fmin) + val = attrdef->m_fmin; + else if (val > attrdef->m_fmax) + val = attrdef->m_fmax; + } + else if (val < attrdef->m_fmin || val > attrdef->m_fmax) + { + PyErr_SetString(PyExc_ValueError, "item value out of range"); + goto UNDO_AND_ERROR; + } + *var = (float)val; + break; + } + default: + // should not happen + PyErr_SetString(PyExc_AttributeError, "attribute type check error, report to blender.org"); + goto UNDO_AND_ERROR; + } + } + // no error, call check function if any + if (attrdef->m_function != NULL) + { + if ((*attrdef->m_function)(self, attrdef) != 0) + { + // post check returned an error, restore values + UNDO_AND_ERROR: + if (undoBuffer) + { + memcpy(sourceBuffer, undoBuffer, bufferSize); + free(undoBuffer); + } + return 1; + } + } + if (undoBuffer) + free(undoBuffer); + return 0; + } + else // simple attribute value + { + + if (attrdef->m_function != NULL) + { + // post check function is provided, prepare undo buffer + sourceBuffer = ptr; + switch (attrdef->m_type) + { + case KX_PYATTRIBUTE_TYPE_BOOL: + bufferSize = sizeof(bool); + break; + case KX_PYATTRIBUTE_TYPE_SHORT: + bufferSize = sizeof(short); + break; + case KX_PYATTRIBUTE_TYPE_ENUM: + case KX_PYATTRIBUTE_TYPE_INT: + bufferSize = sizeof(int); + break; + case KX_PYATTRIBUTE_TYPE_FLOAT: + bufferSize = sizeof(float); + break; + case KX_PYATTRIBUTE_TYPE_STRING: + sourceBuffer = reinterpret_cast<STR_String*>(ptr)->Ptr(); + if (sourceBuffer) + bufferSize = strlen(reinterpret_cast<char*>(sourceBuffer))+1; + break; + default: + PyErr_SetString(PyExc_AttributeError, "unknown attribute type, report to blender.org"); + return 1; + } + if (bufferSize) + { + undoBuffer = malloc(bufferSize); + if (undoBuffer) + { + memcpy(undoBuffer, sourceBuffer, bufferSize); + } + } + } + + switch (attrdef->m_type) + { + case KX_PYATTRIBUTE_TYPE_BOOL: + { + bool *var = reinterpret_cast<bool*>(ptr); + if (PyInt_Check(value)) + { + *var = (PyInt_AsLong(value) != 0); + } + else if (PyBool_Check(value)) + { + *var = (value == Py_True); + } + else + { + PyErr_SetString(PyExc_TypeError, "expected an integer or a bool"); + goto FREE_AND_ERROR; + } + break; + } + case KX_PYATTRIBUTE_TYPE_SHORT: + { + short int *var = reinterpret_cast<short int*>(ptr); + if (PyInt_Check(value)) + { + long val = PyInt_AsLong(value); + if (attrdef->m_clamp) + { + if (val < attrdef->m_imin) + val = attrdef->m_imin; + else if (val > attrdef->m_imax) + val = attrdef->m_imax; + } + else if (val < attrdef->m_imin || val > attrdef->m_imax) + { + PyErr_SetString(PyExc_ValueError, "value out of range"); + goto FREE_AND_ERROR; + } + *var = (short int)val; + } + else + { + PyErr_SetString(PyExc_TypeError, "expected an integer"); + goto FREE_AND_ERROR; + } + break; + } + case KX_PYATTRIBUTE_TYPE_ENUM: + // enum are equivalent to int, just make sure that the field size matches: + if (sizeof(int) != attrdef->m_size) + { + PyErr_SetString(PyExc_AttributeError, "attribute size check error, report to blender.org"); + goto FREE_AND_ERROR; + } + // walkthrough + case KX_PYATTRIBUTE_TYPE_INT: + { + int *var = reinterpret_cast<int*>(ptr); + if (PyInt_Check(value)) + { + long val = PyInt_AsLong(value); + if (attrdef->m_clamp) + { + if (val < attrdef->m_imin) + val = attrdef->m_imin; + else if (val > attrdef->m_imax) + val = attrdef->m_imax; + } + else if (val < attrdef->m_imin || val > attrdef->m_imax) + { + PyErr_SetString(PyExc_ValueError, "value out of range"); + goto FREE_AND_ERROR; + } + *var = (int)val; + } + else + { + PyErr_SetString(PyExc_TypeError, "expected an integer"); + goto FREE_AND_ERROR; + } + break; + } + case KX_PYATTRIBUTE_TYPE_FLOAT: + { + float *var = reinterpret_cast<float*>(ptr); + double val = PyFloat_AsDouble(value); + if (val == -1.0 && PyErr_Occurred()) + { + PyErr_SetString(PyExc_TypeError, "expected a float"); + goto FREE_AND_ERROR; + } + else if (attrdef->m_clamp) + { + if (val < attrdef->m_fmin) + val = attrdef->m_fmin; + else if (val > attrdef->m_fmax) + val = attrdef->m_fmax; + } + else if (val < attrdef->m_fmin || val > attrdef->m_fmax) + { + PyErr_SetString(PyExc_ValueError, "value out of range"); + goto FREE_AND_ERROR; + } + *var = (float)val; + break; + } + case KX_PYATTRIBUTE_TYPE_STRING: + { + STR_String *var = reinterpret_cast<STR_String*>(ptr); + if (PyString_Check(value)) + { + char *val = PyString_AsString(value); + if (attrdef->m_clamp) + { + if (strlen(val) < attrdef->m_imin) + { + // can't increase the length of the string + PyErr_SetString(PyExc_ValueError, "string length too short"); + goto FREE_AND_ERROR; + } + else if (strlen(val) > attrdef->m_imax) + { + // trim the string + char c = val[attrdef->m_imax]; + val[attrdef->m_imax] = 0; + *var = val; + val[attrdef->m_imax] = c; + break; + } + } else if (strlen(val) < attrdef->m_imin || strlen(val) > attrdef->m_imax) + { + PyErr_SetString(PyExc_ValueError, "string length out of range"); + goto FREE_AND_ERROR; + } + *var = val; + } + else + { + PyErr_SetString(PyExc_TypeError, "expected a string"); + goto FREE_AND_ERROR; + } + break; + } + default: + // should not happen + PyErr_SetString(PyExc_AttributeError, "unknown attribute type, report to blender.org"); + goto FREE_AND_ERROR; + } + } + // check if post processing is needed + if (attrdef->m_function != NULL) + { + if ((*attrdef->m_function)(self, attrdef) != 0) + { + // restore value + RESTORE_AND_ERROR: + if (undoBuffer) + { + if (attrdef->m_type == KX_PYATTRIBUTE_TYPE_STRING) + { + // special case for STR_String: restore the string + STR_String *var = reinterpret_cast<STR_String*>(ptr); + *var = reinterpret_cast<char*>(undoBuffer); + } + else + { + // other field type have direct values + memcpy(ptr, undoBuffer, bufferSize); + } + } + FREE_AND_ERROR: + if (undoBuffer) + free(undoBuffer); + return 1; + } + } + if (undoBuffer) + free(undoBuffer); + return 0; + } + } + return -1; +} + /*------------------------------ * PyObjectPlus repr -- representations ------------------------------*/ @@ -157,19 +688,20 @@ bool PyObjectPlus::isA(const char *mytypename) // check typename of each parent for (P = Ps[i=0]; P != NULL; P = Ps[i++]) { - if (STR_String(P->tp_name) == STR_String(mytypename) ) + if (strcmp(P->tp_name, mytypename)==0) return true; } return false; } -PyObject *PyObjectPlus::Py_isA(PyObject *args) // Python wrapper for isA +PyObject *PyObjectPlus::Py_isA(PyObject *value) // Python wrapper for isA { - char *mytypename; - if (!PyArg_ParseTuple(args, "s", &mytypename)) + if (!PyString_Check(value)) { + PyErr_SetString(PyExc_TypeError, "expected a string"); return NULL; - if(isA(mytypename)) + } + if(isA(PyString_AsString(value))) Py_RETURN_TRUE; else Py_RETURN_FALSE; diff --git a/source/gameengine/Expressions/PyObjectPlus.h b/source/gameengine/Expressions/PyObjectPlus.h index 3a054454a0b..0fae175e3cf 100644 --- a/source/gameengine/Expressions/PyObjectPlus.h +++ b/source/gameengine/Expressions/PyObjectPlus.h @@ -72,9 +72,6 @@ typedef int Py_ssize_t; #define PY_METHODCHAR const char * #endif - // some basic python macros -#define Py_Return { Py_INCREF(Py_None); return Py_None;} - static inline void Py_Fatal(const char *M) { //cout << M << endl; exit(-1); @@ -86,6 +83,7 @@ static inline void Py_Fatal(const char *M) { public: \ static PyTypeObject Type; \ static PyMethodDef Methods[]; \ + static PyAttributeDef Attributes[]; \ static PyParentObject Parents[]; \ virtual PyTypeObject *GetType(void) {return &Type;}; \ virtual PyParentObject *GetParents(void) {return Parents;} @@ -96,7 +94,7 @@ static inline void Py_Fatal(const char *M) { // to be properly passed up the hierarchy. #define _getattr_up(Parent) \ PyObject *rvalue = NULL; \ - if (attr=="__methods__") { \ + if (!strcmp(attr, "__methods__")) { \ PyObject *_attr_string = NULL; \ PyMethodDef *meth = Methods; \ rvalue = Parent::_getattr(attr); \ @@ -112,7 +110,7 @@ static inline void Py_Fatal(const char *M) { } \ } \ } else { \ - rvalue = Py_FindMethod(Methods, this, const_cast<char*>(attr.ReadPtr())); \ + rvalue = Py_FindMethod(Methods, this, attr); \ if (rvalue == NULL) { \ PyErr_Clear(); \ rvalue = Parent::_getattr(attr); \ @@ -185,7 +183,10 @@ static inline void Py_Fatal(const char *M) { #define KX_PYMETHODTABLE(class_name, method_name) \ {#method_name , (PyCFunction) class_name::sPy##method_name, METH_VARARGS, (PY_METHODCHAR)class_name::method_name##_doc} -#define KX_PYMETHODTABLE_NOARG(class_name, method_name) \ +#define KX_PYMETHODTABLE_O(class_name, method_name) \ + {#method_name , (PyCFunction) class_name::sPy##method_name, METH_O, (PY_METHODCHAR)class_name::method_name##_doc} + +#define KX_PYMETHODTABLE_NOARGS(class_name, method_name) \ {#method_name , (PyCFunction) class_name::sPy##method_name, METH_NOARGS, (PY_METHODCHAR)class_name::method_name##_doc} /** @@ -195,10 +196,148 @@ static inline void Py_Fatal(const char *M) { const char class_name::method_name##_doc[] = doc_string; \ PyObject* class_name::Py##method_name(PyObject*, PyObject* args, PyObject*) -#define KX_PYMETHODDEF_DOC_NOARG(class_name, method_name, doc_string) \ +#define KX_PYMETHODDEF_DOC_VARARGS(class_name, method_name, doc_string) \ +const char class_name::method_name##_doc[] = doc_string; \ +PyObject* class_name::Py##method_name(PyObject*, PyObject* args) + +#define KX_PYMETHODDEF_DOC_O(class_name, method_name, doc_string) \ +const char class_name::method_name##_doc[] = doc_string; \ +PyObject* class_name::Py##method_name(PyObject*, PyObject* value) + +#define KX_PYMETHODDEF_DOC_NOARGS(class_name, method_name, doc_string) \ const char class_name::method_name##_doc[] = doc_string; \ PyObject* class_name::Py##method_name(PyObject*) +/** + * Attribute management + */ +enum KX_PYATTRIBUTE_TYPE { + KX_PYATTRIBUTE_TYPE_BOOL, + KX_PYATTRIBUTE_TYPE_ENUM, + KX_PYATTRIBUTE_TYPE_SHORT, + KX_PYATTRIBUTE_TYPE_INT, + KX_PYATTRIBUTE_TYPE_FLOAT, + KX_PYATTRIBUTE_TYPE_STRING, + KX_PYATTRIBUTE_TYPE_DUMMY, +}; + +enum KX_PYATTRIBUTE_ACCESS { + KX_PYATTRIBUTE_RW, + KX_PYATTRIBUTE_RO +}; + +struct KX_PYATTRIBUTE_DEF; +typedef int (*KX_PYATTRIBUTE_FUNCTION)(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); + +typedef struct KX_PYATTRIBUTE_DEF { + const char *m_name; // name of the python attribute + KX_PYATTRIBUTE_TYPE m_type; // type of value + KX_PYATTRIBUTE_ACCESS m_access; // read/write access or read-only + int m_imin; // minimum value in case of integer attributes (for string: minimum string length) + int m_imax; // maximum value in case of integer attributes (for string: maximum string length) + float m_fmin; // minimum value in case of float attributes + float m_fmax; // maximum value in case of float attributes + bool m_clamp; // enforce min/max value by clamping + size_t m_offset; // position of field in structure + size_t m_size; // size of field for runtime verification (enum only) + size_t m_length; // length of array, 1=simple attribute + KX_PYATTRIBUTE_FUNCTION m_function; // static function to check the assignment, returns 0 if no error + // The following pointers are just used to have compile time check for attribute type. + // It would have been good to use a union but that would require C99 compatibility + // to initialize specific union fields through designated initializers. + struct { + bool *m_boolPtr; + short int *m_shortPtr; + int *m_intPtr; + float *m_floatPtr; + STR_String *m_stringPtr; + } m_typeCheck; +} PyAttributeDef; + +#define KX_PYATTRIBUTE_DUMMY(name) \ + { name, KX_PYATTRIBUTE_TYPE_DUMMY, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, 0, 0, 1, NULL, {NULL, NULL, NULL, NULL, NULL} } + +#define KX_PYATTRIBUTE_BOOL_RW(name,object,field) \ + { name, KX_PYATTRIBUTE_TYPE_BOOL, KX_PYATTRIBUTE_RW, 0, 1, 0.f, 0.f, false, offsetof(object,field), 0, 1, NULL, {&((object *)0)->field, NULL, NULL, NULL, NULL} } +#define KX_PYATTRIBUTE_BOOL_RW_CHECK(name,object,field,function) \ + { name, KX_PYATTRIBUTE_TYPE_BOOL, KX_PYATTRIBUTE_RW, 0, 1, 0.f, 0.f, false, offsetof(object,field), 0, 1, &object::function, {&((object *)0)->field, NULL, NULL, NULL, NULL} } +#define KX_PYATTRIBUTE_BOOL_RO(name,object,field) \ + { name, KX_PYATTRIBUTE_TYPE_BOOL, KX_PYATTRIBUTE_RO, 0, 1, 0.f, 0.f, false, offsetof(object,field), 0, 1, NULL, {&((object *)0)->field, NULL, NULL, NULL, NULL} } + +// enum field cannot be mapped to pointer (because we would need a pointer for each enum) +// use field size to verify mapping at runtime only, assuming enum size is equal to int size. +#define KX_PYATTRIBUTE_ENUM_RW(name,min,max,clamp,object,field) \ + { name, KX_PYATTRIBUTE_TYPE_ENUM, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), sizeof(((object *)0)->field), 1, NULL, {NULL, NULL, NULL, NULL, NULL} } +#define KX_PYATTRIBUTE_ENUM_RW_CHECK(name,min,max,clamp,object,field,function) \ + { name, KX_PYATTRIBUTE_TYPE_ENUM, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), sizeof(((object *)0)->field), 1, &object::function, {NULL, NULL, NULL, NULL, NULL} } +#define KX_PYATTRIBUTE_ENUM_RO(name,object,field) \ + { name, KX_PYATTRIBUTE_TYPE_ENUM, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), sizeof(((object *)0)->field), 1, NULL, {NULL, NULL, NULL, NULL, NULL} } + +#define KX_PYATTRIBUTE_SHORT_RW(name,min,max,clamp,object,field) \ + { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL} } +#define KX_PYATTRIBUTE_SHORT_RW_CHECK(name,min,max,clamp,object,field,function) \ + { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, &object::function, {NULL, &((object *)0)->field, NULL, NULL, NULL} } +#define KX_PYATTRIBUTE_SHORT_RO(name,object,field) \ + { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, 1, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL} } +#define KX_PYATTRIBUTE_SHORT_ARRAY_RW(name,min,max,clamp,object,field,length) \ + { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, NULL, {NULL, ((object *)0)->field, NULL, NULL, NULL} } +#define KX_PYATTRIBUTE_SHORT_ARRAY_RW_CHECK(name,min,max,clamp,object,field,length,function) \ + { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, &object::function, {NULL, ((object *)0)->field, NULL, NULL, NULL} } +#define KX_PYATTRIBUTE_SHORT_ARRAY_RO(name,object,field,length) \ + { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, length, NULL, {NULL, ((object *)0)->field, NULL, NULL, NULL} } +// SHORT_LIST +#define KX_PYATTRIBUTE_SHORT_LIST_RW(name,min,max,clamp,object,field,length) \ + { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL} } +#define KX_PYATTRIBUTE_SHORT_LIST_RW_CHECK(name,min,max,clamp,object,field,length,function) \ + { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, &object::function, {NULL, &((object *)0)->field, NULL, NULL, NULL} } +#define KX_PYATTRIBUTE_SHORT_LIST_RO(name,object,field,length) \ + { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, length, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL} } + +#define KX_PYATTRIBUTE_INT_RW(name,min,max,clamp,object,field) \ + { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL} } +#define KX_PYATTRIBUTE_INT_RW_CHECK(name,min,max,clamp,object,field,function) \ + { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, &object::function, {NULL, NULL, &((object *)0)->field, NULL, NULL} } +#define KX_PYATTRIBUTE_INT_RO(name,object,field) \ + { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, 1, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL} } +#define KX_PYATTRIBUTE_INT_ARRAY_RW(name,min,max,clamp,object,field,length) \ + { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, NULL, {NULL, NULL, ((object *)0)->field, NULL, NULL} } +#define KX_PYATTRIBUTE_INT_ARRAY_RW_CHECK(name,min,max,clamp,object,field,length,function) \ + { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, &object::function, {NULL, NULL, ((object *)0)->field, NULL, NULL} } +#define KX_PYATTRIBUTE_INT_ARRAY_RO(name,object,field,length) \ + { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, length, NULL, {NULL, NULL, ((object *)0)->field, NULL, NULL} } +// INT_LIST +#define KX_PYATTRIBUTE_INT_LIST_RW(name,min,max,clamp,object,field,length) \ + { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL} } +#define KX_PYATTRIBUTE_INT_LIST_RW_CHECK(name,min,max,clamp,object,field,length,function) \ + { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, &object::function, {NULL, NULL, &((object *)0)->field, NULL, NULL} } +#define KX_PYATTRIBUTE_INT_LIST_RO(name,object,field,length) \ + { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, length, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL} } + +// always clamp for float +#define KX_PYATTRIBUTE_FLOAT_RW(name,min,max,object,field) \ + { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, offsetof(object,field), 0, 1, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL} } +#define KX_PYATTRIBUTE_FLOAT_RW_CHECK(name,min,max,object,field,function) \ + { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, offsetof(object,field), 0, 1, &object::function, {NULL, NULL, NULL, &((object *)0)->field, NULL} } +#define KX_PYATTRIBUTE_FLOAT_RO(name,object,field) \ + { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, 1, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL} } +#define KX_PYATTRIBUTE_FLOAT_ARRAY_RW(name,min,max,object,field,length) \ + { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, offsetof(object,field), 0, length, NULL, {NULL, NULL, NULL, ((object *)0)->field, NULL} } +#define KX_PYATTRIBUTE_FLOAT_ARRAY_RW_CHECK(name,min,max,object,field,length,function) \ + { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, offsetof(object,field), 0, length, &object::function, {NULL, NULL, NULL, ((object *)0)->field, NULL} } +#define KX_PYATTRIBUTE_FLOAT_ARRAY_RO(name,object,field,length) \ + { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, length, NULL, {NULL, NULL, NULL, ((object *)0)->field, NULL} } + +#define KX_PYATTRIBUTE_STRING_RW(name,min,max,clamp,object,field) \ + { name, KX_PYATTRIBUTE_TYPE_STRING, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, NULL, {NULL, NULL, NULL, NULL, &((object *)0)->field} } +#define KX_PYATTRIBUTE_STRING_RW_CHECK(name,min,max,clamp,object,field,function) \ + { name, KX_PYATTRIBUTE_TYPE_STRING, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, &object::function, {NULL, NULL, NULL, NULL, &((object *)0)->field} } +#define KX_PYATTRIBUTE_STRING_RO(name,object,field) \ + { name, KX_PYATTRIBUTE_TYPE_STRING, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, 1 , NULL, {NULL, NULL, NULL, NULL, &((object *)0)->field} } + +//Multiple integer +#define KX_PYATTRIBUTE_MINT_RW_CHECK(name,min,max,clamp,object,field,length,function) \ + { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, &object::function, {NULL, NULL, &((object *)0)->field, NULL, NULL} } + /*------------------------------ * PyObjectPlus ------------------------------*/ @@ -224,21 +363,23 @@ public: // Py_DECREF(this); // }; // decref method - virtual PyObject *_getattr(const STR_String& attr); // _getattr method + virtual PyObject *_getattr(const char *attr); // _getattr method static PyObject *__getattr(PyObject * PyObj, char *attr) // This should be the entry in Type. { - return ((PyObjectPlus*) PyObj)->_getattr(STR_String(attr)); + return ((PyObjectPlus*) PyObj)->_getattr(attr); } + static PyObject *_getattr_self(const PyAttributeDef attrlist[], void *self, const char *attr); + static int _setattr_self(const PyAttributeDef attrlist[], void *self, const char *attr, PyObject *value); - virtual int _delattr(const STR_String& attr); - virtual int _setattr(const STR_String& attr, PyObject *value); // _setattr method + virtual int _delattr(const char *attr); + virtual int _setattr(const char *attr, PyObject *value); // _setattr method static int __setattr(PyObject *PyObj, // This should be the entry in Type. char *attr, PyObject *value) { if (!value) return ((PyObjectPlus*) PyObj)->_delattr(attr); - return ((PyObjectPlus*) PyObj)->_setattr(STR_String(attr), value); + return ((PyObjectPlus*) PyObj)->_setattr(attr, value); } virtual PyObject *_repr(void); // _repr method @@ -250,10 +391,10 @@ public: // isA methods bool isA(PyTypeObject *T); bool isA(const char *mytypename); - PyObject *Py_isA(PyObject *args); - static PyObject *sPy_isA(PyObject *self, PyObject *args, PyObject *kwd) + PyObject *Py_isA(PyObject *value); + static PyObject *sPy_isA(PyObject *self, PyObject *value) { - return ((PyObjectPlus*)self)->Py_isA(args); + return ((PyObjectPlus*)self)->Py_isA(value); } }; diff --git a/source/gameengine/Expressions/SConscript b/source/gameengine/Expressions/SConscript index 809ac31371e..3d855d40623 100644 --- a/source/gameengine/Expressions/SConscript +++ b/source/gameengine/Expressions/SConscript @@ -6,4 +6,9 @@ sources = env.Glob('*.cpp') incs ='. #source/kernel/gen_system #intern/string #intern/moto/include' incs += ' ' + env['BF_PYTHON_INC'] -env.BlenderLib ( 'bf_expressions', sources, Split(incs), [], libtype=['game','player'], priority = [45,125] ) +cxxflags = [] +if env['OURPLATFORM']=='win32-vc': + cxxflags.append ('/GR') + cxxflags.append ('/O2') + +env.BlenderLib ( 'bf_expressions', sources, Split(incs), [], libtype=['game','player'], priority = [45,125], cxx_compileflags=cxxflags) diff --git a/source/gameengine/Expressions/Value.cpp b/source/gameengine/Expressions/Value.cpp index 7296dfbec10..9b26cda01b3 100644 --- a/source/gameengine/Expressions/Value.cpp +++ b/source/gameengine/Expressions/Value.cpp @@ -32,6 +32,7 @@ ////////////////////////////////////////////////////////////////////// double CValue::m_sZeroVec[3] = {0.0,0.0,0.0}; +bool CValue::m_ignore_deprecation_warnings(false); #ifndef NO_EXP_PYTHON_EMBEDDING @@ -673,9 +674,9 @@ static PyMethodDef CValueMethods[] = }; -PyObject* CValue::_getattr(const STR_String& attr) +PyObject* CValue::_getattr(const char *attr) { - CValue* resultattr = FindIdentifier(attr); + CValue* resultattr = FindIdentifier(STR_String(attr)); STR_String text; if (resultattr) { @@ -760,26 +761,27 @@ CValue* CValue::ConvertPythonToValue(PyObject* pyobj) } -int CValue::_delattr(const STR_String& attr) +int CValue::_delattr(const char *attr) { - if (!RemoveProperty(attr)) /* sets error */ + if (!RemoveProperty(STR_String(attr))) /* sets error */ return 1; return 0; } -int CValue::_setattr(const STR_String& attr,PyObject* pyobj) +int CValue::_setattr(const char *attr,PyObject* pyobj) { CValue* vallie = ConvertPythonToValue(pyobj); if (vallie) { - CValue* oldprop = GetProperty(attr); + STR_String attr_str = attr; + CValue* oldprop = GetProperty(attr_str); if (oldprop) { oldprop->SetValue(vallie); } else { - SetProperty(attr,vallie); + SetProperty(attr_str, vallie); } vallie->Release(); } else @@ -849,4 +851,50 @@ void CValue::SetValue(CValue* newval) } /////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////// +/* deprecation warning management */ +void CValue::SetDeprecationWarnings(bool ignoreDeprecationWarnings) +{ + m_ignore_deprecation_warnings = ignoreDeprecationWarnings; +} + +void CValue::ShowDeprecationWarning(const char* old_way,const char* new_way) +{ + if (!m_ignore_deprecation_warnings) { + printf("Method %s is deprecated, please use %s instead.\n", old_way, new_way); + + // import sys; print '\t%s:%d' % (sys._getframe(0).f_code.co_filename, sys._getframe(0).f_lineno) + + PyObject *getframe, *frame; + PyObject *f_lineno, *f_code, *co_filename; + + getframe = PySys_GetObject("_getframe"); // borrowed + if (getframe) { + frame = PyObject_CallObject(getframe, NULL); + if (frame) { + f_lineno= PyObject_GetAttrString(frame, "f_lineno"); + f_code= PyObject_GetAttrString(frame, "f_code"); + if (f_lineno && f_code) { + co_filename= PyObject_GetAttrString(f_code, "co_filename"); + if (co_filename) { + + printf("\t%s:%d\n", PyString_AsString(co_filename), (int)PyInt_AsLong(f_lineno)); + + Py_DECREF(f_lineno); + Py_DECREF(f_code); + Py_DECREF(co_filename); + Py_DECREF(frame); + return; + } + } + + Py_XDECREF(f_lineno); + Py_XDECREF(f_code); + Py_DECREF(frame); + } + + } + PyErr_Clear(); + printf("\tERROR - Could not access sys._getframe(0).f_lineno or sys._getframe().f_code.co_filename\n"); + } +} diff --git a/source/gameengine/Expressions/Value.h b/source/gameengine/Expressions/Value.h index 74fcdae5756..854334b892b 100644 --- a/source/gameengine/Expressions/Value.h +++ b/source/gameengine/Expressions/Value.h @@ -223,7 +223,7 @@ public: - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); void SpecialRelease() { @@ -250,8 +250,8 @@ public: virtual CValue* ConvertPythonToValue(PyObject* pyobj); - virtual int _delattr(const STR_String& attr); - virtual int _setattr(const STR_String& attr,PyObject* value); + virtual int _delattr(const char *attr); + virtual int _setattr(const char *attr, PyObject* value); virtual PyObject* ConvertKeysToPython( void ); @@ -318,6 +318,10 @@ public: STR_String op2str(VALUE_OPERATOR op); + /** enable/disable display of deprecation warnings */ + static void SetDeprecationWarnings(bool ignoreDeprecationWarnings); + /** Shows a deprecation warning */ + static void ShowDeprecationWarning(const char* method,const char* prop); // setting / getting flags inline void SetSelected(bool bSelected) { m_ValFlags.Selected = bSelected; } @@ -349,6 +353,7 @@ private: ValueFlags m_ValFlags; // Frequently used flags in a bitfield (low memoryusage) int m_refcount; // Reference Counter static double m_sZeroVec[3]; + static bool m_ignore_deprecation_warnings; }; diff --git a/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp b/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp index 9ec4ea00337..6fcb1be654c 100644 --- a/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp +++ b/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp @@ -74,7 +74,8 @@ bool SCA_2DFilterActuator::Update() { m_rendertools->Update2DFilter(m_propNames, m_gameObj, m_type, m_int_arg, m_shaderText); } - return true; + // once the filter is in place, no need to update it again => disable the actuator + return false; } @@ -113,6 +114,6 @@ PyMethodDef SCA_2DFilterActuator::Methods[] = { }; -PyObject* SCA_2DFilterActuator::_getattr(const STR_String& attr) { +PyObject* SCA_2DFilterActuator::_getattr(const char *attr) { _getattr_up(SCA_IActuator); } diff --git a/source/gameengine/GameLogic/SCA_2DFilterActuator.h b/source/gameengine/GameLogic/SCA_2DFilterActuator.h index 7ec07cf5b19..9da0500afff 100644 --- a/source/gameengine/GameLogic/SCA_2DFilterActuator.h +++ b/source/gameengine/GameLogic/SCA_2DFilterActuator.h @@ -38,7 +38,7 @@ public: virtual bool Update(); virtual CValue* GetReplica(); - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); }; #endif diff --git a/source/gameengine/GameLogic/SCA_ANDController.cpp b/source/gameengine/GameLogic/SCA_ANDController.cpp index cfc2d25e0ae..98a3c2e96cd 100644 --- a/source/gameengine/GameLogic/SCA_ANDController.cpp +++ b/source/gameengine/GameLogic/SCA_ANDController.cpp @@ -137,7 +137,7 @@ PyMethodDef SCA_ANDController::Methods[] = { {NULL,NULL} //Sentinel }; -PyObject* SCA_ANDController::_getattr(const STR_String& attr) { +PyObject* SCA_ANDController::_getattr(const char *attr) { _getattr_up(SCA_IController); } diff --git a/source/gameengine/GameLogic/SCA_ANDController.h b/source/gameengine/GameLogic/SCA_ANDController.h index 376f4a9a876..eba7e1b545a 100644 --- a/source/gameengine/GameLogic/SCA_ANDController.h +++ b/source/gameengine/GameLogic/SCA_ANDController.h @@ -48,7 +48,7 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); }; diff --git a/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp b/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp index 7c37b237d60..7f8dbef7758 100644 --- a/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp +++ b/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp @@ -149,21 +149,51 @@ PyParentObject SCA_ActuatorSensor::Parents[] = { }; PyMethodDef SCA_ActuatorSensor::Methods[] = { + //Deprecated functions ------> {"getActuator", (PyCFunction) SCA_ActuatorSensor::sPyGetActuator, METH_NOARGS, (PY_METHODCHAR)GetActuator_doc}, {"setActuator", (PyCFunction) SCA_ActuatorSensor::sPySetActuator, METH_VARARGS, (PY_METHODCHAR)SetActuator_doc}, + //<----- Deprecated {NULL,NULL} //Sentinel }; -PyObject* SCA_ActuatorSensor::_getattr(const STR_String& attr) { +PyAttributeDef SCA_ActuatorSensor::Attributes[] = { + KX_PYATTRIBUTE_STRING_RW_CHECK("actuator",0,100,false,SCA_ActuatorSensor,m_checkactname,CheckActuator), + { NULL } //Sentinel +}; + +PyObject* SCA_ActuatorSensor::_getattr(const char *attr) { + PyObject* object = _getattr_self(Attributes, this, attr); + if (object != NULL) + return object; _getattr_up(SCA_ISensor); /* implicit return! */ } +int SCA_ActuatorSensor::CheckActuator(void *self, const PyAttributeDef*) +{ + SCA_ActuatorSensor* sensor = reinterpret_cast<SCA_ActuatorSensor*>(self); + SCA_IActuator* act = sensor->GetParent()->FindActuator(sensor->m_checkactname); + if (act) { + sensor->m_actuator = act; + return 0; + } + PyErr_SetString(PyExc_AttributeError, "string does not correspond to an actuator"); + return 1; +} + +int SCA_ActuatorSensor::_setattr(const char *attr, PyObject *value) { + int ret = _setattr_self(Attributes, this, attr, value); + if (ret >= 0) + return ret; + return SCA_ISensor::_setattr(attr, value); +} + /* 3. getActuator */ const char SCA_ActuatorSensor::GetActuator_doc[] = "getActuator()\n" "\tReturn the Actuator with which the sensor operates.\n"; PyObject* SCA_ActuatorSensor::PyGetActuator(PyObject* self) { + ShowDeprecationWarning("getActuator()", "the actuator property"); return PyString_FromString(m_checkactname); } @@ -175,6 +205,7 @@ const char SCA_ActuatorSensor::SetActuator_doc[] = "\tof this name, the call is ignored.\n"; PyObject* SCA_ActuatorSensor::PySetActuator(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setActuator()", "the actuator property"); /* We should query whether the name exists. Or should we create a prop */ /* on the fly? */ char *actNameArg = NULL; @@ -190,7 +221,7 @@ PyObject* SCA_ActuatorSensor::PySetActuator(PyObject* self, PyObject* args, PyOb } else { ; /* error: bad actuator name */ } - Py_Return; + Py_RETURN_NONE; } /* eof */ diff --git a/source/gameengine/GameLogic/SCA_ActuatorSensor.h b/source/gameengine/GameLogic/SCA_ActuatorSensor.h index a71145f6852..75ee08f42d6 100644 --- a/source/gameengine/GameLogic/SCA_ActuatorSensor.h +++ b/source/gameengine/GameLogic/SCA_ActuatorSensor.h @@ -61,13 +61,15 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject *value); /* 3. setProperty */ KX_PYMETHOD_DOC(SCA_ActuatorSensor,SetActuator); /* 4. getProperty */ KX_PYMETHOD_DOC_NOARGS(SCA_ActuatorSensor,GetActuator); + static int CheckActuator(void *self, const PyAttributeDef*); }; #endif diff --git a/source/gameengine/GameLogic/SCA_AlwaysSensor.cpp b/source/gameengine/GameLogic/SCA_AlwaysSensor.cpp index f9fbf2387c4..76aa328aa48 100644 --- a/source/gameengine/GameLogic/SCA_AlwaysSensor.cpp +++ b/source/gameengine/GameLogic/SCA_AlwaysSensor.cpp @@ -135,7 +135,7 @@ PyMethodDef SCA_AlwaysSensor::Methods[] = { {NULL,NULL} //Sentinel }; -PyObject* SCA_AlwaysSensor::_getattr(const STR_String& attr) { +PyObject* SCA_AlwaysSensor::_getattr(const char *attr) { _getattr_up(SCA_ISensor); } diff --git a/source/gameengine/GameLogic/SCA_AlwaysSensor.h b/source/gameengine/GameLogic/SCA_AlwaysSensor.h index 8bf2a8aa98e..ebe6ba80208 100644 --- a/source/gameengine/GameLogic/SCA_AlwaysSensor.h +++ b/source/gameengine/GameLogic/SCA_AlwaysSensor.h @@ -52,7 +52,7 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); }; diff --git a/source/gameengine/GameLogic/SCA_DelaySensor.cpp b/source/gameengine/GameLogic/SCA_DelaySensor.cpp index f15d4c7249f..25c9888cadd 100644 --- a/source/gameengine/GameLogic/SCA_DelaySensor.cpp +++ b/source/gameengine/GameLogic/SCA_DelaySensor.cpp @@ -158,6 +158,7 @@ PyParentObject SCA_DelaySensor::Parents[] = { }; PyMethodDef SCA_DelaySensor::Methods[] = { + //Deprecated functions ------> /* setProperty */ {"setDelay", (PyCFunction) SCA_DelaySensor::sPySetDelay, METH_VARARGS, (PY_METHODCHAR)SetDelay_doc}, {"setDuration", (PyCFunction) SCA_DelaySensor::sPySetDuration, METH_VARARGS, (PY_METHODCHAR)SetDuration_doc}, @@ -166,13 +167,32 @@ PyMethodDef SCA_DelaySensor::Methods[] = { {"getDelay", (PyCFunction) SCA_DelaySensor::sPyGetDelay, METH_NOARGS, (PY_METHODCHAR)GetDelay_doc}, {"getDuration", (PyCFunction) SCA_DelaySensor::sPyGetDuration, METH_NOARGS, (PY_METHODCHAR)GetDuration_doc}, {"getRepeat", (PyCFunction) SCA_DelaySensor::sPyGetRepeat, METH_NOARGS, (PY_METHODCHAR)GetRepeat_doc}, + //<----- Deprecated {NULL,NULL} //Sentinel }; -PyObject* SCA_DelaySensor::_getattr(const STR_String& attr) { +PyAttributeDef SCA_DelaySensor::Attributes[] = { + KX_PYATTRIBUTE_INT_RW("delay",0,100000,true,SCA_DelaySensor,m_delay), + KX_PYATTRIBUTE_INT_RW("duration",0,100000,true,SCA_DelaySensor,m_duration), + KX_PYATTRIBUTE_BOOL_RW("repeat",SCA_DelaySensor,m_repeat), + { NULL } //Sentinel +}; + +PyObject* SCA_DelaySensor::_getattr(const char *attr) { + PyObject* object = _getattr_self(Attributes, this, attr); + if (object != NULL) + return object; _getattr_up(SCA_ISensor); } +int SCA_DelaySensor::_setattr(const char *attr, PyObject *value) { + int ret = _setattr_self(Attributes, this, attr, value); + if (ret >= 0) + return ret; + return SCA_ISensor::_setattr(attr, value); +} + + const char SCA_DelaySensor::SetDelay_doc[] = "setDelay(delay)\n" "\t- delay: length of the initial OFF period as number of frame\n" @@ -180,6 +200,7 @@ const char SCA_DelaySensor::SetDelay_doc[] = "\tSet the initial delay before the positive trigger\n"; PyObject* SCA_DelaySensor::PySetDelay(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setDelay()", "the delay property"); int delay; if(!PyArg_ParseTuple(args, "i", &delay)) { @@ -190,7 +211,7 @@ PyObject* SCA_DelaySensor::PySetDelay(PyObject* self, PyObject* args, PyObject* return NULL; } m_delay = delay; - Py_Return; + Py_RETURN_NONE; } const char SCA_DelaySensor::SetDuration_doc[] = @@ -201,6 +222,7 @@ const char SCA_DelaySensor::SetDuration_doc[] = "\tIf > 0, a negative trigger is fired at the end of the ON pulse.\n"; PyObject* SCA_DelaySensor::PySetDuration(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setDuration()", "the duration property"); int duration; if(!PyArg_ParseTuple(args, "i", &duration)) { @@ -211,7 +233,7 @@ PyObject* SCA_DelaySensor::PySetDuration(PyObject* self, PyObject* args, PyObjec return NULL; } m_duration = duration; - Py_Return; + Py_RETURN_NONE; } const char SCA_DelaySensor::SetRepeat_doc[] = @@ -221,13 +243,14 @@ const char SCA_DelaySensor::SetRepeat_doc[] = "\tSet the sensor repeat mode\n"; PyObject* SCA_DelaySensor::PySetRepeat(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setRepeat()", "the repeat property"); int repeat; if(!PyArg_ParseTuple(args, "i", &repeat)) { return NULL; } m_repeat = (repeat != 0); - Py_Return; + Py_RETURN_NONE; } const char SCA_DelaySensor::GetDelay_doc[] = @@ -235,6 +258,7 @@ const char SCA_DelaySensor::GetDelay_doc[] = "\tReturn the delay parameter value\n"; PyObject* SCA_DelaySensor::PyGetDelay(PyObject* self) { + ShowDeprecationWarning("getDelay()", "the delay property"); return PyInt_FromLong(m_delay); } @@ -243,6 +267,7 @@ const char SCA_DelaySensor::GetDuration_doc[] = "\tReturn the duration parameter value\n"; PyObject* SCA_DelaySensor::PyGetDuration(PyObject* self) { + ShowDeprecationWarning("getDuration()", "the duration property"); return PyInt_FromLong(m_duration); } @@ -251,6 +276,7 @@ const char SCA_DelaySensor::GetRepeat_doc[] = "\tReturn the repeat parameter value\n"; PyObject* SCA_DelaySensor::PyGetRepeat(PyObject* self) { + ShowDeprecationWarning("getRepeat()", "the repeat property"); return BoolToPyArg(m_repeat); } diff --git a/source/gameengine/GameLogic/SCA_DelaySensor.h b/source/gameengine/GameLogic/SCA_DelaySensor.h index a997fabe3cd..491eee61da8 100644 --- a/source/gameengine/GameLogic/SCA_DelaySensor.h +++ b/source/gameengine/GameLogic/SCA_DelaySensor.h @@ -60,7 +60,8 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject *value); /* setProperty */ KX_PYMETHOD_DOC(SCA_DelaySensor,SetDelay); diff --git a/source/gameengine/GameLogic/SCA_ExpressionController.h b/source/gameengine/GameLogic/SCA_ExpressionController.h index f1db45a19e0..20e1eb77771 100644 --- a/source/gameengine/GameLogic/SCA_ExpressionController.h +++ b/source/gameengine/GameLogic/SCA_ExpressionController.h @@ -53,7 +53,7 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ -// virtual PyObject* _getattr(const STR_String& attr); +// virtual PyObject* _getattr(const char *attr); }; diff --git a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp index abd049e9d64..49d39f75814 100644 --- a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp +++ b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp @@ -247,19 +247,52 @@ PyParentObject SCA_ILogicBrick::Parents[] = { PyMethodDef SCA_ILogicBrick::Methods[] = { {"getOwner", (PyCFunction) SCA_ILogicBrick::sPyGetOwner, METH_NOARGS}, - {"getExecutePriority", (PyCFunction) SCA_ILogicBrick::sPySetExecutePriority, METH_NOARGS}, + // --> Deprecated + {"getExecutePriority", (PyCFunction) SCA_ILogicBrick::sPyGetExecutePriority, METH_NOARGS}, {"setExecutePriority", (PyCFunction) SCA_ILogicBrick::sPySetExecutePriority, METH_VARARGS}, + // <-- Deprecated {NULL,NULL} //Sentinel }; +PyAttributeDef SCA_ILogicBrick::Attributes[] = { + KX_PYATTRIBUTE_INT_RW("executePriority",0,100000,false,SCA_ILogicBrick,m_Execute_Ueber_Priority), + {NULL} //Sentinel +}; +int SCA_ILogicBrick::CheckProperty(void *self, const PyAttributeDef *attrdef) +{ + if (attrdef->m_type != KX_PYATTRIBUTE_TYPE_STRING || attrdef->m_length != 1) { + PyErr_SetString(PyExc_AttributeError, "inconsistent check function for attribute type, report to blender.org"); + return 1; + } + SCA_ILogicBrick* brick = reinterpret_cast<SCA_ILogicBrick*>(self); + STR_String* var = reinterpret_cast<STR_String*>((char*)self+attrdef->m_offset); + CValue* prop = brick->GetParent()->FindIdentifier(*var); + bool error = prop->IsError(); + prop->Release(); + if (error) { + PyErr_SetString(PyExc_ValueError, "string does not correspond to a property"); + return 1; + } + return 0; +} PyObject* -SCA_ILogicBrick::_getattr(const STR_String& attr) +SCA_ILogicBrick::_getattr(const char *attr) { + PyObject* object = _getattr_self(Attributes, this, attr); + if (object != NULL) + return object; _getattr_up(CValue); } +int SCA_ILogicBrick::_setattr(const char *attr, PyObject *value) +{ + int ret = _setattr_self(Attributes, this, attr, value); + if (ret >= 0) + return ret; + return CValue::_setattr(attr, value); +} PyObject* SCA_ILogicBrick::PyGetOwner(PyObject* self) @@ -281,6 +314,7 @@ PyObject* SCA_ILogicBrick::PySetExecutePriority(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setExecutePriority()", "the executePriority property"); int priority=0; @@ -290,13 +324,14 @@ PyObject* SCA_ILogicBrick::PySetExecutePriority(PyObject* self, m_Execute_Ueber_Priority = priority; - Py_Return; + Py_RETURN_NONE; } PyObject* SCA_ILogicBrick::PyGetExecutePriority(PyObject* self) { + ShowDeprecationWarning("getExecutePriority()", "the executePriority property"); return PyInt_FromLong(m_Execute_Ueber_Priority); } diff --git a/source/gameengine/GameLogic/SCA_ILogicBrick.h b/source/gameengine/GameLogic/SCA_ILogicBrick.h index c28711ac0f6..cde1353275b 100644 --- a/source/gameengine/GameLogic/SCA_ILogicBrick.h +++ b/source/gameengine/GameLogic/SCA_ILogicBrick.h @@ -78,7 +78,8 @@ public: virtual bool LessComparedTo(SCA_ILogicBrick* other); - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject *value); static class SCA_LogicManager* m_sCurrentLogicManager; @@ -89,6 +90,9 @@ public: KX_PYMETHOD(SCA_ILogicBrick,SetExecutePriority); KX_PYMETHOD_NOARGS(SCA_ILogicBrick,GetExecutePriority); + // check that attribute is a property + static int CheckProperty(void *self, const PyAttributeDef *attrdef); + enum KX_BOOL_TYPE { KX_BOOL_NODEF = 0, KX_TRUE, diff --git a/source/gameengine/GameLogic/SCA_IObject.cpp b/source/gameengine/GameLogic/SCA_IObject.cpp index b0f8decee26..3afc48b719c 100644 --- a/source/gameengine/GameLogic/SCA_IObject.cpp +++ b/source/gameengine/GameLogic/SCA_IObject.cpp @@ -409,7 +409,7 @@ PyMethodDef SCA_IObject::Methods[] = { -PyObject* SCA_IObject::_getattr(const STR_String& attr) { +PyObject* SCA_IObject::_getattr(const char *attr) { _getattr_up(CValue); } diff --git a/source/gameengine/GameLogic/SCA_IObject.h b/source/gameengine/GameLogic/SCA_IObject.h index 38a7ed29dca..d47353b1ac0 100644 --- a/source/gameengine/GameLogic/SCA_IObject.h +++ b/source/gameengine/GameLogic/SCA_IObject.h @@ -145,7 +145,7 @@ public: // const class MT_Point3& ConvertPythonPylist(PyObject* pylist); // here come the python forwarded methods - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); virtual int GetGameObjectType() {return -1;} diff --git a/source/gameengine/GameLogic/SCA_ISensor.cpp b/source/gameengine/GameLogic/SCA_ISensor.cpp index b10ac676464..e8a072f4c46 100644 --- a/source/gameengine/GameLogic/SCA_ISensor.cpp +++ b/source/gameengine/GameLogic/SCA_ISensor.cpp @@ -139,71 +139,6 @@ void SCA_ISensor::DecLink() { } } -/* python integration */ - -PyTypeObject SCA_ISensor::Type = { - PyObject_HEAD_INIT(&PyType_Type) - 0, - "SCA_ISensor", - sizeof(SCA_ISensor), - 0, - PyDestructor, - 0, - __getattr, - __setattr, - 0, //&MyPyCompare, - __repr, - 0, //&cvalue_as_number, - 0, - 0, - 0, - 0 -}; - -PyParentObject SCA_ISensor::Parents[] = { - &SCA_ISensor::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL -}; -PyMethodDef SCA_ISensor::Methods[] = { - {"isPositive", (PyCFunction) SCA_ISensor::sPyIsPositive, - METH_NOARGS, (PY_METHODCHAR)IsPositive_doc}, - {"isTriggered", (PyCFunction) SCA_ISensor::sPyIsTriggered, - METH_VARARGS, (PY_METHODCHAR)IsTriggered_doc}, - {"getUsePosPulseMode", (PyCFunction) SCA_ISensor::sPyGetUsePosPulseMode, - METH_NOARGS, (PY_METHODCHAR)GetUsePosPulseMode_doc}, - {"setUsePosPulseMode", (PyCFunction) SCA_ISensor::sPySetUsePosPulseMode, - METH_VARARGS, (PY_METHODCHAR)SetUsePosPulseMode_doc}, - {"getFrequency", (PyCFunction) SCA_ISensor::sPyGetFrequency, - METH_NOARGS, (PY_METHODCHAR)GetFrequency_doc}, - {"setFrequency", (PyCFunction) SCA_ISensor::sPySetFrequency, - METH_VARARGS, (PY_METHODCHAR)SetFrequency_doc}, - {"getUseNegPulseMode", (PyCFunction) SCA_ISensor::sPyGetUseNegPulseMode, - METH_NOARGS, (PY_METHODCHAR)GetUseNegPulseMode_doc}, - {"setUseNegPulseMode", (PyCFunction) SCA_ISensor::sPySetUseNegPulseMode, - METH_VARARGS, (PY_METHODCHAR)SetUseNegPulseMode_doc}, - {"getInvert", (PyCFunction) SCA_ISensor::sPyGetInvert, - METH_NOARGS, (PY_METHODCHAR)GetInvert_doc}, - {"setInvert", (PyCFunction) SCA_ISensor::sPySetInvert, - METH_VARARGS, (PY_METHODCHAR)SetInvert_doc}, - {"getLevel", (PyCFunction) SCA_ISensor::sPyGetLevel, - METH_NOARGS, (PY_METHODCHAR)GetLevel_doc}, - {"setLevel", (PyCFunction) SCA_ISensor::sPySetLevel, - METH_VARARGS, (PY_METHODCHAR)SetLevel_doc}, - {"reset", (PyCFunction) SCA_ISensor::sPyReset, - METH_NOARGS, (PY_METHODCHAR)Reset_doc}, - {NULL,NULL} //Sentinel -}; - - -PyObject* -SCA_ISensor::_getattr(const STR_String& attr) -{ - _getattr_up(SCA_ILogicBrick); -} - - void SCA_ISensor::RegisterToManager() { // sensor is just activated, initialize it @@ -275,13 +210,17 @@ void SCA_ISensor::Activate(class SCA_LogicManager* logicmgr, CValue* event) } } } +/* ----------------------------------------------- */ +/* Python Functions */ +/* ----------------------------------------------- */ -/* Python functions: */ +//Deprecated Functions ------> const char SCA_ISensor::IsPositive_doc[] = "isPositive()\n" "\tReturns whether the sensor is in an active state.\n"; PyObject* SCA_ISensor::PyIsPositive(PyObject* self) { + ShowDeprecationWarning("isPositive()", "the read-only positive property"); int retval = IsPositiveTrigger(); return PyInt_FromLong(retval); } @@ -291,6 +230,7 @@ const char SCA_ISensor::IsTriggered_doc[] = "\tReturns whether the sensor has triggered the current controller.\n"; PyObject* SCA_ISensor::PyIsTriggered(PyObject* self) { + ShowDeprecationWarning("isTriggered()", "the read-only triggered property"); // check with the current controller int retval = 0; if (SCA_PythonController::m_sCurrentController) @@ -306,6 +246,7 @@ const char SCA_ISensor::GetUsePosPulseMode_doc[] = "\tReturns whether positive pulse mode is active.\n"; PyObject* SCA_ISensor::PyGetUsePosPulseMode(PyObject* self) { + ShowDeprecationWarning("getUsePosPulseMode()", "the usePosPulseMode property"); return BoolToPyArg(m_pos_pulsemode); } @@ -319,10 +260,11 @@ const char SCA_ISensor::SetUsePosPulseMode_doc[] = "\tSet whether to do pulsing when positive pulses occur.\n"; PyObject* SCA_ISensor::PySetUsePosPulseMode(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setUsePosPulseMode()", "the usePosPulseMode property"); int pyarg = 0; if(!PyArg_ParseTuple(args, "i", &pyarg)) { return NULL; } m_pos_pulsemode = PyArgToBool(pyarg); - Py_Return; + Py_RETURN_NONE; } /** @@ -333,6 +275,7 @@ const char SCA_ISensor::GetFrequency_doc[] = "\tReturns the frequency of the updates in pulse mode.\n" ; PyObject* SCA_ISensor::PyGetFrequency(PyObject* self) { + ShowDeprecationWarning("getFrequency()", "the frequency property"); return PyInt_FromLong(m_pulse_frequency); } @@ -346,6 +289,7 @@ const char SCA_ISensor::SetFrequency_doc[] = "\tIf the frequency is negative, it is set to 0.\n" ; PyObject* SCA_ISensor::PySetFrequency(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setFrequency()", "the frequency property"); int pulse_frequencyArg = 0; if(!PyArg_ParseTuple(args, "i", &pulse_frequencyArg)) { @@ -359,7 +303,7 @@ PyObject* SCA_ISensor::PySetFrequency(PyObject* self, PyObject* args, PyObject* }; m_pulse_frequency = pulse_frequencyArg; - Py_Return; + Py_RETURN_NONE; } @@ -368,6 +312,7 @@ const char SCA_ISensor::GetInvert_doc[] = "\tReturns whether or not pulses from this sensor are inverted.\n" ; PyObject* SCA_ISensor::PyGetInvert(PyObject* self) { + ShowDeprecationWarning("getInvert()", "the invert property"); return BoolToPyArg(m_invert); } @@ -377,10 +322,11 @@ const char SCA_ISensor::SetInvert_doc[] = "\tSet whether to invert pulses.\n"; PyObject* SCA_ISensor::PySetInvert(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setInvert()", "the invert property"); int pyarg = 0; if(!PyArg_ParseTuple(args, "i", &pyarg)) { return NULL; } m_invert = PyArgToBool(pyarg); - Py_Return; + Py_RETURN_NONE; } const char SCA_ISensor::GetLevel_doc[] = @@ -392,6 +338,7 @@ const char SCA_ISensor::GetLevel_doc[] = "\tA edge detector will wait for a state change before generating a pulse.\n"; PyObject* SCA_ISensor::PyGetLevel(PyObject* self) { + ShowDeprecationWarning("getLevel()", "the level property"); return BoolToPyArg(m_level); } @@ -401,10 +348,11 @@ const char SCA_ISensor::SetLevel_doc[] = "\tSet whether to detect level or edge transition when entering a state.\n"; PyObject* SCA_ISensor::PySetLevel(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setLevel()", "the level property"); int pyarg = 0; if(!PyArg_ParseTuple(args, "i", &pyarg)) { return NULL; } m_level = PyArgToBool(pyarg); - Py_Return; + Py_RETURN_NONE; } const char SCA_ISensor::GetUseNegPulseMode_doc[] = @@ -412,6 +360,7 @@ const char SCA_ISensor::GetUseNegPulseMode_doc[] = "\tReturns whether negative pulse mode is active.\n"; PyObject* SCA_ISensor::PyGetUseNegPulseMode(PyObject* self) { + ShowDeprecationWarning("getUseNegPulseMode()", "the useNegPulseMode property"); return BoolToPyArg(m_neg_pulsemode); } @@ -422,21 +371,121 @@ const char SCA_ISensor::SetUseNegPulseMode_doc[] = "\tSet whether to do pulsing when negative pulses occur.\n"; PyObject* SCA_ISensor::PySetUseNegPulseMode(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setUseNegPulseMode()", "the useNegPulseMode property"); int pyarg = 0; if(!PyArg_ParseTuple(args, "i", &pyarg)) { return NULL; } m_neg_pulsemode = PyArgToBool(pyarg); - Py_Return; + Py_RETURN_NONE; } +//<------Deprecated -const char SCA_ISensor::Reset_doc[] = +KX_PYMETHODDEF_DOC_NOARGS(SCA_ISensor, reset, "reset()\n" "\tReset sensor internal state, effect depends on the type of sensor and settings.\n" -"\tThe sensor is put in its initial state as if it was just activated.\n"; -PyObject* SCA_ISensor::PyReset(PyObject* self) +"\tThe sensor is put in its initial state as if it was just activated.\n") { Init(); - Py_Return; + Py_RETURN_NONE; } +/* ----------------------------------------------- */ +/* Python Integration Hooks */ +/* ----------------------------------------------- */ + +PyTypeObject SCA_ISensor::Type = { + PyObject_HEAD_INIT(&PyType_Type) + 0, + "SCA_ISensor", + sizeof(SCA_ISensor), + 0, + PyDestructor, + 0, + __getattr, + __setattr, + 0, //&MyPyCompare, + __repr, + 0, //&cvalue_as_number, + 0, + 0, + 0, + 0 +}; + +PyParentObject SCA_ISensor::Parents[] = { + &SCA_ISensor::Type, + &SCA_ILogicBrick::Type, + &CValue::Type, + NULL +}; +PyMethodDef SCA_ISensor::Methods[] = { + //Deprecated functions -----> + {"isPositive", (PyCFunction) SCA_ISensor::sPyIsPositive, + METH_NOARGS, (PY_METHODCHAR)IsPositive_doc}, + {"isTriggered", (PyCFunction) SCA_ISensor::sPyIsTriggered, + METH_VARARGS, (PY_METHODCHAR)IsTriggered_doc}, + {"getUsePosPulseMode", (PyCFunction) SCA_ISensor::sPyGetUsePosPulseMode, + METH_NOARGS, (PY_METHODCHAR)GetUsePosPulseMode_doc}, + {"setUsePosPulseMode", (PyCFunction) SCA_ISensor::sPySetUsePosPulseMode, + METH_VARARGS, (PY_METHODCHAR)SetUsePosPulseMode_doc}, + {"getFrequency", (PyCFunction) SCA_ISensor::sPyGetFrequency, + METH_NOARGS, (PY_METHODCHAR)GetFrequency_doc}, + {"setFrequency", (PyCFunction) SCA_ISensor::sPySetFrequency, + METH_VARARGS, (PY_METHODCHAR)SetFrequency_doc}, + {"getUseNegPulseMode", (PyCFunction) SCA_ISensor::sPyGetUseNegPulseMode, + METH_NOARGS, (PY_METHODCHAR)GetUseNegPulseMode_doc}, + {"setUseNegPulseMode", (PyCFunction) SCA_ISensor::sPySetUseNegPulseMode, + METH_VARARGS, (PY_METHODCHAR)SetUseNegPulseMode_doc}, + {"getInvert", (PyCFunction) SCA_ISensor::sPyGetInvert, + METH_NOARGS, (PY_METHODCHAR)GetInvert_doc}, + {"setInvert", (PyCFunction) SCA_ISensor::sPySetInvert, + METH_VARARGS, (PY_METHODCHAR)SetInvert_doc}, + {"getLevel", (PyCFunction) SCA_ISensor::sPyGetLevel, + METH_NOARGS, (PY_METHODCHAR)GetLevel_doc}, + {"setLevel", (PyCFunction) SCA_ISensor::sPySetLevel, + METH_VARARGS, (PY_METHODCHAR)SetLevel_doc}, + //<----- Deprecated + KX_PYMETHODTABLE_NOARGS(SCA_ISensor, reset), + {NULL,NULL} //Sentinel +}; + +PyAttributeDef SCA_ISensor::Attributes[] = { + KX_PYATTRIBUTE_BOOL_RW("usePosPulseMode",SCA_ISensor,m_pos_pulsemode), + KX_PYATTRIBUTE_BOOL_RW("useNegPulseMode",SCA_ISensor,m_neg_pulsemode), + KX_PYATTRIBUTE_INT_RW("frequency",0,100000,true,SCA_ISensor,m_pulse_frequency), + KX_PYATTRIBUTE_BOOL_RW("invert",SCA_ISensor,m_invert), + KX_PYATTRIBUTE_BOOL_RW("level",SCA_ISensor,m_level), + // make these properties read-only in _setaddr, must still implement them in _getattr + KX_PYATTRIBUTE_DUMMY("triggered"), + KX_PYATTRIBUTE_DUMMY("positive"), + { NULL } //Sentinel +}; +PyObject* +SCA_ISensor::_getattr(const char *attr) +{ + PyObject* object = _getattr_self(Attributes, this, attr); + if (object != NULL) + return object; + if (!strcmp(attr, "triggered")) + { + int retval = 0; + if (SCA_PythonController::m_sCurrentController) + retval = SCA_PythonController::m_sCurrentController->IsTriggered(this); + return PyInt_FromLong(retval); + } + if (!strcmp(attr, "positive")) + { + int retval = IsPositiveTrigger(); + return PyInt_FromLong(retval); + } + _getattr_up(SCA_ILogicBrick); +} + +int SCA_ISensor::_setattr(const char *attr, PyObject *value) +{ + int ret = _setattr_self(Attributes, this, attr, value); + if (ret >= 0) + return ret; + return SCA_ILogicBrick::_setattr(attr, value); +} /* eof */ diff --git a/source/gameengine/GameLogic/SCA_ISensor.h b/source/gameengine/GameLogic/SCA_ISensor.h index d1872009291..5ae7ced2a2a 100644 --- a/source/gameengine/GameLogic/SCA_ISensor.h +++ b/source/gameengine/GameLogic/SCA_ISensor.h @@ -93,8 +93,7 @@ public: virtual bool Evaluate(CValue* event) = 0; virtual bool IsPositiveTrigger(); virtual void Init(); - - virtual PyObject* _getattr(const STR_String& attr); + virtual CValue* GetReplica()=0; /** Set parameters for the pulsing behaviour. @@ -141,6 +140,11 @@ public: { return !m_links; } /* Python functions: */ + + virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject *value); + + //Deprecated functions -----> KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,IsPositive); KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,IsTriggered); KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,GetUsePosPulseMode); @@ -153,8 +157,8 @@ public: KX_PYMETHOD_DOC(SCA_ISensor,SetInvert); KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,GetLevel); KX_PYMETHOD_DOC(SCA_ISensor,SetLevel); - KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,Reset); - + //<------ + KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,reset); }; #endif //__SCA_ISENSOR diff --git a/source/gameengine/GameLogic/SCA_JoystickSensor.cpp b/source/gameengine/GameLogic/SCA_JoystickSensor.cpp index 8b96840b149..c2d90c830cf 100644 --- a/source/gameengine/GameLogic/SCA_JoystickSensor.cpp +++ b/source/gameengine/GameLogic/SCA_JoystickSensor.cpp @@ -304,6 +304,7 @@ PyParentObject SCA_JoystickSensor::Parents[] = { PyMethodDef SCA_JoystickSensor::Methods[] = { + //Deprecated functions ------> {"getIndex", (PyCFunction) SCA_JoystickSensor::sPyGetIndex, METH_NOARGS, (PY_METHODCHAR)GetIndex_doc}, {"setIndex", (PyCFunction) SCA_JoystickSensor::sPySetIndex, METH_O, (PY_METHODCHAR)SetIndex_doc}, {"getAxis", (PyCFunction) SCA_JoystickSensor::sPyGetAxis, METH_NOARGS, (PY_METHODCHAR)GetAxis_doc}, @@ -313,27 +314,76 @@ PyMethodDef SCA_JoystickSensor::Methods[] = { {"setThreshold", (PyCFunction) SCA_JoystickSensor::sPySetThreshold, METH_VARARGS, (PY_METHODCHAR)SetThreshold_doc}, {"getButton", (PyCFunction) SCA_JoystickSensor::sPyGetButton, METH_NOARGS, (PY_METHODCHAR)GetButton_doc}, {"setButton", (PyCFunction) SCA_JoystickSensor::sPySetButton, METH_O, (PY_METHODCHAR)SetButton_doc}, - {"getButtonValue",(PyCFunction) SCA_JoystickSensor::sPyGetButtonValue, METH_NOARGS,(PY_METHODCHAR)GetButtonValue_doc}, {"getHat", (PyCFunction) SCA_JoystickSensor::sPyGetHat, METH_NOARGS, (PY_METHODCHAR)GetHat_doc}, {"setHat", (PyCFunction) SCA_JoystickSensor::sPySetHat, METH_VARARGS, (PY_METHODCHAR)SetHat_doc}, {"getNumAxes", (PyCFunction) SCA_JoystickSensor::sPyNumberOfAxes, METH_NOARGS, (PY_METHODCHAR)NumberOfAxes_doc}, {"getNumButtons",(PyCFunction) SCA_JoystickSensor::sPyNumberOfButtons,METH_NOARGS, (PY_METHODCHAR)NumberOfButtons_doc}, {"getNumHats", (PyCFunction) SCA_JoystickSensor::sPyNumberOfHats, METH_NOARGS, (PY_METHODCHAR)NumberOfHats_doc}, {"isConnected", (PyCFunction) SCA_JoystickSensor::sPyConnected, METH_NOARGS, (PY_METHODCHAR)Connected_doc}, + {"getButtonValue",(PyCFunction) SCA_JoystickSensor::sPyGetButtonValue, METH_NOARGS,(PY_METHODCHAR)GetButtonValue_doc}, + //<----- Deprecated + {"getButtonActiveList",(PyCFunction) SCA_JoystickSensor::sPyGetButtonActiveList, METH_NOARGS,(PY_METHODCHAR)GetButtonActiveList_doc}, + {"getButtonStatus",(PyCFunction) SCA_JoystickSensor::sPyGetButtonStatus, METH_VARARGS,(PY_METHODCHAR)GetButtonStatus_doc}, {NULL,NULL} //Sentinel }; +PyAttributeDef SCA_JoystickSensor::Attributes[] = { + KX_PYATTRIBUTE_SHORT_RW("index",0,JOYINDEX_MAX-1,true,SCA_JoystickSensor,m_joyindex), + KX_PYATTRIBUTE_INT_RW("threshold",0,32768,true,SCA_JoystickSensor,m_precision), + KX_PYATTRIBUTE_INT_RW("button",0,100,false,SCA_JoystickSensor,m_button), + KX_PYATTRIBUTE_INT_LIST_RW_CHECK("axis",0,3,true,SCA_JoystickSensor,m_axis,2,CheckAxis), + KX_PYATTRIBUTE_INT_LIST_RW_CHECK("hat",0,12,true,SCA_JoystickSensor,m_hat,2,CheckHat), + // dummy attributes will just be read-only in _setattr + // you still need to defined them in _getattr + KX_PYATTRIBUTE_DUMMY("axisPosition"), + KX_PYATTRIBUTE_DUMMY("numAxis"), + KX_PYATTRIBUTE_DUMMY("numButtons"), + KX_PYATTRIBUTE_DUMMY("numHats"), + KX_PYATTRIBUTE_DUMMY("connected"), + { NULL } //Sentinel +}; -PyObject* SCA_JoystickSensor::_getattr(const STR_String& attr) { +PyObject* SCA_JoystickSensor::_getattr(const char *attr) { + SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex); + if (!strcmp(attr, "axisPosition")) { + if(joy) + return Py_BuildValue("[iiii]", joy->GetAxis10(), joy->GetAxis11(), joy->GetAxis20(), joy->GetAxis21()); + else + return Py_BuildValue("[iiii]", 0, 0, 0, 0); + } + if (!strcmp(attr, "numAxis")) { + return PyInt_FromLong( joy ? joy->GetNumberOfAxes() : 0 ); + } + if (!strcmp(attr, "numButtons")) { + return PyInt_FromLong( joy ? joy->GetNumberOfButtons() : 0 ); + } + if (!strcmp(attr, "numHats")) { + return PyInt_FromLong( joy ? joy->GetNumberOfHats() : 0 ); + } + if (!strcmp(attr, "connected")) { + return PyBool_FromLong( joy ? joy->Connected() : 0 ); + } + PyObject* object = _getattr_self(Attributes, this, attr); + if (object != NULL) + return object; _getattr_up(SCA_ISensor); } +int SCA_JoystickSensor::_setattr(const char *attr, PyObject *value) +{ + int ret = _setattr_self(Attributes, this, attr, value); + if (ret >= 0) + return ret; + return SCA_ISensor::_setattr(attr, value); +} + /* get index ---------------------------------------------------------- */ const char SCA_JoystickSensor::GetIndex_doc[] = "getIndex\n" "\tReturns the joystick index to use.\n"; PyObject* SCA_JoystickSensor::PyGetIndex( PyObject* self ) { + ShowDeprecationWarning("getIndex()", "the index property"); return PyInt_FromLong(m_joyindex); } @@ -343,6 +393,7 @@ const char SCA_JoystickSensor::SetIndex_doc[] = "setIndex\n" "\tSets the joystick index to use.\n"; PyObject* SCA_JoystickSensor::PySetIndex( PyObject* self, PyObject* value ) { + ShowDeprecationWarning("setIndex()", "the index property"); int index = PyInt_AsLong( value ); /* -1 on error, will raise an error in this case */ if (index < 0 || index >= JOYINDEX_MAX) { PyErr_SetString(PyExc_ValueError, "joystick index out of range or not an int"); @@ -358,6 +409,7 @@ const char SCA_JoystickSensor::GetAxis_doc[] = "getAxis\n" "\tReturns the current axis this sensor reacts to.\n"; PyObject* SCA_JoystickSensor::PyGetAxis( PyObject* self) { + ShowDeprecationWarning("getAxis()", "the axis property"); return Py_BuildValue("[ii]",m_axis, m_axisf); } @@ -367,6 +419,7 @@ const char SCA_JoystickSensor::SetAxis_doc[] = "setAxis\n" "\tSets the current axis this sensor reacts to.\n"; PyObject* SCA_JoystickSensor::PySetAxis( PyObject* self, PyObject* args ) { + ShowDeprecationWarning("setAxis()", "the axis property"); int axis,axisflag; if(!PyArg_ParseTuple(args, "ii", &axis, &axisflag)){ @@ -383,6 +436,7 @@ const char SCA_JoystickSensor::GetAxisValue_doc[] = "getAxisValue\n" "\tReturns a list of the values for the current state of each axis.\n"; PyObject* SCA_JoystickSensor::PyGetAxisValue( PyObject* self) { + ShowDeprecationWarning("getAxisValue()", "the axisPosition property"); SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex); if(joy) return Py_BuildValue("[iiii]", joy->GetAxis10(), joy->GetAxis11(), joy->GetAxis20(), joy->GetAxis21()); @@ -396,6 +450,7 @@ const char SCA_JoystickSensor::GetThreshold_doc[] = "getThreshold\n" "\tReturns the threshold of the axis.\n"; PyObject* SCA_JoystickSensor::PyGetThreshold( PyObject* self) { + ShowDeprecationWarning("getThreshold()", "the threshold property"); return PyInt_FromLong(m_precision); } @@ -405,6 +460,7 @@ const char SCA_JoystickSensor::SetThreshold_doc[] = "setThreshold\n" "\tSets the threshold of the axis.\n"; PyObject* SCA_JoystickSensor::PySetThreshold( PyObject* self, PyObject* args ) { + ShowDeprecationWarning("setThreshold()", "the threshold property"); int thresh; if(!PyArg_ParseTuple(args, "i", &thresh)){ return NULL; @@ -418,6 +474,7 @@ const char SCA_JoystickSensor::GetButton_doc[] = "getButton\n" "\tReturns the current button this sensor is checking.\n"; PyObject* SCA_JoystickSensor::PyGetButton( PyObject* self) { + ShowDeprecationWarning("getButton()", "the button property"); return PyInt_FromLong(m_button); } @@ -426,6 +483,7 @@ const char SCA_JoystickSensor::SetButton_doc[] = "setButton\n" "\tSets the button the sensor reacts to.\n"; PyObject* SCA_JoystickSensor::PySetButton( PyObject* self, PyObject* value ) { + ShowDeprecationWarning("setButton()", "the button property"); int button = PyInt_AsLong(value); if(button==-1 && PyErr_Occurred()) { PyErr_SetString(PyExc_ValueError, "expected an int"); @@ -440,6 +498,15 @@ const char SCA_JoystickSensor::GetButtonValue_doc[] = "getButtonValue\n" "\tReturns a list containing the indicies of the current pressed state of each button.\n"; PyObject* SCA_JoystickSensor::PyGetButtonValue( PyObject* self) { + ShowDeprecationWarning("getButtonValue()", "getButtonActiveList"); + return PyGetButtonActiveList(self); +} + +/* get button active list -------------------------------------------------- */ +const char SCA_JoystickSensor::GetButtonActiveList_doc[] = +"getButtonActiveList\n" +"\tReturns a list containing the indicies of the button currently pressed.\n"; +PyObject* SCA_JoystickSensor::PyGetButtonActiveList( PyObject* self) { SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex); PyObject *ls = PyList_New(0); PyObject *value; @@ -457,11 +524,30 @@ PyObject* SCA_JoystickSensor::PyGetButtonValue( PyObject* self) { return ls; } +/* get button status -------------------------------------------------- */ +const char SCA_JoystickSensor::GetButtonStatus_doc[] = +"getButtonStatus(buttonIndex)\n" +"\tReturns a bool of the current pressed state of the specified button.\n"; +PyObject* SCA_JoystickSensor::PyGetButtonStatus( PyObject* self, PyObject* args ) { + SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex); + PyObject *value; + int index; + + if(!PyArg_ParseTuple(args, "i", &index)){ + return NULL; + } + if(joy && index >= 0 && index < joy->GetNumberOfButtons()) { + return PyBool_FromLong(joy->aButtonPressIsPositive(index) ? 1 : 0); + } + return PyBool_FromLong(0); +} + /* get hat ----------------------------------------------------------- */ const char SCA_JoystickSensor::GetHat_doc[] = "getHat\n" "\tReturns the current direction of the hat.\n"; PyObject* SCA_JoystickSensor::PyGetHat( PyObject* self ) { + ShowDeprecationWarning("getHat()", "the hat property"); return Py_BuildValue("[ii]",m_hat, m_hatf); } @@ -471,6 +557,7 @@ const char SCA_JoystickSensor::SetHat_doc[] = "setHat\n" "\tSets the hat the sensor reacts to.\n"; PyObject* SCA_JoystickSensor::PySetHat( PyObject* self, PyObject* args ) { + ShowDeprecationWarning("setHat()", "the hat property"); int hat,hatflag; if(!PyArg_ParseTuple(args, "ii", &hat, &hatflag)){ return NULL; @@ -486,6 +573,7 @@ const char SCA_JoystickSensor::NumberOfAxes_doc[] = "getNumAxes\n" "\tReturns the number of axes .\n"; PyObject* SCA_JoystickSensor::PyNumberOfAxes( PyObject* self ) { + ShowDeprecationWarning("getNumAxes()", "the numAxis property"); SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex); // when the joystick is null their is 0 exis still. dumb but scripters should use isConnected() return PyInt_FromLong( joy ? joy->GetNumberOfAxes() : 0 ); @@ -496,6 +584,7 @@ const char SCA_JoystickSensor::NumberOfButtons_doc[] = "getNumButtons\n" "\tReturns the number of buttons .\n"; PyObject* SCA_JoystickSensor::PyNumberOfButtons( PyObject* self ) { + ShowDeprecationWarning("getNumButtons()", "the numButtons property"); SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex); return PyInt_FromLong( joy ? joy->GetNumberOfButtons() : 0 ); } @@ -505,6 +594,7 @@ const char SCA_JoystickSensor::NumberOfHats_doc[] = "getNumHats\n" "\tReturns the number of hats .\n"; PyObject* SCA_JoystickSensor::PyNumberOfHats( PyObject* self ) { + ShowDeprecationWarning("getNumHats()", "the numHats property"); SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex); return PyInt_FromLong( joy ? joy->GetNumberOfHats() : 0 ); } @@ -513,6 +603,7 @@ const char SCA_JoystickSensor::Connected_doc[] = "getConnected\n" "\tReturns True if a joystick is connected at this joysticks index.\n"; PyObject* SCA_JoystickSensor::PyConnected( PyObject* self ) { + ShowDeprecationWarning("getConnected()", "the connected property"); SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex); return PyBool_FromLong( joy ? joy->Connected() : 0 ); } diff --git a/source/gameengine/GameLogic/SCA_JoystickSensor.h b/source/gameengine/GameLogic/SCA_JoystickSensor.h index d316ad1119c..49d220c056d 100644 --- a/source/gameengine/GameLogic/SCA_JoystickSensor.h +++ b/source/gameengine/GameLogic/SCA_JoystickSensor.h @@ -37,11 +37,11 @@ class SCA_JoystickSensor :public SCA_ISensor class SCA_JoystickManager* m_pJoystickMgr; /** - * Axis 1-or-2 + * Axis 1-or-2, MUST be followed by m_axisf */ int m_axis; /** - * Axis flag to find direction + * Axis flag to find direction, MUST be an int */ int m_axisf; /** @@ -53,11 +53,11 @@ class SCA_JoystickSensor :public SCA_ISensor */ int m_buttonf; /** - * The actual hat + * The actual hat. MUST be followed by m_hatf */ int m_hat; /** - * Flag to find direction 1-12 + * Flag to find direction 0-11, MUST be an int */ int m_hatf; /** @@ -121,7 +121,8 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject *value); /* Joystick Index */ KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,GetIndex); @@ -136,6 +137,8 @@ public: KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,GetButton); KX_PYMETHOD_DOC_O(SCA_JoystickSensor,SetButton); KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,GetButtonValue); + KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,GetButtonActiveList); + KX_PYMETHOD_DOC_VARARGS(SCA_JoystickSensor,GetButtonStatus); /* Hats */ KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,GetHat); KX_PYMETHOD_DOC_VARARGS(SCA_JoystickSensor,SetHat); @@ -144,6 +147,26 @@ public: KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,NumberOfButtons); KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,NumberOfHats); KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,Connected); + + /* attribute check */ + static int CheckAxis(void *self, const PyAttributeDef*) + { + SCA_JoystickSensor* sensor = reinterpret_cast<SCA_JoystickSensor*>(self); + if (sensor->m_axis < 1) + sensor->m_axis = 1; + else if (sensor->m_axis > 2) + sensor->m_axis = 2; + return 0; + } + static int CheckHat(void *self, const PyAttributeDef*) + { + SCA_JoystickSensor* sensor = reinterpret_cast<SCA_JoystickSensor*>(self); + if (sensor->m_hat < 1) + sensor->m_hat = 1; + else if (sensor->m_hat > 2) + sensor->m_hat = 2; + return 0; + } }; diff --git a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp index fa39a13679f..324e5eae98a 100644 --- a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp +++ b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp @@ -545,42 +545,17 @@ void SCA_KeyboardSensor::LogKeystrokes(void) /* ------------------------------------------------------------------------- */ -/* Python functions : specific */ +/* Python Functions */ /* ------------------------------------------------------------------------- */ - -PyObject* SCA_KeyboardSensor::PySetAllMode(PyObject* self, - PyObject* args, - PyObject* kwds) -{ - bool allkeys; - - if (!PyArg_ParseTuple(args, "i", &allkeys)) - { - return NULL; - } - - m_bAllKeys = allkeys; - Py_Return -} - - - -PyObject* SCA_KeyboardSensor::sPySetAllMode(PyObject* self, - PyObject* args, - PyObject* kwds) -{ -// printf("sPyIsPositive\n"); - return ((SCA_KeyboardSensor*) self)->PyIsPositive(self); -} - - +//Deprecated -----> /** 1. GetKey : check which key this sensor looks at */ const char SCA_KeyboardSensor::GetKey_doc[] = "getKey()\n" "\tReturn the code of the key this sensor is listening to.\n" ; PyObject* SCA_KeyboardSensor::PyGetKey(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getKey()", "the key property"); return PyInt_FromLong(m_hotkey); } @@ -591,6 +566,7 @@ const char SCA_KeyboardSensor::SetKey_doc[] = "\tSet the key this sensor should listen to.\n" ; PyObject* SCA_KeyboardSensor::PySetKey(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setKey()", "the key property"); int keyCode; if(!PyArg_ParseTuple(args, "i", &keyCode)) { @@ -601,7 +577,7 @@ PyObject* SCA_KeyboardSensor::PySetKey(PyObject* self, PyObject* args, PyObject* /* anything. It's up to the user to provide a sensible number. */ m_hotkey = keyCode; - Py_Return; + Py_RETURN_NONE; } /** 3. GetHold1 : set the first bucky bit */ @@ -611,6 +587,7 @@ const char SCA_KeyboardSensor::GetHold1_doc[] = "\tsensor is listening to.\n" ; PyObject* SCA_KeyboardSensor::PyGetHold1(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getHold1()", "the hold1 property"); return PyInt_FromLong(m_qual); } @@ -621,6 +598,7 @@ const char SCA_KeyboardSensor::SetHold1_doc[] = "\tSet the first modifier to the key this sensor should listen to.\n" ; PyObject* SCA_KeyboardSensor::PySetHold1(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setHold1()", "the hold1 property"); int keyCode; if(!PyArg_ParseTuple(args, "i", &keyCode)) { @@ -631,7 +609,7 @@ PyObject* SCA_KeyboardSensor::PySetHold1(PyObject* self, PyObject* args, PyObjec /* anything. It's up to the user to provide a sensible number. */ m_qual = keyCode; - Py_Return; + Py_RETURN_NONE; } /** 5. GetHold2 : get the second bucky bit */ @@ -641,6 +619,7 @@ const char SCA_KeyboardSensor::GetHold2_doc[] = "\tsensor is listening to.\n" ; PyObject* SCA_KeyboardSensor::PyGetHold2(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getHold2()", "the hold2 property"); return PyInt_FromLong(m_qual2); } @@ -651,6 +630,7 @@ const char SCA_KeyboardSensor::SetHold2_doc[] = "\tSet the first modifier to the key this sensor should listen to.\n" ; PyObject* SCA_KeyboardSensor::PySetHold2(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setHold2()", "the hold2 property"); int keyCode; if(!PyArg_ParseTuple(args, "i", &keyCode)) { @@ -661,7 +641,7 @@ PyObject* SCA_KeyboardSensor::PySetHold2(PyObject* self, PyObject* args, PyObjec /* anything. It's up to the user to provide a sensible number. */ m_qual2 = keyCode; - Py_Return; + Py_RETURN_NONE; } @@ -671,6 +651,8 @@ const char SCA_KeyboardSensor::GetPressedKeys_doc[] = PyObject* SCA_KeyboardSensor::PyGetPressedKeys(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getPressedKeys()", "getEventList()"); + SCA_IInputDevice* inputdev = m_pKeyboardMgr->GetInputDevice(); int num = inputdev->GetNumJustEvents(); @@ -700,7 +682,7 @@ PyObject* SCA_KeyboardSensor::PyGetPressedKeys(PyObject* self, PyObject* args, P if (index>0) return resultlist; } - Py_Return; + Py_RETURN_NONE; } @@ -711,6 +693,8 @@ const char SCA_KeyboardSensor::GetCurrentlyPressedKeys_doc[] = PyObject* SCA_KeyboardSensor::PyGetCurrentlyPressedKeys(PyObject* self, PyObject* args, PyObject* kwds) { +ShowDeprecationWarning("getCurrentlyPressedKeys()", "getEventList()"); + SCA_IInputDevice* inputdev = m_pKeyboardMgr->GetInputDevice(); int num = inputdev->GetNumActiveEvents(); @@ -741,11 +725,56 @@ SCA_IInputDevice* inputdev = m_pKeyboardMgr->GetInputDevice(); if (index > 0) return resultlist; } - Py_Return; + Py_RETURN_NONE; +} +//<---- Deprecated + +KX_PYMETHODDEF_DOC_NOARGS(SCA_KeyboardSensor, getEventList, +"getEventList()\n" +"\tGet the list of the keyboard events in this frame.\n") +{ + SCA_IInputDevice* inputdev = m_pKeyboardMgr->GetInputDevice(); + + PyObject* resultlist = PyList_New(0); + + for (int i=SCA_IInputDevice::KX_BEGINKEY ; i< SCA_IInputDevice::KX_ENDKEY;i++) + { + const SCA_InputEvent & inevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) i); + if (inevent.m_status != SCA_InputEvent::KX_NO_INPUTSTATUS) + { + PyObject* keypair = PyList_New(2); + PyList_SetItem(keypair,0,PyInt_FromLong(i)); + PyList_SetItem(keypair,1,PyInt_FromLong(inevent.m_status)); + PyList_Append(resultlist,keypair); + } + } + return resultlist; +} + +KX_PYMETHODDEF_DOC_O(SCA_KeyboardSensor, getKeyStatus, +"getKeyStatus(keycode)\n" +"\tGet the given key's status (KX_NO_INPUTSTATUS, KX_JUSTACTIVATED, KX_ACTIVE or KX_JUSTRELEASED).\n") +{ + if (PyInt_Check(value)) + { + int keycode = PyInt_AsLong(value); + + if ((keycode < SCA_IInputDevice::KX_BEGINKEY) + || (keycode > SCA_IInputDevice::KX_ENDKEY)){ + PyErr_SetString(PyExc_AttributeError, "invalid keycode specified!"); + return NULL; + } + + SCA_IInputDevice* inputdev = m_pKeyboardMgr->GetInputDevice(); + const SCA_InputEvent & inevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) keycode); + return PyInt_FromLong(inevent.m_status); + } + + Py_RETURN_NONE; } /* ------------------------------------------------------------------------- */ -/* Python functions : integration hooks */ +/* Python Integration Hooks */ /* ------------------------------------------------------------------------- */ PyTypeObject SCA_KeyboardSensor::Type = { @@ -776,23 +805,44 @@ PyParentObject SCA_KeyboardSensor::Parents[] = { }; PyMethodDef SCA_KeyboardSensor::Methods[] = { - {"getKey", (PyCFunction) SCA_KeyboardSensor::sPyGetKey, METH_VARARGS, (PY_METHODCHAR)GetKey_doc}, - {"setKey", (PyCFunction) SCA_KeyboardSensor::sPySetKey, METH_VARARGS, (PY_METHODCHAR)SetKey_doc}, - {"getHold1", (PyCFunction) SCA_KeyboardSensor::sPyGetHold1, METH_VARARGS, (PY_METHODCHAR)GetHold1_doc}, - {"setHold1", (PyCFunction) SCA_KeyboardSensor::sPySetHold1, METH_VARARGS, (PY_METHODCHAR)SetHold1_doc}, - {"getHold2", (PyCFunction) SCA_KeyboardSensor::sPyGetHold2, METH_VARARGS, (PY_METHODCHAR)GetHold2_doc}, - {"setHold2", (PyCFunction) SCA_KeyboardSensor::sPySetHold2, METH_VARARGS, (PY_METHODCHAR)SetHold2_doc}, -// {"getUseAllKeys", (PyCFunction) SCA_KeyboardSensor::sPyGetUseAllKeys, METH_VARARGS, (PY_METHODCHAR)GetUseAllKeys_doc}, -// {"setUseAllKeys", (PyCFunction) SCA_KeyboardSensor::sPySetUseAllKeys, METH_VARARGS, (PY_METHODCHAR)SetUseAllKeys_doc}, - {"getPressedKeys", (PyCFunction) SCA_KeyboardSensor::sPyGetPressedKeys, METH_VARARGS, (PY_METHODCHAR)GetPressedKeys_doc}, - {"getCurrentlyPressedKeys", (PyCFunction) SCA_KeyboardSensor::sPyGetCurrentlyPressedKeys, METH_VARARGS, (PY_METHODCHAR)GetCurrentlyPressedKeys_doc}, -// {"getKeyEvents", (PyCFunction) SCA_KeyboardSensor::sPyGetKeyEvents, METH_VARARGS, (PY_METHODCHAR)GetKeyEvents_doc}, - {NULL,NULL} //Sentinel + //Deprecated functions ------> + {"getKey", (PyCFunction) SCA_KeyboardSensor::sPyGetKey, METH_VARARGS, (PY_METHODCHAR)GetKey_doc}, + {"setKey", (PyCFunction) SCA_KeyboardSensor::sPySetKey, METH_VARARGS, (PY_METHODCHAR)SetKey_doc}, + {"getHold1", (PyCFunction) SCA_KeyboardSensor::sPyGetHold1, METH_VARARGS, (PY_METHODCHAR)GetHold1_doc}, + {"setHold1", (PyCFunction) SCA_KeyboardSensor::sPySetHold1, METH_VARARGS, (PY_METHODCHAR)SetHold1_doc}, + {"getHold2", (PyCFunction) SCA_KeyboardSensor::sPyGetHold2, METH_VARARGS, (PY_METHODCHAR)GetHold2_doc}, + {"setHold2", (PyCFunction) SCA_KeyboardSensor::sPySetHold2, METH_VARARGS, (PY_METHODCHAR)SetHold2_doc}, + {"getPressedKeys", (PyCFunction) SCA_KeyboardSensor::sPyGetPressedKeys, METH_VARARGS, (PY_METHODCHAR)GetPressedKeys_doc}, + {"getCurrentlyPressedKeys", (PyCFunction) SCA_KeyboardSensor::sPyGetCurrentlyPressedKeys, METH_VARARGS, (PY_METHODCHAR)GetCurrentlyPressedKeys_doc}, + //<----- Deprecated + KX_PYMETHODTABLE_NOARGS(SCA_KeyboardSensor, getEventList), + KX_PYMETHODTABLE_O(SCA_KeyboardSensor, getKeyStatus), + {NULL,NULL} //Sentinel +}; + +PyAttributeDef SCA_KeyboardSensor::Attributes[] = { + KX_PYATTRIBUTE_BOOL_RW("useAllKeys",SCA_KeyboardSensor,m_bAllKeys), + KX_PYATTRIBUTE_INT_RW("key",0,SCA_IInputDevice::KX_ENDKEY,true,SCA_KeyboardSensor,m_hotkey), + KX_PYATTRIBUTE_SHORT_RW("hold1",0,SCA_IInputDevice::KX_ENDKEY,true,SCA_KeyboardSensor,m_qual), + KX_PYATTRIBUTE_SHORT_RW("hold2",0,SCA_IInputDevice::KX_ENDKEY,true,SCA_KeyboardSensor,m_qual2), + KX_PYATTRIBUTE_STRING_RW("toggleProperty",0,100,false,SCA_KeyboardSensor,m_toggleprop), + KX_PYATTRIBUTE_STRING_RW("targetProperty",0,100,false,SCA_KeyboardSensor,m_targetprop), + { NULL } //Sentinel }; PyObject* -SCA_KeyboardSensor::_getattr(const STR_String& attr) +SCA_KeyboardSensor::_getattr(const char *attr) { + PyObject* object = _getattr_self(Attributes, this, attr); + if (object != NULL) + return object; _getattr_up(SCA_ISensor); } +int SCA_KeyboardSensor::_setattr(const char *attr, PyObject *value) +{ + int ret = _setattr_self(Attributes, this, attr, value); + if (ret >= 0) + return ret; + return SCA_ISensor::_setattr(attr, value); +} diff --git a/source/gameengine/GameLogic/SCA_KeyboardSensor.h b/source/gameengine/GameLogic/SCA_KeyboardSensor.h index b86f6931d27..bc2f86327a5 100644 --- a/source/gameengine/GameLogic/SCA_KeyboardSensor.h +++ b/source/gameengine/GameLogic/SCA_KeyboardSensor.h @@ -126,16 +126,10 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject *value); - - PyObject* PySetAllMode(PyObject* self, - PyObject* args, - PyObject* kwds); - static PyObject* sPySetAllMode(PyObject* self, - PyObject* args, - PyObject* kwds); - + //Deprecated functions -----> /** 1. GetKey : check which key this sensor looks at */ KX_PYMETHOD_DOC(SCA_KeyboardSensor,GetKey); /** 2. SetKey: change the key to look at */ @@ -152,6 +146,12 @@ public: KX_PYMETHOD_DOC(SCA_KeyboardSensor,GetPressedKeys); /** 9. GetCurrrentlyPressedKeys: */ KX_PYMETHOD_DOC(SCA_KeyboardSensor,GetCurrentlyPressedKeys); + // <------ + + // KeyEvents: + KX_PYMETHOD_DOC_NOARGS(SCA_KeyboardSensor,getEventList); + // KeyStatus: + KX_PYMETHOD_DOC_O(SCA_KeyboardSensor,getKeyStatus); }; #endif //__KX_KEYBOARDSENSOR diff --git a/source/gameengine/GameLogic/SCA_MouseSensor.cpp b/source/gameengine/GameLogic/SCA_MouseSensor.cpp index d4952ce4777..4f4d62f13b9 100644 --- a/source/gameengine/GameLogic/SCA_MouseSensor.cpp +++ b/source/gameengine/GameLogic/SCA_MouseSensor.cpp @@ -25,7 +25,7 @@ * * The Original Code is: all of this file. * - * Contributor(s): none yet. + * Contributor(s): José I. Romero (cleanup and fixes) * * ***** END GPL LICENSE BLOCK ***** */ @@ -59,25 +59,7 @@ SCA_MouseSensor::SCA_MouseSensor(SCA_MouseManager* eventmgr, m_mousemode = mousemode; m_triggermode = true; - switch (m_mousemode) { - case KX_MOUSESENSORMODE_LEFTBUTTON: - m_hotkey = SCA_IInputDevice::KX_LEFTMOUSE; - break; - case KX_MOUSESENSORMODE_MIDDLEBUTTON: - m_hotkey = SCA_IInputDevice::KX_MIDDLEMOUSE; - break; - case KX_MOUSESENSORMODE_RIGHTBUTTON: - m_hotkey = SCA_IInputDevice::KX_RIGHTMOUSE; - break; - case KX_MOUSESENSORMODE_WHEELUP: - m_hotkey = SCA_IInputDevice::KX_WHEELUPMOUSE; - break; - case KX_MOUSESENSORMODE_WHEELDOWN: - m_hotkey = SCA_IInputDevice::KX_WHEELDOWNMOUSE; - break; - default: - ; /* ignore, no hotkey */ - } + UpdateHotkey(this, NULL); Init(); } @@ -92,7 +74,38 @@ SCA_MouseSensor::~SCA_MouseSensor() /* Nothing to be done here. */ } - +int SCA_MouseSensor::UpdateHotkey(void *self, const PyAttributeDef*) +{ + // gosh, this function is so damn stupid + // its here because of a design mistake in the mouse sensor, it should only + // have 3 trigger modes (button, wheel, move), and let the user set the + // hotkey separately, like the other sensors. but instead it has a mode for + // each friggin key and i have to update the hotkey based on it... genius! + SCA_MouseSensor* sensor = reinterpret_cast<SCA_MouseSensor*>(self); + + switch (sensor->m_mousemode) { + case KX_MOUSESENSORMODE_LEFTBUTTON: + sensor->m_hotkey = SCA_IInputDevice::KX_LEFTMOUSE; + break; + case KX_MOUSESENSORMODE_MIDDLEBUTTON: + sensor->m_hotkey = SCA_IInputDevice::KX_MIDDLEMOUSE; + break; + case KX_MOUSESENSORMODE_RIGHTBUTTON: + sensor->m_hotkey = SCA_IInputDevice::KX_RIGHTMOUSE; + break; + case KX_MOUSESENSORMODE_WHEELUP: + sensor->m_hotkey = SCA_IInputDevice::KX_WHEELUPMOUSE; + break; + case KX_MOUSESENSORMODE_WHEELDOWN: + sensor->m_hotkey = SCA_IInputDevice::KX_WHEELDOWNMOUSE; + break; + default: + ; /* ignore, no hotkey */ + } + // return value is used in _setattr(), + // 0=attribute checked ok (see Attributes array definition) + return 0; +} CValue* SCA_MouseSensor::GetReplica() { @@ -137,15 +150,6 @@ bool SCA_MouseSensor::Evaluate(CValue* event) bool reset = m_reset && m_level; SCA_IInputDevice* mousedev = m_pMouseMgr->GetInputDevice(); - - -// SCA_ILogicBrick::RegisterEvent(event); -// if (m_mousemode == KX_MOUSESENSORMODE_MOVEMENT) cout << "\nChecking for movement..."; -//CValue* val = event->GetProperty("val"); - - /* both MOUSEX and MOUSEY. Treat all of these as key-presses. */ - /* So, treat KX_MOUSESENSORMODE_POSITION as */ - /* KX_MOUSESENSORMODE_POSITIONX || KX_MOUSESENSORMODE_POSITIONY */ m_reset = false; switch (m_mousemode) { case KX_MOUSESENSORMODE_LEFTBUTTON: @@ -155,42 +159,34 @@ bool SCA_MouseSensor::Evaluate(CValue* event) case KX_MOUSESENSORMODE_WHEELDOWN: { const SCA_InputEvent& event = mousedev->GetEventValue(m_hotkey); - if (event.m_status == SCA_InputEvent::KX_JUSTACTIVATED) - { + switch (event.m_status){ + case SCA_InputEvent::KX_JUSTACTIVATED: m_val = 1; result = true; - } else - { - if (event.m_status == SCA_InputEvent::KX_JUSTRELEASED) + break; + case SCA_InputEvent::KX_JUSTRELEASED: + m_val = 0; + result = true; + break; + case SCA_InputEvent::KX_ACTIVE: + if (m_val == 0) + { + m_val = 1; + if (m_level) + result = true; + } + break; + default: + if (m_val == 1) { m_val = 0; result = true; - } else - { - if (event.m_status == SCA_InputEvent::KX_ACTIVE) - { - if (m_val == 0) - { - m_val = 1; - if (m_level) - { - result = true; - } - } - } else - { - if (m_val == 1) - { - m_val = 0; - result = true; - } - } } + break; } break; } case KX_MOUSESENSORMODE_MOVEMENT: - { const SCA_InputEvent& eventX = mousedev->GetEventValue(SCA_IInputDevice::KX_MOUSEX); const SCA_InputEvent& eventY = mousedev->GetEventValue(SCA_IInputDevice::KX_MOUSEY); @@ -198,27 +194,26 @@ bool SCA_MouseSensor::Evaluate(CValue* event) if (eventX.m_status == SCA_InputEvent::KX_JUSTACTIVATED || eventY.m_status == SCA_InputEvent::KX_JUSTACTIVATED || eventX.m_status == SCA_InputEvent::KX_ACTIVE || - eventY.m_status == SCA_InputEvent::KX_ACTIVE) - + eventY.m_status == SCA_InputEvent::KX_ACTIVE) { m_val = 1; result = true; - } else - { - if (eventX.m_status == SCA_InputEvent::KX_JUSTRELEASED || + } + else if (eventX.m_status == SCA_InputEvent::KX_JUSTRELEASED || eventY.m_status == SCA_InputEvent::KX_JUSTRELEASED ) + { + m_val = 0; + result = true; + } + else //KX_NO_IMPUTSTATUS + { + if (m_val == 1) { m_val = 0; result = true; - } else - { - if (m_val == 1) - { - m_val = 0; - result = true; - } } } + break; } default: @@ -243,18 +238,67 @@ void SCA_MouseSensor::setY(short y) bool SCA_MouseSensor::isValid(SCA_MouseSensor::KX_MOUSESENSORMODE m) { - bool res = false; + return ((m > KX_MOUSESENSORMODE_NODEF) && (m < KX_MOUSESENSORMODE_MAX)); +} - res = ((m > KX_MOUSESENSORMODE_NODEF) && (m < KX_MOUSESENSORMODE_MAX)); +/* ------------------------------------------------------------------------- */ +/* Python functions */ +/* ------------------------------------------------------------------------- */ + +//Deprecated functions ------> +/* get x position ---------------------------------------------------------- */ +const char SCA_MouseSensor::GetXPosition_doc[] = +"getXPosition\n" +"\tReturns the x-coordinate of the mouse sensor, in frame coordinates.\n" +"\tThe lower-left corner is the origin. The coordinate is given in\n" +"\tpixels\n"; +PyObject* SCA_MouseSensor::PyGetXPosition(PyObject* self, + PyObject* args, + PyObject* kwds) { + ShowDeprecationWarning("getXPosition()", "the position property"); + return PyInt_FromLong(m_x); +} + +/* get y position ---------------------------------------------------------- */ +const char SCA_MouseSensor::GetYPosition_doc[] = +"getYPosition\n" +"\tReturns the y-coordinate of the mouse sensor, in frame coordinates.\n" +"\tThe lower-left corner is the origin. The coordinate is given in\n" +"\tpixels\n"; +PyObject* SCA_MouseSensor::PyGetYPosition(PyObject* self, + PyObject* args, + PyObject* kwds) { + ShowDeprecationWarning("getYPosition()", "the position property"); + return PyInt_FromLong(m_y); +} +//<----- Deprecated + +KX_PYMETHODDEF_DOC_O(SCA_MouseSensor, getButtonStatus, +"getButtonStatus(button)\n" +"\tGet the given button's status (KX_NO_INPUTSTATUS, KX_JUSTACTIVATED, KX_ACTIVE or KX_JUSTRELEASED).\n") +{ + if (PyInt_Check(value)) + { + int button = PyInt_AsLong(value); + + if ((button < SCA_IInputDevice::KX_LEFTMOUSE) + || (button > SCA_IInputDevice::KX_MIDDLEMOUSE)){ + PyErr_SetString(PyExc_ValueError, "invalid button specified!"); + return NULL; + } + + SCA_IInputDevice* mousedev = m_pMouseMgr->GetInputDevice(); + const SCA_InputEvent& event = mousedev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) button); + return PyInt_FromLong(event.m_status); + } - return res; + Py_RETURN_NONE; } /* ------------------------------------------------------------------------- */ -/* Python functions */ +/* Python Integration Hooks */ /* ------------------------------------------------------------------------- */ -/* Integration hooks ------------------------------------------------------- */ PyTypeObject SCA_MouseSensor::Type = { PyObject_HEAD_INIT(&PyType_Type) 0, @@ -283,37 +327,34 @@ PyParentObject SCA_MouseSensor::Parents[] = { }; PyMethodDef SCA_MouseSensor::Methods[] = { + //Deprecated functions ------> {"getXPosition", (PyCFunction) SCA_MouseSensor::sPyGetXPosition, METH_VARARGS, (PY_METHODCHAR)GetXPosition_doc}, {"getYPosition", (PyCFunction) SCA_MouseSensor::sPyGetYPosition, METH_VARARGS, (PY_METHODCHAR)GetYPosition_doc}, + //<----- Deprecated + KX_PYMETHODTABLE_O(SCA_MouseSensor, getButtonStatus), {NULL,NULL} //Sentinel }; -PyObject* SCA_MouseSensor::_getattr(const STR_String& attr) { - _getattr_up(SCA_ISensor); -} +PyAttributeDef SCA_MouseSensor::Attributes[] = { + KX_PYATTRIBUTE_SHORT_RW_CHECK("mode",KX_MOUSESENSORMODE_NODEF,KX_MOUSESENSORMODE_MAX-1,true,SCA_MouseSensor,m_mousemode,UpdateHotkey), + KX_PYATTRIBUTE_SHORT_LIST_RO("position",SCA_MouseSensor,m_x,2), + { NULL } //Sentinel +}; -/* get x position ---------------------------------------------------------- */ -const char SCA_MouseSensor::GetXPosition_doc[] = -"getXPosition\n" -"\tReturns the x-coordinate of the mouse sensor, in frame coordinates.\n" -"\tThe lower-left corner is the origin. The coordinate is given in\n" -"\tpixels\n"; -PyObject* SCA_MouseSensor::PyGetXPosition(PyObject* self, - PyObject* args, - PyObject* kwds) { - return PyInt_FromLong(m_x); +PyObject* SCA_MouseSensor::_getattr(const char *attr) +{ + PyObject* object = _getattr_self(Attributes, this, attr); + if (object != NULL) + return object; + _getattr_up(SCA_ISensor); } -/* get y position ---------------------------------------------------------- */ -const char SCA_MouseSensor::GetYPosition_doc[] = -"getYPosition\n" -"\tReturns the y-coordinate of the mouse sensor, in frame coordinates.\n" -"\tThe lower-left corner is the origin. The coordinate is given in\n" -"\tpixels\n"; -PyObject* SCA_MouseSensor::PyGetYPosition(PyObject* self, - PyObject* args, - PyObject* kwds) { - return PyInt_FromLong(m_y); +int SCA_MouseSensor::_setattr(const char *attr, PyObject *value) +{ + int ret = _setattr_self(Attributes, this, attr, value); + if (ret >= 0) + return ret; + return SCA_ISensor::_setattr(attr, value); } /* eof */ diff --git a/source/gameengine/GameLogic/SCA_MouseSensor.h b/source/gameengine/GameLogic/SCA_MouseSensor.h index 26a1c5e3fd2..30b43fe53cc 100644 --- a/source/gameengine/GameLogic/SCA_MouseSensor.h +++ b/source/gameengine/GameLogic/SCA_MouseSensor.h @@ -24,7 +24,7 @@ * * The Original Code is: all of this file. * - * Contributor(s): none yet. + * Contributor(s): José I. Romero (cleanup and fixes) * * ***** END GPL LICENSE BLOCK ***** */ @@ -58,7 +58,7 @@ class SCA_MouseSensor : public SCA_ISensor SCA_IInputDevice::KX_EnumInputs m_hotkey; /** - * valid x coordinate + * valid x coordinate, MUST be followed by y coordinate */ short m_x; @@ -87,6 +87,8 @@ class SCA_MouseSensor : public SCA_ISensor bool isValid(KX_MOUSESENSORMODE); + static int UpdateHotkey(void *self, const PyAttributeDef*); + SCA_MouseSensor(class SCA_MouseManager* keybdmgr, int startx,int starty, short int mousemode, @@ -107,12 +109,18 @@ class SCA_MouseSensor : public SCA_ISensor /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject *value); + //Deprecated functions -----> /* read x-coordinate */ KX_PYMETHOD_DOC(SCA_MouseSensor,GetXPosition); /* read y-coordinate */ KX_PYMETHOD_DOC(SCA_MouseSensor,GetYPosition); + //<----- deprecated + + // get button status + KX_PYMETHOD_DOC_O(SCA_MouseSensor,getButtonStatus); }; diff --git a/source/gameengine/GameLogic/SCA_NANDController.cpp b/source/gameengine/GameLogic/SCA_NANDController.cpp index 5b869ee8298..0efa8da153a 100644 --- a/source/gameengine/GameLogic/SCA_NANDController.cpp +++ b/source/gameengine/GameLogic/SCA_NANDController.cpp @@ -137,7 +137,7 @@ PyMethodDef SCA_NANDController::Methods[] = { {NULL,NULL} //Sentinel }; -PyObject* SCA_NANDController::_getattr(const STR_String& attr) { +PyObject* SCA_NANDController::_getattr(const char *attr) { _getattr_up(SCA_IController); } diff --git a/source/gameengine/GameLogic/SCA_NANDController.h b/source/gameengine/GameLogic/SCA_NANDController.h index 1193ff64f07..d88504cfc0d 100644 --- a/source/gameengine/GameLogic/SCA_NANDController.h +++ b/source/gameengine/GameLogic/SCA_NANDController.h @@ -48,7 +48,7 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); }; diff --git a/source/gameengine/GameLogic/SCA_NORController.cpp b/source/gameengine/GameLogic/SCA_NORController.cpp index 2866dec0b74..fa24be9ebce 100644 --- a/source/gameengine/GameLogic/SCA_NORController.cpp +++ b/source/gameengine/GameLogic/SCA_NORController.cpp @@ -137,7 +137,7 @@ PyMethodDef SCA_NORController::Methods[] = { {NULL,NULL} //Sentinel }; -PyObject* SCA_NORController::_getattr(const STR_String& attr) { +PyObject* SCA_NORController::_getattr(const char *attr) { _getattr_up(SCA_IController); } diff --git a/source/gameengine/GameLogic/SCA_NORController.h b/source/gameengine/GameLogic/SCA_NORController.h index aab59e3d46c..45b639f3f3f 100644 --- a/source/gameengine/GameLogic/SCA_NORController.h +++ b/source/gameengine/GameLogic/SCA_NORController.h @@ -48,7 +48,7 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); }; diff --git a/source/gameengine/GameLogic/SCA_ORController.cpp b/source/gameengine/GameLogic/SCA_ORController.cpp index 2d4eb31f241..42a29e1959b 100644 --- a/source/gameengine/GameLogic/SCA_ORController.cpp +++ b/source/gameengine/GameLogic/SCA_ORController.cpp @@ -129,7 +129,7 @@ PyMethodDef SCA_ORController::Methods[] = { {NULL,NULL} //Sentinel }; -PyObject* SCA_ORController::_getattr(const STR_String& attr) { +PyObject* SCA_ORController::_getattr(const char *attr) { _getattr_up(SCA_IController); } diff --git a/source/gameengine/GameLogic/SCA_ORController.h b/source/gameengine/GameLogic/SCA_ORController.h index beb69aa2af9..9a6e9e75022 100644 --- a/source/gameengine/GameLogic/SCA_ORController.h +++ b/source/gameengine/GameLogic/SCA_ORController.h @@ -49,7 +49,7 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); }; #endif //__KX_ORCONTROLLER diff --git a/source/gameengine/GameLogic/SCA_PropertyActuator.cpp b/source/gameengine/GameLogic/SCA_PropertyActuator.cpp index 3b541e87f02..c9ace081bae 100644 --- a/source/gameengine/GameLogic/SCA_PropertyActuator.cpp +++ b/source/gameengine/GameLogic/SCA_PropertyActuator.cpp @@ -245,17 +245,35 @@ PyParentObject SCA_PropertyActuator::Parents[] = { }; PyMethodDef SCA_PropertyActuator::Methods[] = { + //Deprecated functions ------> {"setProperty", (PyCFunction) SCA_PropertyActuator::sPySetProperty, METH_VARARGS, (PY_METHODCHAR)SetProperty_doc}, {"getProperty", (PyCFunction) SCA_PropertyActuator::sPyGetProperty, METH_VARARGS, (PY_METHODCHAR)GetProperty_doc}, {"setValue", (PyCFunction) SCA_PropertyActuator::sPySetValue, METH_VARARGS, (PY_METHODCHAR)SetValue_doc}, {"getValue", (PyCFunction) SCA_PropertyActuator::sPyGetValue, METH_VARARGS, (PY_METHODCHAR)GetValue_doc}, + //<----- Deprecated {NULL,NULL} //Sentinel }; -PyObject* SCA_PropertyActuator::_getattr(const STR_String& attr) { +PyAttributeDef SCA_PropertyActuator::Attributes[] = { + KX_PYATTRIBUTE_STRING_RW_CHECK("property",0,100,false,SCA_PropertyActuator,m_propname,CheckProperty), + KX_PYATTRIBUTE_STRING_RW("value",0,100,false,SCA_PropertyActuator,m_exprtxt), + { NULL } //Sentinel +}; + +PyObject* SCA_PropertyActuator::_getattr(const char *attr) { + PyObject* object = _getattr_self(Attributes, this, attr); + if (object != NULL) + return object; _getattr_up(SCA_IActuator); } +int SCA_PropertyActuator::_setattr(const char *attr, PyObject *value) { + int ret = _setattr_self(Attributes, this, attr, value); + if (ret >= 0) + return ret; + return SCA_IActuator::_setattr(attr, value); +} + /* 1. setProperty */ const char SCA_PropertyActuator::SetProperty_doc[] = "setProperty(name)\n" @@ -264,6 +282,7 @@ const char SCA_PropertyActuator::SetProperty_doc[] = "\tof this name, the call is ignored.\n"; PyObject* SCA_PropertyActuator::PySetProperty(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setProperty()", "the 'property' property"); /* Check whether the name exists first ! */ char *nameArg; if (!PyArg_ParseTuple(args, "s", &nameArg)) { @@ -279,7 +298,7 @@ PyObject* SCA_PropertyActuator::PySetProperty(PyObject* self, PyObject* args, Py } prop->Release(); - Py_Return; + Py_RETURN_NONE; } /* 2. getProperty */ @@ -288,6 +307,7 @@ const char SCA_PropertyActuator::GetProperty_doc[] = "\tReturn the property on which the actuator operates.\n"; PyObject* SCA_PropertyActuator::PyGetProperty(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getProperty()", "the 'property' property"); return PyString_FromString(m_propname); } @@ -300,6 +320,7 @@ const char SCA_PropertyActuator::SetValue_doc[] = "\t action is ignored.\n"; PyObject* SCA_PropertyActuator::PySetValue(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setValue()", "the value property"); char *valArg; if(!PyArg_ParseTuple(args, "s", &valArg)) { return NULL; @@ -307,7 +328,7 @@ PyObject* SCA_PropertyActuator::PySetValue(PyObject* self, PyObject* args, PyObj if (valArg) m_exprtxt = valArg; - Py_Return; + Py_RETURN_NONE; } /* 4. getValue */ @@ -316,6 +337,7 @@ const char SCA_PropertyActuator::GetValue_doc[] = "\tReturns the value with which the actuator operates.\n"; PyObject* SCA_PropertyActuator::PyGetValue(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getValue()", "the value property"); return PyString_FromString(m_exprtxt); } diff --git a/source/gameengine/GameLogic/SCA_PropertyActuator.h b/source/gameengine/GameLogic/SCA_PropertyActuator.h index 1e435684572..444d9285796 100644 --- a/source/gameengine/GameLogic/SCA_PropertyActuator.h +++ b/source/gameengine/GameLogic/SCA_PropertyActuator.h @@ -85,7 +85,8 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject *value); // python wrapped methods KX_PYMETHOD_DOC(SCA_PropertyActuator,SetProperty); diff --git a/source/gameengine/GameLogic/SCA_PropertySensor.cpp b/source/gameengine/GameLogic/SCA_PropertySensor.cpp index 64e3d49c6cb..d683c8bb3e7 100644 --- a/source/gameengine/GameLogic/SCA_PropertySensor.cpp +++ b/source/gameengine/GameLogic/SCA_PropertySensor.cpp @@ -293,7 +293,7 @@ CValue* SCA_PropertySensor::FindIdentifier(const STR_String& identifiername) return GetParent()->FindIdentifier(identifiername); } -bool SCA_PropertySensor::validValueForProperty(char *val, STR_String &prop) +int SCA_PropertySensor::validValueForProperty(void *self, const PyAttributeDef*) { bool result = true; /* There is no type checking at this moment, unfortunately... */ @@ -333,25 +333,46 @@ PyParentObject SCA_PropertySensor::Parents[] = { }; PyMethodDef SCA_PropertySensor::Methods[] = { + //Deprecated functions ------> {"getType", (PyCFunction) SCA_PropertySensor::sPyGetType, METH_VARARGS, (PY_METHODCHAR)GetType_doc}, {"setType", (PyCFunction) SCA_PropertySensor::sPySetType, METH_VARARGS, (PY_METHODCHAR)SetType_doc}, {"getProperty", (PyCFunction) SCA_PropertySensor::sPyGetProperty, METH_VARARGS, (PY_METHODCHAR)GetProperty_doc}, {"setProperty", (PyCFunction) SCA_PropertySensor::sPySetProperty, METH_VARARGS, (PY_METHODCHAR)SetProperty_doc}, {"getValue", (PyCFunction) SCA_PropertySensor::sPyGetValue, METH_VARARGS, (PY_METHODCHAR)GetValue_doc}, {"setValue", (PyCFunction) SCA_PropertySensor::sPySetValue, METH_VARARGS, (PY_METHODCHAR)SetValue_doc}, + //<----- Deprecated {NULL,NULL} //Sentinel }; -PyObject* SCA_PropertySensor::_getattr(const STR_String& attr) { +PyAttributeDef SCA_PropertySensor::Attributes[] = { + KX_PYATTRIBUTE_INT_RW("type",KX_PROPSENSOR_NODEF,KX_PROPSENSOR_MAX-1,false,SCA_PropertySensor,m_checktype), + KX_PYATTRIBUTE_STRING_RW_CHECK("property",0,100,false,SCA_PropertySensor,m_checkpropname,CheckProperty), + KX_PYATTRIBUTE_STRING_RW_CHECK("value",0,100,false,SCA_PropertySensor,m_checkpropval,validValueForProperty), + { NULL } //Sentinel +}; + + +PyObject* SCA_PropertySensor::_getattr(const char *attr) { + PyObject* object = _getattr_self(Attributes, this, attr); + if (object != NULL) + return object; _getattr_up(SCA_ISensor); /* implicit return! */ } +int SCA_PropertySensor::_setattr(const char *attr, PyObject *value) { + int ret = _setattr_self(Attributes, this, attr, value); + if (ret >= 0) + return ret; + return SCA_ISensor::_setattr(attr, value); +} + /* 1. getType */ const char SCA_PropertySensor::GetType_doc[] = "getType()\n" "\tReturns the type of check this sensor performs.\n"; PyObject* SCA_PropertySensor::PyGetType(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getType()", "the type property"); return PyInt_FromLong(m_checktype); } @@ -364,6 +385,7 @@ const char SCA_PropertySensor::SetType_doc[] = "\tSet the type of check to perform.\n"; PyObject* SCA_PropertySensor::PySetType(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setType()", "the type property"); int typeArg; if (!PyArg_ParseTuple(args, "i", &typeArg)) { @@ -375,7 +397,7 @@ PyObject* SCA_PropertySensor::PySetType(PyObject* self, PyObject* args, PyObject m_checktype = typeArg; } - Py_Return; + Py_RETURN_NONE; } /* 3. getProperty */ @@ -384,6 +406,7 @@ const char SCA_PropertySensor::GetProperty_doc[] = "\tReturn the property with which the sensor operates.\n"; PyObject* SCA_PropertySensor::PyGetProperty(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getProperty()", "the 'property' property"); return PyString_FromString(m_checkpropname); } @@ -395,6 +418,7 @@ const char SCA_PropertySensor::SetProperty_doc[] = "\tof this name, the call is ignored.\n"; PyObject* SCA_PropertySensor::PySetProperty(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setProperty()", "the 'property' property"); /* We should query whether the name exists. Or should we create a prop */ /* on the fly? */ char *propNameArg = NULL; @@ -410,7 +434,7 @@ PyObject* SCA_PropertySensor::PySetProperty(PyObject* self, PyObject* args, PyOb ; /* error: bad property name */ } prop->Release(); - Py_Return; + Py_RETURN_NONE; } /* 5. getValue */ @@ -419,6 +443,7 @@ const char SCA_PropertySensor::GetValue_doc[] = "\tReturns the value with which the sensor operates.\n"; PyObject* SCA_PropertySensor::PyGetValue(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getValue()", "the value property"); return PyString_FromString(m_checkpropval); } @@ -431,6 +456,7 @@ const char SCA_PropertySensor::SetValue_doc[] = "\t action is ignored.\n"; PyObject* SCA_PropertySensor::PySetValue(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setValue()", "the value property"); /* Here, we need to check whether the value is 'valid' for this property.*/ /* We know that the property exists, or is NULL. */ char *propValArg = NULL; @@ -438,12 +464,13 @@ PyObject* SCA_PropertySensor::PySetValue(PyObject* self, PyObject* args, PyObjec if(!PyArg_ParseTuple(args, "s", &propValArg)) { return NULL; } - - if (validValueForProperty(propValArg, m_checkpropname)) { - m_checkpropval = propValArg; + STR_String oldval = m_checkpropval; + m_checkpropval = propValArg; + if (validValueForProperty(self, NULL)) { + m_checkpropval = oldval; + return NULL; } - - Py_Return; + Py_RETURN_NONE; } /* eof */ diff --git a/source/gameengine/GameLogic/SCA_PropertySensor.h b/source/gameengine/GameLogic/SCA_PropertySensor.h index 6871cb3afdc..933de49de18 100644 --- a/source/gameengine/GameLogic/SCA_PropertySensor.h +++ b/source/gameengine/GameLogic/SCA_PropertySensor.h @@ -47,10 +47,6 @@ class SCA_PropertySensor : public SCA_ISensor bool m_recentresult; CExpression* m_range_expr; - /** - * Test whether this is a sensible value (type check) - */ - bool validValueForProperty(char *val, STR_String &prop); protected: public: @@ -89,7 +85,8 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject *value); /* 1. getType */ KX_PYMETHOD_DOC(SCA_PropertySensor,GetType); @@ -103,7 +100,10 @@ public: KX_PYMETHOD_DOC(SCA_PropertySensor,GetValue); /* 6. setValue */ KX_PYMETHOD_DOC(SCA_PropertySensor,SetValue); - + /** + * Test whether this is a sensible value (type check) + */ + static int validValueForProperty(void* self, const PyAttributeDef*); }; #endif diff --git a/source/gameengine/GameLogic/SCA_PythonController.cpp b/source/gameengine/GameLogic/SCA_PythonController.cpp index c354ab39747..2fff21f22fb 100644 --- a/source/gameengine/GameLogic/SCA_PythonController.cpp +++ b/source/gameengine/GameLogic/SCA_PythonController.cpp @@ -233,9 +233,11 @@ PyMethodDef SCA_PythonController::Methods[] = { {"getActuator", (PyCFunction) SCA_PythonController::sPyGetActuator, METH_O, (PY_METHODCHAR)SCA_PythonController::GetActuator_doc}, {"getSensors", (PyCFunction) SCA_PythonController::sPyGetSensors, METH_NOARGS, (PY_METHODCHAR)SCA_PythonController::GetSensors_doc}, {"getSensor", (PyCFunction) SCA_PythonController::sPyGetSensor, METH_O, (PY_METHODCHAR)SCA_PythonController::GetSensor_doc}, - {"getScript", (PyCFunction) SCA_PythonController::sPyGetScript, METH_NOARGS}, + //Deprecated functions ------> {"setScript", (PyCFunction) SCA_PythonController::sPySetScript, METH_O}, + {"getScript", (PyCFunction) SCA_PythonController::sPyGetScript, METH_NOARGS}, {"getState", (PyCFunction) SCA_PythonController::sPyGetState, METH_NOARGS}, + //<----- Deprecated {NULL,NULL} //Sentinel }; @@ -327,11 +329,39 @@ void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr) -PyObject* SCA_PythonController::_getattr(const STR_String& attr) +PyObject* SCA_PythonController::_getattr(const char *attr) { + if (!strcmp(attr,"state")) { + return PyInt_FromLong(m_statemask); + } + if (!strcmp(attr,"script")) { + return PyString_FromString(m_scriptText); + } _getattr_up(SCA_IController); } +int SCA_PythonController::_setattr(const char *attr, PyObject *value) +{ + if (!strcmp(attr,"state")) { + PyErr_SetString(PyExc_AttributeError, "state is read only"); + return 1; + } + if (!strcmp(attr,"script")) { + char *scriptArg = PyString_AsString(value); + + if (scriptArg==NULL) { + PyErr_SetString(PyExc_TypeError, "expected a string (script name)"); + return -1; + } + + /* set scripttext sets m_bModified to true, + so next time the script is needed, a reparse into byte code is done */ + this->SetScriptText(scriptArg); + + return 1; + } + return SCA_IController::_setattr(attr, value); +} PyObject* SCA_PythonController::PyGetActuators(PyObject* self) @@ -420,6 +450,7 @@ SCA_PythonController::PyGetSensors(PyObject* self) /* 1. getScript */ PyObject* SCA_PythonController::PyGetScript(PyObject* self) { + ShowDeprecationWarning("getScript()", "the script property"); return PyString_FromString(m_scriptText); } @@ -427,6 +458,9 @@ PyObject* SCA_PythonController::PyGetScript(PyObject* self) PyObject* SCA_PythonController::PySetScript(PyObject* self, PyObject* value) { char *scriptArg = PyString_AsString(value); + + ShowDeprecationWarning("setScript()", "the script property"); + if (scriptArg==NULL) { PyErr_SetString(PyExc_TypeError, "expected a string (script name)"); return NULL; @@ -443,6 +477,7 @@ PyObject* SCA_PythonController::PySetScript(PyObject* self, PyObject* value) /* 1. getScript */ PyObject* SCA_PythonController::PyGetState(PyObject* self) { + ShowDeprecationWarning("getState()", "the state property"); return PyInt_FromLong(m_statemask); } diff --git a/source/gameengine/GameLogic/SCA_PythonController.h b/source/gameengine/GameLogic/SCA_PythonController.h index d9b2e242bea..00c30d7f3d5 100644 --- a/source/gameengine/GameLogic/SCA_PythonController.h +++ b/source/gameengine/GameLogic/SCA_PythonController.h @@ -76,7 +76,8 @@ class SCA_PythonController : public SCA_IController static const char* sPyAddActiveActuator__doc__; static PyObject* sPyAddActiveActuator(PyObject* self, PyObject* args); - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject *value); KX_PYMETHOD_DOC_NOARGS(SCA_PythonController,GetSensors); KX_PYMETHOD_DOC_NOARGS(SCA_PythonController,GetActuators); diff --git a/source/gameengine/GameLogic/SCA_RandomActuator.cpp b/source/gameengine/GameLogic/SCA_RandomActuator.cpp index 7b50a483cd8..d6c73f21f37 100644 --- a/source/gameengine/GameLogic/SCA_RandomActuator.cpp +++ b/source/gameengine/GameLogic/SCA_RandomActuator.cpp @@ -339,6 +339,7 @@ PyParentObject SCA_RandomActuator::Parents[] = { }; PyMethodDef SCA_RandomActuator::Methods[] = { + //Deprecated functions ------> {"setSeed", (PyCFunction) SCA_RandomActuator::sPySetSeed, METH_VARARGS, (PY_METHODCHAR)SetSeed_doc}, {"getSeed", (PyCFunction) SCA_RandomActuator::sPyGetSeed, METH_VARARGS, (PY_METHODCHAR)GetSeed_doc}, {"getPara1", (PyCFunction) SCA_RandomActuator::sPyGetPara1, METH_VARARGS, (PY_METHODCHAR)GetPara1_doc}, @@ -346,6 +347,7 @@ PyMethodDef SCA_RandomActuator::Methods[] = { {"getDistribution", (PyCFunction) SCA_RandomActuator::sPyGetDistribution, METH_VARARGS, (PY_METHODCHAR)GetDistribution_doc}, {"setProperty", (PyCFunction) SCA_RandomActuator::sPySetProperty, METH_VARARGS, (PY_METHODCHAR)SetProperty_doc}, {"getProperty", (PyCFunction) SCA_RandomActuator::sPyGetProperty, METH_VARARGS, (PY_METHODCHAR)GetProperty_doc}, + //<----- Deprecated {"setBoolConst", (PyCFunction) SCA_RandomActuator::sPySetBoolConst, METH_VARARGS, (PY_METHODCHAR)SetBoolConst_doc}, {"setBoolUniform", (PyCFunction) SCA_RandomActuator::sPySetBoolUniform, METH_VARARGS, (PY_METHODCHAR)SetBoolUniform_doc}, {"setBoolBernouilli",(PyCFunction) SCA_RandomActuator::sPySetBoolBernouilli, METH_VARARGS, (PY_METHODCHAR)SetBoolBernouilli_doc}, @@ -359,10 +361,42 @@ PyMethodDef SCA_RandomActuator::Methods[] = { {NULL,NULL} //Sentinel }; -PyObject* SCA_RandomActuator::_getattr(const STR_String& attr) { +PyAttributeDef SCA_RandomActuator::Attributes[] = { + KX_PYATTRIBUTE_FLOAT_RO("para1",SCA_RandomActuator,m_parameter1), + KX_PYATTRIBUTE_FLOAT_RO("para2",SCA_RandomActuator,m_parameter2), + KX_PYATTRIBUTE_ENUM_RO("distribution",SCA_RandomActuator,m_distribution), + KX_PYATTRIBUTE_STRING_RW_CHECK("property",0,100,false,SCA_RandomActuator,m_propname,CheckProperty), + { NULL } //Sentinel +}; + +PyObject* SCA_RandomActuator::_getattr(const char *attr) { + PyObject* object = _getattr_self(Attributes, this, attr); + if (object != NULL) + return object; + if (!strcmp(attr, "seed")) { + return PyInt_FromLong(m_base->GetSeed()); + } _getattr_up(SCA_IActuator); } +int SCA_RandomActuator::_setattr(const char *attr, PyObject *value) +{ + int ret = _setattr_self(Attributes, this, attr, value); + if (ret >= 0) + return ret; + if (!strcmp(attr, "seed")) { + if (PyInt_Check(value)) { + int ival = PyInt_AsLong(value); + m_base->SetSeed(ival); + return 0; + } else { + PyErr_SetString(PyExc_TypeError, "expected an integer"); + return 1; + } + } + return SCA_IActuator::_setattr(attr, value); +} + /* 1. setSeed */ const char SCA_RandomActuator::SetSeed_doc[] = "setSeed(seed)\n" @@ -371,6 +405,7 @@ const char SCA_RandomActuator::SetSeed_doc[] = "\tequal series. If the seed is 0, the generator will produce\n" "\tthe same value on every call.\n"; PyObject* SCA_RandomActuator::PySetSeed(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setSeed()", "the seed property"); long seedArg; if(!PyArg_ParseTuple(args, "i", &seedArg)) { return NULL; @@ -378,7 +413,7 @@ PyObject* SCA_RandomActuator::PySetSeed(PyObject* self, PyObject* args, PyObject m_base->SetSeed(seedArg); - Py_Return; + Py_RETURN_NONE; } /* 2. getSeed */ const char SCA_RandomActuator::GetSeed_doc[] = @@ -386,6 +421,7 @@ const char SCA_RandomActuator::GetSeed_doc[] = "\tReturns the initial seed of the generator. Equal seeds produce\n" "\tequal series.\n"; PyObject* SCA_RandomActuator::PyGetSeed(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getSeed()", "the seed property"); return PyInt_FromLong(m_base->GetSeed()); } @@ -396,6 +432,7 @@ const char SCA_RandomActuator::GetPara1_doc[] = "\tto the documentation of the generator types for the meaning\n" "\tof this value."; PyObject* SCA_RandomActuator::PyGetPara1(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getPara1()", "the para1 property"); return PyFloat_FromDouble(m_parameter1); } @@ -406,6 +443,7 @@ const char SCA_RandomActuator::GetPara2_doc[] = "\tto the documentation of the generator types for the meaning\n" "\tof this value."; PyObject* SCA_RandomActuator::PyGetPara2(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getPara2()", "the para2 property"); return PyFloat_FromDouble(m_parameter2); } @@ -414,6 +452,7 @@ const char SCA_RandomActuator::GetDistribution_doc[] = "getDistribution()\n" "\tReturns the type of the active distribution.\n"; PyObject* SCA_RandomActuator::PyGetDistribution(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getDistribution()", "the distribution property"); return PyInt_FromLong(m_distribution); } @@ -424,6 +463,7 @@ const char SCA_RandomActuator::SetProperty_doc[] = "\tSet the property to which the random value is assigned. If the \n" "\tgenerator and property types do not match, the assignment is ignored.\n"; PyObject* SCA_RandomActuator::PySetProperty(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setProperty()", "the 'property' property"); char *nameArg; if (!PyArg_ParseTuple(args, "s", &nameArg)) { return NULL; @@ -438,7 +478,7 @@ PyObject* SCA_RandomActuator::PySetProperty(PyObject* self, PyObject* args, PyOb } prop->Release(); - Py_Return; + Py_RETURN_NONE; } /* 10. getProperty */ const char SCA_RandomActuator::GetProperty_doc[] = @@ -446,6 +486,7 @@ const char SCA_RandomActuator::GetProperty_doc[] = "\tReturn the property to which the random value is assigned. If the \n" "\tgenerator and property types do not match, the assignment is ignored.\n"; PyObject* SCA_RandomActuator::PyGetProperty(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getProperty()", "the 'property' property"); return PyString_FromString(m_propname); } @@ -463,11 +504,9 @@ PyObject* SCA_RandomActuator::PySetBoolConst(PyObject* self, } m_distribution = KX_RANDOMACT_BOOL_CONST; - if (paraArg) { - m_parameter1 = 1; - } + m_parameter1 = (paraArg) ? 1.0 : 0.0; - Py_Return; + Py_RETURN_NONE; } /* 12. setBoolUniform, */ const char SCA_RandomActuator::SetBoolUniform_doc[] = @@ -479,7 +518,7 @@ PyObject* SCA_RandomActuator::PySetBoolUniform(PyObject* self, /* no args */ m_distribution = KX_RANDOMACT_BOOL_UNIFORM; enforceConstraints(); - Py_Return; + Py_RETURN_NONE; } /* 13. setBoolBernouilli, */ const char SCA_RandomActuator::SetBoolBernouilli_doc[] = @@ -497,7 +536,7 @@ PyObject* SCA_RandomActuator::PySetBoolBernouilli(PyObject* self, m_distribution = KX_RANDOMACT_BOOL_BERNOUILLI; m_parameter1 = paraArg; enforceConstraints(); - Py_Return; + Py_RETURN_NONE; } /* 14. setIntConst,*/ const char SCA_RandomActuator::SetIntConst_doc[] = @@ -515,7 +554,7 @@ PyObject* SCA_RandomActuator::PySetIntConst(PyObject* self, m_distribution = KX_RANDOMACT_INT_CONST; m_parameter1 = paraArg; enforceConstraints(); - Py_Return; + Py_RETURN_NONE; } /* 15. setIntUniform,*/ const char SCA_RandomActuator::SetIntUniform_doc[] = @@ -536,7 +575,7 @@ PyObject* SCA_RandomActuator::PySetIntUniform(PyObject* self, m_parameter1 = paraArg1; m_parameter2 = paraArg2; enforceConstraints(); - Py_Return; + Py_RETURN_NONE; } /* 16. setIntPoisson, */ const char SCA_RandomActuator::SetIntPoisson_doc[] = @@ -556,7 +595,7 @@ PyObject* SCA_RandomActuator::PySetIntPoisson(PyObject* self, m_distribution = KX_RANDOMACT_INT_POISSON; m_parameter1 = paraArg; enforceConstraints(); - Py_Return; + Py_RETURN_NONE; } /* 17. setFloatConst,*/ const char SCA_RandomActuator::SetFloatConst_doc[] = @@ -574,7 +613,7 @@ PyObject* SCA_RandomActuator::PySetFloatConst(PyObject* self, m_distribution = KX_RANDOMACT_FLOAT_CONST; m_parameter1 = paraArg; enforceConstraints(); - Py_Return; + Py_RETURN_NONE; } /* 18. setFloatUniform, */ const char SCA_RandomActuator::SetFloatUniform_doc[] = @@ -595,7 +634,7 @@ PyObject* SCA_RandomActuator::PySetFloatUniform(PyObject* self, m_parameter1 = paraArg1; m_parameter2 = paraArg2; enforceConstraints(); - Py_Return; + Py_RETURN_NONE; } /* 19. setFloatNormal, */ const char SCA_RandomActuator::SetFloatNormal_doc[] = @@ -616,7 +655,7 @@ PyObject* SCA_RandomActuator::PySetFloatNormal(PyObject* self, m_parameter1 = paraArg1; m_parameter2 = paraArg2; enforceConstraints(); - Py_Return; + Py_RETURN_NONE; } /* 20. setFloatNegativeExponential, */ const char SCA_RandomActuator::SetFloatNegativeExponential_doc[] = @@ -635,7 +674,7 @@ PyObject* SCA_RandomActuator::PySetFloatNegativeExponential(PyObject* self, m_distribution = KX_RANDOMACT_FLOAT_NEGATIVE_EXPONENTIAL; m_parameter1 = paraArg; enforceConstraints(); - Py_Return; + Py_RETURN_NONE; } /* eof */ diff --git a/source/gameengine/GameLogic/SCA_RandomActuator.h b/source/gameengine/GameLogic/SCA_RandomActuator.h index f6da0595d1a..0d404fa8a9f 100644 --- a/source/gameengine/GameLogic/SCA_RandomActuator.h +++ b/source/gameengine/GameLogic/SCA_RandomActuator.h @@ -96,7 +96,8 @@ class SCA_RandomActuator : public SCA_IActuator /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject *value); /* 1. setSeed */ KX_PYMETHOD_DOC(SCA_RandomActuator,SetSeed); @@ -135,7 +136,6 @@ class SCA_RandomActuator : public SCA_IActuator KX_PYMETHOD_DOC(SCA_RandomActuator,SetFloatNormal); /* 20. setFloatNegativeExponential, */ KX_PYMETHOD_DOC(SCA_RandomActuator,SetFloatNegativeExponential); - }; /* end of class KX_EditObjectActuator : public SCA_PropertyActuator */ #endif diff --git a/source/gameengine/GameLogic/SCA_RandomSensor.cpp b/source/gameengine/GameLogic/SCA_RandomSensor.cpp index 202fd6382e6..5354c120f52 100644 --- a/source/gameengine/GameLogic/SCA_RandomSensor.cpp +++ b/source/gameengine/GameLogic/SCA_RandomSensor.cpp @@ -160,10 +160,39 @@ PyMethodDef SCA_RandomSensor::Methods[] = { {NULL,NULL} //Sentinel }; -PyObject* SCA_RandomSensor::_getattr(const STR_String& attr) { +PyAttributeDef SCA_RandomSensor::Attributes[] = { + KX_PYATTRIBUTE_BOOL_RO("lastDraw",SCA_RandomSensor,m_lastdraw), + {NULL} //Sentinel +}; + +PyObject* SCA_RandomSensor::_getattr(const char *attr) { + PyObject* object = _getattr_self(Attributes, this, attr); + if (object != NULL) + return object; + if (!strcmp(attr,"seed")) { + return PyInt_FromLong(m_basegenerator->GetSeed()); + } _getattr_up(SCA_ISensor); } +int SCA_RandomSensor::_setattr(const char *attr, PyObject *value) +{ + int ret = _setattr_self(Attributes, this, attr, value); + if (ret >= 0) + return ret; + if (!strcmp(attr,"seed")) { + if (PyInt_Check(value)) { + int ival = PyInt_AsLong(value); + m_basegenerator->SetSeed(ival); + return 0; + } else { + PyErr_SetString(PyExc_TypeError, "expected an integer"); + return 1; + } + } + return SCA_ISensor::_setattr(attr, value); +} + /* 1. setSeed */ const char SCA_RandomSensor::SetSeed_doc[] = "setSeed(seed)\n" @@ -172,6 +201,7 @@ const char SCA_RandomSensor::SetSeed_doc[] = "\tequal series. If the seed is 0, the generator will produce\n" "\tthe same value on every call.\n"; PyObject* SCA_RandomSensor::PySetSeed(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setSeed()", "the seed property"); long seedArg; if(!PyArg_ParseTuple(args, "i", &seedArg)) { return NULL; @@ -179,7 +209,7 @@ PyObject* SCA_RandomSensor::PySetSeed(PyObject* self, PyObject* args, PyObject* m_basegenerator->SetSeed(seedArg); - Py_Return; + Py_RETURN_NONE; } /* 2. getSeed */ @@ -188,6 +218,7 @@ const char SCA_RandomSensor::GetSeed_doc[] = "\tReturns the initial seed of the generator. Equal seeds produce\n" "\tequal series.\n"; PyObject* SCA_RandomSensor::PyGetSeed(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getSeed()", "the seed property"); return PyInt_FromLong(m_basegenerator->GetSeed()); } @@ -196,6 +227,7 @@ const char SCA_RandomSensor::GetLastDraw_doc[] = "getLastDraw()\n" "\tReturn the last value that was drawn.\n"; PyObject* SCA_RandomSensor::PyGetLastDraw(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getLastDraw()", "the lastDraw property"); return PyInt_FromLong(m_lastdraw); } diff --git a/source/gameengine/GameLogic/SCA_RandomSensor.h b/source/gameengine/GameLogic/SCA_RandomSensor.h index d29bfb6837a..d808db07536 100644 --- a/source/gameengine/GameLogic/SCA_RandomSensor.h +++ b/source/gameengine/GameLogic/SCA_RandomSensor.h @@ -60,7 +60,8 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject *value); /* 1. setSeed */ KX_PYMETHOD_DOC(SCA_RandomSensor,SetSeed); diff --git a/source/gameengine/GameLogic/SCA_XNORController.cpp b/source/gameengine/GameLogic/SCA_XNORController.cpp index 3ef7c07fe0a..b019aedc93d 100644 --- a/source/gameengine/GameLogic/SCA_XNORController.cpp +++ b/source/gameengine/GameLogic/SCA_XNORController.cpp @@ -141,7 +141,7 @@ PyMethodDef SCA_XNORController::Methods[] = { {NULL,NULL} //Sentinel }; -PyObject* SCA_XNORController::_getattr(const STR_String& attr) { +PyObject* SCA_XNORController::_getattr(const char *attr) { _getattr_up(SCA_IController); } diff --git a/source/gameengine/GameLogic/SCA_XNORController.h b/source/gameengine/GameLogic/SCA_XNORController.h index 4b1eaee95d8..a431a72c177 100644 --- a/source/gameengine/GameLogic/SCA_XNORController.h +++ b/source/gameengine/GameLogic/SCA_XNORController.h @@ -48,7 +48,7 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); }; diff --git a/source/gameengine/GameLogic/SCA_XORController.cpp b/source/gameengine/GameLogic/SCA_XORController.cpp index 6499c62f5f2..11ffa19b8f1 100644 --- a/source/gameengine/GameLogic/SCA_XORController.cpp +++ b/source/gameengine/GameLogic/SCA_XORController.cpp @@ -141,7 +141,7 @@ PyMethodDef SCA_XORController::Methods[] = { {NULL,NULL} //Sentinel }; -PyObject* SCA_XORController::_getattr(const STR_String& attr) { +PyObject* SCA_XORController::_getattr(const char *attr) { _getattr_up(SCA_IController); } diff --git a/source/gameengine/GameLogic/SCA_XORController.h b/source/gameengine/GameLogic/SCA_XORController.h index f50cd33c125..2fbc7866ecf 100644 --- a/source/gameengine/GameLogic/SCA_XORController.h +++ b/source/gameengine/GameLogic/SCA_XORController.h @@ -48,7 +48,7 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); }; diff --git a/source/gameengine/GameLogic/SConscript b/source/gameengine/GameLogic/SConscript index b4e2159dc22..ebf225f728f 100644 --- a/source/gameengine/GameLogic/SConscript +++ b/source/gameengine/GameLogic/SConscript @@ -17,4 +17,9 @@ if env['WITH_BF_SDL']: else: defs += ' DISABLE_SDL' -env.BlenderLib ( 'bf_logic', sources, Split(incs), Split(defs), libtype=['game','player'], priority=[30, 110] ) +cxxflags = [] +if env['OURPLATFORM']=='win32-vc': + cxxflags.append ('/GR') + cxxflags.append ('/O2') + +env.BlenderLib ( 'bf_logic', sources, Split(incs), Split(defs), libtype=['game','player'], priority=[30, 110], cxx_compileflags=cxxflags ) diff --git a/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp b/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp index 78d8eaf2aa3..c0d6248a3ca 100644 --- a/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp +++ b/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp @@ -85,7 +85,7 @@ void GPC_RenderTools::EndFrame(RAS_IRasterizer* rasty) * has a maximum of 8 lights (simultaneous), so 20 * 8 lights are possible in * a scene. */ -void GPC_RenderTools::ProcessLighting(int layer, const MT_Transform& viewmat) +void GPC_RenderTools::ProcessLighting(RAS_IRasterizer *rasty, int layer, const MT_Transform& viewmat) { if(m_lastlightlayer == layer) return; @@ -106,12 +106,12 @@ void GPC_RenderTools::ProcessLighting(int layer, const MT_Transform& viewmat) } if(enable) - EnableOpenGLLights(); + EnableOpenGLLights(rasty); else DisableOpenGLLights(); } -void GPC_RenderTools::EnableOpenGLLights() +void GPC_RenderTools::EnableOpenGLLights(RAS_IRasterizer *rasty) { if(m_lastlighting == true) return; @@ -120,7 +120,8 @@ void GPC_RenderTools::EnableOpenGLLights() glEnable(GL_COLOR_MATERIAL); glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); - glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, true); + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); + glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, (rasty->GetCameraOrtho())? GL_FALSE: GL_TRUE); if (GLEW_EXT_separate_specular_color || GLEW_VERSION_1_2) glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); diff --git a/source/gameengine/GamePlayer/common/GPC_RenderTools.h b/source/gameengine/GamePlayer/common/GPC_RenderTools.h index 382956e73ea..2a1b66a3aa9 100644 --- a/source/gameengine/GamePlayer/common/GPC_RenderTools.h +++ b/source/gameengine/GamePlayer/common/GPC_RenderTools.h @@ -65,9 +65,9 @@ public: void EndFrame(RAS_IRasterizer* rasty); void BeginFrame(RAS_IRasterizer* rasty); - void EnableOpenGLLights(); + void EnableOpenGLLights(RAS_IRasterizer *rasty); void DisableOpenGLLights(); - void ProcessLighting(int layer, const MT_Transform& viewmat); + void ProcessLighting(RAS_IRasterizer *rasty, int layer, const MT_Transform& viewmat); /* @attention mode is ignored here */ void RenderText2D(RAS_TEXT_RENDER_MODE mode, diff --git a/source/gameengine/GamePlayer/common/SConscript b/source/gameengine/GamePlayer/common/SConscript index 30f20a670d3..c9bda78d905 100644 --- a/source/gameengine/GamePlayer/common/SConscript +++ b/source/gameengine/GamePlayer/common/SConscript @@ -67,8 +67,9 @@ incs += Split(env['BF_SOLID_INC']) incs += Split(env['BF_PNG_INC']) incs += Split(env['BF_ZLIB_INC']) -cflags=[] +cxxflags = [] if env['OURPLATFORM']=='win32-vc': - cflags = ['/GR'] + cxxflags.append ('/GR') + cxxflags.append ('/O2') -env.BlenderLib (libname='gp_common', sources=source_files, includes=incs, defines = [], libtype='player', priority=5, compileflags=cflags) +env.BlenderLib (libname='gp_common', sources=source_files, includes=incs, defines = [], libtype='player', priority=5, cxx_compileflags=cxxflags) diff --git a/source/gameengine/GamePlayer/common/unix/Makefile b/source/gameengine/GamePlayer/common/unix/Makefile index a2bdb7225a0..3d44a41afee 100644 --- a/source/gameengine/GamePlayer/common/unix/Makefile +++ b/source/gameengine/GamePlayer/common/unix/Makefile @@ -35,6 +35,7 @@ include nan_compile.mk CCFLAGS += $(LEVEL_1_CPP_WARNINGS) +CPPFLAGS += -I$(NAN_GLEW)/include CPPFLAGS += -I$(OPENGL_HEADERS) CPPFLAGS += -I$(NAN_STRING)/include diff --git a/source/gameengine/GamePlayer/ghost/CMakeLists.txt b/source/gameengine/GamePlayer/ghost/CMakeLists.txt index 5e0ca93ac06..a3cd8296da3 100644 --- a/source/gameengine/GamePlayer/ghost/CMakeLists.txt +++ b/source/gameengine/GamePlayer/ghost/CMakeLists.txt @@ -70,5 +70,9 @@ SET(INC ${PYTHON_INC} ) +IF(WITH_FFMPEG) + ADD_DEFINITIONS(-DWITH_FFMPEG) +ENDIF(WITH_FFMPEG) + BLENDERLIB_NOLIST(gp_ghost "${SRC}" "${INC}") #env.BlenderLib (libname='gp_ghost', sources=source_files, includes = incs, defines = [], libtype='player',priority=0, compileflags=cflags) diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp index aa5e5835cdc..e858c852b70 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp @@ -530,6 +530,7 @@ bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode) bool fixed_framerate= (SYS_GetCommandLineInt(syshandle, "fixed_framerate", fixedFr) != 0); bool frameRate = (SYS_GetCommandLineInt(syshandle, "show_framerate", 0) != 0); bool useLists = (SYS_GetCommandLineInt(syshandle, "displaylists", G.fileflags & G_FILE_DISPLAY_LISTS) != 0); + bool nodepwarnings = (SYS_GetCommandLineInt(syshandle, "ignore_deprecation_warnings", 0) != 0); if(GLEW_ARB_multitexture && GLEW_VERSION_1_1) m_blendermat = (SYS_GetCommandLineInt(syshandle, "blender_material", 1) != 0); @@ -604,6 +605,8 @@ bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode) m_ketsjiengine->SetAudioDevice(m_audiodevice); m_ketsjiengine->SetTimingDisplay(frameRate, false, false); + CValue::SetDeprecationWarnings(nodepwarnings); + m_ketsjiengine->SetUseFixedTime(fixed_framerate); m_ketsjiengine->SetTimingDisplay(frameRate, profile, properties); @@ -686,8 +689,9 @@ bool GPG_Application::startEngine(void) initGameKeys(); initPythonConstraintBinding(); initMathutils(); +#ifdef WITH_FFMPEG initVideoTexture(); - +#endif // Set the GameLogic.globalDict from marshal'd data, so we can // load new blend files and keep data in GameLogic.globalDict loadGamePythonConfig(m_pyGlobalDictString, m_pyGlobalDictString_Length); diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp index 0bf0317d8f2..70272d57357 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp @@ -162,11 +162,10 @@ void usage(const char* program) consoleoption = ""; #endif - printf("usage: %s [-w [-p l t w h]] %s[-g gamengineoptions] " + printf("usage: %s [-w l t w h] %s[-g gamengineoptions] " "[-s stereomode] filename.blend\n", program, consoleoption); printf(" -h: Prints this command summary\n"); printf(" -w: display in a window\n"); - printf(" -p: specify window position\n"); printf(" l = window left coordinate\n"); printf(" t = window top coordinate\n"); printf(" w = window width\n"); @@ -190,17 +189,18 @@ void usage(const char* program) printf(" -c: keep console window open\n"); #endif printf(" -d: turn debugging on\n"); - printf(" -g: game engine options:\n"); - printf(" Name Default Description\n"); - printf(" ----------------------------------------\n"); - printf(" fixedtime 0 Do the same timestep each frame \"Enable all frames\"\n"); - printf(" nomipmap 0 Disable mipmaps\n"); - printf(" show_framerate 0 Show the frame rate\n"); - printf(" show_properties 0 Show debug properties\n"); - printf(" show_profile 0 Show profiling information\n"); - printf(" blender_material 0 Enable material settings\n"); + printf(" -g: game engine options:\n\n"); + printf(" Name Default Description\n"); + printf(" ------------------------------------------------------------------------\n"); + printf(" fixedtime 0 \"Enable all frames\"\n"); + printf(" nomipmap 0 Disable mipmaps\n"); + printf(" show_framerate 0 Show the frame rate\n"); + printf(" show_properties 0 Show debug properties\n"); + printf(" show_profile 0 Show profiling information\n"); + printf(" blender_material 0 Enable material settings\n"); + printf(" ignore_deprecation_warnings 0 Ignore deprecation warnings\n"); printf("\n"); - printf("example: %s -p 10 10 320 200 -g noaudio c:\\loadtest.blend\n", program); + printf("example: %s -w 10 10 320 200 -g noaudio c:\\loadtest.blend\n", program); printf("example: %s -g show_framerate = 0 c:\\loadtest.blend\n", program); } diff --git a/source/gameengine/GamePlayer/ghost/Makefile b/source/gameengine/GamePlayer/ghost/Makefile index 52e219db8f2..5f90d804611 100644 --- a/source/gameengine/GamePlayer/ghost/Makefile +++ b/source/gameengine/GamePlayer/ghost/Makefile @@ -82,3 +82,6 @@ CPPFLAGS += -I$(NAN_STRING)/include CPPFLAGS += -I$(NAN_GHOST)/include CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION) +ifeq ($(WITH_FFMPEG), true) + CPPFLAGS += -DWITH_FFMPEG +endif diff --git a/source/gameengine/GamePlayer/ghost/SConscript b/source/gameengine/GamePlayer/ghost/SConscript index 33cf07b6211..0785ce4bd0d 100644 --- a/source/gameengine/GamePlayer/ghost/SConscript +++ b/source/gameengine/GamePlayer/ghost/SConscript @@ -45,9 +45,14 @@ incs = ['.', incs += Split(env['BF_PYTHON_INC']) incs += Split(env['BF_SOLID_INC']) -cflags = [] + +cxxflags = [] if env['OURPLATFORM']=='win32-vc': - cflags = ['/GR'] + cxxflags.append ('/GR') + cxxflags.append ('/O2') +defs = '' +if env['WITH_BF_FFMPEG']: + defs += ' WITH_FFMPEG' -env.BlenderLib (libname='gp_ghost', sources=source_files, includes = incs, defines = [], libtype='player',priority=0, compileflags=cflags) +env.BlenderLib (libname='gp_ghost', sources=source_files, includes = incs, defines = Split(defs), libtype='player',priority=0, cxx_compileflags=cxxflags) diff --git a/source/gameengine/Ketsji/BL_Shader.cpp b/source/gameengine/Ketsji/BL_Shader.cpp index 80892764089..2a4a74d5b90 100644 --- a/source/gameengine/Ketsji/BL_Shader.cpp +++ b/source/gameengine/Ketsji/BL_Shader.cpp @@ -729,7 +729,7 @@ void BL_Shader::SetUniform(int uniform, const int* val, int len) } -PyObject* BL_Shader::_getattr(const STR_String& attr) +PyObject* BL_Shader::_getattr(const char *attr) { _getattr_up(PyObjectPlus); } @@ -796,7 +796,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setSource," setSource(vertexProgram, fragmentProg if(mShader !=0 && mOk ) { // already set... - Py_Return; + Py_RETURN_NONE; } char *v,*f; int apply=0; @@ -807,12 +807,12 @@ KX_PYMETHODDEF_DOC( BL_Shader, setSource," setSource(vertexProgram, fragmentProg if( LinkProgram() ) { glUseProgramObjectARB( mShader ); mUse = apply!=0; - Py_Return; + Py_RETURN_NONE; } vertProg = 0; fragProg = 0; mUse = 0; - Py_Return; + Py_RETURN_NONE; } return NULL; } @@ -827,7 +827,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, delSource, "delSource( )" ) mShader = 0; mOk = 0; mUse = 0; - Py_Return; + Py_RETURN_NONE; } KX_PYMETHODDEF_DOC( BL_Shader, isValid, "isValid()" ) @@ -871,7 +871,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, validate, "validate()") MEM_freeN(logInf); logInf=0; } - Py_Return; + Py_RETURN_NONE; } @@ -912,7 +912,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setNumberOfPasses, "setNumberOfPasses( max-pass ) return NULL; mPass = 1; - Py_Return; + Py_RETURN_NONE; } /// access functions @@ -935,7 +935,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform1f, "setUniform1f(name, fx)" ) SetUniform( loc, (float)value ); #endif } - Py_Return; + Py_RETURN_NONE; } return NULL; } @@ -959,7 +959,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform2f , "setUniform2f(name, fx, fy)") SetUniform(loc, array, 2); #endif } - Py_Return; + Py_RETURN_NONE; } return NULL; } @@ -983,7 +983,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform3f, "setUniform3f(name, fx,fy,fz) ") SetUniform(loc, array, 3); #endif } - Py_Return; + Py_RETURN_NONE; } return NULL; @@ -1008,7 +1008,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform4f, "setUniform4f(name, fx,fy,fz, fw) " SetUniform(loc, array, 4); #endif } - Py_Return; + Py_RETURN_NONE; } return NULL; } @@ -1032,7 +1032,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform1i, "setUniform1i(name, ix)" ) SetUniform(loc, (int)value); #endif } - Py_Return; + Py_RETURN_NONE; } return NULL; } @@ -1056,7 +1056,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform2i , "setUniform2i(name, ix, iy)") SetUniform(loc, array, 2); #endif } - Py_Return; + Py_RETURN_NONE; } return NULL; } @@ -1081,7 +1081,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform3i, "setUniform3i(name, ix,iy,iz) ") SetUniform(loc, array, 3); #endif } - Py_Return; + Py_RETURN_NONE; } return NULL; } @@ -1104,7 +1104,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform4i, "setUniform4i(name, ix,iy,iz, iw) " SetUniform(loc, array, 4); #endif } - Py_Return; + Py_RETURN_NONE; } return NULL; } @@ -1144,7 +1144,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformfv , "setUniformfv( float (list2 or lis #else SetUniform(loc, array2, 2); #endif - Py_Return; + Py_RETURN_NONE; } break; case 3: { @@ -1154,7 +1154,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformfv , "setUniformfv( float (list2 or lis #else SetUniform(loc, array3, 3); #endif - Py_Return; + Py_RETURN_NONE; }break; case 4: { @@ -1164,7 +1164,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformfv , "setUniformfv( float (list2 or lis #else SetUniform(loc, array4, 4); #endif - Py_Return; + Py_RETURN_NONE; }break; default: { @@ -1212,7 +1212,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformiv, "setUniformiv( int (list2 or list3 #else SetUniform(loc, array2, 2); #endif - Py_Return; + Py_RETURN_NONE; } break; case 3: { @@ -1223,7 +1223,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformiv, "setUniformiv( int (list2 or list3 #else SetUniform(loc, array3, 3); #endif - Py_Return; + Py_RETURN_NONE; }break; case 4: { @@ -1234,7 +1234,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformiv, "setUniformiv( int (list2 or list3 #else SetUniform(loc, array4, 4); #endif - Py_Return; + Py_RETURN_NONE; }break; default: { @@ -1282,7 +1282,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformMatrix4, #else SetUniform(loc,mat,(transp!=0)); #endif - Py_Return; + Py_RETURN_NONE; } } } @@ -1323,7 +1323,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformMatrix3, #else SetUniform(loc,mat,(transp!=0)); #endif - Py_Return; + Py_RETURN_NONE; } } @@ -1346,7 +1346,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setAttrib, "setAttrib(enum)" ) mAttr=SHD_TANGENT; glUseProgramObjectARB(mShader); glBindAttribLocationARB(mShader, mAttr, "Tangent"); - Py_Return; + Py_RETURN_NONE; } return NULL; } @@ -1376,7 +1376,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformDef, "setUniformDef(name, enum)" ) } if(defined) { - Py_Return; + Py_RETURN_NONE; } BL_DefUniform *uni = new BL_DefUniform(); @@ -1384,7 +1384,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformDef, "setUniformDef(name, enum)" ) uni->mType = nloc; uni->mFlag = 0; mPreDef.push_back(uni); - Py_Return; + Py_RETURN_NONE; } } return NULL; diff --git a/source/gameengine/Ketsji/BL_Shader.h b/source/gameengine/Ketsji/BL_Shader.h index 18ca8f8b4f8..52cbd0cda51 100644 --- a/source/gameengine/Ketsji/BL_Shader.h +++ b/source/gameengine/Ketsji/BL_Shader.h @@ -202,7 +202,7 @@ public: void SetUniform(int uniform, const int val); // Python interface - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); // ----------------------------------- KX_PYMETHOD_DOC( BL_Shader, setSource ); diff --git a/source/gameengine/Ketsji/BL_Texture.cpp b/source/gameengine/Ketsji/BL_Texture.cpp index f0ef84032f7..5d40ba7d75c 100644 --- a/source/gameengine/Ketsji/BL_Texture.cpp +++ b/source/gameengine/Ketsji/BL_Texture.cpp @@ -609,7 +609,7 @@ int BL_Texture::GetPow2(int n) void BL_Texture::SplitEnvMap(EnvMap *map) { - if (!map || !map->ima || map->ima && !map->ima->ok) return; + if (!map || !map->ima || (map->ima && !map->ima->ok)) return; ImBuf *ibuf= BKE_image_get_ibuf(map->ima, NULL); if (ibuf) my_envmap_split_ima(map, ibuf); diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.cpp b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.cpp index 85921ae75ca..31f1d2dd3ee 100644 --- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.cpp +++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.cpp @@ -143,7 +143,7 @@ PyMethodDef KX_NetworkMessageActuator::Methods[] = { {NULL,NULL} // Sentinel }; -PyObject* KX_NetworkMessageActuator::_getattr(const STR_String& attr) { +PyObject* KX_NetworkMessageActuator::_getattr(const char *attr) { _getattr_up(SCA_IActuator); } @@ -162,7 +162,7 @@ PyObject* KX_NetworkMessageActuator::PySetToPropName( return NULL; } - Py_Return; + Py_RETURN_NONE; } // 2. SetSubject @@ -180,7 +180,7 @@ PyObject* KX_NetworkMessageActuator::PySetSubject( return NULL; } - Py_Return; + Py_RETURN_NONE; } // 3. SetBodyType @@ -198,7 +198,7 @@ PyObject* KX_NetworkMessageActuator::PySetBodyType( return NULL; } - Py_Return; + Py_RETURN_NONE; } // 4. SetBody @@ -216,6 +216,6 @@ PyObject* KX_NetworkMessageActuator::PySetBody( return NULL; } - Py_Return; + Py_RETURN_NONE; } diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.h b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.h index 653107699c7..96b55ef839b 100644 --- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.h +++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.h @@ -61,7 +61,7 @@ public: /* Python interface ------------------------------------------- */ /* ------------------------------------------------------------ */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); KX_PYMETHOD(KX_NetworkMessageActuator, SetToPropName); KX_PYMETHOD(KX_NetworkMessageActuator, SetSubject); diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp index 8956df9c96b..cb9956d4616 100644 --- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp +++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp @@ -213,7 +213,7 @@ PyMethodDef KX_NetworkMessageSensor::Methods[] = { {NULL,NULL} //Sentinel }; -PyObject* KX_NetworkMessageSensor::_getattr(const STR_String& attr) { +PyObject* KX_NetworkMessageSensor::_getattr(const char *attr) { _getattr_up(SCA_ISensor); // implicit return! } diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h index 8cdfd6cdb5a..26adbc9945a 100644 --- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h +++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h @@ -72,7 +72,7 @@ public: /* Python interface -------------------------------------------- */ /* ------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); KX_PYMETHOD_DOC_O(KX_NetworkMessageSensor, SetSubjectFilterText); KX_PYMETHOD_DOC_NOARGS(KX_NetworkMessageSensor, GetFrameMessageCount); diff --git a/source/gameengine/Ketsji/KXNetwork/SConscript b/source/gameengine/Ketsji/KXNetwork/SConscript index 2297b96c19e..2476ed1f275 100644 --- a/source/gameengine/Ketsji/KXNetwork/SConscript +++ b/source/gameengine/Ketsji/KXNetwork/SConscript @@ -9,4 +9,10 @@ incs += ' #source/gameengine/Network' incs += ' ' + env['BF_PYTHON_INC'] -env.BlenderLib ( 'kx_network', Split(sources), Split(incs), defines=[],libtype=['game2', 'player'], priority=[5, 155] ) +cxxflags = [] +if env['OURPLATFORM']=='win32-vc': + cxxflags.append ('/GR') + cxxflags.append ('/O2') + + +env.BlenderLib ( 'kx_network', Split(sources), Split(incs), defines=[],libtype=['game2', 'player'], priority=[5, 155], cxx_compileflags=cxxflags ) diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp index f92200780d5..5fa19924267 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp @@ -772,12 +772,12 @@ PyParentObject KX_BlenderMaterial::Parents[] = { }; -PyObject* KX_BlenderMaterial::_getattr(const STR_String& attr) +PyObject* KX_BlenderMaterial::_getattr(const char *attr) { _getattr_up(PyObjectPlus); } -int KX_BlenderMaterial::_setattr(const STR_String& attr, PyObject *pyvalue) +int KX_BlenderMaterial::_setattr(const char *attr, PyObject *pyvalue) { return PyObjectPlus::_setattr(attr, pyvalue); } @@ -790,7 +790,7 @@ KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getShader , "getShader()") spit("Fragment shaders not supported"); mModified = true; - Py_Return; + Py_RETURN_NONE; } if( !GLEW_ARB_vertex_shader) { @@ -798,14 +798,14 @@ KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getShader , "getShader()") spit("Vertex shaders not supported"); mModified = true; - Py_Return; + Py_RETURN_NONE; } if(!GLEW_ARB_shader_objects) { if(!mModified) spit("GLSL not supported"); mModified = true; - Py_Return; + Py_RETURN_NONE; } else { // returns Py_None on error @@ -838,7 +838,7 @@ KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getShader , "getShader()") } } } - Py_Return; + Py_RETURN_NONE; } PyErr_Format(PyExc_ValueError, "GLSL Error"); return NULL; @@ -910,7 +910,7 @@ KX_PYMETHODDEF_DOC( KX_BlenderMaterial, setBlending , "setBlending( GameLogic.sr return NULL; } mUserDefBlend = true; - Py_Return; + Py_RETURN_NONE; } return NULL; } diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.h b/source/gameengine/Ketsji/KX_BlenderMaterial.h index 6e5db1b56c1..2cf623dbd85 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.h +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.h @@ -82,8 +82,8 @@ public: ); // -------------------------------- - virtual PyObject* _getattr(const STR_String& attr); - virtual int _setattr(const STR_String& attr, PyObject *pyvalue); + virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject *pyvalue); KX_PYMETHOD_DOC( KX_BlenderMaterial, getShader ); KX_PYMETHOD_DOC( KX_BlenderMaterial, getMaterialIndex ); diff --git a/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp b/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp index bf838e60210..534c48661b7 100644 --- a/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp +++ b/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp @@ -17,10 +17,11 @@ #include "BulletSoftBody/btSoftBody.h" -KX_BulletPhysicsController::KX_BulletPhysicsController (const CcdConstructionInfo& ci, bool dyna) -: KX_IPhysicsController(dyna,(PHY_IPhysicsController*)this), +KX_BulletPhysicsController::KX_BulletPhysicsController (const CcdConstructionInfo& ci, bool dyna, bool compound) +: KX_IPhysicsController(dyna,compound,(PHY_IPhysicsController*)this), CcdPhysicsController(ci), -m_savedCollisionFlags(0) +m_savedCollisionFlags(0), +m_bulletChildShape(NULL) { } @@ -175,6 +176,152 @@ void KX_BulletPhysicsController::setRigidBody(bool rigid) { } +/* This function dynamically adds the collision shape of another controller to + the current controller shape provided it is a compound shape. + The idea is that dynamic parenting on a compound object will dynamically extend the shape +*/ +void KX_BulletPhysicsController::AddCompoundChild(KX_IPhysicsController* child) +{ + if (child == NULL || !IsCompound()) + return; + // other controller must be a bullet controller too + // verify that body and shape exist and match + KX_BulletPhysicsController* childCtrl = dynamic_cast<KX_BulletPhysicsController*>(child); + btRigidBody* rootBody = GetRigidBody(); + btRigidBody* childBody = childCtrl->GetRigidBody(); + if (!rootBody || !childBody) + return; + const btCollisionShape* rootShape = rootBody->getCollisionShape(); + const btCollisionShape* childShape = childBody->getCollisionShape(); + if (!rootShape || + !childShape || + rootShape->getShapeType() != COMPOUND_SHAPE_PROXYTYPE || + childShape->getShapeType() == COMPOUND_SHAPE_PROXYTYPE) + return; + btCompoundShape* compoundShape = (btCompoundShape*)rootShape; + // compute relative transformation between parent and child + btTransform rootTrans; + btTransform childTrans; + rootBody->getMotionState()->getWorldTransform(rootTrans); + childBody->getMotionState()->getWorldTransform(childTrans); + btVector3 rootScale = rootShape->getLocalScaling(); + rootScale[0] = 1.0/rootScale[0]; + rootScale[1] = 1.0/rootScale[1]; + rootScale[2] = 1.0/rootScale[2]; + // relative scale = child_scale/parent_scale + btVector3 relativeScale = childShape->getLocalScaling()*rootScale; + btMatrix3x3 rootRotInverse = rootTrans.getBasis().transpose(); + // relative pos = parent_rot^-1 * ((parent_pos-child_pos)/parent_scale) + btVector3 relativePos = rootRotInverse*((childTrans.getOrigin()-rootTrans.getOrigin())*rootScale); + // relative rot = parent_rot^-1 * child_rot + btMatrix3x3 relativeRot = rootRotInverse*childTrans.getBasis(); + // create a proxy shape info to store the transformation + CcdShapeConstructionInfo* proxyShapeInfo = new CcdShapeConstructionInfo(); + // store the transformation to this object shapeinfo + proxyShapeInfo->m_childTrans.setOrigin(relativePos); + proxyShapeInfo->m_childTrans.setBasis(relativeRot); + proxyShapeInfo->m_childScale.setValue(relativeScale[0], relativeScale[1], relativeScale[2]); + // we will need this to make sure that we remove the right proxy later when unparenting + proxyShapeInfo->m_userData = childCtrl; + proxyShapeInfo->SetProxy(childCtrl->GetShapeInfo()->AddRef()); + // add to parent compound shapeinfo + GetShapeInfo()->AddShape(proxyShapeInfo); + // create new bullet collision shape from the object shapeinfo and set scaling + btCollisionShape* newChildShape = proxyShapeInfo->CreateBulletShape(); + newChildShape->setLocalScaling(relativeScale); + // add bullet collision shape to parent compound collision shape + compoundShape->addChildShape(proxyShapeInfo->m_childTrans,newChildShape); + // remember we created this shape + childCtrl->m_bulletChildShape = newChildShape; + // recompute inertia of parent + if (!rootBody->isStaticOrKinematicObject()) + { + btVector3 localInertia; + float mass = 1.f/rootBody->getInvMass(); + compoundShape->calculateLocalInertia(mass,localInertia); + rootBody->setMassProps(mass,localInertia); + } + // must update the broadphase cache, + GetPhysicsEnvironment()->refreshCcdPhysicsController(this); + // remove the children + GetPhysicsEnvironment()->disableCcdPhysicsController(childCtrl); +} + +/* Reverse function of the above, it will remove a shape from a compound shape + provided that the former was added to the later using AddCompoundChild() +*/ +void KX_BulletPhysicsController::RemoveCompoundChild(KX_IPhysicsController* child) +{ + if (child == NULL || !IsCompound()) + return; + // other controller must be a bullet controller too + // verify that body and shape exist and match + KX_BulletPhysicsController* childCtrl = dynamic_cast<KX_BulletPhysicsController*>(child); + btRigidBody* rootBody = GetRigidBody(); + btRigidBody* childBody = childCtrl->GetRigidBody(); + if (!rootBody || !childBody) + return; + const btCollisionShape* rootShape = rootBody->getCollisionShape(); + if (!rootShape || + rootShape->getShapeType() != COMPOUND_SHAPE_PROXYTYPE) + return; + btCompoundShape* compoundShape = (btCompoundShape*)rootShape; + // retrieve the shapeInfo + CcdShapeConstructionInfo* childShapeInfo = childCtrl->GetShapeInfo(); + CcdShapeConstructionInfo* rootShapeInfo = GetShapeInfo(); + // and verify that the child is part of the parent + int i = rootShapeInfo->FindChildShape(childShapeInfo, childCtrl); + if (i < 0) + return; + rootShapeInfo->RemoveChildShape(i); + if (childCtrl->m_bulletChildShape) + { + int numChildren = compoundShape->getNumChildShapes(); + for (i=0; i<numChildren; i++) + { + if (compoundShape->getChildShape(i) == childCtrl->m_bulletChildShape) + { + compoundShape->removeChildShapeByIndex(i); + compoundShape->recalculateLocalAabb(); + break; + } + } + delete childCtrl->m_bulletChildShape; + childCtrl->m_bulletChildShape = NULL; + } + // recompute inertia of parent + if (!rootBody->isStaticOrKinematicObject()) + { + btVector3 localInertia; + float mass = 1.f/rootBody->getInvMass(); + compoundShape->calculateLocalInertia(mass,localInertia); + rootBody->setMassProps(mass,localInertia); + } + // must update the broadphase cache, + GetPhysicsEnvironment()->refreshCcdPhysicsController(this); + // reactivate the children + GetPhysicsEnvironment()->enableCcdPhysicsController(childCtrl); +} + +void KX_BulletPhysicsController::SetMass(MT_Scalar newmass) +{ + btRigidBody *body = GetRigidBody(); + if (body && body->getActivationState() != DISABLE_SIMULATION && + newmass>MT_EPSILON && GetMass()>MT_EPSILON) + { + btVector3 grav = body->getGravity(); + btVector3 accel = grav / GetMass(); + + btBroadphaseProxy* handle = body->getBroadphaseHandle(); + GetPhysicsEnvironment()->updateCcdPhysicsController(this, + newmass, + body->getCollisionFlags(), + handle->m_collisionFilterGroup, + handle->m_collisionFilterMask); + body->setGravity(accel); + } +} + void KX_BulletPhysicsController::SuspendDynamics(bool ghost) { btRigidBody *body = GetRigidBody(); @@ -185,7 +332,8 @@ void KX_BulletPhysicsController::SuspendDynamics(bool ghost) m_savedMass = GetMass(); m_savedCollisionFilterGroup = handle->m_collisionFilterGroup; m_savedCollisionFilterMask = handle->m_collisionFilterMask; - body->setActivationState(DISABLE_SIMULATION); + m_savedActivationState = body->getActivationState(); + body->forceActivationState(DISABLE_SIMULATION); GetPhysicsEnvironment()->updateCcdPhysicsController(this, 0.0, btCollisionObject::CF_STATIC_OBJECT|((ghost)?btCollisionObject::CF_NO_CONTACT_RESPONSE:(m_savedCollisionFlags&btCollisionObject::CF_NO_CONTACT_RESPONSE)), @@ -204,7 +352,7 @@ void KX_BulletPhysicsController::RestoreDynamics() m_savedCollisionFlags, m_savedCollisionFilterGroup, m_savedCollisionFilterMask); - GetRigidBody()->forceActivationState(ACTIVE_TAG); + body->forceActivationState(m_savedActivationState); } } @@ -250,6 +398,7 @@ SG_Controller* KX_BulletPhysicsController::GetReplica(class SG_Node* destnode) physicsreplica->setParentCtrl(ccdParent); physicsreplica->PostProcessReplica(motionstate,parentctrl); physicsreplica->m_userdata = (PHY_IPhysicsController*)physicsreplica; + physicsreplica->m_bulletChildShape = NULL; return physicsreplica; } diff --git a/source/gameengine/Ketsji/KX_BulletPhysicsController.h b/source/gameengine/Ketsji/KX_BulletPhysicsController.h index cdcb82c87ca..44fbde7054e 100644 --- a/source/gameengine/Ketsji/KX_BulletPhysicsController.h +++ b/source/gameengine/Ketsji/KX_BulletPhysicsController.h @@ -9,13 +9,15 @@ class KX_BulletPhysicsController : public KX_IPhysicsController ,public CcdPhysi { private: int m_savedCollisionFlags; + int m_savedActivationState; short int m_savedCollisionFilterGroup; short int m_savedCollisionFilterMask; MT_Scalar m_savedMass; + btCollisionShape* m_bulletChildShape; public: - KX_BulletPhysicsController (const CcdConstructionInfo& ci, bool dyna); + KX_BulletPhysicsController (const CcdConstructionInfo& ci, bool dyna, bool compound); virtual ~KX_BulletPhysicsController (); /////////////////////////////////// @@ -39,8 +41,11 @@ public: virtual void setPosition(const MT_Point3& pos); virtual void setScaling(const MT_Vector3& scaling); virtual MT_Scalar GetMass(); + virtual void SetMass(MT_Scalar newmass); virtual MT_Vector3 getReactionForce(); virtual void setRigidBody(bool rigid); + virtual void AddCompoundChild(KX_IPhysicsController* child); + virtual void RemoveCompoundChild(KX_IPhysicsController* child); virtual void resolveCombinedVelocities(float linvelX,float linvelY,float linvelZ,float angVelX,float angVelY,float angVelZ); diff --git a/source/gameengine/Ketsji/KX_CDActuator.cpp b/source/gameengine/Ketsji/KX_CDActuator.cpp index a5d7f6d799a..7d238e28add 100644 --- a/source/gameengine/Ketsji/KX_CDActuator.cpp +++ b/source/gameengine/Ketsji/KX_CDActuator.cpp @@ -199,7 +199,7 @@ PyMethodDef KX_CDActuator::Methods[] = { -PyObject* KX_CDActuator::_getattr(const STR_String& attr) +PyObject* KX_CDActuator::_getattr(const char *attr) { _getattr_up(SCA_IActuator); } @@ -210,7 +210,7 @@ PyObject* KX_CDActuator::_getattr(const STR_String& attr) PyObject* KX_CDActuator::PyStartCD(PyObject* self, PyObject* args, PyObject* kwds) { SND_CDObject::Instance()->SetPlaystate(SND_MUST_PLAY); - Py_Return; + Py_RETURN_NONE; } @@ -218,7 +218,7 @@ PyObject* KX_CDActuator::PyStartCD(PyObject* self, PyObject* args, PyObject* kwd PyObject* KX_CDActuator::PyPauseCD(PyObject* self, PyObject* args, PyObject* kwds) { SND_CDObject::Instance()->SetPlaystate(SND_MUST_PAUSE); - Py_Return; + Py_RETURN_NONE; } @@ -226,7 +226,7 @@ PyObject* KX_CDActuator::PyPauseCD(PyObject* self, PyObject* args, PyObject* kwd PyObject* KX_CDActuator::PyStopCD(PyObject* self, PyObject* args, PyObject* kwds) { SND_CDObject::Instance()->SetPlaystate(SND_MUST_STOP); - Py_Return; + Py_RETURN_NONE; } @@ -239,7 +239,7 @@ PyObject* KX_CDActuator::PySetGain(PyObject* self, PyObject* args, PyObject* kwd SND_CDObject::Instance()->SetGain(gain); - Py_Return; + Py_RETURN_NONE; } diff --git a/source/gameengine/Ketsji/KX_CDActuator.h b/source/gameengine/Ketsji/KX_CDActuator.h index f46dd99b6dc..393c49083f9 100644 --- a/source/gameengine/Ketsji/KX_CDActuator.h +++ b/source/gameengine/Ketsji/KX_CDActuator.h @@ -81,7 +81,7 @@ public: /* Python interface --------------------------------------------------- */ /* -------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); KX_PYMETHOD(KX_CDActuator,StartCD); KX_PYMETHOD(KX_CDActuator,PauseCD); diff --git a/source/gameengine/Ketsji/KX_Camera.cpp b/source/gameengine/Ketsji/KX_Camera.cpp index 53b3e348a36..99e2d3b7c06 100644 --- a/source/gameengine/Ketsji/KX_Camera.cpp +++ b/source/gameengine/Ketsji/KX_Camera.cpp @@ -259,10 +259,75 @@ void KX_Camera::ExtractFrustumSphere() if (m_set_frustum_center) return; - // The most extreme points on the near and far plane. (normalized device coords) - MT_Vector4 hnear(1., 1., 0., 1.), hfar(1., 1., 1., 1.); + // compute sphere for the general case and not only symmetric frustum: + // the mirror code in ImageRender can use very asymmetric frustum. + // We will put the sphere center on the line that goes from origin to the center of the far clipping plane + // This is the optimal position if the frustum is symmetric or very asymmetric and probably close + // to optimal for the general case. The sphere center position is computed so that the distance to + // the near and far extreme frustum points are equal. + + // get the transformation matrix from device coordinate to camera coordinate MT_Matrix4x4 clip_camcs_matrix = m_projection_matrix; clip_camcs_matrix.invert(); + + // detect which of the corner of the far clipping plane is the farthest to the origin + MT_Vector4 nfar; // far point in device normalized coordinate + MT_Point3 farpoint; // most extreme far point in camera coordinate + MT_Point3 nearpoint;// most extreme near point in camera coordinate + MT_Point3 farcenter(0.,0.,0.);// center of far cliping plane in camera coordinate + MT_Scalar F=1.0, N; // square distance of far and near point to origin + MT_Scalar f, n; // distance of far and near point to z axis. f is always > 0 but n can be < 0 + MT_Scalar e, s; // far and near clipping distance (<0) + MT_Scalar c; // slope of center line = distance of far clipping center to z axis / far clipping distance + MT_Scalar z; // projection of sphere center on z axis (<0) + // tmp value + MT_Vector4 npoint(1., 1., 1., 1.); + MT_Vector4 hpoint; + MT_Point3 point; + MT_Scalar len; + for (int i=0; i<4; i++) + { + hpoint = clip_camcs_matrix*npoint; + point.setValue(hpoint[0]/hpoint[3], hpoint[1]/hpoint[3], hpoint[2]/hpoint[3]); + len = point.dot(point); + if (len > F) + { + nfar = npoint; + farpoint = point; + F = len; + } + // rotate by 90 degree along the z axis to walk through the 4 extreme points of the far clipping plane + len = npoint[0]; + npoint[0] = -npoint[1]; + npoint[1] = len; + farcenter += point; + } + // the far center is the average of the far clipping points + farcenter *= 0.25; + // the extreme near point is the opposite point on the near clipping plane + nfar.setValue(-nfar[0], -nfar[1], -1., 1.); + nfar = clip_camcs_matrix*nfar; + nearpoint.setValue(nfar[0]/nfar[3], nfar[1]/nfar[3], nfar[2]/nfar[3]); + N = nearpoint.dot(nearpoint); + e = farpoint[2]; + s = nearpoint[2]; + // projection on XY plane for distance to axis computation + MT_Point2 farxy(farpoint[0], farpoint[1]); + // f is forced positive by construction + f = farxy.length(); + // get corresponding point on the near plane + farxy *= s/e; + // this formula preserve the sign of n + n = f*s/e - MT_Point2(nearpoint[0]-farxy[0], nearpoint[1]-farxy[1]).length(); + c = MT_Point2(farcenter[0], farcenter[1]).length()/e; + // the big formula, it simplifies to (F-N)/(2(e-s)) for the symmetric case + z = (F-N)/(2.0*(e-s+c*(f-n))); + m_frustum_center = MT_Point3(farcenter[0]*z/e, farcenter[1]*z/e, z); + m_frustum_radius = m_frustum_center.distance(farpoint); + +#if 0 + // The most extreme points on the near and far plane. (normalized device coords) + MT_Vector4 hnear(1., 1., 0., 1.), hfar(1., 1., 1., 1.); // Transform to hom camera local space hnear = clip_camcs_matrix*hnear; @@ -273,10 +338,12 @@ void KX_Camera::ExtractFrustumSphere() MT_Point3 farpoint(hfar[0]/hfar[3], hfar[1]/hfar[3], hfar[2]/hfar[3]); // Compute center + // don't use camera data in case the user specifies the matrix directly m_frustum_center = MT_Point3(0., 0., - (nearpoint.dot(nearpoint) - farpoint.dot(farpoint))/(2.0*(m_camdata.m_clipend - m_camdata.m_clipstart))); + (nearpoint.dot(nearpoint) - farpoint.dot(farpoint))/(2.0*(nearpoint[2]-farpoint[2] /*m_camdata.m_clipend - m_camdata.m_clipstart*/))); m_frustum_radius = m_frustum_center.distance(farpoint); - +#endif + // Transform to world space. m_frustum_center = GetCameraToWorld()(m_frustum_center); m_frustum_radius /= fabs(NodeGetWorldScaling()[NodeGetWorldScaling().closestAxis()]); @@ -403,15 +470,15 @@ int KX_Camera::GetViewportTop() const PyMethodDef KX_Camera::Methods[] = { KX_PYMETHODTABLE(KX_Camera, sphereInsideFrustum), - KX_PYMETHODTABLE(KX_Camera, boxInsideFrustum), - KX_PYMETHODTABLE(KX_Camera, pointInsideFrustum), - KX_PYMETHODTABLE(KX_Camera, getCameraToWorld), - KX_PYMETHODTABLE(KX_Camera, getWorldToCamera), - KX_PYMETHODTABLE(KX_Camera, getProjectionMatrix), - KX_PYMETHODTABLE(KX_Camera, setProjectionMatrix), - KX_PYMETHODTABLE(KX_Camera, enableViewport), + KX_PYMETHODTABLE_O(KX_Camera, boxInsideFrustum), + KX_PYMETHODTABLE_O(KX_Camera, pointInsideFrustum), + KX_PYMETHODTABLE_NOARGS(KX_Camera, getCameraToWorld), + KX_PYMETHODTABLE_NOARGS(KX_Camera, getWorldToCamera), + KX_PYMETHODTABLE_NOARGS(KX_Camera, getProjectionMatrix), + KX_PYMETHODTABLE_O(KX_Camera, setProjectionMatrix), + KX_PYMETHODTABLE_O(KX_Camera, enableViewport), KX_PYMETHODTABLE(KX_Camera, setViewport), - KX_PYMETHODTABLE(KX_Camera, setOnTop), + KX_PYMETHODTABLE_NOARGS(KX_Camera, setOnTop), {NULL,NULL} //Sentinel }; @@ -471,48 +538,48 @@ PyParentObject KX_Camera::Parents[] = { NULL }; -PyObject* KX_Camera::_getattr(const STR_String& attr) +PyObject* KX_Camera::_getattr(const char *attr) { - if (attr == "INSIDE") + if (!strcmp(attr, "INSIDE")) return PyInt_FromLong(INSIDE); /* new ref */ - if (attr == "OUTSIDE") + if (!strcmp(attr, "OUTSIDE")) return PyInt_FromLong(OUTSIDE); /* new ref */ - if (attr == "INTERSECT") + if (!strcmp(attr, "INTERSECT")) return PyInt_FromLong(INTERSECT); /* new ref */ - if (attr == "lens") + if (!strcmp(attr, "lens")) return PyFloat_FromDouble(GetLens()); /* new ref */ - if (attr == "near") + if (!strcmp(attr, "near")) return PyFloat_FromDouble(GetCameraNear()); /* new ref */ - if (attr == "far") + if (!strcmp(attr, "far")) return PyFloat_FromDouble(GetCameraFar()); /* new ref */ - if (attr == "frustum_culling") + if (!strcmp(attr, "frustum_culling")) return PyInt_FromLong(m_frustum_culling); /* new ref */ - if (attr == "perspective") + if (!strcmp(attr, "perspective")) return PyInt_FromLong(m_camdata.m_perspective); /* new ref */ - if (attr == "projection_matrix") + if (!strcmp(attr, "projection_matrix")) return PyObjectFrom(GetProjectionMatrix()); /* new ref */ - if (attr == "modelview_matrix") + if (!strcmp(attr, "modelview_matrix")) return PyObjectFrom(GetModelviewMatrix()); /* new ref */ - if (attr == "camera_to_world") + if (!strcmp(attr, "camera_to_world")) return PyObjectFrom(GetCameraToWorld()); /* new ref */ - if (attr == "world_to_camera") + if (!strcmp(attr, "world_to_camera")) return PyObjectFrom(GetWorldToCamera()); /* new ref */ _getattr_up(KX_GameObject); } -int KX_Camera::_setattr(const STR_String &attr, PyObject *pyvalue) +int KX_Camera::_setattr(const char *attr, PyObject *pyvalue) { if (PyInt_Check(pyvalue)) { - if (attr == "frustum_culling") + if (!strcmp(attr, "frustum_culling")) { m_frustum_culling = PyInt_AsLong(pyvalue); return 0; } - if (attr == "perspective") + if (!strcmp(attr, "perspective")) { m_camdata.m_perspective = PyInt_AsLong(pyvalue); return 0; @@ -521,19 +588,19 @@ int KX_Camera::_setattr(const STR_String &attr, PyObject *pyvalue) if (PyFloat_Check(pyvalue)) { - if (attr == "lens") + if (!strcmp(attr, "lens")) { m_camdata.m_lens = PyFloat_AsDouble(pyvalue); m_set_projection_matrix = false; return 0; } - if (attr == "near") + if (!strcmp(attr, "near")) { m_camdata.m_clipstart = PyFloat_AsDouble(pyvalue); m_set_projection_matrix = false; return 0; } - if (attr == "far") + if (!strcmp(attr, "far")) { m_camdata.m_clipend = PyFloat_AsDouble(pyvalue); m_set_projection_matrix = false; @@ -543,7 +610,7 @@ int KX_Camera::_setattr(const STR_String &attr, PyObject *pyvalue) if (PyObject_IsMT_Matrix(pyvalue, 4)) { - if (attr == "projection_matrix") + if (!strcmp(attr, "projection_matrix")) { MT_Matrix4x4 mat; if (PyMatTo(pyvalue, mat)) @@ -557,7 +624,7 @@ int KX_Camera::_setattr(const STR_String &attr, PyObject *pyvalue) return KX_GameObject::_setattr(attr, pyvalue); } -KX_PYMETHODDEF_DOC(KX_Camera, sphereInsideFrustum, +KX_PYMETHODDEF_DOC_VARARGS(KX_Camera, sphereInsideFrustum, "sphereInsideFrustum(center, radius) -> Integer\n" "\treturns INSIDE, OUTSIDE or INTERSECT if the given sphere is\n" "\tinside/outside/intersects this camera's viewing frustum.\n\n" @@ -591,7 +658,7 @@ KX_PYMETHODDEF_DOC(KX_Camera, sphereInsideFrustum, return NULL; } -KX_PYMETHODDEF_DOC(KX_Camera, boxInsideFrustum, +KX_PYMETHODDEF_DOC_O(KX_Camera, boxInsideFrustum, "boxInsideFrustum(box) -> Integer\n" "\treturns INSIDE, OUTSIDE or INTERSECT if the given box is\n" "\tinside/outside/intersects this camera's viewing frustum.\n\n" @@ -616,34 +683,27 @@ KX_PYMETHODDEF_DOC(KX_Camera, boxInsideFrustum, "\t\t# Box is outside the frustum !\n" ) { - PyObject *pybox; - if (PyArg_ParseTuple(args, "O", &pybox)) + unsigned int num_points = PySequence_Size(value); + if (num_points != 8) { - unsigned int num_points = PySequence_Size(pybox); - if (num_points != 8) - { - PyErr_Format(PyExc_TypeError, "boxInsideFrustum: Expected eight (8) points, got %d", num_points); + PyErr_Format(PyExc_TypeError, "boxInsideFrustum: Expected eight (8) points, got %d", num_points); + return NULL; + } + + MT_Point3 box[8]; + for (unsigned int p = 0; p < 8 ; p++) + { + PyObject *item = PySequence_GetItem(value, p); /* new ref */ + bool error = !PyVecTo(item, box[p]); + Py_DECREF(item); + if (error) return NULL; - } - - MT_Point3 box[8]; - for (unsigned int p = 0; p < 8 ; p++) - { - PyObject *item = PySequence_GetItem(pybox, p); /* new ref */ - bool error = !PyVecTo(item, box[p]); - Py_DECREF(item); - if (error) - return NULL; - } - - return PyInt_FromLong(BoxInsideFrustum(box)); /* new ref */ } - PyErr_SetString(PyExc_TypeError, "boxInsideFrustum: Expected argument: list of points."); - return NULL; + return PyInt_FromLong(BoxInsideFrustum(box)); /* new ref */ } -KX_PYMETHODDEF_DOC(KX_Camera, pointInsideFrustum, +KX_PYMETHODDEF_DOC_O(KX_Camera, pointInsideFrustum, "pointInsideFrustum(point) -> Bool\n" "\treturns 1 if the given point is inside this camera's viewing frustum.\n\n" "\tpoint = The point to test (in world coordinates.)\n\n" @@ -660,7 +720,7 @@ KX_PYMETHODDEF_DOC(KX_Camera, pointInsideFrustum, ) { MT_Point3 point; - if (PyVecArgTo(args, point)) + if (PyVecTo(value, point)) { return PyInt_FromLong(PointInsideFrustum(point)); /* new ref */ } @@ -669,7 +729,7 @@ KX_PYMETHODDEF_DOC(KX_Camera, pointInsideFrustum, return NULL; } -KX_PYMETHODDEF_DOC(KX_Camera, getCameraToWorld, +KX_PYMETHODDEF_DOC_NOARGS(KX_Camera, getCameraToWorld, "getCameraToWorld() -> Matrix4x4\n" "\treturns the camera to world transformation matrix, as a list of four lists of four values.\n\n" "\tie: [[1.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0, 1.0]])\n" @@ -678,7 +738,7 @@ KX_PYMETHODDEF_DOC(KX_Camera, getCameraToWorld, return PyObjectFrom(GetCameraToWorld()); /* new ref */ } -KX_PYMETHODDEF_DOC(KX_Camera, getWorldToCamera, +KX_PYMETHODDEF_DOC_NOARGS(KX_Camera, getWorldToCamera, "getWorldToCamera() -> Matrix4x4\n" "\treturns the world to camera transformation matrix, as a list of four lists of four values.\n\n" "\tie: [[1.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0, 1.0]])\n" @@ -687,7 +747,7 @@ KX_PYMETHODDEF_DOC(KX_Camera, getWorldToCamera, return PyObjectFrom(GetWorldToCamera()); /* new ref */ } -KX_PYMETHODDEF_DOC(KX_Camera, getProjectionMatrix, +KX_PYMETHODDEF_DOC_NOARGS(KX_Camera, getProjectionMatrix, "getProjectionMatrix() -> Matrix4x4\n" "\treturns this camera's projection matrix, as a list of four lists of four values.\n\n" "\tie: [[1.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0, 1.0]])\n" @@ -696,7 +756,7 @@ KX_PYMETHODDEF_DOC(KX_Camera, getProjectionMatrix, return PyObjectFrom(GetProjectionMatrix()); /* new ref */ } -KX_PYMETHODDEF_DOC(KX_Camera, setProjectionMatrix, +KX_PYMETHODDEF_DOC_O(KX_Camera, setProjectionMatrix, "setProjectionMatrix(MT_Matrix4x4 m) -> None\n" "\tSets this camera's projection matrix\n" "\n" @@ -738,56 +798,50 @@ KX_PYMETHODDEF_DOC(KX_Camera, setProjectionMatrix, "\tcam = co.getOwner()\n" "\tcam.setProjectionMatrix(Perspective(-1.0, 1.0, -1.0, 1.0, 0.1, 1))\n") { - PyObject *pymat; - if (PyArg_ParseTuple(args, "O", &pymat)) + MT_Matrix4x4 mat; + if (!PyMatTo(value, mat)) { - MT_Matrix4x4 mat; - if (PyMatTo(pymat, mat)) - { - SetProjectionMatrix(mat); - Py_Return; - } + PyErr_SetString(PyExc_TypeError, "setProjectionMatrix: Expected 4x4 list as matrix argument."); + return NULL; } - - PyErr_SetString(PyExc_TypeError, "setProjectionMatrix: Expected 4x4 list as matrix argument."); - return NULL; + + SetProjectionMatrix(mat); + Py_RETURN_NONE; } -KX_PYMETHODDEF_DOC(KX_Camera, enableViewport, +KX_PYMETHODDEF_DOC_O(KX_Camera, enableViewport, "enableViewport(viewport)\n" "Sets this camera's viewport status\n" ) { - int viewport; - if (PyArg_ParseTuple(args,"i",&viewport)) - { - if(viewport) - EnableViewport(true); - else - EnableViewport(false); - } - else { + int viewport = PyObject_IsTrue(value); + + if (viewport == -1) { + PyErr_SetString(PyExc_ValueError, "expected True/False or 0/1"); return NULL; } - Py_Return; + if(viewport) + EnableViewport(true); + else + EnableViewport(false); + + Py_RETURN_NONE; } -KX_PYMETHODDEF_DOC(KX_Camera, setViewport, +KX_PYMETHODDEF_DOC_VARARGS(KX_Camera, setViewport, "setViewport(left, bottom, right, top)\n" "Sets this camera's viewport\n") { int left, bottom, right, top; - if (PyArg_ParseTuple(args,"iiii",&left, &bottom, &right, &top)) - { - SetViewport(left, bottom, right, top); - } else { + if (!PyArg_ParseTuple(args,"iiii:setViewport",&left, &bottom, &right, &top)) return NULL; - } - Py_Return; + + SetViewport(left, bottom, right, top); + Py_RETURN_NONE; } -KX_PYMETHODDEF_DOC(KX_Camera, setOnTop, +KX_PYMETHODDEF_DOC_NOARGS(KX_Camera, setOnTop, "setOnTop()\n" "Sets this camera's viewport on top\n") { @@ -796,5 +850,5 @@ KX_PYMETHODDEF_DOC(KX_Camera, setOnTop, scene = KX_GetActiveScene(); MT_assert(scene); scene->SetCameraOnTop(this); - Py_Return; + Py_RETURN_NONE; } diff --git a/source/gameengine/Ketsji/KX_Camera.h b/source/gameengine/Ketsji/KX_Camera.h index 75d574cd697..efd18f99390 100644 --- a/source/gameengine/Ketsji/KX_Camera.h +++ b/source/gameengine/Ketsji/KX_Camera.h @@ -126,7 +126,7 @@ protected: void ExtractFrustumSphere(); public: - typedef enum { INSIDE, INTERSECT, OUTSIDE } ; + enum { INSIDE, INTERSECT, OUTSIDE } ; KX_Camera(void* sgReplicationInfo,SG_Callbacks callbacks,const RAS_CameraData& camdata, bool frustum_culling = true, PyTypeObject *T = &Type); virtual ~KX_Camera(); @@ -257,21 +257,21 @@ public: int GetViewportTop() const; - KX_PYMETHOD_DOC(KX_Camera, sphereInsideFrustum); - KX_PYMETHOD_DOC(KX_Camera, boxInsideFrustum); - KX_PYMETHOD_DOC(KX_Camera, pointInsideFrustum); + KX_PYMETHOD_DOC_VARARGS(KX_Camera, sphereInsideFrustum); + KX_PYMETHOD_DOC_O(KX_Camera, boxInsideFrustum); + KX_PYMETHOD_DOC_O(KX_Camera, pointInsideFrustum); - KX_PYMETHOD_DOC(KX_Camera, getCameraToWorld); - KX_PYMETHOD_DOC(KX_Camera, getWorldToCamera); - KX_PYMETHOD_DOC(KX_Camera, getProjectionMatrix); - KX_PYMETHOD_DOC(KX_Camera, setProjectionMatrix); + KX_PYMETHOD_DOC_NOARGS(KX_Camera, getCameraToWorld); + KX_PYMETHOD_DOC_NOARGS(KX_Camera, getWorldToCamera); + KX_PYMETHOD_DOC_NOARGS(KX_Camera, getProjectionMatrix); + KX_PYMETHOD_DOC_O(KX_Camera, setProjectionMatrix); - KX_PYMETHOD_DOC(KX_Camera, enableViewport); - KX_PYMETHOD_DOC(KX_Camera, setViewport); - KX_PYMETHOD_DOC(KX_Camera, setOnTop); + KX_PYMETHOD_DOC_O(KX_Camera, enableViewport); + KX_PYMETHOD_DOC_VARARGS(KX_Camera, setViewport); + KX_PYMETHOD_DOC_NOARGS(KX_Camera, setOnTop); - virtual PyObject* _getattr(const STR_String& attr); /* lens, near, far, projection_matrix */ - virtual int _setattr(const STR_String& attr, PyObject *pyvalue); + virtual PyObject* _getattr(const char *attr); /* lens, near, far, projection_matrix */ + virtual int _setattr(const char *attr, PyObject *pyvalue); }; diff --git a/source/gameengine/Ketsji/KX_CameraActuator.cpp b/source/gameengine/Ketsji/KX_CameraActuator.cpp index 4d24e83843e..65f3aea12f9 100644 --- a/source/gameengine/Ketsji/KX_CameraActuator.cpp +++ b/source/gameengine/Ketsji/KX_CameraActuator.cpp @@ -36,6 +36,7 @@ #include "KX_GameObject.h" #include "PyObjectPlus.h" +#include "blendef.h" STR_String KX_CameraActuator::X_AXIS_STRING = "x"; STR_String KX_CameraActuator::Y_AXIS_STRING = "y"; @@ -52,9 +53,9 @@ STR_String KX_CameraActuator::Y_AXIS_STRING = "y"; KX_CameraActuator::KX_CameraActuator( SCA_IObject* gameobj, SCA_IObject *obj, - MT_Scalar hght, - MT_Scalar minhght, - MT_Scalar maxhght, + float hght, + float minhght, + float maxhght, bool xytog, PyTypeObject* T ): @@ -397,6 +398,7 @@ PyParentObject KX_CameraActuator::Parents[] = { }; PyMethodDef KX_CameraActuator::Methods[] = { + // ---> deprecated (all) {"setObject",(PyCFunction) KX_CameraActuator::sPySetObject, METH_O, (PY_METHODCHAR)SetObject_doc}, {"getObject",(PyCFunction) KX_CameraActuator::sPyGetObject, METH_VARARGS, (PY_METHODCHAR)GetObject_doc}, {"setMin" ,(PyCFunction) KX_CameraActuator::sPySetMin, METH_VARARGS, (PY_METHODCHAR)SetMin_doc}, @@ -410,9 +412,54 @@ PyMethodDef KX_CameraActuator::Methods[] = { {NULL,NULL,NULL,NULL} //Sentinel }; -PyObject* KX_CameraActuator::_getattr(const STR_String& attr) { +PyAttributeDef KX_CameraActuator::Attributes[] = { + KX_PYATTRIBUTE_FLOAT_RW("min",-MAXFLOAT,MAXFLOAT,KX_CameraActuator,m_minHeight), + KX_PYATTRIBUTE_FLOAT_RW("max",-MAXFLOAT,MAXFLOAT,KX_CameraActuator,m_maxHeight), + KX_PYATTRIBUTE_FLOAT_RW("height",-MAXFLOAT,MAXFLOAT,KX_CameraActuator,m_height), + KX_PYATTRIBUTE_BOOL_RW("xy",KX_CameraActuator,m_x), + {NULL} +}; + +PyObject* KX_CameraActuator::_getattr(const char *attr) { + PyObject* object; + + if (!strcmp(attr, "object")) { + if (!m_ob) Py_RETURN_NONE; + else return m_ob->AddRef(); + } + + object = _getattr_self(Attributes, this, attr); + if (object != NULL) + return object; _getattr_up(SCA_IActuator); } + +int KX_CameraActuator::_setattr(const char *attr, PyObject* value) { + int ret; + + if (!strcmp(attr, "object")) { + KX_GameObject *gameobj; + + if (!ConvertPythonToGameObject(value, &gameobj, true)) + return 1; // ConvertPythonToGameObject sets the error + + if (m_ob != NULL) + m_ob->UnregisterActuator(this); + + m_ob = (SCA_IObject*)gameobj; + + if (m_ob) + m_ob->RegisterActuator(this); + + return 0; + } + + ret = _setattr_self(Attributes, this, attr, value); + if (ret >= 0) + return ret; + return SCA_IActuator::_setattr(attr, value); +} + /* get obj ---------------------------------------------------------- */ const char KX_CameraActuator::GetObject_doc[] = "getObject(name_only = 1)\n" @@ -421,6 +468,9 @@ const char KX_CameraActuator::GetObject_doc[] = PyObject* KX_CameraActuator::PyGetObject(PyObject* self, PyObject* args) { int ret_name_only = 1; + + ShowDeprecationWarning("getObject()", "the object property"); + if (!PyArg_ParseTuple(args, "|i", &ret_name_only)) return NULL; @@ -441,6 +491,8 @@ PyObject* KX_CameraActuator::PySetObject(PyObject* self, PyObject* value) { KX_GameObject *gameobj; + ShowDeprecationWarning("setObject()", "the object property"); + if (!ConvertPythonToGameObject(value, &gameobj, true)) return NULL; // ConvertPythonToGameObject sets the error @@ -462,6 +514,7 @@ PyObject* KX_CameraActuator::PyGetMin(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getMin()", "the min property"); return PyFloat_FromDouble(m_minHeight); } /* set min ---------------------------------------------------------- */ @@ -472,11 +525,12 @@ PyObject* KX_CameraActuator::PySetMin(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setMin()", "the min property"); float min; if(PyArg_ParseTuple(args,"f", &min)) { m_minHeight = min; - Py_Return; + Py_RETURN_NONE; } return NULL; } @@ -488,6 +542,7 @@ PyObject* KX_CameraActuator::PyGetMax(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getMax()", "the max property"); return PyFloat_FromDouble(m_maxHeight); } /* set min ---------------------------------------------------------- */ @@ -498,11 +553,12 @@ PyObject* KX_CameraActuator::PySetMax(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getMax()", "the max property"); float max; if(PyArg_ParseTuple(args,"f", &max)) { m_maxHeight = max; - Py_Return; + Py_RETURN_NONE; } return NULL; } @@ -514,6 +570,7 @@ PyObject* KX_CameraActuator::PyGetHeight(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getHeight()", "the height property"); return PyFloat_FromDouble(m_height); } /* set height ---------------------------------------------------------- */ @@ -524,11 +581,12 @@ PyObject* KX_CameraActuator::PySetHeight(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getHeight()", "the height property"); float height; if(PyArg_ParseTuple(args,"f", &height)) { m_height = height; - Py_Return; + Py_RETURN_NONE; } return NULL; } @@ -541,11 +599,12 @@ PyObject* KX_CameraActuator::PySetXY(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setXY()", "the xy property"); int value; if(PyArg_ParseTuple(args,"i", &value)) { m_x = value != 0; - Py_Return; + Py_RETURN_NONE; } return NULL; } @@ -559,6 +618,7 @@ PyObject* KX_CameraActuator::PyGetXY(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getXY()", "the xy property"); return PyInt_FromLong(m_x); } diff --git a/source/gameengine/Ketsji/KX_CameraActuator.h b/source/gameengine/Ketsji/KX_CameraActuator.h index d53d12b3b82..3b08536fc21 100644 --- a/source/gameengine/Ketsji/KX_CameraActuator.h +++ b/source/gameengine/Ketsji/KX_CameraActuator.h @@ -59,13 +59,13 @@ private : //const MT_Scalar m_maxHeight; /** height (float), */ - MT_Scalar m_height; + float m_height; /** min (float), */ - MT_Scalar m_minHeight; + float m_minHeight; /** max (float), */ - MT_Scalar m_maxHeight; + float m_maxHeight; /** xy toggle (pick one): true == x, false == y */ bool m_x; @@ -88,9 +88,9 @@ private : SCA_IObject *gameobj, //const CValue *ob, SCA_IObject *ob, - MT_Scalar hght, - MT_Scalar minhght, - MT_Scalar maxhght, + float hght, + float minhght, + float maxhght, bool xytog, PyTypeObject* T=&Type @@ -120,8 +120,9 @@ private : /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); - + virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject* value); + /* set object to look at */ KX_PYMETHOD_DOC_O(KX_CameraActuator,SetObject); /* get current object */ diff --git a/source/gameengine/Ketsji/KX_ConstraintActuator.cpp b/source/gameengine/Ketsji/KX_ConstraintActuator.cpp index 76357e9c58f..c0d802a9cf9 100644 --- a/source/gameengine/Ketsji/KX_ConstraintActuator.cpp +++ b/source/gameengine/Ketsji/KX_ConstraintActuator.cpp @@ -612,7 +612,7 @@ PyMethodDef KX_ConstraintActuator::Methods[] = { {NULL,NULL} //Sentinel }; -PyObject* KX_ConstraintActuator::_getattr(const STR_String& attr) { +PyObject* KX_ConstraintActuator::_getattr(const char *attr) { _getattr_up(SCA_IActuator); } @@ -633,7 +633,7 @@ PyObject* KX_ConstraintActuator::PySetDamp(PyObject* self, m_posDampTime = dampArg; if (m_posDampTime < 0) m_posDampTime = 0; - Py_Return; + Py_RETURN_NONE; } /* 3. getDamp */ const char KX_ConstraintActuator::GetDamp_doc[] = @@ -660,7 +660,7 @@ PyObject* KX_ConstraintActuator::PySetRotDamp(PyObject* self, m_rotDampTime = dampArg; if (m_rotDampTime < 0) m_rotDampTime = 0; - Py_Return; + Py_RETURN_NONE; } /* 3. getRotDamp */ const char KX_ConstraintActuator::GetRotDamp_doc[] = @@ -695,7 +695,7 @@ PyObject* KX_ConstraintActuator::PySetDirection(PyObject* self, } m_refDirection = dir/len; - Py_Return; + Py_RETURN_NONE; } /* 3. getDirection */ const char KX_ConstraintActuator::GetDirection_doc[] = @@ -730,7 +730,7 @@ PyObject* KX_ConstraintActuator::PySetOption(PyObject* self, m_option = option; - Py_Return; + Py_RETURN_NONE; } /* 3. getOption */ const char KX_ConstraintActuator::GetOption_doc[] = @@ -759,7 +759,7 @@ PyObject* KX_ConstraintActuator::PySetTime(PyObject* self, t = 0; m_activeTime = t; - Py_Return; + Py_RETURN_NONE; } /* 3. getTime */ const char KX_ConstraintActuator::GetTime_doc[] = @@ -789,7 +789,7 @@ PyObject* KX_ConstraintActuator::PySetProperty(PyObject* self, m_property[sizeof(m_property)-1] = 0; } - Py_Return; + Py_RETURN_NONE; } /* 3. getProperty */ const char KX_ConstraintActuator::GetProperty_doc[] = @@ -829,7 +829,7 @@ PyObject* KX_ConstraintActuator::PySetMin(PyObject* self, break; } - Py_Return; + Py_RETURN_NONE; } /* 5. getDistance */ const char KX_ConstraintActuator::GetDistance_doc[] = @@ -874,7 +874,7 @@ PyObject* KX_ConstraintActuator::PySetMax(PyObject* self, break; } - Py_Return; + Py_RETURN_NONE; } /* 7. getRayLength */ const char KX_ConstraintActuator::GetRayLength_doc[] = @@ -918,7 +918,7 @@ PyObject* KX_ConstraintActuator::PySetLimit(PyObject* self, if (IsValidMode((KX_CONSTRAINTTYPE)locrotArg)) m_locrot = locrotArg; - Py_Return; + Py_RETURN_NONE; } /* 9. getLimit */ const char KX_ConstraintActuator::GetLimit_doc[] = diff --git a/source/gameengine/Ketsji/KX_ConstraintActuator.h b/source/gameengine/Ketsji/KX_ConstraintActuator.h index 28b9b1e6a0b..132b8a7328a 100644 --- a/source/gameengine/Ketsji/KX_ConstraintActuator.h +++ b/source/gameengine/Ketsji/KX_ConstraintActuator.h @@ -142,7 +142,7 @@ protected: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); KX_PYMETHOD_DOC(KX_ConstraintActuator,SetDamp); KX_PYMETHOD_DOC_NOARGS(KX_ConstraintActuator,GetDamp); diff --git a/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp b/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp index c9095ff34f6..9ceb4a05b06 100644 --- a/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp +++ b/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp @@ -92,32 +92,30 @@ PyParentObject KX_ConstraintWrapper::Parents[] = { NULL }; -PyObject* KX_ConstraintWrapper::_getattr(const STR_String& attr) +PyObject* KX_ConstraintWrapper::_getattr(const char *attr) { //here you can search for existing data members (like mass,friction etc.) _getattr_up(PyObjectPlus); } -int KX_ConstraintWrapper::_setattr(const STR_String& attr,PyObject* pyobj) +int KX_ConstraintWrapper::_setattr(const char *attr,PyObject* pyobj) { - - PyTypeObject* type = pyobj->ob_type; int result = 1; - if (type == &PyList_Type) + if (PyList_Check(pyobj)) { result = 0; } - if (type == &PyFloat_Type) + if (PyFloat_Check(pyobj)) { result = 0; } - if (type == &PyInt_Type) + if (PyInt_Check(pyobj)) { result = 0; } - if (type == &PyString_Type) + if (PyString_Check(pyobj)) { result = 0; } diff --git a/source/gameengine/Ketsji/KX_ConstraintWrapper.h b/source/gameengine/Ketsji/KX_ConstraintWrapper.h index 79fb3dc21aa..36606d2d67b 100644 --- a/source/gameengine/Ketsji/KX_ConstraintWrapper.h +++ b/source/gameengine/Ketsji/KX_ConstraintWrapper.h @@ -35,8 +35,8 @@ class KX_ConstraintWrapper : public PyObjectPlus { Py_Header; - virtual PyObject* _getattr(const STR_String& attr); - virtual int _setattr(const STR_String& attr, PyObject *value); + virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject *value); public: KX_ConstraintWrapper(PHY_ConstraintType ctype,int constraintId,class PHY_IPhysicsEnvironment* physenv,PyTypeObject *T = &Type); virtual ~KX_ConstraintWrapper (); diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp index 0e7a6d92ec1..46e46b014b5 100644 --- a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp +++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp @@ -1084,7 +1084,7 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, ci.m_bSoft = objprop->m_softbody; MT_Vector3 scaling = gameobj->NodeGetWorldScaling(); ci.m_scaling.setValue(scaling[0], scaling[1], scaling[2]); - KX_BulletPhysicsController* physicscontroller = new KX_BulletPhysicsController(ci,isbulletdyna); + KX_BulletPhysicsController* physicscontroller = new KX_BulletPhysicsController(ci,isbulletdyna,objprop->m_hasCompoundChildren); // shapeInfo is reference counted, decrement now as we don't use it anymore if (shapeInfo) shapeInfo->Release(); diff --git a/source/gameengine/Ketsji/KX_GameActuator.cpp b/source/gameengine/Ketsji/KX_GameActuator.cpp index 76459e46731..2387dcdef3a 100644 --- a/source/gameengine/Ketsji/KX_GameActuator.cpp +++ b/source/gameengine/Ketsji/KX_GameActuator.cpp @@ -270,13 +270,13 @@ PyObject* KX_GameActuator::PySetFile(PyObject* self, PyObject* args, PyObject* k m_filename = STR_String(new_file); - Py_Return; + Py_RETURN_NONE; } -PyObject* KX_GameActuator::_getattr(const STR_String& attr) +PyObject* KX_GameActuator::_getattr(const char *attr) { _getattr_up(SCA_IActuator); } diff --git a/source/gameengine/Ketsji/KX_GameActuator.h b/source/gameengine/Ketsji/KX_GameActuator.h index bb3448995dc..856fa0c24e9 100644 --- a/source/gameengine/Ketsji/KX_GameActuator.h +++ b/source/gameengine/Ketsji/KX_GameActuator.h @@ -77,7 +77,7 @@ protected: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); KX_PYMETHOD_DOC(KX_GameActuator,GetFile); KX_PYMETHOD_DOC(KX_GameActuator,SetFile); diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index a168beb9a70..82b5fff534c 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -252,6 +252,20 @@ void KX_GameObject::SetParent(KX_Scene *scene, KX_GameObject* obj) if (rootlist->RemoveValue(this)) // the object was in parent list, decrement ref count as it's now removed Release(); + // if the new parent is a compound object, add this object shape to the compound shape. + // step 0: verify this object has physical controller + if (m_pPhysicsController1) + { + // step 1: find the top parent (not necessarily obj) + KX_GameObject* rootobj = (KX_GameObject*)obj->GetSGNode()->GetRootSGParent()->GetSGClientObject(); + // step 2: verify it has a physical controller and compound shape + if (rootobj != NULL && + rootobj->m_pPhysicsController1 != NULL && + rootobj->m_pPhysicsController1->IsCompound()) + { + rootobj->m_pPhysicsController1->AddCompoundChild(m_pPhysicsController1); + } + } } } @@ -260,6 +274,8 @@ void KX_GameObject::RemoveParent(KX_Scene *scene) // check on valid node in case a python controller holds a reference to a deleted object if (GetSGNode() && GetSGNode()->GetSGParent()) { + // get the root object to remove us from compound object if needed + KX_GameObject* rootobj = (KX_GameObject*)GetSGNode()->GetRootSGParent()->GetSGClientObject(); // Set us to the right spot GetSGNode()->SetLocalScale(GetSGNode()->GetWorldScaling()); GetSGNode()->SetLocalOrientation(GetSGNode()->GetWorldOrientation()); @@ -275,6 +291,13 @@ void KX_GameObject::RemoveParent(KX_Scene *scene) rootlist->Add(AddRef()); if (m_pPhysicsController1) { + // in case this controller was added as a child shape to the parent + if (rootobj != NULL && + rootobj->m_pPhysicsController1 != NULL && + rootobj->m_pPhysicsController1->IsCompound()) + { + rootobj->m_pPhysicsController1->RemoveCompoundChild(m_pPhysicsController1); + } m_pPhysicsController1->RestoreDynamics(); } } @@ -498,7 +521,7 @@ KX_GameObject::UpdateMaterialData( { KX_BlenderMaterial *m = static_cast<KX_BlenderMaterial*>(poly); - if (matname_hash == NULL) + if (matname_hash == 0) { m->UpdateIPO(rgba, specrgb,hard,spec,ref,emit, alpha); // if mesh has only one material attached to it then use original hack with no need to edit vertices (better performance) @@ -615,6 +638,7 @@ void KX_GameObject::setAngularVelocity(const MT_Vector3& ang_vel,bool local) m_pPhysicsController1->SetAngularVelocity(ang_vel,local); } + void KX_GameObject::ResolveCombinedVelocities( const MT_Vector3 & lin_vel, const MT_Vector3 & ang_vel, @@ -969,6 +993,10 @@ PyMethodDef KX_GameObject::Methods[] = { {"getPosition", (PyCFunction) KX_GameObject::sPyGetPosition, METH_NOARGS}, {"setPosition", (PyCFunction) KX_GameObject::sPySetPosition, METH_O}, {"setWorldPosition", (PyCFunction) KX_GameObject::sPySetWorldPosition, METH_O}, + {"applyForce", (PyCFunction) KX_GameObject::sPyApplyForce, METH_VARARGS}, + {"applyTorque", (PyCFunction) KX_GameObject::sPyApplyTorque, METH_VARARGS}, + {"applyRotation", (PyCFunction) KX_GameObject::sPyApplyRotation, METH_VARARGS}, + {"applyMovement", (PyCFunction) KX_GameObject::sPyApplyMovement, METH_VARARGS}, {"getLinearVelocity", (PyCFunction) KX_GameObject::sPyGetLinearVelocity, METH_VARARGS}, {"setLinearVelocity", (PyCFunction) KX_GameObject::sPySetLinearVelocity, METH_VARARGS}, {"getAngularVelocity", (PyCFunction) KX_GameObject::sPyGetAngularVelocity, METH_VARARGS}, @@ -1002,8 +1030,8 @@ PyMethodDef KX_GameObject::Methods[] = { {"endObject",(PyCFunction) KX_GameObject::sPyEndObject, METH_NOARGS}, KX_PYMETHODTABLE(KX_GameObject, rayCastTo), KX_PYMETHODTABLE(KX_GameObject, rayCast), - KX_PYMETHODTABLE(KX_GameObject, getDistanceTo), - KX_PYMETHODTABLE(KX_GameObject, getVectTo), + KX_PYMETHODTABLE_O(KX_GameObject, getDistanceTo), + KX_PYMETHODTABLE_O(KX_GameObject, getVectTo), {NULL,NULL} //Sentinel }; @@ -1096,40 +1124,39 @@ PyParentObject KX_GameObject::Parents[] = { -PyObject* KX_GameObject::_getattr(const STR_String& attr) +PyObject* KX_GameObject::_getattr(const char *attr) { if (m_pPhysicsController1) { - if (attr == "mass") - return PyFloat_FromDouble(GetPhysicsController()->GetMass()); + if (!strcmp(attr, "mass")) + return PyFloat_FromDouble(m_pPhysicsController1->GetMass()); } - if (attr == "parent") + if (!strcmp(attr, "parent")) { KX_GameObject* parent = GetParent(); if (parent) - { - parent->AddRef(); - return parent; - } + return parent->AddRef(); Py_RETURN_NONE; } - if (attr == "visible") + if (!strcmp(attr, "visible")) return PyInt_FromLong(m_bVisible); - if (attr == "position") + if (!strcmp(attr, "position")) return PyObjectFrom(NodeGetWorldPosition()); - if (attr == "orientation") + if (!strcmp(attr, "orientation")) return PyObjectFrom(NodeGetWorldOrientation()); - if (attr == "scaling") + if (!strcmp(attr, "scaling")) return PyObjectFrom(NodeGetWorldScaling()); - if (attr == "name") + if (!strcmp(attr, "name")) return PyString_FromString(m_name.ReadPtr()); - if (attr == "timeOffset") { + + if (!strcmp(attr, "timeOffset")) + { if (m_pSGNode->GetSGParent()->IsSlowParent()) { return PyFloat_FromDouble(static_cast<KX_SlowParentRelation *>(m_pSGNode->GetSGParent()->GetParentRelation())->GetTimeOffset()); } else { @@ -1141,14 +1168,10 @@ PyObject* KX_GameObject::_getattr(const STR_String& attr) _getattr_up(SCA_IObject); } -int KX_GameObject::_setattr(const STR_String& attr, PyObject *value) // _setattr method +int KX_GameObject::_setattr(const char *attr, PyObject *value) // _setattr method { - if (attr == "mass") { - PyErr_SetString(PyExc_AttributeError, "attribute \"mass\" is read only"); - return 1; - } - if (attr == "parent") { + if (!strcmp(attr, "parent")) { PyErr_SetString(PyExc_AttributeError, "attribute \"mass\" is read only\nUse setParent()"); return 1; } @@ -1156,7 +1179,7 @@ int KX_GameObject::_setattr(const STR_String& attr, PyObject *value) // _setattr if (PyInt_Check(value)) { int val = PyInt_AsLong(value); - if (attr == "visible") + if (!strcmp(attr, "visible")) { SetVisible(val != 0, false); UpdateBuckets(false); @@ -1167,7 +1190,7 @@ int KX_GameObject::_setattr(const STR_String& attr, PyObject *value) // _setattr if (PyFloat_Check(value)) { MT_Scalar val = PyFloat_AsDouble(value); - if (attr == "timeOffset") { + if (!strcmp(attr, "timeOffset")) { if (m_pSGNode->GetSGParent() && m_pSGNode->GetSGParent()->IsSlowParent()) { static_cast<KX_SlowParentRelation *>(m_pSGNode->GetSGParent()->GetParentRelation())->SetTimeOffset(val); return 0; @@ -1175,11 +1198,16 @@ int KX_GameObject::_setattr(const STR_String& attr, PyObject *value) // _setattr return 0; } } + if (!strcmp(attr, "mass")) { + if (m_pPhysicsController1) + m_pPhysicsController1->SetMass(val); + return 0; + } } if (PySequence_Check(value)) { - if (attr == "orientation") + if (!strcmp(attr, "orientation")) { MT_Matrix3x3 rot; if (PyObject_IsMT_Matrix(value, 3)) @@ -1222,7 +1250,7 @@ int KX_GameObject::_setattr(const STR_String& attr, PyObject *value) // _setattr return 1; } - if (attr == "position") + if (!strcmp(attr, "position")) { MT_Point3 pos; if (PyVecTo(value, pos)) @@ -1234,7 +1262,7 @@ int KX_GameObject::_setattr(const STR_String& attr, PyObject *value) // _setattr return 1; } - if (attr == "scaling") + if (!strcmp(attr, "scaling")) { MT_Vector3 scale; if (PyVecTo(value, scale)) @@ -1249,7 +1277,7 @@ int KX_GameObject::_setattr(const STR_String& attr, PyObject *value) // _setattr if (PyString_Check(value)) { - if (attr == "name") + if (!strcmp(attr, "name")) { m_name = PyString_AsString(value); return 0; @@ -1261,12 +1289,71 @@ int KX_GameObject::_setattr(const STR_String& attr, PyObject *value) // _setattr return SCA_IObject::_setattr(attr, value); } +PyObject* KX_GameObject::PyApplyForce(PyObject* self, PyObject* args) +{ + int local = 0; + PyObject* pyvect; + + if (PyArg_ParseTuple(args, "O|i:applyForce", &pyvect, &local)) { + MT_Vector3 force; + if (PyVecTo(pyvect, force)) { + ApplyForce(force, (local!=0)); + Py_RETURN_NONE; + } + } + return NULL; +} + +PyObject* KX_GameObject::PyApplyTorque(PyObject* self, PyObject* args) +{ + int local = 0; + PyObject* pyvect; + + if (PyArg_ParseTuple(args, "O|i:applyTorque", &pyvect, &local)) { + MT_Vector3 torque; + if (PyVecTo(pyvect, torque)) { + ApplyTorque(torque, (local!=0)); + Py_RETURN_NONE; + } + } + return NULL; +} + +PyObject* KX_GameObject::PyApplyRotation(PyObject* self, PyObject* args) +{ + int local = 0; + PyObject* pyvect; + + if (PyArg_ParseTuple(args, "O|i:applyRotation", &pyvect, &local)) { + MT_Vector3 rotation; + if (PyVecTo(pyvect, rotation)) { + ApplyRotation(rotation, (local!=0)); + Py_RETURN_NONE; + } + } + return NULL; +} + +PyObject* KX_GameObject::PyApplyMovement(PyObject* self, PyObject* args) +{ + int local = 0; + PyObject* pyvect; + + if (PyArg_ParseTuple(args, "O|i:applyMovement", &pyvect, &local)) { + MT_Vector3 movement; + if (PyVecTo(pyvect, movement)) { + ApplyMovement(movement, (local!=0)); + Py_RETURN_NONE; + } + } + return NULL; +} PyObject* KX_GameObject::PyGetLinearVelocity(PyObject* self, PyObject* args) { // only can get the velocity if we have a physics object connected to us... int local = 0; - if (PyArg_ParseTuple(args,"|i",&local)) + if (PyArg_ParseTuple(args,"|i:getLinearVelocity",&local)) { return PyObjectFrom(GetLinearVelocity((local!=0))); } @@ -1281,7 +1368,7 @@ PyObject* KX_GameObject::PySetLinearVelocity(PyObject* self, PyObject* args) int local = 0; PyObject* pyvect; - if (PyArg_ParseTuple(args,"O|i",&pyvect,&local)) { + if (PyArg_ParseTuple(args,"O|i:setLinearVelocity",&pyvect,&local)) { MT_Vector3 velocity; if (PyVecTo(pyvect, velocity)) { setLinearVelocity(velocity, (local!=0)); @@ -1295,7 +1382,7 @@ PyObject* KX_GameObject::PyGetAngularVelocity(PyObject* self, PyObject* args) { // only can get the velocity if we have a physics object connected to us... int local = 0; - if (PyArg_ParseTuple(args,"|i",&local)) + if (PyArg_ParseTuple(args,"|i:getAngularVelocity",&local)) { return PyObjectFrom(GetAngularVelocity((local!=0))); } @@ -1310,7 +1397,7 @@ PyObject* KX_GameObject::PySetAngularVelocity(PyObject* self, PyObject* args) int local = 0; PyObject* pyvect; - if (PyArg_ParseTuple(args,"O|i",&pyvect,&local)) { + if (PyArg_ParseTuple(args,"O|i:setAngularVelocity",&pyvect,&local)) { MT_Vector3 velocity; if (PyVecTo(pyvect, velocity)) { setAngularVelocity(velocity, (local!=0)); @@ -1323,7 +1410,7 @@ PyObject* KX_GameObject::PySetAngularVelocity(PyObject* self, PyObject* args) PyObject* KX_GameObject::PySetVisible(PyObject* self, PyObject* args) { int visible, recursive = 0; - if (!PyArg_ParseTuple(args,"i|i",&visible, &recursive)) + if (!PyArg_ParseTuple(args,"i|i:setVisible",&visible, &recursive)) return NULL; SetVisible(visible ? true:false, recursive ? true:false); @@ -1374,7 +1461,7 @@ PyObject* KX_GameObject::PyGetVelocity(PyObject* self, PyObject* args) PyObject* pypos = NULL; - if (PyArg_ParseTuple(args, "|O", &pypos)) + if (PyArg_ParseTuple(args, "|O:getVelocity", &pypos)) { if (pypos) PyVecTo(pypos, point); @@ -1430,10 +1517,7 @@ PyObject* KX_GameObject::PyGetParent(PyObject* self) { KX_GameObject* parent = this->GetParent(); if (parent) - { - parent->AddRef(); - return parent; - } + return parent->AddRef(); Py_RETURN_NONE; } @@ -1502,7 +1586,7 @@ PyObject* KX_GameObject::PyGetMesh(PyObject* self, PyObject* args) { int mesh = 0; - if (!PyArg_ParseTuple(args, "|i", &mesh)) + if (!PyArg_ParseTuple(args, "|i:getMesh", &mesh)) return NULL; // python sets a simple error if (((unsigned int)mesh < m_meshes.size()) && mesh >= 0) @@ -1548,7 +1632,7 @@ PyObject* KX_GameObject::PyApplyImpulse(PyObject* self, PyObject* args) return NULL; } - if (PyArg_ParseTuple(args, "OO", &pyattach, &pyimpulse)) + if (PyArg_ParseTuple(args, "OO:applyImpulse", &pyattach, &pyimpulse)) { MT_Point3 attach; MT_Vector3 impulse; @@ -1615,7 +1699,7 @@ PyObject* KX_GameObject::PyAlignAxisToVect(PyObject* self, PyObject* args) int axis = 2; //z axis is the default float fac = 1.0; - if (PyArg_ParseTuple(args,"O|if",&pyvect,&axis, &fac)) + if (PyArg_ParseTuple(args,"O|if:alignAxisToVect",&pyvect,&axis, &fac)) { MT_Vector3 vect; if (PyVecTo(pyvect, vect)) @@ -1683,19 +1767,18 @@ PyObject* KX_GameObject::PyGetPropertyNames(PyObject* self) return ConvertKeysToPython(); } -KX_PYMETHODDEF_DOC(KX_GameObject, getDistanceTo, +KX_PYMETHODDEF_DOC_O(KX_GameObject, getDistanceTo, "getDistanceTo(other): get distance to another point/KX_GameObject") { MT_Point3 b; - if (PyVecArgTo(args, b)) + if (PyVecTo(value, b)) { return PyFloat_FromDouble(NodeGetWorldPosition().distance(b)); } PyErr_Clear(); - PyObject *pyother; KX_GameObject *other; - if (PyArg_ParseTuple(args, "O", &pyother) && ConvertPythonToGameObject(pyother, &other, false)) + if (ConvertPythonToGameObject(value, &other, false)) { return PyFloat_FromDouble(NodeGetWorldPosition().distance(other->NodeGetWorldPosition())); } @@ -1703,7 +1786,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, getDistanceTo, return NULL; } -KX_PYMETHODDEF_DOC(KX_GameObject, getVectTo, +KX_PYMETHODDEF_DOC_O(KX_GameObject, getVectTo, "getVectTo(other): get vector and the distance to another point/KX_GameObject\n" "Returns a 3-tuple with (distance,worldVector,localVector)\n") { @@ -1712,14 +1795,13 @@ KX_PYMETHODDEF_DOC(KX_GameObject, getVectTo, MT_Scalar distance; PyObject *returnValue; - PyObject *pyother; - if (!PyVecArgTo(args, toPoint)) + if (!PyVecTo(value, toPoint)) { PyErr_Clear(); KX_GameObject *other; - if (PyArg_ParseTuple(args, "O", &pyother) && ConvertPythonToGameObject(pyother, &other, false)) + if (ConvertPythonToGameObject(value, &other, false)) { toPoint = other->NodeGetWorldPosition(); } else @@ -1804,7 +1886,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo, float dist = 0.0f; char *propName = NULL; - if (!PyArg_ParseTuple(args,"O|fs", &pyarg, &dist, &propName)) { + if (!PyArg_ParseTuple(args,"O|fs:rayCastTo", &pyarg, &dist, &propName)) { return NULL; // python sets simple error } @@ -1847,10 +1929,8 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo, KX_RayCast::RayTest(pe, fromPoint, toPoint, callback); if (m_pHitObject) - { - m_pHitObject->AddRef(); - return m_pHitObject; - } + return m_pHitObject->AddRef(); + Py_RETURN_NONE; } @@ -1883,7 +1963,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast, KX_GameObject *other; int face=0, xray=0, poly=0; - if (!PyArg_ParseTuple(args,"O|Ofsiii", &pyto, &pyfrom, &dist, &propName, &face, &xray, &poly)) { + if (!PyArg_ParseTuple(args,"O|Ofsiii:rayCast", &pyto, &pyfrom, &dist, &propName, &face, &xray, &poly)) { return NULL; // Python sets a simple error } @@ -2018,7 +2098,6 @@ bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py PyErr_SetString(PyExc_TypeError, "Expected KX_GameObject or a string for a name of a KX_GameObject, None is invalid"); return false; } - return (py_none_ok ? true : false); } if (PyString_Check(value)) { diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index 20b15787d27..d95e3751d33 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -756,22 +756,16 @@ public: * @section Python interface functions. */ - virtual - PyObject* - _getattr( - const STR_String& attr - ); - - virtual - int - _setattr( - const STR_String& attr, - PyObject *value - ); // _setattr method + virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject *value); // _setattr method KX_PYMETHOD_NOARGS(KX_GameObject,GetPosition); KX_PYMETHOD_O(KX_GameObject,SetPosition); KX_PYMETHOD_O(KX_GameObject,SetWorldPosition); + KX_PYMETHOD_VARARGS(KX_GameObject, ApplyForce); + KX_PYMETHOD_VARARGS(KX_GameObject, ApplyTorque); + KX_PYMETHOD_VARARGS(KX_GameObject, ApplyRotation); + KX_PYMETHOD_VARARGS(KX_GameObject, ApplyMovement); KX_PYMETHOD_VARARGS(KX_GameObject,GetLinearVelocity); KX_PYMETHOD_VARARGS(KX_GameObject,SetLinearVelocity); KX_PYMETHOD_VARARGS(KX_GameObject,GetAngularVelocity); @@ -805,8 +799,8 @@ public: KX_PYMETHOD_NOARGS(KX_GameObject,EndObject); KX_PYMETHOD_DOC(KX_GameObject,rayCastTo); KX_PYMETHOD_DOC(KX_GameObject,rayCast); - KX_PYMETHOD_DOC(KX_GameObject,getDistanceTo); - KX_PYMETHOD_DOC(KX_GameObject,getVectTo); + KX_PYMETHOD_DOC_O(KX_GameObject,getDistanceTo); + KX_PYMETHOD_DOC_O(KX_GameObject,getVectTo); private : diff --git a/source/gameengine/Ketsji/KX_IPhysicsController.cpp b/source/gameengine/Ketsji/KX_IPhysicsController.cpp index 5cd66efd965..a38222c5f7e 100644 --- a/source/gameengine/Ketsji/KX_IPhysicsController.cpp +++ b/source/gameengine/Ketsji/KX_IPhysicsController.cpp @@ -35,9 +35,10 @@ #include "PHY_DynamicTypes.h" -KX_IPhysicsController::KX_IPhysicsController(bool dyna,void* userdata) +KX_IPhysicsController::KX_IPhysicsController(bool dyna, bool compound, void* userdata) : m_bDyna(dyna), + m_bCompound(compound), m_suspendDynamics(false), m_userdata(userdata) { diff --git a/source/gameengine/Ketsji/KX_IPhysicsController.h b/source/gameengine/Ketsji/KX_IPhysicsController.h index 4ea283e9f98..13501f1fbbd 100644 --- a/source/gameengine/Ketsji/KX_IPhysicsController.h +++ b/source/gameengine/Ketsji/KX_IPhysicsController.h @@ -32,6 +32,7 @@ #include "SG_Controller.h" #include "MT_Vector3.h" #include "MT_Point3.h" +#include "MT_Transform.h" #include "MT_Matrix3x3.h" struct KX_ClientObjectInfo; @@ -48,10 +49,11 @@ class KX_IPhysicsController : public SG_Controller { protected: bool m_bDyna; + bool m_bCompound; bool m_suspendDynamics; void* m_userdata; public: - KX_IPhysicsController(bool dyna,void* userdata); + KX_IPhysicsController(bool dyna,bool compound, void* userdata); virtual ~KX_IPhysicsController(); @@ -76,8 +78,11 @@ public: virtual void setPosition(const MT_Point3& pos)=0; virtual void setScaling(const MT_Vector3& scaling)=0; virtual MT_Scalar GetMass()=0; + virtual void SetMass(MT_Scalar newmass)=0; virtual MT_Vector3 getReactionForce()=0; virtual void setRigidBody(bool rigid)=0; + virtual void AddCompoundChild(KX_IPhysicsController* child) = 0; + virtual void RemoveCompoundChild(KX_IPhysicsController* child) = 0; virtual void SuspendDynamics(bool ghost=false)=0; virtual void RestoreDynamics()=0; @@ -92,6 +97,10 @@ public: return m_bDyna; } + bool IsCompound(void) { + return m_bCompound; + } + virtual MT_Scalar GetRadius()=0; virtual void SetSumoTransform(bool nondynaonly)=0; // todo: remove next line ! diff --git a/source/gameengine/Ketsji/KX_IpoActuator.cpp b/source/gameengine/Ketsji/KX_IpoActuator.cpp index f5e17118ffb..ca8419666b5 100644 --- a/source/gameengine/Ketsji/KX_IpoActuator.cpp +++ b/source/gameengine/Ketsji/KX_IpoActuator.cpp @@ -457,7 +457,7 @@ PyMethodDef KX_IpoActuator::Methods[] = { {NULL,NULL} //Sentinel }; -PyObject* KX_IpoActuator::_getattr(const STR_String& attr) { +PyObject* KX_IpoActuator::_getattr(const char *attr) { _getattr_up(SCA_IActuator); } @@ -503,7 +503,7 @@ PyObject* KX_IpoActuator::PySet(PyObject* self, ; /* error */ } - Py_Return; + Py_RETURN_NONE; } /* set property ----------------------------------------------------------- */ @@ -523,7 +523,7 @@ PyObject* KX_IpoActuator::PySetProperty(PyObject* self, m_propname = propertyName; - Py_Return; + Py_RETURN_NONE; } /* 4. setStart: */ @@ -541,7 +541,7 @@ PyObject* KX_IpoActuator::PySetStart(PyObject* self, m_startframe = startArg; - Py_Return; + Py_RETURN_NONE; } /* 5. getStart: */ const char KX_IpoActuator::GetStart_doc[] = @@ -566,7 +566,7 @@ PyObject* KX_IpoActuator::PySetEnd(PyObject* self, m_endframe = endArg; - Py_Return; + Py_RETURN_NONE; } /* 7. getEnd: */ const char KX_IpoActuator::GetEnd_doc[] = @@ -594,7 +594,7 @@ PyObject* KX_IpoActuator::PySetIpoAsForce(PyObject* self, if (m_ipo_as_force) m_ipo_add = false; - Py_Return; + Py_RETURN_NONE; } /* 7. getIpoAsForce: */ const char KX_IpoActuator::GetIpoAsForce_doc[] = @@ -622,7 +622,7 @@ PyObject* KX_IpoActuator::PySetIpoAdd(PyObject* self, if (m_ipo_add) m_ipo_as_force = false; - Py_Return; + Py_RETURN_NONE; } /* 7. getIpoAsForce: */ const char KX_IpoActuator::GetIpoAdd_doc[] = @@ -651,7 +651,7 @@ PyObject* KX_IpoActuator::PySetType(PyObject* self, m_type = (IpoActType) typeArg; } - Py_Return; + Py_RETURN_NONE; } /* 9. getType: */ const char KX_IpoActuator::GetType_doc[] = @@ -679,7 +679,7 @@ PyObject* KX_IpoActuator::PySetForceIpoActsLocal(PyObject* self, m_ipo_local = PyArgToBool(boolArg); - Py_Return; + Py_RETURN_NONE; } /* 11. getForceIpoActsLocal: */ const char KX_IpoActuator::GetForceIpoActsLocal_doc[] = diff --git a/source/gameengine/Ketsji/KX_IpoActuator.h b/source/gameengine/Ketsji/KX_IpoActuator.h index 8e5baed0530..12e1835ab49 100644 --- a/source/gameengine/Ketsji/KX_IpoActuator.h +++ b/source/gameengine/Ketsji/KX_IpoActuator.h @@ -141,7 +141,7 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); //KX_PYMETHOD_DOC KX_PYMETHOD_DOC(KX_IpoActuator,Set); KX_PYMETHOD_DOC(KX_IpoActuator,SetProperty); diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index 8bcda4479e1..1271474802c 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -732,6 +732,26 @@ void KX_KetsjiEngine::Render() // do the rendering //RenderFrame(scene); RenderFrame(scene, cam); + + list<class KX_Camera*>* cameras = scene->GetCameras(); + + // Draw the scene once for each camera with an enabled viewport + list<KX_Camera*>::iterator it = cameras->begin(); + while(it != cameras->end()) + { + if((*it)->GetViewport()) + { + if (scene->IsClearingZBuffer()) + m_rasterizer->ClearDepthBuffer(); + + m_rendertools->SetAuxilaryClientInfo(scene); + + // do the rendering + RenderFrame(scene, (*it)); + } + + it++; + } } } // if(m_rasterizer->Stereo()) diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.h b/source/gameengine/Ketsji/KX_KetsjiEngine.h index 4184202c518..8516049f6d8 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.h +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.h @@ -184,7 +184,6 @@ private: void RenderDebugProperties(); void RenderShadowBuffers(KX_Scene *scene); void SetBackGround(KX_WorldInfo* worldinfo); - void SetWorldSettings(KX_WorldInfo* worldinfo); void DoSound(KX_Scene* scene); public: @@ -193,6 +192,7 @@ public: virtual ~KX_KetsjiEngine(); // set the devices and stuff. the client must take care of creating these + void SetWorldSettings(KX_WorldInfo* worldinfo); void SetKeyboardDevice(SCA_IInputDevice* keyboarddevice); void SetMouseDevice(SCA_IInputDevice* mousedevice); void SetNetworkDevice(NG_NetworkDeviceInterface* networkdevice); @@ -205,6 +205,8 @@ public: void SetGame2IpoMode(bool game2ipo,int startFrame); RAS_IRasterizer* GetRasterizer(){return m_rasterizer;}; + RAS_ICanvas* GetCanvas(){return m_canvas;}; + RAS_IRenderTools* GetRenderTools(){return m_rendertools;}; ///returns true if an update happened to indicate -> Render bool NextFrame(); diff --git a/source/gameengine/Ketsji/KX_Light.cpp b/source/gameengine/Ketsji/KX_Light.cpp index e0f171e78e0..36700265260 100644 --- a/source/gameengine/Ketsji/KX_Light.cpp +++ b/source/gameengine/Ketsji/KX_Light.cpp @@ -172,65 +172,59 @@ void KX_LightObject::UnbindShadowBuffer(RAS_IRasterizer *ras) GPU_lamp_shadow_buffer_unbind(lamp); } -PyObject* KX_LightObject::_getattr(const STR_String& attr) +PyObject* KX_LightObject::_getattr(const char *attr) { - if (attr == "layer") + if (!strcmp(attr, "layer")) return PyInt_FromLong(m_lightobj.m_layer); - if (attr == "energy") + if (!strcmp(attr, "energy")) return PyFloat_FromDouble(m_lightobj.m_energy); - if (attr == "distance") + if (!strcmp(attr, "distance")) return PyFloat_FromDouble(m_lightobj.m_distance); - if (attr == "colour" || attr == "color") + if (!strcmp(attr, "colour") || !strcmp(attr, "color")) return Py_BuildValue("[fff]", m_lightobj.m_red, m_lightobj.m_green, m_lightobj.m_blue); - if (attr == "lin_attenuation") + if (!strcmp(attr, "lin_attenuation")) return PyFloat_FromDouble(m_lightobj.m_att1); - if (attr == "quad_attenuation") + if (!strcmp(attr, "quad_attenuation")) return PyFloat_FromDouble(m_lightobj.m_att2); - if (attr == "spotsize") + if (!strcmp(attr, "spotsize")) return PyFloat_FromDouble(m_lightobj.m_spotsize); - if (attr == "spotblend") + if (!strcmp(attr, "spotblend")) return PyFloat_FromDouble(m_lightobj.m_spotblend); - if (attr == "SPOT") + if (!strcmp(attr, "SPOT")) return PyInt_FromLong(RAS_LightObject::LIGHT_SPOT); - if (attr == "SUN") + if (!strcmp(attr, "SUN")) return PyInt_FromLong(RAS_LightObject::LIGHT_SUN); - if (attr == "NORMAL") + if (!strcmp(attr, "NORMAL")) return PyInt_FromLong(RAS_LightObject::LIGHT_NORMAL); - if (attr == "type") + if (!strcmp(attr, "type")) return PyInt_FromLong(m_lightobj.m_type); _getattr_up(KX_GameObject); } -int KX_LightObject::_setattr(const STR_String& attr, PyObject *pyvalue) -{ - if (attr == "SPOT" || attr == "SUN" || attr == "NORMAL") - { - PyErr_Format(PyExc_RuntimeError, "Attribute %s is read only.", attr.ReadPtr()); - return 1; - } - +int KX_LightObject::_setattr(const char *attr, PyObject *pyvalue) +{ if (PyInt_Check(pyvalue)) { int value = PyInt_AsLong(pyvalue); - if (attr == "layer") + if (!strcmp(attr, "layer")) { m_lightobj.m_layer = value; return 0; } - if (attr == "type") + if (!strcmp(attr, "type")) { if (value >= RAS_LightObject::LIGHT_SPOT && value <= RAS_LightObject::LIGHT_NORMAL) m_lightobj.m_type = (RAS_LightObject::LightType) value; @@ -241,37 +235,37 @@ int KX_LightObject::_setattr(const STR_String& attr, PyObject *pyvalue) if (PyFloat_Check(pyvalue)) { float value = PyFloat_AsDouble(pyvalue); - if (attr == "energy") + if (!strcmp(attr, "energy")) { m_lightobj.m_energy = value; return 0; } - if (attr == "distance") + if (!strcmp(attr, "distance")) { m_lightobj.m_distance = value; return 0; } - if (attr == "lin_attenuation") + if (!strcmp(attr, "lin_attenuation")) { m_lightobj.m_att1 = value; return 0; } - if (attr == "quad_attenuation") + if (!strcmp(attr, "quad_attenuation")) { m_lightobj.m_att2 = value; return 0; } - if (attr == "spotsize") + if (!strcmp(attr, "spotsize")) { m_lightobj.m_spotsize = value; return 0; } - if (attr == "spotblend") + if (!strcmp(attr, "spotblend")) { m_lightobj.m_spotblend = value; return 0; @@ -280,7 +274,7 @@ int KX_LightObject::_setattr(const STR_String& attr, PyObject *pyvalue) if (PySequence_Check(pyvalue)) { - if (attr == "colour" || attr == "color") + if (!strcmp(attr, "colour") || !strcmp(attr, "color")) { MT_Vector3 color; if (PyVecTo(pyvalue, color)) @@ -294,6 +288,12 @@ int KX_LightObject::_setattr(const STR_String& attr, PyObject *pyvalue) } } + if (!strcmp(attr, "SPOT") || !strcmp(attr, "SUN") || !strcmp(attr, "NORMAL")) + { + PyErr_Format(PyExc_RuntimeError, "Attribute %s is read only.", attr); + return 1; + } + return KX_GameObject::_setattr(attr, pyvalue); } diff --git a/source/gameengine/Ketsji/KX_Light.h b/source/gameengine/Ketsji/KX_Light.h index e5dbf0b7f4a..47edd09b5b9 100644 --- a/source/gameengine/Ketsji/KX_Light.h +++ b/source/gameengine/Ketsji/KX_Light.h @@ -63,8 +63,8 @@ public: void UnbindShadowBuffer(class RAS_IRasterizer *ras); void Update(); - virtual PyObject* _getattr(const STR_String& attr); /* lens, near, far, projection_matrix */ - virtual int _setattr(const STR_String& attr, PyObject *pyvalue); + virtual PyObject* _getattr(const char *attr); /* lens, near, far, projection_matrix */ + virtual int _setattr(const char *attr, PyObject *pyvalue); virtual bool IsLight(void) { return true; } }; diff --git a/source/gameengine/Ketsji/KX_MeshProxy.cpp b/source/gameengine/Ketsji/KX_MeshProxy.cpp index 5cc102248f2..4b949903c88 100644 --- a/source/gameengine/Ketsji/KX_MeshProxy.cpp +++ b/source/gameengine/Ketsji/KX_MeshProxy.cpp @@ -93,9 +93,9 @@ void KX_MeshProxy::SetMeshModified(bool v) PyObject* -KX_MeshProxy::_getattr(const STR_String& attr) +KX_MeshProxy::_getattr(const char *attr) { - if (attr == "materials") + if (!strcmp(attr, "materials")) { PyObject *materials = PyList_New(0); list<RAS_MeshMaterial>::iterator mit = m_meshobj->GetFirstMaterial(); diff --git a/source/gameengine/Ketsji/KX_MeshProxy.h b/source/gameengine/Ketsji/KX_MeshProxy.h index 3335c349673..34f60a54a3a 100644 --- a/source/gameengine/Ketsji/KX_MeshProxy.h +++ b/source/gameengine/Ketsji/KX_MeshProxy.h @@ -53,7 +53,7 @@ public: virtual CValue* GetReplica(); // stuff for python integration - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); KX_PYMETHOD(KX_MeshProxy,GetNumMaterials); KX_PYMETHOD(KX_MeshProxy,GetMaterialName); KX_PYMETHOD(KX_MeshProxy,GetTextureName); diff --git a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp index 28279b9a6b8..bd15d3cffbe 100644 --- a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp +++ b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp @@ -331,7 +331,7 @@ PyMethodDef KX_MouseFocusSensor::Methods[] = { {NULL,NULL} //Sentinel }; -PyObject* KX_MouseFocusSensor::_getattr(const STR_String& attr) { +PyObject* KX_MouseFocusSensor::_getattr(const char *attr) { _getattr_up(SCA_MouseSensor); } @@ -347,7 +347,7 @@ PyObject* KX_MouseFocusSensor::PyGetHitObject(PyObject* self, { return m_hitObject->AddRef(); } - Py_Return; + Py_RETURN_NONE; } diff --git a/source/gameengine/Ketsji/KX_MouseFocusSensor.h b/source/gameengine/Ketsji/KX_MouseFocusSensor.h index 6731444699b..704198ce5a3 100644 --- a/source/gameengine/Ketsji/KX_MouseFocusSensor.h +++ b/source/gameengine/Ketsji/KX_MouseFocusSensor.h @@ -87,7 +87,7 @@ class KX_MouseFocusSensor : public SCA_MouseSensor /* --------------------------------------------------------------------- */ /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); KX_PYMETHOD_DOC(KX_MouseFocusSensor,GetRayTarget); KX_PYMETHOD_DOC(KX_MouseFocusSensor,GetRaySource); diff --git a/source/gameengine/Ketsji/KX_NearSensor.cpp b/source/gameengine/Ketsji/KX_NearSensor.cpp index bae87c28123..7ef544618f8 100644 --- a/source/gameengine/Ketsji/KX_NearSensor.cpp +++ b/source/gameengine/Ketsji/KX_NearSensor.cpp @@ -320,7 +320,7 @@ PyMethodDef KX_NearSensor::Methods[] = { PyObject* -KX_NearSensor::_getattr(const STR_String& attr) +KX_NearSensor::_getattr(const char *attr) { _getattr_up(KX_TouchSensor); } diff --git a/source/gameengine/Ketsji/KX_NearSensor.h b/source/gameengine/Ketsji/KX_NearSensor.h index 3f7078ef9fd..58c7cc7da91 100644 --- a/source/gameengine/Ketsji/KX_NearSensor.h +++ b/source/gameengine/Ketsji/KX_NearSensor.h @@ -79,7 +79,7 @@ public: virtual void RegisterSumo(KX_TouchEventManager *touchman); virtual void UnregisterSumo(KX_TouchEventManager* touchman); - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); }; diff --git a/source/gameengine/Ketsji/KX_ObjectActuator.cpp b/source/gameengine/Ketsji/KX_ObjectActuator.cpp index 98e73d4f0d7..9a620998538 100644 --- a/source/gameengine/Ketsji/KX_ObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_ObjectActuator.cpp @@ -332,7 +332,7 @@ PyMethodDef KX_ObjectActuator::Methods[] = { {NULL,NULL} //Sentinel }; -PyObject* KX_ObjectActuator::_getattr(const STR_String& attr) { +PyObject* KX_ObjectActuator::_getattr(const char *attr) { _getattr_up(SCA_IActuator); }; @@ -365,7 +365,7 @@ PyObject* KX_ObjectActuator::PySetForce(PyObject* self, m_force.setValue(vecArg); m_bitLocalFlag.Force = PyArgToBool(bToggle); UpdateFuzzyFlags(); - Py_Return; + Py_RETURN_NONE; } /* 4. getTorque */ @@ -394,7 +394,7 @@ PyObject* KX_ObjectActuator::PySetTorque(PyObject* self, m_torque.setValue(vecArg); m_bitLocalFlag.Torque = PyArgToBool(bToggle); UpdateFuzzyFlags(); - Py_Return; + Py_RETURN_NONE; } /* 6. getDLoc */ @@ -423,7 +423,7 @@ PyObject* KX_ObjectActuator::PySetDLoc(PyObject* self, m_dloc.setValue(vecArg); m_bitLocalFlag.DLoc = PyArgToBool(bToggle); UpdateFuzzyFlags(); - Py_Return; + Py_RETURN_NONE; } /* 8. getDRot */ @@ -452,7 +452,7 @@ PyObject* KX_ObjectActuator::PySetDRot(PyObject* self, m_drot.setValue(vecArg); m_bitLocalFlag.DRot = PyArgToBool(bToggle); UpdateFuzzyFlags(); - Py_Return; + Py_RETURN_NONE; } /* 10. getLinearVelocity */ @@ -480,7 +480,7 @@ PyObject* KX_ObjectActuator::PySetLinearVelocity(PyObject* self, m_linear_velocity.setValue(vecArg); m_bitLocalFlag.LinearVelocity = PyArgToBool(bToggle); UpdateFuzzyFlags(); - Py_Return; + Py_RETURN_NONE; } @@ -508,7 +508,7 @@ PyObject* KX_ObjectActuator::PySetAngularVelocity(PyObject* self, m_angular_velocity.setValue(vecArg); m_bitLocalFlag.AngularVelocity = PyArgToBool(bToggle); UpdateFuzzyFlags(); - Py_Return; + Py_RETURN_NONE; } /* 13. setDamping */ @@ -520,7 +520,7 @@ PyObject* KX_ObjectActuator::PySetDamping(PyObject* self, return NULL; } m_damping = damping; - Py_Return; + Py_RETURN_NONE; } /* 13. getVelocityDamping */ @@ -551,7 +551,7 @@ PyObject* KX_ObjectActuator::PySetForceLimitX(PyObject* self, m_drot[0] = vecArg[0]; m_dloc[0] = vecArg[1]; m_bitLocalFlag.Torque = PyArgToBool(bToggle); - Py_Return; + Py_RETURN_NONE; } /* 6. getForceLimitY */ @@ -578,7 +578,7 @@ PyObject* KX_ObjectActuator::PySetForceLimitY(PyObject* self, m_drot[1] = vecArg[0]; m_dloc[1] = vecArg[1]; m_bitLocalFlag.DLoc = PyArgToBool(bToggle); - Py_Return; + Py_RETURN_NONE; } /* 6. getForceLimitZ */ @@ -605,7 +605,7 @@ PyObject* KX_ObjectActuator::PySetForceLimitZ(PyObject* self, m_drot[2] = vecArg[0]; m_dloc[2] = vecArg[1]; m_bitLocalFlag.DRot = PyArgToBool(bToggle); - Py_Return; + Py_RETURN_NONE; } /* 4. getPID */ @@ -629,7 +629,7 @@ PyObject* KX_ObjectActuator::PySetPID(PyObject* self, return NULL; } m_torque.setValue(vecArg); - Py_Return; + Py_RETURN_NONE; } diff --git a/source/gameengine/Ketsji/KX_ObjectActuator.h b/source/gameengine/Ketsji/KX_ObjectActuator.h index aa686f41233..0331c67617c 100644 --- a/source/gameengine/Ketsji/KX_ObjectActuator.h +++ b/source/gameengine/Ketsji/KX_ObjectActuator.h @@ -153,7 +153,7 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); KX_PYMETHOD_NOARGS(KX_ObjectActuator,GetForce); KX_PYMETHOD(KX_ObjectActuator,SetForce); diff --git a/source/gameengine/Ketsji/KX_OdePhysicsController.cpp b/source/gameengine/Ketsji/KX_OdePhysicsController.cpp index 6a701a5f25b..dc6990267d4 100644 --- a/source/gameengine/Ketsji/KX_OdePhysicsController.cpp +++ b/source/gameengine/Ketsji/KX_OdePhysicsController.cpp @@ -50,7 +50,7 @@ KX_OdePhysicsController::KX_OdePhysicsController( float extends[3], float radius ) -: KX_IPhysicsController(dyna,(PHY_IPhysicsController*)this), +: KX_IPhysicsController(dyna,false,(PHY_IPhysicsController*)this), ODEPhysicsController( dyna,fullRigidBody,phantom,motionstate, space,world,mass,friction,restitution, diff --git a/source/gameengine/Ketsji/KX_OdePhysicsController.h b/source/gameengine/Ketsji/KX_OdePhysicsController.h index 53050f6ce3e..e3b5336c0b5 100644 --- a/source/gameengine/Ketsji/KX_OdePhysicsController.h +++ b/source/gameengine/Ketsji/KX_OdePhysicsController.h @@ -73,6 +73,8 @@ public: virtual MT_Scalar GetMass(); virtual MT_Vector3 getReactionForce(); virtual void setRigidBody(bool rigid); + virtual void AddCompoundChild(KX_IPhysicsController* child) { } + virtual void RemoveCompoundChild(KX_IPhysicsController* child) { } virtual void SuspendDynamics(bool); virtual void RestoreDynamics(); diff --git a/source/gameengine/Ketsji/KX_ParentActuator.cpp b/source/gameengine/Ketsji/KX_ParentActuator.cpp index 89549ca6b57..5a908186235 100644 --- a/source/gameengine/Ketsji/KX_ParentActuator.cpp +++ b/source/gameengine/Ketsji/KX_ParentActuator.cpp @@ -166,15 +166,44 @@ PyParentObject KX_ParentActuator::Parents[] = { }; PyMethodDef KX_ParentActuator::Methods[] = { + // ---> deprecated (all) {"setObject", (PyCFunction) KX_ParentActuator::sPySetObject, METH_O, (PY_METHODCHAR)SetObject_doc}, {"getObject", (PyCFunction) KX_ParentActuator::sPyGetObject, METH_VARARGS, (PY_METHODCHAR)GetObject_doc}, {NULL,NULL} //Sentinel }; -PyObject* KX_ParentActuator::_getattr(const STR_String& attr) { +PyObject* KX_ParentActuator::_getattr(const char *attr) { + + if (!strcmp(attr, "object")) { + if (!m_ob) Py_RETURN_NONE; + else return m_ob->AddRef(); + } + _getattr_up(SCA_IActuator); } +int KX_ParentActuator::_setattr(const char *attr, PyObject* value) { + + if (!strcmp(attr, "object")) { + KX_GameObject *gameobj; + + if (!ConvertPythonToGameObject(value, &gameobj, true)) + return 1; // ConvertPythonToGameObject sets the error + + if (m_ob != NULL) + m_ob->UnregisterActuator(this); + + m_ob = (SCA_IObject*)gameobj; + + if (m_ob) + m_ob->RegisterActuator(this); + + return 0; + } + + return SCA_IActuator::_setattr(attr, value); +} + /* 1. setObject */ const char KX_ParentActuator::SetObject_doc[] = "setObject(object)\n" @@ -183,6 +212,8 @@ const char KX_ParentActuator::SetObject_doc[] = PyObject* KX_ParentActuator::PySetObject(PyObject* self, PyObject* value) { KX_GameObject *gameobj; + ShowDeprecationWarning("setObject()", "the object property"); + if (!ConvertPythonToGameObject(value, &gameobj, true)) return NULL; // ConvertPythonToGameObject sets the error @@ -206,6 +237,9 @@ const char KX_ParentActuator::GetObject_doc[] = PyObject* KX_ParentActuator::PyGetObject(PyObject* self, PyObject* args) { int ret_name_only = 1; + + ShowDeprecationWarning("getObject()", "the object property"); + if (!PyArg_ParseTuple(args, "|i", &ret_name_only)) return NULL; diff --git a/source/gameengine/Ketsji/KX_ParentActuator.h b/source/gameengine/Ketsji/KX_ParentActuator.h index e2b30ba2d0f..c974001c0d0 100644 --- a/source/gameengine/Ketsji/KX_ParentActuator.h +++ b/source/gameengine/Ketsji/KX_ParentActuator.h @@ -76,7 +76,8 @@ class KX_ParentActuator : public SCA_IActuator /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject* value); /* 1. setObject */ KX_PYMETHOD_DOC_O(KX_ParentActuator,SetObject); diff --git a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp index da4f05ced7c..246c63feb21 100644 --- a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp +++ b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp @@ -142,23 +142,21 @@ PyParentObject KX_PhysicsObjectWrapper::Parents[] = { NULL }; -PyObject* KX_PhysicsObjectWrapper::_getattr(const STR_String& attr) +PyObject* KX_PhysicsObjectWrapper::_getattr(const char *attr) { _getattr_up(PyObjectPlus); } -int KX_PhysicsObjectWrapper::_setattr(const STR_String& attr,PyObject* pyobj) +int KX_PhysicsObjectWrapper::_setattr(const char *attr,PyObject *pyobj) { - PyTypeObject* type = pyobj->ob_type; int result = 1; - - if (type == &PyInt_Type) + if (PyInt_Check(pyobj)) { result = 0; } - if (type == &PyString_Type) + if (PyString_Check(pyobj)) { result = 0; } diff --git a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.h b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.h index 3dbd1be9323..95560698896 100644 --- a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.h +++ b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.h @@ -36,8 +36,8 @@ class KX_PhysicsObjectWrapper : public PyObjectPlus { Py_Header; - virtual PyObject* _getattr(const STR_String& attr); - virtual int _setattr(const STR_String& attr, PyObject *value); + virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject *value); public: KX_PhysicsObjectWrapper(class PHY_IPhysicsController* ctrl,class PHY_IPhysicsEnvironment* physenv,PyTypeObject *T = &Type); virtual ~KX_PhysicsObjectWrapper(); diff --git a/source/gameengine/Ketsji/KX_PolyProxy.cpp b/source/gameengine/Ketsji/KX_PolyProxy.cpp index c6f6bc2db01..1c9e2a49c11 100644 --- a/source/gameengine/Ketsji/KX_PolyProxy.cpp +++ b/source/gameengine/Ketsji/KX_PolyProxy.cpp @@ -65,30 +65,29 @@ PyParentObject KX_PolyProxy::Parents[] = { }; PyMethodDef KX_PolyProxy::Methods[] = { - KX_PYMETHODTABLE_NOARG(KX_PolyProxy,getMaterialIndex), - KX_PYMETHODTABLE_NOARG(KX_PolyProxy,getNumVertex), - KX_PYMETHODTABLE_NOARG(KX_PolyProxy,isVisible), - KX_PYMETHODTABLE_NOARG(KX_PolyProxy,isCollider), - KX_PYMETHODTABLE_NOARG(KX_PolyProxy,getMaterialName), - KX_PYMETHODTABLE_NOARG(KX_PolyProxy,getTextureName), + KX_PYMETHODTABLE_NOARGS(KX_PolyProxy,getMaterialIndex), + KX_PYMETHODTABLE_NOARGS(KX_PolyProxy,getNumVertex), + KX_PYMETHODTABLE_NOARGS(KX_PolyProxy,isVisible), + KX_PYMETHODTABLE_NOARGS(KX_PolyProxy,isCollider), + KX_PYMETHODTABLE_NOARGS(KX_PolyProxy,getMaterialName), + KX_PYMETHODTABLE_NOARGS(KX_PolyProxy,getTextureName), KX_PYMETHODTABLE(KX_PolyProxy,getVertexIndex), - KX_PYMETHODTABLE_NOARG(KX_PolyProxy,getMesh), - KX_PYMETHODTABLE_NOARG(KX_PolyProxy,getMaterial), + KX_PYMETHODTABLE_NOARGS(KX_PolyProxy,getMesh), + KX_PYMETHODTABLE_NOARGS(KX_PolyProxy,getMaterial), {NULL,NULL} //Sentinel }; -PyObject* -KX_PolyProxy::_getattr(const STR_String& attr) +PyObject* KX_PolyProxy::_getattr(const char *attr) { - if (attr == "matname") + if (!strcmp(attr, "matname")) { return PyString_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetMaterialName()); } - if (attr == "texture") + if (!strcmp(attr, "texture")) { return PyString_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetTextureName()); } - if (attr == "material") + if (!strcmp(attr, "material")) { RAS_IPolyMaterial *polymat = m_polygon->GetMaterial()->GetPolyMaterial(); if(polymat->GetFlag() & RAS_BLENDERMAT) @@ -104,7 +103,7 @@ KX_PolyProxy::_getattr(const STR_String& attr) return mat; } } - if (attr == "matid") + if (!strcmp(attr, "matid")) { // we'll have to scan through the material bucket of the mes and compare with // the one of the polygon @@ -119,27 +118,27 @@ KX_PolyProxy::_getattr(const STR_String& attr) } return PyInt_FromLong(matid); } - if (attr == "v1") + if (!strcmp(attr, "v1")) { return PyInt_FromLong(m_polygon->GetVertexOffset(0)); } - if (attr == "v2") + if (!strcmp(attr, "v2")) { return PyInt_FromLong(m_polygon->GetVertexOffset(1)); } - if (attr == "v3") + if (!strcmp(attr, "v3")) { return PyInt_FromLong(m_polygon->GetVertexOffset(2)); } - if (attr == "v4") + if (!strcmp(attr, "v4")) { return PyInt_FromLong(((m_polygon->VertexCount()>3)?m_polygon->GetVertexOffset(3):0)); } - if (attr == "visible") + if (!strcmp(attr, "visible")) { return PyInt_FromLong(m_polygon->IsVisible()); } - if (attr == "collide") + if (!strcmp(attr, "collide")) { return PyInt_FromLong(m_polygon->IsCollider()); } @@ -171,7 +170,7 @@ void KX_PolyProxy::ReplicaSetName(STR_String) {}; // stuff for python integration -KX_PYMETHODDEF_DOC_NOARG(KX_PolyProxy, getMaterialIndex, +KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getMaterialIndex, "getMaterialIndex() : return the material index of the polygon in the mesh\n") { RAS_MaterialBucket* polyBucket = m_polygon->GetMaterial(); @@ -186,31 +185,31 @@ KX_PYMETHODDEF_DOC_NOARG(KX_PolyProxy, getMaterialIndex, return PyInt_FromLong(matid); } -KX_PYMETHODDEF_DOC_NOARG(KX_PolyProxy, getNumVertex, +KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getNumVertex, "getNumVertex() : returns the number of vertex of the polygon, 3 or 4\n") { return PyInt_FromLong(m_polygon->VertexCount()); } -KX_PYMETHODDEF_DOC_NOARG(KX_PolyProxy, isVisible, +KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, isVisible, "isVisible() : returns whether the polygon is visible or not\n") { return PyInt_FromLong(m_polygon->IsVisible()); } -KX_PYMETHODDEF_DOC_NOARG(KX_PolyProxy, isCollider, +KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, isCollider, "isCollider() : returns whether the polygon is receives collision or not\n") { return PyInt_FromLong(m_polygon->IsCollider()); } -KX_PYMETHODDEF_DOC_NOARG(KX_PolyProxy, getMaterialName, +KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getMaterialName, "getMaterialName() : returns the polygon material name, \"NoMaterial\" if no material\n") { return PyString_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetMaterialName()); } -KX_PYMETHODDEF_DOC_NOARG(KX_PolyProxy, getTextureName, +KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getTextureName, "getTexturelName() : returns the polygon texture name, \"NULL\" if no texture\n") { return PyString_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetTextureName()); @@ -239,14 +238,14 @@ KX_PYMETHODDEF_DOC(KX_PolyProxy, getVertexIndex, return PyInt_FromLong(0); } -KX_PYMETHODDEF_DOC_NOARG(KX_PolyProxy, getMesh, +KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getMesh, "getMesh() : returns a mesh proxy\n") { KX_MeshProxy* meshproxy = new KX_MeshProxy((RAS_MeshObject*)m_mesh); return meshproxy; } -KX_PYMETHODDEF_DOC_NOARG(KX_PolyProxy, getMaterial, +KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getMaterial, "getMaterial() : returns a material\n") { RAS_IPolyMaterial *polymat = m_polygon->GetMaterial()->GetPolyMaterial(); diff --git a/source/gameengine/Ketsji/KX_PolyProxy.h b/source/gameengine/Ketsji/KX_PolyProxy.h index 506e2c2a656..9b548f9490d 100644 --- a/source/gameengine/Ketsji/KX_PolyProxy.h +++ b/source/gameengine/Ketsji/KX_PolyProxy.h @@ -53,7 +53,7 @@ public: // stuff for python integration - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); KX_PYMETHOD_DOC_NOARGS(KX_PolyProxy,getMaterialIndex) KX_PYMETHOD_DOC_NOARGS(KX_PolyProxy,getNumVertex) diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp index c9180bf3a80..52c5b013e65 100644 --- a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp +++ b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp @@ -202,17 +202,17 @@ PyParentObject KX_PolygonMaterial::Parents[] = { NULL }; -PyObject* KX_PolygonMaterial::_getattr(const STR_String& attr) +PyObject* KX_PolygonMaterial::_getattr(const char *attr) { - if (attr == "texture") + if (!strcmp(attr, "texture")) return PyString_FromString(m_texturename.ReadPtr()); - if (attr == "material") + if (!strcmp(attr, "material")) return PyString_FromString(m_materialname.ReadPtr()); - if (attr == "tface") + if (!strcmp(attr, "tface")) return PyCObject_FromVoidPtr(m_tface, NULL); - if (attr == "gl_texture") + if (!strcmp(attr, "gl_texture")) { Image *ima = m_tface->tpage; int bind = 0; @@ -222,49 +222,49 @@ PyObject* KX_PolygonMaterial::_getattr(const STR_String& attr) return PyInt_FromLong(bind); } - if (attr == "tile") + if (!strcmp(attr, "tile")) return PyInt_FromLong(m_tile); - if (attr == "tilexrep") + if (!strcmp(attr, "tilexrep")) return PyInt_FromLong(m_tilexrep); - if (attr == "tileyrep") + if (!strcmp(attr, "tileyrep")) return PyInt_FromLong(m_tileyrep); - if (attr == "drawingmode") + if (!strcmp(attr, "drawingmode")) return PyInt_FromLong(m_drawingmode); - if (attr == "transparent") + if (!strcmp(attr, "transparent")) return PyInt_FromLong(m_alpha); - if (attr == "zsort") + if (!strcmp(attr, "zsort")) return PyInt_FromLong(m_zsort); - if (attr == "lightlayer") + if (!strcmp(attr, "lightlayer")) return PyInt_FromLong(m_lightlayer); - if (attr == "triangle") + if (!strcmp(attr, "triangle")) // deprecated, triangle/quads shouldn't have been a material property return 0; - if (attr == "diffuse") + if (!strcmp(attr, "diffuse")) return PyObjectFrom(m_diffuse); - if (attr == "shininess") + if (!strcmp(attr, "shininess")) return PyFloat_FromDouble(m_shininess); - if (attr == "specular") + if (!strcmp(attr, "specular")) return PyObjectFrom(m_specular); - if (attr == "specularity") + if (!strcmp(attr, "specularity")) return PyFloat_FromDouble(m_specularity); _getattr_up(PyObjectPlus); } -int KX_PolygonMaterial::_setattr(const STR_String &attr, PyObject *pyvalue) +int KX_PolygonMaterial::_setattr(const char *attr, PyObject *pyvalue) { if (PyFloat_Check(pyvalue)) { float value = PyFloat_AsDouble(pyvalue); - if (attr == "shininess") + if (!strcmp(attr, "shininess")) { m_shininess = value; return 0; } - if (attr == "specularity") + if (!strcmp(attr, "specularity")) { m_specularity = value; return 0; @@ -274,50 +274,50 @@ int KX_PolygonMaterial::_setattr(const STR_String &attr, PyObject *pyvalue) if (PyInt_Check(pyvalue)) { int value = PyInt_AsLong(pyvalue); - if (attr == "tile") + if (!strcmp(attr, "tile")) { m_tile = value; return 0; } - if (attr == "tilexrep") + if (!strcmp(attr, "tilexrep")) { m_tilexrep = value; return 0; } - if (attr == "tileyrep") + if (!strcmp(attr, "tileyrep")) { m_tileyrep = value; return 0; } - if (attr == "drawingmode") + if (!strcmp(attr, "drawingmode")) { m_drawingmode = value; return 0; } - if (attr == "transparent") + if (!strcmp(attr, "transparent")) { m_alpha = value; return 0; } - if (attr == "zsort") + if (!strcmp(attr, "zsort")) { m_zsort = value; return 0; } - if (attr == "lightlayer") + if (!strcmp(attr, "lightlayer")) { m_lightlayer = value; return 0; } // This probably won't work... - if (attr == "triangle") + if (!strcmp(attr, "triangle")) { // deprecated, triangle/quads shouldn't have been a material property return 0; @@ -331,13 +331,13 @@ int KX_PolygonMaterial::_setattr(const STR_String &attr, PyObject *pyvalue) MT_Vector3 value; if (PyVecTo(pyvalue, value)) { - if (attr == "diffuse") + if (!strcmp(attr, "diffuse")) { m_diffuse = value; return 0; } - if (attr == "specular") + if (!strcmp(attr, "specular")) { m_specular = value; return 0; @@ -354,12 +354,12 @@ KX_PYMETHODDEF_DOC(KX_PolygonMaterial, setCustomMaterial, "setCustomMaterial(mat PyObject *material; if (PyArg_ParseTuple(args, "O", &material)) { - if (m_pymaterial) + if (m_pymaterial) { Py_DECREF(m_pymaterial); - + } m_pymaterial = material; Py_INCREF(m_pymaterial); - Py_Return; + Py_RETURN_NONE; } return NULL; @@ -375,7 +375,7 @@ KX_PYMETHODDEF_DOC(KX_PolygonMaterial, updateTexture, "updateTexture(tface, rast Image *ima = (Image*)tface->tpage; GPU_update_image_time(ima, rasty->GetTime()); - Py_Return; + Py_RETURN_NONE; } return NULL; @@ -388,7 +388,7 @@ KX_PYMETHODDEF_DOC(KX_PolygonMaterial, setTexture, "setTexture(tface)") { MTFace *tface = (MTFace*) PyCObject_AsVoidPtr(pytface); GPU_set_tpage(tface); - Py_Return; + Py_RETURN_NONE; } return NULL; @@ -404,7 +404,7 @@ KX_PYMETHODDEF_DOC(KX_PolygonMaterial, activate, "activate(rasty, cachingInfo)") if (rasty && cachingInfo) { DefaultActivate(rasty, *cachingInfo); - Py_Return; + Py_RETURN_NONE; } } diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.h b/source/gameengine/Ketsji/KX_PolygonMaterial.h index fe116f757db..a3ef4ca51ef 100644 --- a/source/gameengine/Ketsji/KX_PolygonMaterial.h +++ b/source/gameengine/Ketsji/KX_PolygonMaterial.h @@ -115,8 +115,8 @@ public: KX_PYMETHOD_DOC(KX_PolygonMaterial, setCustomMaterial); KX_PYMETHOD_DOC(KX_PolygonMaterial, loadProgram); - virtual PyObject* _getattr(const STR_String& attr); - virtual int _setattr(const STR_String& attr, PyObject *pyvalue); + virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject *pyvalue); }; #endif // __KX_POLYGONMATERIAL_H__ diff --git a/source/gameengine/Ketsji/KX_PyMath.cpp b/source/gameengine/Ketsji/KX_PyMath.cpp index afb20acec2d..92f18590a7e 100644 --- a/source/gameengine/Ketsji/KX_PyMath.cpp +++ b/source/gameengine/Ketsji/KX_PyMath.cpp @@ -77,35 +77,92 @@ bool PyObject_IsMT_Matrix(PyObject *pymat, unsigned int rank) PyObject* PyObjectFrom(const MT_Matrix4x4 &mat) { +#if 0 return Py_BuildValue("[[ffff][ffff][ffff][ffff]]", mat[0][0], mat[0][1], mat[0][2], mat[0][3], mat[1][0], mat[1][1], mat[1][2], mat[1][3], mat[2][0], mat[2][1], mat[2][2], mat[2][3], mat[3][0], mat[3][1], mat[3][2], mat[3][3]); +#else + PyObject *list = PyList_New(4); + PyObject *sublist; + int i; + + for(i=0; i < 4; i++) { + sublist = PyList_New(4); + PyList_SET_ITEM(sublist, 0, PyFloat_FromDouble(mat[i][0])); + PyList_SET_ITEM(sublist, 1, PyFloat_FromDouble(mat[i][1])); + PyList_SET_ITEM(sublist, 2, PyFloat_FromDouble(mat[i][2])); + PyList_SET_ITEM(sublist, 2, PyFloat_FromDouble(mat[i][3])); + PyList_SET_ITEM(list, i, sublist); + } + + return list; +#endif } PyObject* PyObjectFrom(const MT_Matrix3x3 &mat) { +#if 0 return Py_BuildValue("[[fff][fff][fff]]", mat[0][0], mat[0][1], mat[0][2], mat[1][0], mat[1][1], mat[1][2], mat[2][0], mat[2][1], mat[2][2]); +#else + PyObject *list = PyList_New(3); + PyObject *sublist; + int i; + + for(i=0; i < 3; i++) { + sublist = PyList_New(3); + PyList_SET_ITEM(sublist, 0, PyFloat_FromDouble(mat[i][0])); + PyList_SET_ITEM(sublist, 1, PyFloat_FromDouble(mat[i][1])); + PyList_SET_ITEM(sublist, 2, PyFloat_FromDouble(mat[i][2])); + PyList_SET_ITEM(list, i, sublist); + } + + return list; +#endif } PyObject* PyObjectFrom(const MT_Tuple4 &vec) { +#if 0 return Py_BuildValue("[ffff]", vec[0], vec[1], vec[2], vec[3]); +#else + PyObject *list = PyList_New(4); + PyList_SET_ITEM(list, 0, PyFloat_FromDouble(vec[0])); + PyList_SET_ITEM(list, 1, PyFloat_FromDouble(vec[1])); + PyList_SET_ITEM(list, 2, PyFloat_FromDouble(vec[2])); + PyList_SET_ITEM(list, 3, PyFloat_FromDouble(vec[3])); + return list; +#endif } PyObject* PyObjectFrom(const MT_Tuple3 &vec) { +#if 0 return Py_BuildValue("[fff]", vec[0], vec[1], vec[2]); +#else + PyObject *list = PyList_New(3); + PyList_SET_ITEM(list, 0, PyFloat_FromDouble(vec[0])); + PyList_SET_ITEM(list, 1, PyFloat_FromDouble(vec[1])); + PyList_SET_ITEM(list, 2, PyFloat_FromDouble(vec[2])); + return list; +#endif } PyObject* PyObjectFrom(const MT_Tuple2 &vec) { +#if 0 return Py_BuildValue("[ff]", vec[0], vec[1]); +#else + PyObject *list = PyList_New(2); + PyList_SET_ITEM(list, 0, PyFloat_FromDouble(vec[0])); + PyList_SET_ITEM(list, 1, PyFloat_FromDouble(vec[1])); + return list; +#endif } diff --git a/source/gameengine/Ketsji/KX_PyMath.h b/source/gameengine/Ketsji/KX_PyMath.h index 4e383e9b3d4..39c9c358792 100644 --- a/source/gameengine/Ketsji/KX_PyMath.h +++ b/source/gameengine/Ketsji/KX_PyMath.h @@ -131,20 +131,6 @@ bool PyVecTo(PyObject* pyval, T& vec) } /** - * Converts a python argument to an MT class. - * This paramater expects arguments as passed to a python method. - */ -template<class T> -bool PyVecArgTo(PyObject* args, T& vec) -{ - PyObject* pylist; - if (PyArg_ParseTuple(args,"O",&pylist)) - return PyVecTo(pylist, vec); - - return false; -} - -/** * Converts an MT_Matrix4x4 to a python object. */ PyObject* PyObjectFrom(const MT_Matrix4x4 &mat); diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index 0032d83c2ff..c3ae3d0ec52 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -125,10 +125,10 @@ static PyObject* gPyGetRandomFloat(PyObject*) return PyFloat_FromDouble(MT_random()); } -static PyObject* gPySetGravity(PyObject*, PyObject* args) +static PyObject* gPySetGravity(PyObject*, PyObject* value) { - MT_Vector3 vec = MT_Vector3(0., 0., 0.); - if (!PyVecArgTo(args, vec)) + MT_Vector3 vec; + if (!PyVecTo(value, vec)) return NULL; if (gp_KetsjiScene) @@ -412,7 +412,7 @@ static struct PyMethodDef game_methods[] = { METH_VARARGS, (PY_METHODCHAR)SCA_PythonController::sPyAddActiveActuator__doc__}, {"getRandomFloat",(PyCFunction) gPyGetRandomFloat, METH_NOARGS, (PY_METHODCHAR)gPyGetRandomFloat_doc.Ptr()}, - {"setGravity",(PyCFunction) gPySetGravity, METH_VARARGS, (PY_METHODCHAR)"set Gravitation"}, + {"setGravity",(PyCFunction) gPySetGravity, METH_O, (PY_METHODCHAR)"set Gravitation"}, {"getSpectrum",(PyCFunction) gPyGetSpectrum, METH_NOARGS, (PY_METHODCHAR)"get audio spectrum"}, {"stopDSP",(PyCFunction) gPyStopDSP, METH_VARARGS, (PY_METHODCHAR)"stop using the audio dsp (for performance reasons)"}, {"getLogicTicRate", (PyCFunction) gPyGetLogicTicRate, METH_NOARGS, (PY_METHODCHAR)"Gets the logic tic rate"}, @@ -542,11 +542,11 @@ static PyObject* gPyGetFocalLength(PyObject*, PyObject*, PyObject*) Py_RETURN_NONE; } -static PyObject* gPySetBackgroundColor(PyObject*, PyObject* args) +static PyObject* gPySetBackgroundColor(PyObject*, PyObject* value) { - MT_Vector4 vec = MT_Vector4(0., 0., 0.3, 0.); - if (!PyVecArgTo(args, vec)) + MT_Vector4 vec; + if (!PyVecTo(value, vec)) return NULL; if (gp_Canvas) @@ -558,11 +558,11 @@ static PyObject* gPySetBackgroundColor(PyObject*, PyObject* args) -static PyObject* gPySetMistColor(PyObject*, PyObject* args) +static PyObject* gPySetMistColor(PyObject*, PyObject* value) { - MT_Vector3 vec = MT_Vector3(0., 0., 0.); - if (!PyVecArgTo(args, vec)) + MT_Vector3 vec; + if (!PyVecTo(value, vec)) return NULL; if (!gp_Rasterizer) { @@ -613,11 +613,11 @@ static PyObject* gPySetMistEnd(PyObject*, PyObject* args) } -static PyObject* gPySetAmbientColor(PyObject*, PyObject* args) +static PyObject* gPySetAmbientColor(PyObject*, PyObject* value) { - MT_Vector3 vec = MT_Vector3(0., 0., 0.); - if (!PyVecArgTo(args, vec)) + MT_Vector3 vec; + if (!PyVecTo(value, vec)) return NULL; if (!gp_Rasterizer) { @@ -812,9 +812,9 @@ static PyObject* gPyDrawLine(PyObject*, PyObject* args) if (!PyArg_ParseTuple(args,"OOO",&ob_from,&ob_to,&ob_color)) return NULL; - MT_Vector3 from(0., 0., 0.); - MT_Vector3 to(0., 0., 0.); - MT_Vector3 color(0., 0., 0.); + MT_Vector3 from; + MT_Vector3 to; + MT_Vector3 color; if (!PyVecTo(ob_from, from)) return NULL; if (!PyVecTo(ob_to, to)) @@ -840,9 +840,9 @@ static struct PyMethodDef rasterizer_methods[] = { METH_VARARGS, "showMouse(bool visible)"}, {"setMousePosition",(PyCFunction) gPySetMousePosition, METH_VARARGS, "setMousePosition(int x,int y)"}, - {"setBackgroundColor",(PyCFunction)gPySetBackgroundColor,METH_VARARGS,"set Background Color (rgb)"}, - {"setAmbientColor",(PyCFunction)gPySetAmbientColor,METH_VARARGS,"set Ambient Color (rgb)"}, - {"setMistColor",(PyCFunction)gPySetMistColor,METH_VARARGS,"set Mist Color (rgb)"}, + {"setBackgroundColor",(PyCFunction)gPySetBackgroundColor,METH_O,"set Background Color (rgb)"}, + {"setAmbientColor",(PyCFunction)gPySetAmbientColor,METH_O,"set Ambient Color (rgb)"}, + {"setMistColor",(PyCFunction)gPySetMistColor,METH_O,"set Mist Color (rgb)"}, {"setMistStart",(PyCFunction)gPySetMistStart,METH_VARARGS,"set Mist Start(rgb)"}, {"setMistEnd",(PyCFunction)gPySetMistEnd,METH_VARARGS,"set Mist End(rgb)"}, {"enableMotionBlur",(PyCFunction)gPyEnableMotionBlur,METH_VARARGS,"enable motion blur"}, @@ -963,11 +963,11 @@ PyObject* initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack KX_MACRO_addTypesToDict(d, KX_SOUNDACT_LOOPBIDIRECTIONAL_STOP, KX_SoundActuator::KX_SOUNDACT_LOOPBIDIRECTIONAL_STOP); /* 7. Action actuator */ - KX_MACRO_addTypesToDict(d, KX_ACTIONACT_PLAY, BL_ActionActuator::KX_ACT_ACTION_PLAY); - KX_MACRO_addTypesToDict(d, KX_ACTIONACT_FLIPPER, BL_ActionActuator::KX_ACT_ACTION_FLIPPER); - KX_MACRO_addTypesToDict(d, KX_ACTIONACT_LOOPSTOP, BL_ActionActuator::KX_ACT_ACTION_LOOPSTOP); - KX_MACRO_addTypesToDict(d, KX_ACTIONACT_LOOPEND, BL_ActionActuator::KX_ACT_ACTION_LOOPEND); - KX_MACRO_addTypesToDict(d, KX_ACTIONACT_PROPERTY, BL_ActionActuator::KX_ACT_ACTION_PROPERTY); + KX_MACRO_addTypesToDict(d, KX_ACTIONACT_PLAY, ACT_ACTION_PLAY); + KX_MACRO_addTypesToDict(d, KX_ACTIONACT_FLIPPER, ACT_ACTION_FLIPPER); + KX_MACRO_addTypesToDict(d, KX_ACTIONACT_LOOPSTOP, ACT_ACTION_LOOP_STOP); + KX_MACRO_addTypesToDict(d, KX_ACTIONACT_LOOPEND, ACT_ACTION_LOOP_END); + KX_MACRO_addTypesToDict(d, KX_ACTIONACT_PROPERTY, ACT_ACTION_FROM_PROP); /*8. GL_BlendFunc */ KX_MACRO_addTypesToDict(d, BL_ZERO, GL_ZERO); diff --git a/source/gameengine/Ketsji/KX_RadarSensor.cpp b/source/gameengine/Ketsji/KX_RadarSensor.cpp index 244e9b75d8e..1321b862463 100644 --- a/source/gameengine/Ketsji/KX_RadarSensor.cpp +++ b/source/gameengine/Ketsji/KX_RadarSensor.cpp @@ -229,7 +229,7 @@ PyMethodDef KX_RadarSensor::Methods[] = { {NULL,NULL,NULL,NULL} //Sentinel }; -PyObject* KX_RadarSensor::_getattr(const STR_String& attr) { +PyObject* KX_RadarSensor::_getattr(const char *attr) { _getattr_up(KX_TouchSensor); } diff --git a/source/gameengine/Ketsji/KX_RadarSensor.h b/source/gameengine/Ketsji/KX_RadarSensor.h index 7272b219e37..f8f80725145 100644 --- a/source/gameengine/Ketsji/KX_RadarSensor.h +++ b/source/gameengine/Ketsji/KX_RadarSensor.h @@ -81,7 +81,7 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); KX_PYMETHOD_DOC(KX_RadarSensor,GetConeOrigin); KX_PYMETHOD_DOC(KX_RadarSensor,GetConeTarget); diff --git a/source/gameengine/Ketsji/KX_RaySensor.cpp b/source/gameengine/Ketsji/KX_RaySensor.cpp index e24fb773eac..b8ebce28814 100644 --- a/source/gameengine/Ketsji/KX_RaySensor.cpp +++ b/source/gameengine/Ketsji/KX_RaySensor.cpp @@ -353,7 +353,7 @@ PyObject* KX_RaySensor::PyGetHitObject(PyObject* self, { return m_hitObject->AddRef(); } - Py_Return; + Py_RETURN_NONE; } @@ -418,6 +418,6 @@ PyObject* KX_RaySensor::PyGetHitNormal(PyObject* self, -PyObject* KX_RaySensor::_getattr(const STR_String& attr) { +PyObject* KX_RaySensor::_getattr(const char *attr) { _getattr_up(SCA_ISensor); } diff --git a/source/gameengine/Ketsji/KX_RaySensor.h b/source/gameengine/Ketsji/KX_RaySensor.h index 02a755fedc1..2baec12f74e 100644 --- a/source/gameengine/Ketsji/KX_RaySensor.h +++ b/source/gameengine/Ketsji/KX_RaySensor.h @@ -79,7 +79,7 @@ public: KX_PYMETHOD_DOC(KX_RaySensor,GetHitNormal); KX_PYMETHOD_DOC(KX_RaySensor,GetRayDirection); - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); }; diff --git a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp index 5777f54b799..017ab5d6c97 100644 --- a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp @@ -188,9 +188,7 @@ PyParentObject KX_SCA_AddObjectActuator::Parents[] = { NULL }; PyMethodDef KX_SCA_AddObjectActuator::Methods[] = { - {"setObject", (PyCFunction) KX_SCA_AddObjectActuator::sPySetObject, METH_O, (PY_METHODCHAR)SetObject_doc}, {"setTime", (PyCFunction) KX_SCA_AddObjectActuator::sPySetTime, METH_O, (PY_METHODCHAR)SetTime_doc}, - {"getObject", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetObject, METH_VARARGS, (PY_METHODCHAR)GetObject_doc}, {"getTime", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetTime, METH_NOARGS, (PY_METHODCHAR)GetTime_doc}, {"getLinearVelocity", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetLinearVelocity, METH_NOARGS, (PY_METHODCHAR)GetLinearVelocity_doc}, {"setLinearVelocity", (PyCFunction) KX_SCA_AddObjectActuator::sPySetLinearVelocity, METH_VARARGS, (PY_METHODCHAR)SetLinearVelocity_doc}, @@ -199,15 +197,49 @@ PyMethodDef KX_SCA_AddObjectActuator::Methods[] = { {"getLastCreatedObject", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetLastCreatedObject, METH_NOARGS,"getLastCreatedObject() : get the object handle to the last created object\n"}, {"instantAddObject", (PyCFunction) KX_SCA_AddObjectActuator::sPyInstantAddObject, METH_NOARGS,"instantAddObject() : immediately add object without delay\n"}, + // ---> deprecated + {"setObject", (PyCFunction) KX_SCA_AddObjectActuator::sPySetObject, METH_O, (PY_METHODCHAR)SetObject_doc}, + {"getObject", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetObject, METH_VARARGS, (PY_METHODCHAR)GetObject_doc}, + {NULL,NULL} //Sentinel }; -PyObject* KX_SCA_AddObjectActuator::_getattr(const STR_String& attr) +PyObject* KX_SCA_AddObjectActuator::_getattr(const char *attr) { + if (!strcmp(attr, "object")) { + if (!m_OriginalObject) Py_RETURN_NONE; + else return m_OriginalObject->AddRef(); + } else if (!strcmp(attr, "objectLastCreated")) { + if (!m_OriginalObject) Py_RETURN_NONE; + else return m_lastCreatedObject->AddRef(); + } + _getattr_up(SCA_IActuator); } +int KX_SCA_AddObjectActuator::_setattr(const char *attr, PyObject* value) { + + if (!strcmp(attr, "object")) { + KX_GameObject *gameobj; + + if (!ConvertPythonToGameObject(value, &gameobj, true)) + return 1; // ConvertPythonToGameObject sets the error + + if (m_OriginalObject != NULL) + m_OriginalObject->UnregisterActuator(this); + + m_OriginalObject = (SCA_IObject*)gameobj; + + if (m_OriginalObject) + m_OriginalObject->RegisterActuator(this); + + return 0; + } + + return SCA_IActuator::_setattr(attr, value); +} + /* 1. setObject */ const char KX_SCA_AddObjectActuator::SetObject_doc[] = "setObject(object)\n" @@ -218,6 +250,8 @@ PyObject* KX_SCA_AddObjectActuator::PySetObject(PyObject* self, PyObject* value) { KX_GameObject *gameobj; + ShowDeprecationWarning("setObject()", "the object property"); + if (!ConvertPythonToGameObject(value, &gameobj, true)) return NULL; // ConvertPythonToGameObject sets the error @@ -277,6 +311,9 @@ const char KX_SCA_AddObjectActuator::GetObject_doc[] = PyObject* KX_SCA_AddObjectActuator::PyGetObject(PyObject* self, PyObject* args) { int ret_name_only = 1; + + ShowDeprecationWarning("getObject()", "the object property"); + if (!PyArg_ParseTuple(args, "|i", &ret_name_only)) return NULL; diff --git a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h index 278d4180284..18298cbcb0c 100644 --- a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h +++ b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h @@ -60,13 +60,16 @@ class KX_SCA_AddObjectActuator : public SCA_IActuator /// Linear velocity upon creation of the object. MT_Vector3 m_linear_velocity; + /// Apply the velocity locally + bool m_localLinvFlag; /// Angular velocity upon creation of the object. MT_Vector3 m_angular_velocity; - /// Apply the velocity locally - bool m_localLinvFlag; - bool m_localAngvFlag; + bool m_localAngvFlag; + + + SCA_IObject* m_lastCreatedObject; @@ -107,10 +110,8 @@ public: virtual bool Update(); - virtual PyObject* - _getattr( - const STR_String& attr - ); + virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject* value); SCA_IObject* GetLastCreatedObject( diff --git a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp index d44ab477749..1aba05c1d83 100644 --- a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp @@ -87,7 +87,7 @@ PyMethodDef KX_SCA_DynamicActuator::Methods[] = { -PyObject* KX_SCA_DynamicActuator::_getattr(const STR_String& attr) +PyObject* KX_SCA_DynamicActuator::_getattr(const char *attr) { _getattr_up(SCA_IActuator); } @@ -115,7 +115,7 @@ KX_PYMETHODDEF_DOC(KX_SCA_DynamicActuator, setOperation, return NULL; } m_dyn_operation= dyn_operation; - Py_Return; + Py_RETURN_NONE; } KX_PYMETHODDEF_DOC(KX_SCA_DynamicActuator, getOperation, @@ -133,10 +133,12 @@ KX_PYMETHODDEF_DOC(KX_SCA_DynamicActuator, getOperation, KX_SCA_DynamicActuator::KX_SCA_DynamicActuator(SCA_IObject *gameobj, short dyn_operation, + float setmass, PyTypeObject* T) : SCA_IActuator(gameobj, T), - m_dyn_operation(dyn_operation) + m_dyn_operation(dyn_operation), + m_setmass(setmass) { } /* End of constructor */ @@ -179,6 +181,9 @@ bool KX_SCA_DynamicActuator::Update() case 3: controller->setRigidBody(false); break; + case 4: + controller->SetMass(m_setmass); + break; } return false; diff --git a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.h b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.h index b47c3a511d9..a82cddd66a7 100644 --- a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.h +++ b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.h @@ -45,10 +45,12 @@ class KX_SCA_DynamicActuator : public SCA_IActuator // dynamics operation to apply to the game object short m_dyn_operation; + float m_setmass; public: KX_SCA_DynamicActuator( SCA_IObject* gameobj, short dyn_operation, + float setmass, PyTypeObject* T=&Type ); @@ -62,10 +64,7 @@ class KX_SCA_DynamicActuator : public SCA_IActuator virtual bool Update(); - virtual PyObject* - _getattr( - const STR_String& attr - ); + virtual PyObject* _getattr(const char *attr); /* 1. setOperation */ KX_PYMETHOD_DOC(KX_SCA_DynamicActuator,setOperation); diff --git a/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp b/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp index ec29448907f..443921d22b0 100644 --- a/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp @@ -128,7 +128,7 @@ PyMethodDef KX_SCA_EndObjectActuator::Methods[] = { }; -PyObject* KX_SCA_EndObjectActuator::_getattr(const STR_String& attr) +PyObject* KX_SCA_EndObjectActuator::_getattr(const char *attr) { _getattr_up(SCA_IActuator); } diff --git a/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.h b/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.h index add9c05b000..12118743f0a 100644 --- a/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.h +++ b/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.h @@ -64,10 +64,7 @@ class KX_SCA_EndObjectActuator : public SCA_IActuator /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* - _getattr( - const STR_String& attr - ); + virtual PyObject* _getattr(const char *attr); }; /* end of class KX_EditObjectActuator : public SCA_PropertyActuator */ diff --git a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp index 261d9ec8f0c..ccc3b8fdb18 100644 --- a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp @@ -91,7 +91,7 @@ PyMethodDef KX_SCA_ReplaceMeshActuator::Methods[] = { -PyObject* KX_SCA_ReplaceMeshActuator::_getattr(const STR_String& attr) +PyObject* KX_SCA_ReplaceMeshActuator::_getattr(const char *attr) { _getattr_up(SCA_IActuator); } diff --git a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h index 1da154cc222..0ba60650683 100644 --- a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h +++ b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h @@ -69,10 +69,7 @@ class KX_SCA_ReplaceMeshActuator : public SCA_IActuator virtual bool Update(); - virtual PyObject* - _getattr( - const STR_String& attr - ); + virtual PyObject* _getattr(const char *attr); void InstantReplaceMesh(); /* 1. setMesh */ diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index caa71441b1d..7fcbf5b54bb 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -1249,7 +1249,7 @@ void KX_Scene::MarkVisible(RAS_IRasterizer* rasty, KX_GameObject* gameobj,KX_Cam // If the camera is inside this node, then the object is visible. if (!vis) { - vis = gameobj->GetSGNode()->inside( GetActiveCamera()->GetCameraLocation() ); + vis = gameobj->GetSGNode()->inside( cam->GetCameraLocation() ); } // Test the object's bound sphere against the view frustum. @@ -1512,9 +1512,9 @@ double KX_Scene::getSuspendedDelta() //Python PyMethodDef KX_Scene::Methods[] = { - KX_PYMETHODTABLE(KX_Scene, getLightList), - KX_PYMETHODTABLE(KX_Scene, getObjectList), - KX_PYMETHODTABLE(KX_Scene, getName), + KX_PYMETHODTABLE_NOARGS(KX_Scene, getLightList), + KX_PYMETHODTABLE_NOARGS(KX_Scene, getObjectList), + KX_PYMETHODTABLE_NOARGS(KX_Scene, getName), {NULL,NULL} //Sentinel }; @@ -1544,28 +1544,27 @@ PyParentObject KX_Scene::Parents[] = { NULL }; -PyObject* KX_Scene::_getattr(const STR_String& attr) +PyObject* KX_Scene::_getattr(const char *attr) { - if (attr == "name") + if (!strcmp(attr, "name")) return PyString_FromString(GetName()); - if (attr == "active_camera") - { - KX_Camera *camera = GetActiveCamera(); - camera->AddRef(); - return (PyObject*) camera; - } + if (!strcmp(attr, "objects")) + return (PyObject*) m_objectlist->AddRef(); - if (attr == "suspended") + if (!strcmp(attr, "active_camera")) + return (PyObject*) GetActiveCamera()->AddRef(); + + if (!strcmp(attr, "suspended")) return PyInt_FromLong(m_suspend); - if (attr == "activity_culling") + if (!strcmp(attr, "activity_culling")) return PyInt_FromLong(m_activity_culling); - if (attr == "activity_culling_radius") + if (!strcmp(attr, "activity_culling_radius")) return PyFloat_FromDouble(m_activity_box_radius); - PyObject* value = PyDict_GetItemString(m_attrlist, const_cast<char *>(attr.ReadPtr())); + PyObject* value = PyDict_GetItemString(m_attrlist, attr); if (value) { Py_INCREF(value); @@ -1575,40 +1574,38 @@ PyObject* KX_Scene::_getattr(const STR_String& attr) _getattr_up(PyObjectPlus); } -int KX_Scene::_delattr(const STR_String &attr) +int KX_Scene::_delattr(const char *attr) { - PyDict_DelItemString(m_attrlist, const_cast<char *>(attr.ReadPtr())); + PyDict_DelItemString(m_attrlist, attr); return 0; } -int KX_Scene::_setattr(const STR_String &attr, PyObject *pyvalue) +int KX_Scene::_setattr(const char *attr, PyObject *pyvalue) { - - if (!PyDict_SetItemString(m_attrlist, const_cast<char *>(attr.ReadPtr()), pyvalue)) + if (!PyDict_SetItemString(m_attrlist, attr, pyvalue)) return 0; return PyObjectPlus::_setattr(attr, pyvalue); } -KX_PYMETHODDEF_DOC(KX_Scene, getLightList, +KX_PYMETHODDEF_DOC_NOARGS(KX_Scene, getLightList, "getLightList() -> list [KX_Light]\n" "Returns a list of all lights in the scene.\n" ) { - m_lightlist->AddRef(); - return (PyObject*) m_lightlist; + return (PyObject*) m_lightlist->AddRef(); } -KX_PYMETHODDEF_DOC(KX_Scene, getObjectList, +KX_PYMETHODDEF_DOC_NOARGS(KX_Scene, getObjectList, "getObjectList() -> list [KX_GameObject]\n" "Returns a list of all game objects in the scene.\n" ) { - m_objectlist->AddRef(); - return (PyObject*) m_objectlist; + // ShowDeprecationWarning("getObjectList()", "the objects property"); // XXX Grr, why doesnt this work? + return (PyObject*) m_objectlist->AddRef(); } -KX_PYMETHODDEF_DOC(KX_Scene, getName, +KX_PYMETHODDEF_DOC_NOARGS(KX_Scene, getName, "getName() -> string\n" "Returns the name of the scene.\n" ) diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h index 5f7e1167e27..e4d4b6fe2cd 100644 --- a/source/gameengine/Ketsji/KX_Scene.h +++ b/source/gameengine/Ketsji/KX_Scene.h @@ -547,9 +547,9 @@ public: */ void SetNodeTree(SG_Tree* root); - KX_PYMETHOD_DOC(KX_Scene, getLightList); - KX_PYMETHOD_DOC(KX_Scene, getObjectList); - KX_PYMETHOD_DOC(KX_Scene, getName); + KX_PYMETHOD_DOC_NOARGS(KX_Scene, getLightList); + KX_PYMETHOD_DOC_NOARGS(KX_Scene, getObjectList); + KX_PYMETHOD_DOC_NOARGS(KX_Scene, getName); /* KX_PYMETHOD_DOC(KX_Scene, getActiveCamera); KX_PYMETHOD_DOC(KX_Scene, getActiveCamera); @@ -564,9 +564,9 @@ public: KX_PYMETHOD_DOC(KX_Scene, setSceneViewport); */ - virtual PyObject* _getattr(const STR_String& attr); /* name, active_camera, gravity, suspended, viewport, framing, activity_culling, activity_culling_radius */ - virtual int _setattr(const STR_String &attr, PyObject *pyvalue); - virtual int _delattr(const STR_String &attr); + virtual PyObject* _getattr(const char *attr); /* name, active_camera, gravity, suspended, viewport, framing, activity_culling, activity_culling_radius */ + virtual int _setattr(const char *attr, PyObject *pyvalue); + virtual int _delattr(const char *attr); /** * Sets the time the scene was suspended diff --git a/source/gameengine/Ketsji/KX_SceneActuator.cpp b/source/gameengine/Ketsji/KX_SceneActuator.cpp index 35484699b17..8e33177cf3a 100644 --- a/source/gameengine/Ketsji/KX_SceneActuator.cpp +++ b/source/gameengine/Ketsji/KX_SceneActuator.cpp @@ -270,7 +270,7 @@ PyMethodDef KX_SceneActuator::Methods[] = -PyObject* KX_SceneActuator::_getattr(const STR_String& attr) +PyObject* KX_SceneActuator::_getattr(const char *attr) { _getattr_up(SCA_IActuator); } @@ -295,7 +295,7 @@ PyObject* KX_SceneActuator::PySetUseRestart(PyObject* self, m_restart = boolArg != 0; - Py_Return; + Py_RETURN_NONE; } @@ -333,7 +333,7 @@ PyObject* KX_SceneActuator::PySetScene(PyObject* self, /* Scene switch is done by name. */ m_nextSceneName = scene_name; - Py_Return; + Py_RETURN_NONE; } @@ -368,7 +368,7 @@ PyObject* KX_SceneActuator::PySetCamera(PyObject* self, m_camera = (KX_Camera*) cam; if (m_camera) m_camera->RegisterActuator(this); - Py_Return; + Py_RETURN_NONE; } PyErr_Clear(); @@ -388,7 +388,7 @@ PyObject* KX_SceneActuator::PySetCamera(PyObject* self, m_camera->RegisterActuator(this); } - Py_Return; + Py_RETURN_NONE; } diff --git a/source/gameengine/Ketsji/KX_SceneActuator.h b/source/gameengine/Ketsji/KX_SceneActuator.h index 55aaf629d7c..af11af955bf 100644 --- a/source/gameengine/Ketsji/KX_SceneActuator.h +++ b/source/gameengine/Ketsji/KX_SceneActuator.h @@ -92,7 +92,7 @@ class KX_SceneActuator : public SCA_IActuator /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); /* 1. set */ /* Removed */ diff --git a/source/gameengine/Ketsji/KX_SoundActuator.cpp b/source/gameengine/Ketsji/KX_SoundActuator.cpp index afa5af3bc04..37604518486 100644 --- a/source/gameengine/Ketsji/KX_SoundActuator.cpp +++ b/source/gameengine/Ketsji/KX_SoundActuator.cpp @@ -287,7 +287,7 @@ PyMethodDef KX_SoundActuator::Methods[] = { -PyObject* KX_SoundActuator::_getattr(const STR_String& attr) +PyObject* KX_SoundActuator::_getattr(const char *attr) { _getattr_up(SCA_IActuator); } @@ -302,7 +302,7 @@ PyObject* KX_SoundActuator::PySetFilename(PyObject* self, PyObject* args, PyObje if (!PyArg_ParseTuple(args, "s", &soundName)) return NULL; - Py_Return; + Py_RETURN_NONE; } @@ -332,7 +332,7 @@ PyObject* KX_SoundActuator::PyStartSound(PyObject* self, PyObject* args, PyObjec // To start the sound you must activate the actuator. // This function is to restart the sound. m_soundObject->StartSound(); - Py_Return; + Py_RETURN_NONE; } @@ -342,7 +342,7 @@ PyObject* KX_SoundActuator::PyPauseSound(PyObject* self, PyObject* args, PyObjec if (m_soundObject) // unfortunately, openal does not implement pause correctly, it is equivalent to a stop m_soundObject->PauseSound(); - Py_Return; + Py_RETURN_NONE; } @@ -351,7 +351,7 @@ PyObject* KX_SoundActuator::PyStopSound(PyObject* self, PyObject* args, PyObject { if (m_soundObject) m_soundObject->StopSound(); - Py_Return; + Py_RETURN_NONE; } @@ -365,7 +365,7 @@ PyObject* KX_SoundActuator::PySetGain(PyObject* self, PyObject* args, PyObject* if (m_soundObject) m_soundObject->SetGain(gain); - Py_Return; + Py_RETURN_NONE; } @@ -389,7 +389,7 @@ PyObject* KX_SoundActuator::PySetPitch(PyObject* self, PyObject* args, PyObject* if (m_soundObject) m_soundObject->SetPitch(pitch); - Py_Return; + Py_RETURN_NONE; } @@ -413,7 +413,7 @@ PyObject* KX_SoundActuator::PySetRollOffFactor(PyObject* self, PyObject* args, P if (m_soundObject) m_soundObject->SetRollOffFactor(rollofffactor); - Py_Return; + Py_RETURN_NONE; } @@ -437,7 +437,7 @@ PyObject* KX_SoundActuator::PySetLooping(PyObject* self, PyObject* args, PyObjec if (m_soundObject) m_soundObject->SetLoopMode(looping); - Py_Return; + Py_RETURN_NONE; } @@ -465,7 +465,7 @@ PyObject* KX_SoundActuator::PySetPosition(PyObject* self, PyObject* args, PyObje if (m_soundObject) m_soundObject->SetPosition(pos); - Py_Return; + Py_RETURN_NONE; } @@ -483,7 +483,7 @@ PyObject* KX_SoundActuator::PySetVelocity(PyObject* self, PyObject* args, PyObje if (m_soundObject) m_soundObject->SetVelocity(vel); - Py_Return; + Py_RETURN_NONE; } @@ -507,7 +507,7 @@ PyObject* KX_SoundActuator::PySetOrientation(PyObject* self, PyObject* args, PyO if (m_soundObject) m_soundObject->SetOrientation(ori); - Py_Return; + Py_RETURN_NONE; } PyObject* KX_SoundActuator::PySetType(PyObject* self, PyObject* args, PyObject* kwds) @@ -523,7 +523,7 @@ PyObject* KX_SoundActuator::PySetType(PyObject* self, PyObject* args, PyObject* m_type = (KX_SOUNDACT_TYPE) typeArg; } - Py_Return; + Py_RETURN_NONE; } PyObject* KX_SoundActuator::PyGetType(PyObject* self, PyObject* args, PyObject* kwds) diff --git a/source/gameengine/Ketsji/KX_SoundActuator.h b/source/gameengine/Ketsji/KX_SoundActuator.h index 5a9edbc4c5e..68d5b792729 100644 --- a/source/gameengine/Ketsji/KX_SoundActuator.h +++ b/source/gameengine/Ketsji/KX_SoundActuator.h @@ -80,7 +80,7 @@ public: /* Python interface --------------------------------------------------- */ /* -------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); KX_PYMETHOD(KX_SoundActuator,SetFilename); KX_PYMETHOD(KX_SoundActuator,GetFilename); diff --git a/source/gameengine/Ketsji/KX_StateActuator.cpp b/source/gameengine/Ketsji/KX_StateActuator.cpp index e360c4bac1f..cd5c5d29ab1 100644 --- a/source/gameengine/Ketsji/KX_StateActuator.cpp +++ b/source/gameengine/Ketsji/KX_StateActuator.cpp @@ -146,10 +146,7 @@ KX_StateActuator::Methods[] = { {NULL,NULL} //Sentinel }; -PyObject* -KX_StateActuator::_getattr( - const STR_String& attr - ) +PyObject* KX_StateActuator::_getattr(const char *attr) { _getattr_up(SCA_IActuator); }; @@ -176,7 +173,7 @@ KX_StateActuator::PySetOperation(PyObject* self, m_operation = oper; - Py_Return; + Py_RETURN_NONE; } /* set mask ---------------------------------------------------------- */ @@ -201,7 +198,7 @@ KX_StateActuator::PySetMask(PyObject* self, m_mask = mask; - Py_Return; + Py_RETURN_NONE; } diff --git a/source/gameengine/Ketsji/KX_StateActuator.h b/source/gameengine/Ketsji/KX_StateActuator.h index 8698e51b2c1..023b8993d7c 100644 --- a/source/gameengine/Ketsji/KX_StateActuator.h +++ b/source/gameengine/Ketsji/KX_StateActuator.h @@ -73,7 +73,7 @@ class KX_StateActuator : public SCA_IActuator /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); //KX_PYMETHOD_DOC KX_PYMETHOD_DOC(KX_StateActuator,SetOperation); KX_PYMETHOD_DOC(KX_StateActuator,SetMask); diff --git a/source/gameengine/Ketsji/KX_SumoPhysicsController.cpp b/source/gameengine/Ketsji/KX_SumoPhysicsController.cpp index c842ca1ee14..7631ee05b0b 100644 --- a/source/gameengine/Ketsji/KX_SumoPhysicsController.cpp +++ b/source/gameengine/Ketsji/KX_SumoPhysicsController.cpp @@ -205,6 +205,10 @@ MT_Scalar KX_SumoPhysicsController::GetMass() return SumoPhysicsController::getMass(); } +void KX_SumoPhysicsController::SetMass(MT_Scalar newmass) +{ +} + MT_Scalar KX_SumoPhysicsController::GetRadius() { return SumoPhysicsController::GetRadius(); diff --git a/source/gameengine/Ketsji/KX_SumoPhysicsController.h b/source/gameengine/Ketsji/KX_SumoPhysicsController.h index abe48d99043..46c8ba6df45 100644 --- a/source/gameengine/Ketsji/KX_SumoPhysicsController.h +++ b/source/gameengine/Ketsji/KX_SumoPhysicsController.h @@ -53,7 +53,7 @@ public: class SM_Object* sumoObj, class PHY_IMotionState* motionstate ,bool dyna) - : KX_IPhysicsController(dyna,NULL) , + : KX_IPhysicsController(dyna,false,NULL) , SumoPhysicsController(sumoScene,/*solidscene,*/sumoObj,motionstate,dyna) { }; @@ -78,12 +78,16 @@ public: void SuspendDynamics(bool); void RestoreDynamics(); + virtual void AddCompoundChild(KX_IPhysicsController* child) { } + virtual void RemoveCompoundChild(KX_IPhysicsController* child) { } + virtual void getOrientation(MT_Quaternion& orn); virtual void setOrientation(const MT_Matrix3x3& orn); virtual void setPosition(const MT_Point3& pos); virtual void setScaling(const MT_Vector3& scaling); virtual MT_Scalar GetMass(); + virtual void SetMass(MT_Scalar newmass); virtual MT_Scalar GetRadius(); virtual MT_Vector3 getReactionForce(); virtual void setRigidBody(bool rigid); diff --git a/source/gameengine/Ketsji/KX_TouchSensor.cpp b/source/gameengine/Ketsji/KX_TouchSensor.cpp index 1935a0bde39..117adb44742 100644 --- a/source/gameengine/Ketsji/KX_TouchSensor.cpp +++ b/source/gameengine/Ketsji/KX_TouchSensor.cpp @@ -100,8 +100,8 @@ m_eventmgr(eventmgr) m_colliders = new CListValue(); KX_ClientObjectInfo *client_info = gameobj->getClientInfo(); - client_info->m_gameobject = gameobj; - client_info->m_auxilary_info = NULL; + //client_info->m_gameobject = gameobj; + //client_info->m_auxilary_info = NULL; client_info->m_sensors.push_back(this); m_physCtrl = dynamic_cast<PHY_IPhysicsController*>(gameobj->GetPhysicsController()); @@ -143,8 +143,8 @@ void KX_TouchSensor::ReParent(SCA_IObject* parent) // m_solidHandle = m_sumoObj->getObjectHandle(); KX_ClientObjectInfo *client_info = gameobj->getClientInfo(); - client_info->m_gameobject = gameobj; - client_info->m_auxilary_info = NULL; + //client_info->m_gameobject = gameobj; + //client_info->m_auxilary_info = NULL; client_info->m_sensors.push_back(this); SCA_ISensor::ReParent(parent); @@ -199,7 +199,7 @@ bool KX_TouchSensor::NewHandleCollision(void*object1,void*object2,const PHY_Coll { if (client_info->m_auxilary_info) { - found = (m_touchedpropname == STR_String((char*)client_info->m_auxilary_info)); + found = (!strcmp(m_touchedpropname.Ptr(), (char*)client_info->m_auxilary_info)); } } else { @@ -261,7 +261,7 @@ PyMethodDef KX_TouchSensor::Methods[] = { {NULL,NULL} //Sentinel }; -PyObject* KX_TouchSensor::_getattr(const STR_String& attr) { +PyObject* KX_TouchSensor::_getattr(const char *attr) { _getattr_up(SCA_ISensor); } @@ -291,7 +291,7 @@ PyObject* KX_TouchSensor::PySetProperty(PyObject* self, } prop->Release(); - Py_Return; + Py_RETURN_NONE; } /* 2. getProperty */ const char KX_TouchSensor::GetProperty_doc[] = @@ -318,7 +318,7 @@ PyObject* KX_TouchSensor::PyGetHitObject(PyObject* self, { return m_hitObject->AddRef(); } - Py_Return; + Py_RETURN_NONE; } const char KX_TouchSensor::GetHitObjectList_doc[] = @@ -354,7 +354,7 @@ PyObject* KX_TouchSensor::PyGetHitObjectList(PyObject* self, if (spc) { KX_ClientObjectInfo* cl_inf = static_cast<KX_ClientObjectInfo*>(spc->getNewClientInfo()); - if (m_touchedpropname == ((char*)cl_inf->m_auxilary_info)) { + if (NULL != cl_inf->m_auxilary_info && m_touchedpropname == ((char*)cl_inf->m_auxilary_info)) { newList->Add(m_colliders->GetValue(i)->AddRef()); } } @@ -402,7 +402,7 @@ PyObject* KX_TouchSensor::PySetTouchMaterial(PyObject* self, PyObject* args, PyO m_bFindMaterial = pulseArg != 0; - Py_Return; + Py_RETURN_NONE; } diff --git a/source/gameengine/Ketsji/KX_TouchSensor.h b/source/gameengine/Ketsji/KX_TouchSensor.h index 8fbb1c676ba..e07f89f0a31 100644 --- a/source/gameengine/Ketsji/KX_TouchSensor.h +++ b/source/gameengine/Ketsji/KX_TouchSensor.h @@ -106,7 +106,7 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); /* 1. setProperty */ KX_PYMETHOD_DOC(KX_TouchSensor,SetProperty); diff --git a/source/gameengine/Ketsji/KX_TrackToActuator.cpp b/source/gameengine/Ketsji/KX_TrackToActuator.cpp index acc4a6ab5d7..89dfc8e57ad 100644 --- a/source/gameengine/Ketsji/KX_TrackToActuator.cpp +++ b/source/gameengine/Ketsji/KX_TrackToActuator.cpp @@ -456,23 +456,51 @@ PyParentObject KX_TrackToActuator::Parents[] = { PyMethodDef KX_TrackToActuator::Methods[] = { - {"setObject", (PyCFunction) KX_TrackToActuator::sPySetObject, METH_O, (PY_METHODCHAR)SetObject_doc}, - {"getObject", (PyCFunction) KX_TrackToActuator::sPyGetObject, METH_VARARGS, (PY_METHODCHAR)GetObject_doc}, {"setTime", (PyCFunction) KX_TrackToActuator::sPySetTime, METH_VARARGS, (PY_METHODCHAR)SetTime_doc}, {"getTime", (PyCFunction) KX_TrackToActuator::sPyGetTime, METH_VARARGS, (PY_METHODCHAR)GetTime_doc}, {"setUse3D", (PyCFunction) KX_TrackToActuator::sPySetUse3D, METH_VARARGS, (PY_METHODCHAR)SetUse3D_doc}, {"getUse3D", (PyCFunction) KX_TrackToActuator::sPyGetUse3D, METH_VARARGS, (PY_METHODCHAR)GetUse3D_doc}, + + // ---> deprecated + {"setObject", (PyCFunction) KX_TrackToActuator::sPySetObject, METH_O, (PY_METHODCHAR)SetObject_doc}, + {"getObject", (PyCFunction) KX_TrackToActuator::sPyGetObject, METH_VARARGS, (PY_METHODCHAR)GetObject_doc}, + {NULL,NULL} //Sentinel }; -PyObject* KX_TrackToActuator::_getattr(const STR_String& attr) +PyObject* KX_TrackToActuator::_getattr(const char *attr) { + if (!strcmp(attr, "object")) { + if (!m_object) Py_RETURN_NONE; + else return m_object->AddRef(); + } + _getattr_up(SCA_IActuator); } +int KX_TrackToActuator::_setattr(const char *attr, PyObject* value) +{ + if (!strcmp(attr, "object")) { + KX_GameObject *gameobj; + + if (!ConvertPythonToGameObject(value, &gameobj, true)) + return 1; // ConvertPythonToGameObject sets the error + + if (m_object != NULL) + m_object->UnregisterActuator(this); + m_object = (SCA_IObject*)gameobj; + + if (m_object) + m_object->RegisterActuator(this); + + return 0; + } + + return SCA_IActuator::_setattr(attr, value); +} /* 1. setObject */ const char KX_TrackToActuator::SetObject_doc[] = @@ -483,6 +511,8 @@ PyObject* KX_TrackToActuator::PySetObject(PyObject* self, PyObject* value) { KX_GameObject *gameobj; + ShowDeprecationWarning("setObject()", "the object property"); + if (!ConvertPythonToGameObject(value, &gameobj, true)) return NULL; // ConvertPythonToGameObject sets the error @@ -506,6 +536,9 @@ const char KX_TrackToActuator::GetObject_doc[] = PyObject* KX_TrackToActuator::PyGetObject(PyObject* self, PyObject* args) { int ret_name_only = 1; + + ShowDeprecationWarning("getObject()", "the object property"); + if (!PyArg_ParseTuple(args, "|i", &ret_name_only)) return NULL; @@ -536,7 +569,7 @@ PyObject* KX_TrackToActuator::PySetTime(PyObject* self, PyObject* args, PyObject m_time= timeArg; - Py_Return; + Py_RETURN_NONE; } @@ -580,7 +613,7 @@ PyObject* KX_TrackToActuator::PySetUse3D(PyObject* self, PyObject* args, PyObjec m_allow3D = !(boolArg == 0); - Py_Return; + Py_RETURN_NONE; } /* eof */ diff --git a/source/gameengine/Ketsji/KX_TrackToActuator.h b/source/gameengine/Ketsji/KX_TrackToActuator.h index 445132a6094..392e55402f1 100644 --- a/source/gameengine/Ketsji/KX_TrackToActuator.h +++ b/source/gameengine/Ketsji/KX_TrackToActuator.h @@ -72,7 +72,8 @@ class KX_TrackToActuator : public SCA_IActuator virtual bool Update(double curtime, bool frame); /* Python part */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject* value); /* 1. setObject */ KX_PYMETHOD_DOC_O(KX_TrackToActuator,SetObject); diff --git a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp index 028f96f6c5b..057e10f195a 100644 --- a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp +++ b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp @@ -322,13 +322,13 @@ PyParentObject KX_VehicleWrapper::Parents[] = { NULL }; -PyObject* KX_VehicleWrapper::_getattr(const STR_String& attr) +PyObject* KX_VehicleWrapper::_getattr(const char *attr) { //here you can search for existing data members (like mass,friction etc.) _getattr_up(PyObjectPlus); } -int KX_VehicleWrapper::_setattr(const STR_String& attr,PyObject* pyobj) +int KX_VehicleWrapper::_setattr(const char *attr,PyObject* pyobj) { PyTypeObject* type = pyobj->ob_type; diff --git a/source/gameengine/Ketsji/KX_VehicleWrapper.h b/source/gameengine/Ketsji/KX_VehicleWrapper.h index b98369d401a..cad926ce85a 100644 --- a/source/gameengine/Ketsji/KX_VehicleWrapper.h +++ b/source/gameengine/Ketsji/KX_VehicleWrapper.h @@ -12,8 +12,8 @@ class PHY_IMotionState; class KX_VehicleWrapper : public PyObjectPlus { Py_Header; - virtual PyObject* _getattr(const STR_String& attr); - virtual int _setattr(const STR_String& attr, PyObject *value); + virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject *value); std::vector<PHY_IMotionState*> m_motionStates; diff --git a/source/gameengine/Ketsji/KX_VertexProxy.cpp b/source/gameengine/Ketsji/KX_VertexProxy.cpp index 25205714308..1c427768b66 100644 --- a/source/gameengine/Ketsji/KX_VertexProxy.cpp +++ b/source/gameengine/Ketsji/KX_VertexProxy.cpp @@ -63,31 +63,59 @@ PyParentObject KX_VertexProxy::Parents[] = { }; PyMethodDef KX_VertexProxy::Methods[] = { -{"getXYZ", (PyCFunction)KX_VertexProxy::sPyGetXYZ,METH_VARARGS}, -{"setXYZ", (PyCFunction)KX_VertexProxy::sPySetXYZ,METH_VARARGS}, -{"getUV", (PyCFunction)KX_VertexProxy::sPyGetUV,METH_VARARGS}, -{"setUV", (PyCFunction)KX_VertexProxy::sPySetUV,METH_VARARGS}, +{"getXYZ", (PyCFunction)KX_VertexProxy::sPyGetXYZ,METH_NOARGS}, +{"setXYZ", (PyCFunction)KX_VertexProxy::sPySetXYZ,METH_O}, +{"getUV", (PyCFunction)KX_VertexProxy::sPyGetUV,METH_NOARGS}, +{"setUV", (PyCFunction)KX_VertexProxy::sPySetUV,METH_O}, -{"getUV2", (PyCFunction)KX_VertexProxy::sPyGetUV2,METH_VARARGS}, +{"getUV2", (PyCFunction)KX_VertexProxy::sPyGetUV2,METH_NOARGS}, {"setUV2", (PyCFunction)KX_VertexProxy::sPySetUV2,METH_VARARGS}, -{"getRGBA", (PyCFunction)KX_VertexProxy::sPyGetRGBA,METH_VARARGS}, -{"setRGBA", (PyCFunction)KX_VertexProxy::sPySetRGBA,METH_VARARGS}, -{"getNormal", (PyCFunction)KX_VertexProxy::sPyGetNormal,METH_VARARGS}, -{"setNormal", (PyCFunction)KX_VertexProxy::sPySetNormal,METH_VARARGS}, +{"getRGBA", (PyCFunction)KX_VertexProxy::sPyGetRGBA,METH_NOARGS}, +{"setRGBA", (PyCFunction)KX_VertexProxy::sPySetRGBA,METH_O}, +{"getNormal", (PyCFunction)KX_VertexProxy::sPyGetNormal,METH_NOARGS}, +{"setNormal", (PyCFunction)KX_VertexProxy::sPySetNormal,METH_O}, {NULL,NULL} //Sentinel }; PyObject* -KX_VertexProxy::_getattr(const STR_String& attr) +KX_VertexProxy::_getattr(const char *attr) { - if (attr == "XYZ") + + if (attr[1]=='\0') { // Group single letters + // pos + if (attr[0]=='x') + return PyFloat_FromDouble(m_vertex->getXYZ()[0]); + if (attr[0]=='y') + return PyFloat_FromDouble(m_vertex->getXYZ()[1]); + if (attr[0]=='z') + return PyFloat_FromDouble(m_vertex->getXYZ()[2]); + + // Col + if (attr[0]=='r') + return PyFloat_FromDouble(m_vertex->getRGBA()[0]/255.0); + if (attr[0]=='g') + return PyFloat_FromDouble(m_vertex->getRGBA()[1]/255.0); + if (attr[0]=='b') + return PyFloat_FromDouble(m_vertex->getRGBA()[2]/255.0); + if (attr[0]=='a') + return PyFloat_FromDouble(m_vertex->getRGBA()[3]/255.0); + + // UV + if (attr[0]=='u') + return PyFloat_FromDouble(m_vertex->getUV1()[0]); + if (attr[0]=='v') + return PyFloat_FromDouble(m_vertex->getUV1()[1]); + } + + + if (!strcmp(attr, "XYZ")) return PyObjectFrom(MT_Vector3(m_vertex->getXYZ())); - if (attr == "UV") + if (!strcmp(attr, "UV")) return PyObjectFrom(MT_Point2(m_vertex->getUV1())); - if (attr == "colour" || attr == "color") + if (!strcmp(attr, "color") || !strcmp(attr, "colour")) { const unsigned char *colp = m_vertex->getRGBA(); MT_Vector4 color(colp[0], colp[1], colp[2], colp[3]); @@ -95,43 +123,19 @@ KX_VertexProxy::_getattr(const STR_String& attr) return PyObjectFrom(color); } - if (attr == "normal") + if (!strcmp(attr, "normal")) { return PyObjectFrom(MT_Vector3(m_vertex->getNormal())); } - - // pos - if (attr == "x") - return PyFloat_FromDouble(m_vertex->getXYZ()[0]); - if (attr == "y") - return PyFloat_FromDouble(m_vertex->getXYZ()[1]); - if (attr == "z") - return PyFloat_FromDouble(m_vertex->getXYZ()[2]); - - // Col - if (attr == "r") - return PyFloat_FromDouble(m_vertex->getRGBA()[0]/255.0); - if (attr == "g") - return PyFloat_FromDouble(m_vertex->getRGBA()[1]/255.0); - if (attr == "b") - return PyFloat_FromDouble(m_vertex->getRGBA()[2]/255.0); - if (attr == "a") - return PyFloat_FromDouble(m_vertex->getRGBA()[3]/255.0); - - // UV - if (attr == "u") - return PyFloat_FromDouble(m_vertex->getUV1()[0]); - if (attr == "v") - return PyFloat_FromDouble(m_vertex->getUV1()[1]); - + _getattr_up(SCA_IObject); } -int KX_VertexProxy::_setattr(const STR_String& attr, PyObject *pyvalue) +int KX_VertexProxy::_setattr(const char *attr, PyObject *pyvalue) { if (PySequence_Check(pyvalue)) { - if (attr == "XYZ") + if (!strcmp(attr, "XYZ")) { MT_Point3 vec; if (PyVecTo(pyvalue, vec)) @@ -143,7 +147,7 @@ int KX_VertexProxy::_setattr(const STR_String& attr, PyObject *pyvalue) return 1; } - if (attr == "UV") + if (!strcmp(attr, "UV")) { MT_Point2 vec; if (PyVecTo(pyvalue, vec)) @@ -155,7 +159,7 @@ int KX_VertexProxy::_setattr(const STR_String& attr, PyObject *pyvalue) return 1; } - if (attr == "colour" || attr == "color") + if (!strcmp(attr, "color") || !strcmp(attr, "colour")) { MT_Vector4 vec; if (PyVecTo(pyvalue, vec)) @@ -167,7 +171,7 @@ int KX_VertexProxy::_setattr(const STR_String& attr, PyObject *pyvalue) return 1; } - if (attr == "normal") + if (!strcmp(attr, "normal")) { MT_Vector3 vec; if (PyVecTo(pyvalue, vec)) @@ -185,7 +189,7 @@ int KX_VertexProxy::_setattr(const STR_String& attr, PyObject *pyvalue) float val = PyFloat_AsDouble(pyvalue); // pos MT_Point3 pos(m_vertex->getXYZ()); - if (attr == "x") + if (!strcmp(attr, "x")) { pos.x() = val; m_vertex->SetXYZ(pos); @@ -193,7 +197,7 @@ int KX_VertexProxy::_setattr(const STR_String& attr, PyObject *pyvalue) return 0; } - if (attr == "y") + if (!strcmp(attr, "y")) { pos.y() = val; m_vertex->SetXYZ(pos); @@ -201,7 +205,7 @@ int KX_VertexProxy::_setattr(const STR_String& attr, PyObject *pyvalue) return 0; } - if (attr == "z") + if (!strcmp(attr, "z")) { pos.z() = val; m_vertex->SetXYZ(pos); @@ -211,7 +215,7 @@ int KX_VertexProxy::_setattr(const STR_String& attr, PyObject *pyvalue) // uv MT_Point2 uv = m_vertex->getUV1(); - if (attr == "u") + if (!strcmp(attr, "u")) { uv[0] = val; m_vertex->SetUV(uv); @@ -219,7 +223,7 @@ int KX_VertexProxy::_setattr(const STR_String& attr, PyObject *pyvalue) return 0; } - if (attr == "v") + if (!strcmp(attr, "v")) { uv[1] = val; m_vertex->SetUV(uv); @@ -229,7 +233,7 @@ int KX_VertexProxy::_setattr(const STR_String& attr, PyObject *pyvalue) // uv MT_Point2 uv2 = m_vertex->getUV2(); - if (attr == "u2") + if (!strcmp(attr, "u2")) { uv[0] = val; m_vertex->SetUV2(uv); @@ -237,7 +241,7 @@ int KX_VertexProxy::_setattr(const STR_String& attr, PyObject *pyvalue) return 0; } - if (attr == "v2") + if (!strcmp(attr, "v2")) { uv[1] = val; m_vertex->SetUV2(uv); @@ -249,28 +253,28 @@ int KX_VertexProxy::_setattr(const STR_String& attr, PyObject *pyvalue) unsigned int icol = *((const unsigned int *)m_vertex->getRGBA()); unsigned char *cp = (unsigned char*) &icol; val *= 255.0; - if (attr == "r") + if (!strcmp(attr, "r")) { cp[0] = (unsigned char) val; m_vertex->SetRGBA(icol); m_mesh->SetMeshModified(true); return 0; } - if (attr == "g") + if (!strcmp(attr, "g")) { cp[1] = (unsigned char) val; m_vertex->SetRGBA(icol); m_mesh->SetMeshModified(true); return 0; } - if (attr == "b") + if (!strcmp(attr, "b")) { cp[2] = (unsigned char) val; m_vertex->SetRGBA(icol); m_mesh->SetMeshModified(true); return 0; } - if (attr == "a") + if (!strcmp(attr, "a")) { cp[3] = (unsigned char) val; m_vertex->SetRGBA(icol); @@ -308,130 +312,103 @@ void KX_VertexProxy::ReplicaSetName(STR_String) {}; // stuff for python integration -PyObject* KX_VertexProxy::PyGetXYZ(PyObject*, - PyObject*, - PyObject*) +PyObject* KX_VertexProxy::PyGetXYZ(PyObject*) { return PyObjectFrom(MT_Point3(m_vertex->getXYZ())); } -PyObject* KX_VertexProxy::PySetXYZ(PyObject*, - PyObject* args, - PyObject*) +PyObject* KX_VertexProxy::PySetXYZ(PyObject*, PyObject* value) { MT_Point3 vec; - if (PyVecArgTo(args, vec)) - { - m_vertex->SetXYZ(vec); - m_mesh->SetMeshModified(true); - Py_Return; - } - - return NULL; + if (!PyVecTo(value, vec)) + return NULL; + + m_vertex->SetXYZ(vec); + m_mesh->SetMeshModified(true); + Py_RETURN_NONE; } -PyObject* KX_VertexProxy::PyGetNormal(PyObject*, - PyObject*, - PyObject*) +PyObject* KX_VertexProxy::PyGetNormal(PyObject*) { return PyObjectFrom(MT_Vector3(m_vertex->getNormal())); } -PyObject* KX_VertexProxy::PySetNormal(PyObject*, - PyObject* args, - PyObject*) +PyObject* KX_VertexProxy::PySetNormal(PyObject*, PyObject* value) { MT_Vector3 vec; - if (PyVecArgTo(args, vec)) - { - m_vertex->SetNormal(vec); - m_mesh->SetMeshModified(true); - Py_Return; - } + if (!PyVecTo(value, vec)) + return NULL; - return NULL; + m_vertex->SetNormal(vec); + m_mesh->SetMeshModified(true); + Py_RETURN_NONE; } -PyObject* KX_VertexProxy::PyGetRGBA(PyObject*, - PyObject*, - PyObject*) +PyObject* KX_VertexProxy::PyGetRGBA(PyObject*) { int *rgba = (int *) m_vertex->getRGBA(); return PyInt_FromLong(*rgba); } -PyObject* KX_VertexProxy::PySetRGBA(PyObject*, - PyObject* args, - PyObject*) +PyObject* KX_VertexProxy::PySetRGBA(PyObject*, PyObject* value) { - float r, g, b, a; - if (PyArg_ParseTuple(args, "(ffff)", &r, &g, &b, &a)) - { - m_vertex->SetRGBA(MT_Vector4(r, g, b, a)); - m_mesh->SetMeshModified(true); - Py_Return; - } - PyErr_Clear(); - - int rgba; - if (PyArg_ParseTuple(args,"i",&rgba)) - { + if PyInt_Check(value) { + int rgba = PyInt_AsLong(value); m_vertex->SetRGBA(rgba); m_mesh->SetMeshModified(true); - Py_Return; + Py_RETURN_NONE; + } + else { + MT_Vector4 vec; + if (PyVecTo(value, vec)) + { + m_vertex->SetRGBA(vec); + m_mesh->SetMeshModified(true); + Py_RETURN_NONE; + } } + PyErr_SetString(PyExc_TypeError, "expected a 4D vector or an int"); return NULL; } -PyObject* KX_VertexProxy::PyGetUV(PyObject*, - PyObject*, - PyObject*) +PyObject* KX_VertexProxy::PyGetUV(PyObject*) { return PyObjectFrom(MT_Vector2(m_vertex->getUV1())); } -PyObject* KX_VertexProxy::PySetUV(PyObject*, - PyObject* args, - PyObject*) +PyObject* KX_VertexProxy::PySetUV(PyObject*, PyObject* value) { MT_Point2 vec; - if (PyVecArgTo(args, vec)) - { - m_vertex->SetUV(vec); - m_mesh->SetMeshModified(true); - Py_Return; - } + if (!PyVecTo(value, vec)) + return NULL; - return NULL; + m_vertex->SetUV(vec); + m_mesh->SetMeshModified(true); + Py_RETURN_NONE; } -PyObject* KX_VertexProxy::PyGetUV2(PyObject*, - PyObject*, - PyObject*) +PyObject* KX_VertexProxy::PyGetUV2(PyObject*) { return PyObjectFrom(MT_Vector2(m_vertex->getUV2())); } -PyObject* KX_VertexProxy::PySetUV2(PyObject*, - PyObject* args, - PyObject*) +PyObject* KX_VertexProxy::PySetUV2(PyObject*, PyObject* args) { MT_Point2 vec; unsigned int unit=0; - PyObject* list=0; - if(PyArg_ParseTuple(args, "Oi", &list, &unit)) - { - if (PyVecTo(list, vec)) - { - m_vertex->SetFlag((m_vertex->getFlag()|RAS_TexVert::SECOND_UV)); - m_vertex->SetUnit(unit); - m_vertex->SetUV2(vec); - m_mesh->SetMeshModified(true); - Py_Return; - } - } - return NULL; + PyObject* list= NULL; + if(!PyArg_ParseTuple(args, "Oi:setUV2", &list, &unit)) + return NULL; + + if (!PyVecTo(list, vec)) + return NULL; + + m_vertex->SetFlag((m_vertex->getFlag()|RAS_TexVert::SECOND_UV)); + m_vertex->SetUnit(unit); + m_vertex->SetUV2(vec); + m_mesh->SetMeshModified(true); + Py_RETURN_NONE; } diff --git a/source/gameengine/Ketsji/KX_VertexProxy.h b/source/gameengine/Ketsji/KX_VertexProxy.h index e154ea11b40..28196075904 100644 --- a/source/gameengine/Ketsji/KX_VertexProxy.h +++ b/source/gameengine/Ketsji/KX_VertexProxy.h @@ -54,21 +54,21 @@ public: // stuff for python integration - virtual PyObject* _getattr(const STR_String& attr); - virtual int _setattr(const STR_String& attr, PyObject *pyvalue); + virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject *pyvalue); - KX_PYMETHOD(KX_VertexProxy,GetXYZ); - KX_PYMETHOD(KX_VertexProxy,SetXYZ); - KX_PYMETHOD(KX_VertexProxy,GetUV); - KX_PYMETHOD(KX_VertexProxy,SetUV); + KX_PYMETHOD_NOARGS(KX_VertexProxy,GetXYZ); + KX_PYMETHOD_O(KX_VertexProxy,SetXYZ); + KX_PYMETHOD_NOARGS(KX_VertexProxy,GetUV); + KX_PYMETHOD_O(KX_VertexProxy,SetUV); - KX_PYMETHOD(KX_VertexProxy,GetUV2); - KX_PYMETHOD(KX_VertexProxy,SetUV2); + KX_PYMETHOD_NOARGS(KX_VertexProxy,GetUV2); + KX_PYMETHOD_VARARGS(KX_VertexProxy,SetUV2); - KX_PYMETHOD(KX_VertexProxy,GetRGBA); - KX_PYMETHOD(KX_VertexProxy,SetRGBA); - KX_PYMETHOD(KX_VertexProxy,GetNormal); - KX_PYMETHOD(KX_VertexProxy,SetNormal); + KX_PYMETHOD_NOARGS(KX_VertexProxy,GetRGBA); + KX_PYMETHOD_O(KX_VertexProxy,SetRGBA); + KX_PYMETHOD_NOARGS(KX_VertexProxy,GetNormal); + KX_PYMETHOD_O(KX_VertexProxy,SetNormal); }; diff --git a/source/gameengine/Ketsji/KX_VisibilityActuator.cpp b/source/gameengine/Ketsji/KX_VisibilityActuator.cpp index 4b0db5a7953..ca89a63de62 100644 --- a/source/gameengine/Ketsji/KX_VisibilityActuator.cpp +++ b/source/gameengine/Ketsji/KX_VisibilityActuator.cpp @@ -126,10 +126,7 @@ KX_VisibilityActuator::Methods[] = { {NULL,NULL} //Sentinel }; -PyObject* -KX_VisibilityActuator::_getattr( - const STR_String& attr - ) +PyObject* KX_VisibilityActuator::_getattr(const char *attr) { _getattr_up(SCA_IActuator); }; @@ -155,7 +152,7 @@ KX_VisibilityActuator::PySetVisible(PyObject* self, m_visible = PyArgToBool(vis); - Py_Return; + Py_RETURN_NONE; } diff --git a/source/gameengine/Ketsji/KX_VisibilityActuator.h b/source/gameengine/Ketsji/KX_VisibilityActuator.h index d1b85ab998c..323280de8cb 100644 --- a/source/gameengine/Ketsji/KX_VisibilityActuator.h +++ b/source/gameengine/Ketsji/KX_VisibilityActuator.h @@ -67,7 +67,7 @@ class KX_VisibilityActuator : public SCA_IActuator /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); //KX_PYMETHOD_DOC KX_PYMETHOD_DOC(KX_VisibilityActuator,SetVisible); diff --git a/source/gameengine/Ketsji/SConscript b/source/gameengine/Ketsji/SConscript index f5c620b583f..e9e68f14df8 100644 --- a/source/gameengine/Ketsji/SConscript +++ b/source/gameengine/Ketsji/SConscript @@ -34,11 +34,6 @@ incs += ' #source/gameengine/Physics/Sumo #source/gameengine/Physics/Sumo/includ incs += ' #source/gameengine/Physics/Sumo/Fuzzics/include #source/gameengine/Network/LoopBackNetwork' incs += ' #source/blender/misc #source/blender/blenloader #extern/glew/include #source/blender/gpu' -cflags = [] -if env['OURPLATFORM'] == 'win32-vc': - cflags.append('/GR') - cflags.append('/Ox') - incs += ' ' + env['BF_SOLID_INC'] incs += ' ' + env['BF_PYTHON_INC'] incs += ' ' + env['BF_BULLET_INC'] @@ -47,4 +42,9 @@ incs += ' ' + env['BF_OPENGL_INC'] if env['WITH_BF_SDL']: incs += ' ' + env['BF_SDL_INC'] -env.BlenderLib ( 'bf_ketsji', sources, Split(incs), [], libtype=['game','player'], priority=[25, 72], compileflags = cflags ) +cxxflags = [] +if env['OURPLATFORM']=='win32-vc': + cxxflags.append ('/GR') + cxxflags.append ('/O2') + +env.BlenderLib ( 'bf_ketsji', sources, Split(incs), [], libtype=['game','player'], priority=[25, 72], cxx_compileflags = cxxflags ) diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp index c9c30c1b450..d09ad58fe3b 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp @@ -74,10 +74,10 @@ CcdPhysicsController::CcdPhysicsController (const CcdConstructionInfo& ci) ///??? -#ifdef WIN32 +/*#ifdef WIN32 if (GetRigidBody() && !GetRigidBody()->isStaticObject()) GetRigidBody()->setLinearVelocity(startVel); -#endif +#endif*/ } @@ -1276,7 +1276,7 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, bool polytope,bo // assume no shape information // no support for dynamic change of shape yet - assert(m_meshObject == NULL); + assert(IsUnused()); m_shapeType = PHY_SHAPE_NONE; m_vertexArray.clear(); m_polygonIndexArray.clear(); @@ -1398,6 +1398,17 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, bool polytope,bo return true; } +bool CcdShapeConstructionInfo::SetProxy(CcdShapeConstructionInfo* shapeInfo) +{ + if (shapeInfo == NULL) + return false; + // no support for dynamic change + assert(IsUnused()); + m_shapeType = PHY_SHAPE_PROXY; + m_shapeProxy = shapeInfo; + return true; +} + btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape() { btCollisionShape* collisionShape = 0; @@ -1406,9 +1417,12 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape() btCompoundShape* compoundShape = 0; CcdShapeConstructionInfo* nextShapeInfo; + if (m_shapeType == PHY_SHAPE_PROXY && m_shapeProxy != NULL) + return m_shapeProxy->CreateBulletShape(); + switch (m_shapeType) { - case PHY_SHAPE_NONE: + default: break; case PHY_SHAPE_BOX: @@ -1522,6 +1536,10 @@ CcdShapeConstructionInfo::~CcdShapeConstructionInfo() m_meshShapeMap.erase(mit); } } + if (m_shapeType == PHY_SHAPE_PROXY && m_shapeProxy != NULL) + { + m_shapeProxy->Release(); + } } diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.h b/source/gameengine/Physics/Bullet/CcdPhysicsController.h index 054ec91122a..c771aa2624b 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.h @@ -67,11 +67,13 @@ public: m_height(1.0), m_halfExtend(0.f,0.f,0.f), m_childScale(1.0f,1.0f,1.0f), + m_userData(NULL), m_refCount(1), m_meshObject(NULL), m_unscaledShape(NULL), m_useGimpact(false), - m_weldingThreshold(0.f) + m_weldingThreshold(0.f), + m_shapeProxy(NULL) { m_childTrans.setIdentity(); } @@ -92,6 +94,11 @@ public: return 0; } + bool IsUnused(void) + { + return (m_meshObject==NULL && m_shapeArray.size() == 0 && m_shapeProxy == NULL); + } + void AddShape(CcdShapeConstructionInfo* shapeInfo); btTriangleMeshShape* GetMeshShape(void) @@ -105,6 +112,32 @@ public: return m_shapeArray.at(i); } + int FindChildShape(CcdShapeConstructionInfo* shapeInfo, void* userData) + { + if (shapeInfo == NULL) + return -1; + for (int i=0; i<m_shapeArray.size(); i++) + { + CcdShapeConstructionInfo* childInfo = m_shapeArray.at(i); + if ((userData == NULL || userData == childInfo->m_userData) && + (childInfo == shapeInfo || + (childInfo->m_shapeType == PHY_SHAPE_PROXY && + childInfo->m_shapeProxy == shapeInfo))) + return i; + } + return -1; + } + + bool RemoveChildShape(int i) + { + if (i < 0 || i >= m_shapeArray.size()) + return false; + m_shapeArray.at(i)->Release(); + if (i < m_shapeArray.size()-1) + m_shapeArray[i] = m_shapeArray.back(); + m_shapeArray.pop_back(); + return true; + } bool SetMesh(RAS_MeshObject* mesh, bool polytope,bool useGimpact); RAS_MeshObject* GetMesh(void) @@ -112,6 +145,12 @@ public: return m_meshObject; } + bool SetProxy(CcdShapeConstructionInfo* shapeInfo); + CcdShapeConstructionInfo* GetProxy(void) + { + return m_shapeProxy; + } + btCollisionShape* CreateBulletShape(); // member variables @@ -121,6 +160,7 @@ public: btVector3 m_halfExtend; btTransform m_childTrans; btVector3 m_childScale; + void* m_userData; std::vector<btPoint3> m_vertexArray; // Contains both vertex array for polytope shape and // triangle array for concave mesh shape. // In this case a triangle is made of 3 consecutive points @@ -146,7 +186,7 @@ protected: std::vector<CcdShapeConstructionInfo*> m_shapeArray; // for compound shapes bool m_useGimpact; //use gimpact for concave dynamic/moving collision detection float m_weldingThreshold; //welding closeby vertices together can improve softbody stability etc. - + CcdShapeConstructionInfo* m_shapeProxy; // only used for PHY_SHAPE_PROXY, pointer to actual shape info }; struct CcdConstructionInfo diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp index 4fe35630784..d2274c1e8d6 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp @@ -536,12 +536,24 @@ void CcdPhysicsEnvironment::disableCcdPhysicsController(CcdPhysicsController* ct { } else { - m_dynamicsWorld->removeCollisionObject(body); + m_dynamicsWorld->removeCollisionObject(ctrl->GetCollisionObject()); } } } } +void CcdPhysicsEnvironment::refreshCcdPhysicsController(CcdPhysicsController* ctrl) +{ + btCollisionObject* obj = ctrl->GetCollisionObject(); + if (obj) + { + btBroadphaseProxy* proxy = obj->getBroadphaseHandle(); + if (proxy) + { + m_dynamicsWorld->getPairCache()->cleanProxyFromPairs(proxy,m_dynamicsWorld->getDispatcher()); + } + } +} void CcdPhysicsEnvironment::beginFrame() { diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h index 74384dd8cf2..4b28d3fddfc 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h @@ -196,6 +196,8 @@ protected: void enableCcdPhysicsController(CcdPhysicsController* ctrl); + void refreshCcdPhysicsController(CcdPhysicsController* ctrl); + btBroadphaseInterface* getBroadphase(); btDispatcher* getDispatcher(); diff --git a/source/gameengine/Physics/Bullet/SConscript b/source/gameengine/Physics/Bullet/SConscript index 0936d45197a..0d5bf4933d8 100644 --- a/source/gameengine/Physics/Bullet/SConscript +++ b/source/gameengine/Physics/Bullet/SConscript @@ -7,9 +7,9 @@ incs = '. ../common #source/kernel/gen_system #intern/string #intern/moto/includ incs += ' ' + env['BF_BULLET_INC'] -cflags = [] +cxxflags = [] if env['OURPLATFORM']=='win32-vc': - cflags.append('/GR') - cflags.append('/O2') + cxxflags.append ('/GR') + cxxflags.append ('/O2') -env.BlenderLib ( 'bf_bullet', Split(sources), Split(incs), [], libtype=['game','player'], priority=[15,90] ) +env.BlenderLib ( 'bf_bullet', Split(sources), Split(incs), [], libtype=['game','player'], priority=[15,90], cxx_compileflags=cxxflags ) diff --git a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Scene.h b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Scene.h index 2326bdee523..3d8eef2bae0 100644 --- a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Scene.h +++ b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Scene.h @@ -46,7 +46,7 @@ #include "SM_Object.h" -typedef enum +enum { FH_RESPONSE, SENSOR_RESPONSE, /* Touch Sensors */ diff --git a/source/gameengine/Physics/common/PHY_DynamicTypes.h b/source/gameengine/Physics/common/PHY_DynamicTypes.h index 3b3e42c38d2..c5cf92b553a 100644 --- a/source/gameengine/Physics/common/PHY_DynamicTypes.h +++ b/source/gameengine/Physics/common/PHY_DynamicTypes.h @@ -36,7 +36,7 @@ struct PHY__Vector3 }; //typedef float PHY__Vector3[4]; -typedef enum +enum { PHY_FH_RESPONSE, PHY_SENSOR_RESPONSE, /* Touch Sensors */ @@ -95,7 +95,8 @@ typedef enum PHY_ShapeType { PHY_SHAPE_CONE, PHY_SHAPE_MESH, PHY_SHAPE_POLYTOPE, - PHY_SHAPE_COMPOUND + PHY_SHAPE_COMPOUND, + PHY_SHAPE_PROXY } PHY_ShapeType; diff --git a/source/gameengine/Physics/common/SConscript b/source/gameengine/Physics/common/SConscript index 91c5101675e..474536e1f76 100644 --- a/source/gameengine/Physics/common/SConscript +++ b/source/gameengine/Physics/common/SConscript @@ -5,4 +5,9 @@ sources = 'PHY_IMotionState.cpp PHY_IPhysicsController.cpp PHY_IPhysicsEnvironme incs = '. ../Dummy #intern/moto/include' -env.BlenderLib ( 'bf_common', Split(sources), Split(incs), [], libtype=['game', 'game2','player'], priority=[20, 35, 95] ) +cxxflags = [] +if env['OURPLATFORM']=='win32-vc': + cxxflags.append ('/GR') + cxxflags.append ('/O2') + +env.BlenderLib ( 'bf_common', Split(sources), Split(incs), [], libtype=['game', 'game2','player'], priority=[20, 35, 95], cxx_compileflags = cxxflags ) diff --git a/source/gameengine/PyDoc/BL_ActionActuator.py b/source/gameengine/PyDoc/BL_ActionActuator.py index b68d3014115..3e95befe16b 100644 --- a/source/gameengine/PyDoc/BL_ActionActuator.py +++ b/source/gameengine/PyDoc/BL_ActionActuator.py @@ -5,9 +5,52 @@ from SCA_IActuator import * class BL_ActionActuator(SCA_IActuator): """ Action Actuators apply an action to an actor. + + @ivar action: The name of the action to set as the current action. + @type action: string + @ivar start: Specifies the starting frame of the animation. + @type start: float + @type end: Specifies the ending frame of the animation. + @type end: float + @ivar blendin: Specifies the number of frames of animation to generate when making transitions between actions. + @type blendin: float + @ivar priority: Sets the priority of this actuator. Actuators will lower + priority numbers will override actuators with higher + numbers. + @type priority: integer + @ivar frame: Sets the current frame for the animation. + @type frame: float + @ivar property: Sets the property to be used in FromProp playback mode. + @type property: string + @ivar blendTime: Sets the internal frame timer. This property must be in + the range from 0.0 to blendin. + @type blendTime: float + @ivar type: The operation mode of the actuator. + KX_ACTIONACT_PLAY, KX_ACTIONACT_PROPERTY, KX_ACTIONACT_FLIPPER, + KX_ACTIONACT_LOOPSTOP, KX_ACTIONACT_LOOPEND + @type type: integer + @ivar continue: The actions continue option, True or False. + When True, the action will always play from where last left off, + otherwise negative events to this actuator will reset it to its start frame. + @type: boolean + @ivar frameProperty: The name of the property that is set to the current frame number. + @type frameProperty: string """ + def setChannel(channel, matrix, mode = False): + """ + @param channel: A string specifying the name of the bone channel. + @type channel: string + @param matrix: A 4x4 matrix specifying the overriding transformation + as an offset from the bone's rest position. + @type matrix: list [[float]] + @param mode: True for armature/world space, False for bone space + @type mode: boolean + """ + + #--The following methods are deprecated-- def setAction(action, reset = True): """ + DEPRECATED: use the 'action' property Sets the current action. @param action: The name of the action to set as the current action. @@ -21,6 +64,7 @@ class BL_ActionActuator(SCA_IActuator): def setStart(start): """ + DEPRECATED: use the 'start' property Specifies the starting frame of the animation. @param start: the starting frame of the animation @@ -29,6 +73,7 @@ class BL_ActionActuator(SCA_IActuator): def setEnd(end): """ + DEPRECATED: use the 'end' property Specifies the ending frame of the animation. @param end: the ending frame of the animation @@ -36,6 +81,7 @@ class BL_ActionActuator(SCA_IActuator): """ def setBlendin(blendin): """ + DEPRECATED: use the 'blendin' property Specifies the number of frames of animation to generate when making transitions between actions. @@ -45,6 +91,7 @@ class BL_ActionActuator(SCA_IActuator): def setPriority(priority): """ + DEPRECATED: use the 'priority' property Sets the priority of this actuator. @param priority: Specifies the new priority. Actuators will lower @@ -54,6 +101,7 @@ class BL_ActionActuator(SCA_IActuator): """ def setFrame(frame): """ + DEPRECATED: use the 'frame' property Sets the current frame for the animation. @param frame: Specifies the new current frame for the animation @@ -62,6 +110,7 @@ class BL_ActionActuator(SCA_IActuator): def setProperty(prop): """ + DEPRECATED: use the 'property' property Sets the property to be used in FromProp playback mode. @param prop: the name of the property to use. @@ -70,6 +119,7 @@ class BL_ActionActuator(SCA_IActuator): def setBlendtime(blendtime): """ + DEPRECATED: use the 'blendTime' property Sets the internal frame timer. Allows the script to directly modify the internal timer @@ -81,6 +131,7 @@ class BL_ActionActuator(SCA_IActuator): def setType(mode): """ + DEPRECATED: use the 'type' property Sets the operation mode of the actuator @param mode: KX_ACTIONACT_PLAY, KX_ACTIONACT_PROPERTY, KX_ACTIONACT_FLIPPER, KX_ACTIONACT_LOOPSTOP, KX_ACTIONACT_LOOPEND @@ -89,6 +140,7 @@ class BL_ActionActuator(SCA_IActuator): def setContinue(cont): """ + DEPRECATED: use the 'continue' property Set the actions continue option True or False. see getContinue. @param cont: The continue option. @@ -97,6 +149,7 @@ class BL_ActionActuator(SCA_IActuator): def getType(): """ + DEPRECATED: use the 'type' property Returns the operation mode of the actuator @rtype: integer @@ -105,6 +158,7 @@ class BL_ActionActuator(SCA_IActuator): def getContinue(): """ + DEPRECATED: use the 'continue' property When True, the action will always play from where last left off, otherwise negative events to this actuator will reset it to its start frame. @rtype: bool @@ -112,6 +166,7 @@ class BL_ActionActuator(SCA_IActuator): def getAction(): """ + DEPRECATED: use the 'action' property getAction() returns the name of the action associated with this actuator. @rtype: string @@ -119,24 +174,28 @@ class BL_ActionActuator(SCA_IActuator): def getStart(): """ + DEPRECATED: use the 'start' property Returns the starting frame of the action. @rtype: float """ def getEnd(): """ + DEPRECATED: use the 'end' property Returns the last frame of the action. @rtype: float """ def getBlendin(): """ + DEPRECATED: use the 'blendin' property Returns the number of interpolation animation frames to be generated when this actuator is triggered. @rtype: float """ def getPriority(): """ + DEPRECATED: use the 'priority' property Returns the priority for this actuator. Actuators with lower Priority numbers will override actuators with higher numbers. @@ -144,33 +203,27 @@ class BL_ActionActuator(SCA_IActuator): """ def getFrame(): """ + DEPRECATED: use the 'frame' property Returns the current frame number. @rtype: float """ def getProperty(): """ + DEPRECATED: use the 'property' property Returns the name of the property to be used in FromProp mode. @rtype: string """ - def setChannel(channel, matrix, mode = False): - """ - @param channel: A string specifying the name of the bone channel. - @type channel: string - @param matrix: A 4x4 matrix specifying the overriding transformation - as an offset from the bone's rest position. - @type matrix: list [[float]] - @param mode: True for armature/world space, False for bone space - @type mode: boolean - """ def setFrameProperty(prop): """ + DEPRECATED: use the 'frameProperty' property @param prop: A string specifying the property of the object that will be updated with the action frame number. @type prop: string """ def getFrameProperty(): """ + DEPRECATED: use the 'frameProperty' property Returns the name of the property that is set to the current frame number. @rtype: string diff --git a/source/gameengine/PyDoc/BL_ShapeActionActuator.py b/source/gameengine/PyDoc/BL_ShapeActionActuator.py index a26b276a2da..209ff4e5580 100644 --- a/source/gameengine/PyDoc/BL_ShapeActionActuator.py +++ b/source/gameengine/PyDoc/BL_ShapeActionActuator.py @@ -4,10 +4,38 @@ from SCA_IActuator import * class BL_ShapeActionActuator(SCA_IActuator): """ - ShapeAction Actuators apply an shape action to an mesh object. + ShapeAction Actuators apply an shape action to an mesh object.\ + + @ivar action: The name of the action to set as the current shape action. + @type action: string + @ivar start: Specifies the starting frame of the shape animation. + @type start: float + @type end: Specifies the ending frame of the shape animation. + @type end: float + @ivar blendin: Specifies the number of frames of animation to generate when making transitions between actions. + @type blendin: float + @ivar priority: Sets the priority of this actuator. Actuators will lower + priority numbers will override actuators with higher + numbers. + @type priority: integer + @ivar frame: Sets the current frame for the animation. + @type frame: float + @ivar property: Sets the property to be used in FromProp playback mode. + @type property: string + @ivar blendTime: Sets the internal frame timer. This property must be in + the range from 0.0 to blendin. + @type blendTime: float + @ivar type: The operation mode of the actuator. + KX_ACTIONACT_PLAY, KX_ACTIONACT_PROPERTY, KX_ACTIONACT_FLIPPER, + KX_ACTIONACT_LOOPSTOP, KX_ACTIONACT_LOOPEND + @type type: integer + @ivar frameProperty: The name of the property that is set to the current frame number. + @type frameProperty: string + """ def setAction(action, reset = True): """ + DEPRECATED: use the 'action' property Sets the current action. @param action: The name of the action to set as the current action. @@ -21,6 +49,7 @@ class BL_ShapeActionActuator(SCA_IActuator): def setStart(start): """ + DEPRECATED: use the 'start' property Specifies the starting frame of the animation. @param start: the starting frame of the animation @@ -29,6 +58,7 @@ class BL_ShapeActionActuator(SCA_IActuator): def setEnd(end): """ + DEPRECATED: use the 'end' property Specifies the ending frame of the animation. @param end: the ending frame of the animation @@ -36,6 +66,7 @@ class BL_ShapeActionActuator(SCA_IActuator): """ def setBlendin(blendin): """ + DEPRECATED: use the 'blendin' property Specifies the number of frames of animation to generate when making transitions between actions. @@ -45,6 +76,7 @@ class BL_ShapeActionActuator(SCA_IActuator): def setPriority(priority): """ + DEPRECATED: use the 'priority' property Sets the priority of this actuator. @param priority: Specifies the new priority. Actuators will lower @@ -54,6 +86,7 @@ class BL_ShapeActionActuator(SCA_IActuator): """ def setFrame(frame): """ + DEPRECATED: use the 'frame' property Sets the current frame for the animation. @param frame: Specifies the new current frame for the animation @@ -62,6 +95,7 @@ class BL_ShapeActionActuator(SCA_IActuator): def setProperty(prop): """ + DEPRECATED: use the 'property' property Sets the property to be used in FromProp playback mode. @param prop: the name of the property to use. @@ -70,6 +104,7 @@ class BL_ShapeActionActuator(SCA_IActuator): def setBlendtime(blendtime): """ + DEPRECATED: use the 'blendTime' property Sets the internal frame timer. Allows the script to directly modify the internal timer @@ -81,37 +116,25 @@ class BL_ShapeActionActuator(SCA_IActuator): def setType(mode): """ + DEPRECATED: use the 'type' property Sets the operation mode of the actuator @param mode: KX_ACTIONACT_PLAY, KX_ACTIONACT_PROPERTY, KX_ACTIONACT_FLIPPER, KX_ACTIONACT_LOOPSTOP, KX_ACTIONACT_LOOPEND @type mode: integer """ - def setContinue(cont): - """ - Set the actions continue option True or False. see getContinue. - - @param cont: The continue option. - @type cont: bool - """ - def getType(): """ + DEPRECATED: use the 'type' property Returns the operation mode of the actuator @rtype: integer @return: KX_ACTIONACT_PLAY, KX_ACTIONACT_PROPERTY, KX_ACTIONACT_FLIPPER, KX_ACTIONACT_LOOPSTOP, KX_ACTIONACT_LOOPEND """ - def getContinue(): - """ - When True, the action will always play from where last left off, otherwise negative events to this actuator will reset it to its start frame. - - @rtype: bool - """ - def getAction(): """ + DEPRECATED: use the 'action' property getAction() returns the name of the action associated with this actuator. @rtype: string @@ -119,24 +142,28 @@ class BL_ShapeActionActuator(SCA_IActuator): def getStart(): """ + DEPRECATED: use the 'start' property Returns the starting frame of the action. @rtype: float """ def getEnd(): """ + DEPRECATED: use the 'end' property Returns the last frame of the action. @rtype: float """ def getBlendin(): """ + DEPRECATED: use the 'blendin' property Returns the number of interpolation animation frames to be generated when this actuator is triggered. @rtype: float """ def getPriority(): """ + DEPRECATED: use the 'priority' property Returns the priority for this actuator. Actuators with lower Priority numbers will override actuators with higher numbers. @@ -144,23 +171,27 @@ class BL_ShapeActionActuator(SCA_IActuator): """ def getFrame(): """ + DEPRECATED: use the 'frame' property Returns the current frame number. @rtype: float """ def getProperty(): """ + DEPRECATED: use the 'property' property Returns the name of the property to be used in FromProp mode. @rtype: string """ def setFrameProperty(prop): """ + DEPRECATED: use the 'frameProperty' property @param prop: A string specifying the property of the object that will be updated with the action frame number. @type prop: string """ def getFrameProperty(): """ + DEPRECATED: use the 'frameProperty' property Returns the name of the property that is set to the current frame number. @rtype: string diff --git a/source/gameengine/PyDoc/KX_ActuatorSensor.py b/source/gameengine/PyDoc/KX_ActuatorSensor.py index cdfbf27576e..b0e138a8009 100644 --- a/source/gameengine/PyDoc/KX_ActuatorSensor.py +++ b/source/gameengine/PyDoc/KX_ActuatorSensor.py @@ -8,15 +8,22 @@ class KX_ActuatorSensor(SCA_ISensor): Actuator sensor detect change in actuator state of the parent object. It generates a positive pulse if the corresponding actuator is activated and a negative pulse if the actuator is deactivated. + + Properties: + + @ivar actuator: the name of the actuator that the sensor is monitoring. + @type actuator: string """ def getActuator(): """ + DEPRECATED: use the actuator property Return the Actuator with which the sensor operates. @rtype: string """ def setActuator(name): """ + DEPRECATED: use the actuator property Sets the Actuator with which to operate. If there is no Actuator of this name, the function has no effect. diff --git a/source/gameengine/PyDoc/KX_CameraActuator.py b/source/gameengine/PyDoc/KX_CameraActuator.py index 9a9abaf3d57..6ffc55a5854 100644 --- a/source/gameengine/PyDoc/KX_CameraActuator.py +++ b/source/gameengine/PyDoc/KX_CameraActuator.py @@ -6,6 +6,16 @@ class KX_CameraActuator(SCA_IActuator): """ Applies changes to a camera. + @ivar min: minimum distance to the target object maintained by the actuator + @type min: float + @ivar max: maximum distance to stay from the target object + @type max: float + @ivar height: height to stay above the target object + @type height: float + @ivar xy: axis this actuator is tracking, true=X, false=Y + @type xy: boolean + @ivar object: the object this actuator tracks. + @type object: KX_GameObject or None @author: snail """ def getObject(name_only = 1): diff --git a/source/gameengine/PyDoc/KX_GameObject.py b/source/gameengine/PyDoc/KX_GameObject.py index 505ce253dd1..efeffab2eed 100644 --- a/source/gameengine/PyDoc/KX_GameObject.py +++ b/source/gameengine/PyDoc/KX_GameObject.py @@ -123,6 +123,50 @@ class KX_GameObject: @return: The game object's rotation matrix @note: When using this matrix with Blender.Mathutils.Matrix() types, it will need to be transposed. """ + def applyMovement(movement, local = 0): + """ + Sets the game object's movement. + + @type movement: 3d vector. + @param movement: movement vector. + @type local: boolean + @param local: - False: you get the "global" movement ie: relative to world orientation (default). + - True: you get the "local" movement ie: relative to object orientation. + """ + def applyRotation(movement, local = 0): + """ + Sets the game object's rotation. + + @type rotation: 3d vector. + @param rotation: rotation vector. + @type local: boolean + @param local: - False: you get the "global" rotation ie: relative to world orientation (default). + - True: you get the "local" rotation ie: relative to object orientation. + """ + def applyForce(force, local = 0): + """ + Sets the game object's force. + + This requires a dynamic object. + + @type force: 3d vector. + @param force: force vector. + @type local: boolean + @param local: - False: you get the "global" force ie: relative to world orientation (default). + - True: you get the "local" force ie: relative to object orientation. + """ + def applyTorque(torque, local = 0): + """ + Sets the game object's torque. + + This requires a dynamic object. + + @type torque: 3d vector. + @param torque: torque vector. + @type local: boolean + @param local: - False: you get the "global" torque ie: relative to world orientation (default). + - True: you get the "local" torque ie: relative to object orientation. + """ def getLinearVelocity(local = 0): """ Gets the game object's linear velocity. @@ -143,6 +187,8 @@ class KX_GameObject: This method sets game object's velocity through it's centre of mass, ie no angular velocity component. + This requires a dynamic object. + @type velocity: 3d vector. @param velocity: linear velocity vector. @type local: boolean @@ -163,6 +209,8 @@ class KX_GameObject: """ Sets the game object's angular velocity. + This requires a dynamic object. + @type velocity: 3d vector. @param velocity: angular velocity vector. @type local: boolean diff --git a/source/gameengine/PyDoc/KX_ParentActuator.py b/source/gameengine/PyDoc/KX_ParentActuator.py index 6d6e0937257..7b5625ec82d 100644 --- a/source/gameengine/PyDoc/KX_ParentActuator.py +++ b/source/gameengine/PyDoc/KX_ParentActuator.py @@ -5,6 +5,9 @@ from SCA_IActuator import * class KX_ParentActuator(SCA_IActuator): """ The parent actuator can set or remove an objects parent object. + + @ivar object: the object this actuator sets the parent too. + @type object: KX_GameObject or None """ def setObject(object): """ diff --git a/source/gameengine/PyDoc/KX_SCA_AddObjectActuator.py b/source/gameengine/PyDoc/KX_SCA_AddObjectActuator.py index c3b2e947ddb..56068fa641a 100644 --- a/source/gameengine/PyDoc/KX_SCA_AddObjectActuator.py +++ b/source/gameengine/PyDoc/KX_SCA_AddObjectActuator.py @@ -5,6 +5,10 @@ from SCA_IActuator import * class KX_SCA_AddObjectActuator(SCA_IActuator): """ Edit Object Actuator (in Add Object Mode) + @ivar object: the object this actuator adds. + @type object: KX_GameObject or None + @ivar objectLastCreated: the last added object from this actuator (read only). + @type objectLastCreated: KX_GameObject or None @warning: An Add Object actuator will be ignored if at game start, the linked object doesn't exist (or is empty) or the linked object is in an active layer. diff --git a/source/gameengine/PyDoc/KX_TrackToActuator.py b/source/gameengine/PyDoc/KX_TrackToActuator.py index 948302991b7..730ab21166b 100644 --- a/source/gameengine/PyDoc/KX_TrackToActuator.py +++ b/source/gameengine/PyDoc/KX_TrackToActuator.py @@ -13,6 +13,8 @@ class KX_TrackToActuator(SCA_IActuator): C{ERROR: GameObject I{OBName} no object in EditObjectActuator I{ActuatorName}} + @ivar object: the object this actuator tracks. + @type object: KX_GameObject or None """ def setObject(object): """ diff --git a/source/gameengine/PyDoc/SCA_DelaySensor.py b/source/gameengine/PyDoc/SCA_DelaySensor.py index 19df589ea7b..b99ed08bed5 100644 --- a/source/gameengine/PyDoc/SCA_DelaySensor.py +++ b/source/gameengine/PyDoc/SCA_DelaySensor.py @@ -13,9 +13,21 @@ class SCA_DelaySensor(SCA_ISensor): The sensor runs the OFF-ON cycle once unless the repeat option is set: the OFF-ON cycle repeats indefinately (or the OFF cycle if duration is 0). Use SCA_ISensor::reset() at any time to restart sensor. + + Properties: + + @ivar delay: length of the initial OFF period as number of frame, 0 for immediate trigger. + @type delay: integer. + @ivar duration: length of the ON period in number of frame after the initial OFF period. + If duration is greater than 0, a negative trigger is sent at the end of the ON pulse. + @type duration: integer + @ivar repeat: 1 if the OFF-ON cycle should be repeated indefinately, 0 if it should run once. + @type repeat: integer + """ def setDelay(delay): """ + DEPRECATED: use the delay property Set the initial delay before the positive trigger. @param delay: length of the initial OFF period as number of frame, 0 for immediate trigger @@ -23,6 +35,7 @@ class SCA_DelaySensor(SCA_ISensor): """ def setDuration(duration): """ + DEPRECATED: use the duration property Set the duration of the ON pulse after initial delay and the generation of the positive trigger. If duration is greater than 0, a negative trigger is sent at the end of the ON pulse. @@ -31,6 +44,7 @@ class SCA_DelaySensor(SCA_ISensor): """ def setRepeat(repeat): """ + DEPRECATED: use the repeat property Set if the sensor repeat mode. @param repeat: 1 if the OFF-ON cycle should be repeated indefinately, 0 if it should run once. @@ -38,18 +52,21 @@ class SCA_DelaySensor(SCA_ISensor): """ def getDelay(): """ + DEPRECATED: use the delay property Return the delay parameter value. @rtype: integer """ def getDuration(): """ + DEPRECATED: use the duration property Return the duration parameter value @rtype: integer """ def getRepeat(): """ + DEPRECATED: use the repeat property Return the repeat parameter value @rtype: KX_TRUE or KX_FALSE diff --git a/source/gameengine/PyDoc/SCA_ILogicBrick.py b/source/gameengine/PyDoc/SCA_ILogicBrick.py index ea09fcaea37..18cb900f28d 100644 --- a/source/gameengine/PyDoc/SCA_ILogicBrick.py +++ b/source/gameengine/PyDoc/SCA_ILogicBrick.py @@ -5,6 +5,9 @@ from KX_GameObject import * class SCA_ILogicBrick: """ Base class for all logic bricks. + + @ivar executePriority: This determines the order controllers are evaluated, and actuators are activated (lower priority is executed first). + @type executePriority: int """ def getOwner(): @@ -13,6 +16,8 @@ class SCA_ILogicBrick: @rtype: L{KX_GameObject} """ + + #--The following methods are deprecated-- def setExecutePriority(priority): """ Sets the priority of this logic brick. @@ -20,6 +25,8 @@ class SCA_ILogicBrick: This determines the order controllers are evaluated, and actuators are activated. Bricks with lower priority will be executed first. + Deprecated: Use the "executePriority" property instead. + @type priority: integer @param priority: the priority of this logic brick. """ @@ -27,6 +34,8 @@ class SCA_ILogicBrick: """ Gets the execution priority of this logic brick. + Deprecated: Use the "executePriority" property instead. + @rtype: integer @return: this logic bricks current priority. """ diff --git a/source/gameengine/PyDoc/SCA_ISensor.py b/source/gameengine/PyDoc/SCA_ISensor.py index 14858505e24..ab35996aa50 100644 --- a/source/gameengine/PyDoc/SCA_ISensor.py +++ b/source/gameengine/PyDoc/SCA_ISensor.py @@ -5,8 +5,35 @@ from SCA_ILogicBrick import * class SCA_ISensor(SCA_ILogicBrick): """ Base class for all sensor logic bricks. + + @ivar usePosPulseMode: Flag to turn positive pulse mode on and off. + @type usePosPulseMode: boolean + @ivar useNegPulseMode: Flag to turn negative pulse mode on and off. + @type useNegPulseMode: boolean + @ivar frequency: The frequency for pulse mode sensors. + @type frequency: int + @ivar level: Flag to set whether to detect level or edge transition when entering a state. + It makes a difference only in case of logic state transition (state actuator). + A level detector will immediately generate a pulse, negative or positive + depending on the sensor condition, as soon as the state is activated. + A edge detector will wait for a state change before generating a pulse. + @type level: boolean + @ivar invert: Flag to set if this sensor activates on positive or negative events. + @type invert: boolean + @ivar triggered: True if this sensor brick is in a positive state. (Read only) + @type triggered: boolean + @ivar positive: True if this sensor brick is in a positive state. (Read only) + @type positive: boolean """ + def reset(): + """ + Reset sensor internal state, effect depends on the type of sensor and settings. + + The sensor is put in its initial state as if it was just activated. + """ + + #--The following methods are deprecated-- def isPositive(): """ True if this sensor brick is in a positive state. @@ -82,10 +109,3 @@ class SCA_ISensor(SCA_ILogicBrick): @param level: Detect level instead of edge? (KX_TRUE, KX_FALSE) @type level: boolean """ - def reset(): - """ - Reset sensor internal state, effect depends on the type of sensor and settings. - - The sensor is put in its initial state as if it was just activated. - """ - diff --git a/source/gameengine/PyDoc/SCA_JoystickSensor.py b/source/gameengine/PyDoc/SCA_JoystickSensor.py index d1dab9afcaf..111ee7f4cfa 100644 --- a/source/gameengine/PyDoc/SCA_JoystickSensor.py +++ b/source/gameengine/PyDoc/SCA_JoystickSensor.py @@ -5,15 +5,58 @@ from SCA_ISensor import * class SCA_JoystickSensor(SCA_ISensor): """ This sensor detects player joystick events. + + Properties: + + @ivar axisPosition: (read-only) The state of the joysticks axis as a list of 4 values, each spesifying the value of an axis between -32767 and 32767 depending on how far the axis is pushed, 0 for nothing. + The first 2 values are used by most joysticks and gamepads for directional control. 3rd and 4th values are only on some joysticks and can be used for arbitary controls. + left:[-32767, 0, ...], right:[32767, 0, ...], up:[0, -32767, ...], down:[0, 32767, ...] + @type axisPosition: [integer, integer, integer, integer] + @ivar numAxis: (read-only) The number of axes for the joystick at this index. + @type numAxis: integer + @ivar numButtons: (read-only) The number of buttons for the joystick at this index. + @type numButtons: integer + @ivar numHats: (read-only) The number of hats for the joystick at this index. + @type numHats: integer + @ivar connected: (read-only) True if a joystick is connected at this joysticks index. + @type connected: boolean + @ivar index: The joystick index to use (from 0 to 7). The first joystick is always 0. + @type index: integer + @ivar threshold: Axis threshold. Joystick axis motion below this threshold wont trigger an event. Use values between (0 and 32767), lower values are more sensitive. + @type threshold: integer + @ivar button: The button index the sensor reacts to (first button = 0). When the "All Events" toggle is set, this option has no effect. + @type button: integer + @ivar axis: The axis this sensor reacts to, as a list of two values [axisIndex, axisDirection] + axisIndex: the axis index to use when detecting axis movement, 1=primary directional control, 2=secondary directional control. + axisDirection: 0=right, 1=up, 2=left, 3=down + @type axis: [integer, integer] + @ivar hat: The hat the sensor reacts to, as a list of two values: [hatIndex, hatDirection] + hatIndex: the hat index to use when detecting hat movement, 1=primary hat, 2=secondary hat. + hatDirection: 0-11 + @type hat: [integer, integer] """ + def getButtonActiveList(): + """ + Returns a list containing the indicies of the currently pressed buttons. + @rtype: list + """ + def getButtonStatus(buttonIndex): + """ + Returns a bool of the current pressed state of the specified button. + @param buttonIndex: the button index, 0=first button + @type buttonIndex: integer + @rtype: bool + """ def getIndex(): """ + DEPRECATED: use the 'index' property. Returns the joystick index to use (from 1 to 8). @rtype: integer """ def setIndex(index): """ + DEPRECATED: use the 'index' property. Sets the joystick index to use. @param index: The index of this joystick sensor, Clamped between 1 and 8. @type index: integer @@ -21,6 +64,7 @@ class SCA_JoystickSensor(SCA_ISensor): """ def getAxis(): """ + DEPRECATED: use the 'axis' property. Returns the current axis this sensor reacts to. See L{getAxisValue()<SCA_JoystickSensor.getAxisValue>} for the current axis state. @rtype: list @return: 2 values returned are [axisIndex, axisDirection] - see L{setAxis()<SCA_JoystickSensor.setAxis>} for their purpose. @@ -28,6 +72,7 @@ class SCA_JoystickSensor(SCA_ISensor): """ def setAxis(axisIndex, axisDirection): """ + DEPRECATED: use the 'axis' property. @param axisIndex: Set the axis index to use when detecting axis movement. @type axisIndex: integer from 1 to 2 @param axisDirection: Set the axis direction used for detecting motion. 0:right, 1:up, 2:left, 3:down. @@ -36,6 +81,7 @@ class SCA_JoystickSensor(SCA_ISensor): """ def getAxisValue(): """ + DEPRECATED: use the 'axisPosition' property. Returns the state of the joysticks axis. See differs to L{getAxis()<SCA_JoystickSensor.getAxis>} returning the current state of the joystick. @rtype: list @return: 4 values, each spesifying the value of an axis between -32767 and 32767 depending on how far the axis is pushed, 0 for nothing. @@ -47,60 +93,71 @@ class SCA_JoystickSensor(SCA_ISensor): """ def getThreshold(): """ + DEPRECATED: use the 'threshold' property. Get the axis threshold. See L{setThreshold()<SCA_JoystickSensor.setThreshold>} for details. @rtype: integer """ def setThreshold(threshold): """ + DEPRECATED: use the 'threshold' property. Set the axis threshold. @param threshold: Joystick axis motion below this threshold wont trigger an event. Use values between (0 and 32767), lower values are more sensitive. @type threshold: integer """ def getButton(): """ + DEPRECATED: use the 'button' property. Returns the button index the sensor reacts to. See L{getButtonValue()<SCA_JoystickSensor.getButtonValue>} for a list of pressed buttons. @rtype: integer @note: When the "All Events" toggle is set, this option has no effect. """ def setButton(index): """ + DEPRECATED: use the 'button' property. Sets the button index the sensor reacts to when the "All Events" option is not set. @note: When the "All Events" toggle is set, this option has no effect. """ def getButtonValue(): """ + DEPRECATED: use the 'getButtonActiveList' method. Returns a list containing the indicies of the currently pressed buttons. @rtype: list """ def getHat(): """ + DEPRECATED: use the 'hat' property. Returns the current hat direction this sensor is set to. [hatNumber, hatDirection]. @rtype: list @note: When the "All Events" toggle is set, this option has no effect. """ - def setHat(index): + def setHat(index,direction): """ + DEPRECATED: use the 'hat' property. Sets the hat index the sensor reacts to when the "All Events" option is not set. @type index: integer """ def getNumAxes(): """ + DEPRECATED: use the 'numAxis' property. Returns the number of axes for the joystick at this index. @rtype: integer """ def getNumButtons(): """ + DEPRECATED: use the 'numButtons' property. Returns the number of buttons for the joystick at this index. @rtype: integer """ def getNumHats(): """ + DEPRECATED: use the 'numHats' property. Returns the number of hats for the joystick at this index. @rtype: integer """ def isConnected(): """ + DEPRECATED: use the 'connected' property. Returns True if a joystick is detected at this joysticks index. @rtype: bool """ diff --git a/source/gameengine/PyDoc/SCA_KeyboardSensor.py b/source/gameengine/PyDoc/SCA_KeyboardSensor.py index 2f741f7d6a2..f6a7a7d8a97 100644 --- a/source/gameengine/PyDoc/SCA_KeyboardSensor.py +++ b/source/gameengine/PyDoc/SCA_KeyboardSensor.py @@ -7,44 +7,99 @@ class SCA_KeyboardSensor(SCA_ISensor): A keyboard sensor detects player key presses. See module L{GameKeys} for keycode values. + + @ivar key: The key code this sensor is looking for. + @type key: keycode from L{GameKeys} module + @ivar hold1: The key code for the first modifier this sensor is looking for. + @type hold1: keycode from L{GameKeys} module + @ivar hold2: The key code for the second modifier this sensor is looking for. + @type hold2: keycode from L{GameKeys} module + @ivar toggleProperty: The name of the property that indicates whether or not to log keystrokes as a string. + @type toggleProperty: string + @ivar targetProperty: The name of the property that receives keystrokes in case in case a string is logged. + @type targetProperty: string + @ivar useAllKeys: Flag to determine whether or not to accept all keys. + @type useAllKeys: boolean """ + def getEventList(): + """ + Get a list of pressed keys that have either been pressed, or just released, or are active this frame. + + @rtype: list of key status. [[keycode, status]] + @return: A list of keyboard events + """ + + def getKeyStatus(keycode): + """ + Get the status of a key. + + @rtype: key state (KX_NO_INPUTSTATUS, KX_JUSTACTIVATED, KX_ACTIVE or KX_JUSTRELEASED) + @return: The state of the given key + @type keycode: integer + @param keycode: The code that represents the key you want to get the state of + """ + #--The following methods are deprecated-- def getKey(): """ Returns the key code this sensor is looking for. + + Deprecated: Use the "key" property instead. + + @rtype: keycode from L{GameKeys} module """ def setKey(keycode): """ Set the key this sensor should listen for. + Deprecated: Use the "key" property instead. + @type keycode: keycode from L{GameKeys} module """ def getHold1(): """ Returns the key code for the first modifier this sensor is looking for. + + Deprecated: Use the "hold1" property instead. + + @rtype: keycode from L{GameKeys} module """ - def setHold1(): + def setHold1(keycode): """ Sets the key code for the first modifier this sensor should look for. + + Deprecated: Use the "hold1" property instead. + + @type keycode: keycode from L{GameKeys} module """ def getHold2(): """ Returns the key code for the second modifier this sensor is looking for. + + Deprecated: Use the "hold2" property instead. + + @rtype: keycode from L{GameKeys} module """ - def setHold2(): + def setHold2(keycode): """ Sets the key code for the second modifier this sensor should look for. + + Deprecated: Use the "hold2" property instead. + + @type keycode: keycode from L{GameKeys} module """ def getPressedKeys(): """ Get a list of keys that have either been pressed, or just released this frame. + Deprecated: Use getEventList() instead. + @rtype: list of key status. [[keycode, status]] """ @@ -52,7 +107,7 @@ class SCA_KeyboardSensor(SCA_ISensor): """ Get a list of currently pressed keys that have either been pressed, or just released + Deprecated: Use getEventList() instead. + @rtype: list of key status. [[keycode, status]] - """ - - + """
\ No newline at end of file diff --git a/source/gameengine/PyDoc/SCA_MouseSensor.py b/source/gameengine/PyDoc/SCA_MouseSensor.py index 06b261f67fa..9550cbb4105 100644 --- a/source/gameengine/PyDoc/SCA_MouseSensor.py +++ b/source/gameengine/PyDoc/SCA_MouseSensor.py @@ -5,10 +5,20 @@ from SCA_ISensor import * class SCA_MouseSensor(SCA_ISensor): """ Mouse Sensor logic brick. + + Properties: + + @ivar position: current [x,y] coordinates of the mouse, in frame coordinates (pixels) + @type position: [integer,interger] + @ivar mode: sensor mode: 1=KX_MOUSESENSORMODE_LEFTBUTTON 2=KX_MOUSESENSORMODE_MIDDLEBUTTON + 3=KX_MOUSESENSORMODE_RIGHTBUTTON 4=KX_MOUSESENSORMODE_WHEELUP + 5=KX_MOUSESENSORMODE_WHEELDOWN 9=KX_MOUSESENSORMODE_MOVEMENT + @type mode: integer """ def getXPosition(): """ + DEPRECATED: use the position property Gets the x coordinate of the mouse. @rtype: integer @@ -16,6 +26,7 @@ class SCA_MouseSensor(SCA_ISensor): """ def getYPosition(): """ + DEPRECATED: use the position property Gets the y coordinate of the mouse. @rtype: integer diff --git a/source/gameengine/PyDoc/SCA_PropertyActuator.py b/source/gameengine/PyDoc/SCA_PropertyActuator.py index dc1233ddfb7..52aefcae651 100644 --- a/source/gameengine/PyDoc/SCA_PropertyActuator.py +++ b/source/gameengine/PyDoc/SCA_PropertyActuator.py @@ -5,9 +5,17 @@ from SCA_IActuator import * class SCA_PropertyActuator(SCA_IActuator): """ Property Actuator + + Properties: + + @ivar property: the property on which to operate. + @type property: string + @ivar value: the value with which the actuator operates. + @type value: string """ def setProperty(prop): """ + DEPRECATED: use the 'property' property Set the property on which to operate. If there is no property of this name, the call is ignored. @@ -17,12 +25,14 @@ class SCA_PropertyActuator(SCA_IActuator): """ def getProperty(): """ + DEPRECATED: use the 'property' property Returns the name of the property on which to operate. @rtype: string """ def setValue(value): """ + DEPRECATED: use the 'value' property Set the value with which the actuator operates. If the value is not compatible with the type of the @@ -32,6 +42,7 @@ class SCA_PropertyActuator(SCA_IActuator): """ def getValue(): """ + DEPRECATED: use the 'value' property Gets the value with which this actuator operates. @rtype: string diff --git a/source/gameengine/PyDoc/SCA_PropertySensor.py b/source/gameengine/PyDoc/SCA_PropertySensor.py index 22de8d8b986..949ffd3b703 100644 --- a/source/gameengine/PyDoc/SCA_PropertySensor.py +++ b/source/gameengine/PyDoc/SCA_PropertySensor.py @@ -5,10 +5,22 @@ from SCA_ISensor import * class SCA_PropertySensor(SCA_ISensor): """ Activates when the game object property matches. + + Properties: + + @ivar type: type of check on the property: + KX_PROPSENSOR_EQUAL(1), KX_PROPSENSOR_NOTEQUAL(2), KX_PROPSENSOR_INTERVAL(3), + KX_PROPSENSOR_CHANGED(4), KX_PROPSENSOR_EXPRESSION(5) + @type type: integer + @ivar property: the property with which the sensor operates. + @type property: string + @ivar value: the value with which the sensor compares to the value of the property. + @type value: string """ def getType(): """ + DEPRECATED: use the type property Gets when to activate this sensor. @return: KX_PROPSENSOR_EQUAL, KX_PROPSENSOR_NOTEQUAL, @@ -18,6 +30,7 @@ class SCA_PropertySensor(SCA_ISensor): def setType(checktype): """ + DEPRECATED: use the type property Set the type of check to perform. @type checktype: KX_PROPSENSOR_EQUAL, KX_PROPSENSOR_NOTEQUAL, @@ -27,6 +40,7 @@ class SCA_PropertySensor(SCA_ISensor): def getProperty(): """ + DEPRECATED: use the property property Return the property with which the sensor operates. @rtype: string @@ -34,6 +48,7 @@ class SCA_PropertySensor(SCA_ISensor): """ def setProperty(name): """ + DEPRECATED: use the property property Sets the property with which to operate. If there is no property of that name, this call is ignored. @@ -41,6 +56,7 @@ class SCA_PropertySensor(SCA_ISensor): """ def getValue(): """ + DEPRECATED: use the value property Return the value with which the sensor compares to the value of the property. @rtype: string @@ -48,6 +64,7 @@ class SCA_PropertySensor(SCA_ISensor): """ def setValue(value): """ + DEPRECATED: use the value property Set the value with which the sensor operates. If the value is not compatible with the type of the property, the subsequent action is ignored. diff --git a/source/gameengine/PyDoc/SCA_PythonController.py b/source/gameengine/PyDoc/SCA_PythonController.py index 6d91736d636..06f2b7e9d1d 100644 --- a/source/gameengine/PyDoc/SCA_PythonController.py +++ b/source/gameengine/PyDoc/SCA_PythonController.py @@ -6,6 +6,14 @@ class SCA_PythonController(SCA_IController): """ A Python controller uses a Python script to activate it's actuators, based on it's sensors. + + Properties: + + @ivar script: the Python script this controller executes + @type script: string, read-only + @ivar state: the controllers state bitmask. + This can be used with the GameObject's state to test if the controller is active. + @type state: integer """ def getSensors(): @@ -36,6 +44,7 @@ class SCA_PythonController(SCA_IController): """ def getScript(): """ + DEPRECATED: use the script property Gets the Python script this controller executes. @rtype: string @@ -48,6 +57,7 @@ class SCA_PythonController(SCA_IController): """ def getState(): """ + DEPRECATED: use the state property Get the controllers state bitmask, this can be used with the GameObject's state to test if the the controller is active. This for instance will always be true however you could compare with a previous state to see when the state was activated. GameLogic.getCurrentController().getState() & GameLogic.getCurrentController().getOwner().getState() diff --git a/source/gameengine/PyDoc/SCA_RandomActuator.py b/source/gameengine/PyDoc/SCA_RandomActuator.py index 353b398b1ff..000a1af7846 100644 --- a/source/gameengine/PyDoc/SCA_RandomActuator.py +++ b/source/gameengine/PyDoc/SCA_RandomActuator.py @@ -5,9 +5,35 @@ from SCA_IActuator import * class SCA_RandomActuator(SCA_IActuator): """ Random Actuator + + Properties: + + @ivar seed: Seed of the random number generator. + Equal seeds produce equal series. If the seed is 0, + the generator will produce the same value on every call. + @type seed: integer + @ivar para1: the first parameter of the active distribution. + Refer to the documentation of the generator types for the meaning + of this value. + @type para1: float, read-only + @ivar para2: the second parameter of the active distribution. + Refer to the documentation of the generator types for the meaning + of this value. + @type para2: float, read-only + @ivar distribution: distribution type: + KX_RANDOMACT_BOOL_CONST, KX_RANDOMACT_BOOL_UNIFORM, KX_RANDOMACT_BOOL_BERNOUILLI, + KX_RANDOMACT_INT_CONST, KX_RANDOMACT_INT_UNIFORM, KX_RANDOMACT_INT_POISSON, + KX_RANDOMACT_FLOAT_CONST, KX_RANDOMACT_FLOAT_UNIFORM, KX_RANDOMACT_FLOAT_NORMAL, + KX_RANDOMACT_FLOAT_NEGATIVE_EXPONENTIAL + @type distribution: integer, read-only + @ivar property: the name of the property to set with the random value. + If the generator and property types do not match, the assignment is ignored. + @type property: string + """ def setSeed(seed): """ + DEPRECATED: use the seed property Sets the seed of the random number generator. Equal seeds produce equal series. If the seed is 0, @@ -17,12 +43,14 @@ class SCA_RandomActuator(SCA_IActuator): """ def getSeed(): """ + DEPRECATED: use the seed property Returns the initial seed of the generator. @rtype: integer """ def getPara1(): """ + DEPRECATED: use the para1 property Returns the first parameter of the active distribution. Refer to the documentation of the generator types for the meaning @@ -32,6 +60,7 @@ class SCA_RandomActuator(SCA_IActuator): """ def getPara2(): """ + DEPRECATED: use the para2 property Returns the second parameter of the active distribution. Refer to the documentation of the generator types for the meaning @@ -41,6 +70,7 @@ class SCA_RandomActuator(SCA_IActuator): """ def getDistribution(): """ + DEPRECATED: use the distribution property Returns the type of random distribution. @rtype: distribution type @@ -51,6 +81,7 @@ class SCA_RandomActuator(SCA_IActuator): """ def setProperty(property): """ + DEPRECATED: use the property property Set the property to which the random value is assigned. If the generator and property types do not match, the assignment is ignored. @@ -60,6 +91,7 @@ class SCA_RandomActuator(SCA_IActuator): """ def getProperty(): """ + DEPRECATED: use the property property Returns the name of the property to set. @rtype: string diff --git a/source/gameengine/Rasterizer/RAS_FramingManager.h b/source/gameengine/Rasterizer/RAS_FramingManager.h index 9cb59f300f7..610bd13ff12 100644 --- a/source/gameengine/Rasterizer/RAS_FramingManager.h +++ b/source/gameengine/Rasterizer/RAS_FramingManager.h @@ -212,9 +212,6 @@ public : RAS_FrameFrustum &frustum ); - -private : - static void ComputeDefaultFrustum( @@ -225,6 +222,8 @@ private : RAS_FrameFrustum & frustum ); +private : + static void ComputeBestFitViewRect( diff --git a/source/gameengine/Rasterizer/RAS_IRasterizer.h b/source/gameengine/Rasterizer/RAS_IRasterizer.h index 411b28fa3b7..d529ca8973a 100644 --- a/source/gameengine/Rasterizer/RAS_IRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_IRasterizer.h @@ -200,6 +200,7 @@ public: * @return true if stereo mode is enabled. */ virtual bool Stereo()=0; + virtual StereoMode GetStereoMode()=0; virtual bool InterlacedStereo()=0; /** * Sets which eye buffer subsequent primitives will be rendered to. @@ -254,6 +255,8 @@ public: /** */ virtual const MT_Point3& GetCameraPosition()=0; + virtual bool GetCameraOrtho()=0; + /** */ virtual void SetFog(float start, diff --git a/source/gameengine/Rasterizer/RAS_IRenderTools.h b/source/gameengine/Rasterizer/RAS_IRenderTools.h index 57f331e64cb..a289ffed492 100644 --- a/source/gameengine/Rasterizer/RAS_IRenderTools.h +++ b/source/gameengine/Rasterizer/RAS_IRenderTools.h @@ -134,6 +134,7 @@ public: virtual void ProcessLighting( + RAS_IRasterizer *rasty, int layer, const MT_Transform& trans )=0; diff --git a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp index ad8d7ebd5b0..d8631c1edf6 100644 --- a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp +++ b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp @@ -517,9 +517,9 @@ bool RAS_MaterialBucket::ActivateMaterial(const MT_Transform& cameratrans, RAS_I return false; if (m_material->UsesLighting(rasty)) - rendertools->ProcessLighting(RAS_IRenderTools::RAS_LIGHT_OBJECT_LAYER, cameratrans); + rendertools->ProcessLighting(rasty, RAS_IRenderTools::RAS_LIGHT_OBJECT_LAYER, cameratrans); else - rendertools->ProcessLighting(-1, cameratrans); + rendertools->ProcessLighting(rasty, -1, cameratrans); return true; } diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp index 87a0a1d8b9e..08c600e7682 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp @@ -59,6 +59,8 @@ RAS_OpenGLRasterizer::RAS_OpenGLRasterizer(RAS_ICanvas* canvas) m_2DCanvas(canvas), m_fogenabled(false), m_time(0.0), + m_campos(0.0f, 0.0f, 0.0f), + m_camortho(false), m_stereomode(RAS_STEREO_NOSTEREO), m_curreye(RAS_STEREO_LEFTEYE), m_eyeseparation(0.0), @@ -406,14 +408,16 @@ void RAS_OpenGLRasterizer::SetRenderArea() break; } } - void RAS_OpenGLRasterizer::SetStereoMode(const StereoMode stereomode) { m_stereomode = stereomode; } - +RAS_IRasterizer::StereoMode RAS_OpenGLRasterizer::GetStereoMode() +{ + return m_stereomode; +} bool RAS_OpenGLRasterizer::Stereo() { @@ -754,8 +758,9 @@ void RAS_OpenGLRasterizer::SetProjectionMatrix(MT_CmMatrix4x4 &mat) glMatrixMode(GL_PROJECTION); double* matrix = &mat(0,0); glLoadMatrixd(matrix); -} + m_camortho= (mat(3, 3) != 0.0f); +} void RAS_OpenGLRasterizer::SetProjectionMatrix(const MT_Matrix4x4 & mat) { @@ -765,6 +770,8 @@ void RAS_OpenGLRasterizer::SetProjectionMatrix(const MT_Matrix4x4 & mat) mat.getValue(matrix); /* Internally, MT_Matrix4x4 uses doubles (MT_Scalar). */ glLoadMatrixd(matrix); + + m_camortho= (mat[3][3] != 0.0f); } MT_Matrix4x4 RAS_OpenGLRasterizer::GetFrustumMatrix( @@ -775,7 +782,7 @@ MT_Matrix4x4 RAS_OpenGLRasterizer::GetFrustumMatrix( float frustnear, float frustfar, float focallength, - bool + bool ){ MT_Matrix4x4 result; double mat[16]; @@ -881,6 +888,10 @@ const MT_Point3& RAS_OpenGLRasterizer::GetCameraPosition() return m_campos; } +bool RAS_OpenGLRasterizer::GetCameraOrtho() +{ + return m_camortho; +} void RAS_OpenGLRasterizer::SetCullFace(bool enable) { diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h index 0717cce0ce8..c72d4880437 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h @@ -80,6 +80,7 @@ class RAS_OpenGLRasterizer : public RAS_IRasterizer MT_Matrix4x4 m_viewmatrix; MT_Matrix4x4 m_viewinvmatrix; MT_Point3 m_campos; + bool m_camortho; StereoMode m_stereomode; StereoEye m_curreye; @@ -137,6 +138,7 @@ public: virtual void SetRenderArea(); virtual void SetStereoMode(const StereoMode stereomode); + virtual RAS_IRasterizer::StereoMode GetStereoMode(); virtual bool Stereo(); virtual bool InterlacedStereo(); virtual void SetEye(const StereoEye eye); @@ -167,6 +169,7 @@ public: ); virtual const MT_Point3& GetCameraPosition(); + virtual bool GetCameraOrtho(); virtual void SetFog( float start, diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript index 8d46528f7f0..6731da9a776 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript @@ -6,4 +6,9 @@ sources = env.Glob('*.cpp') incs = '. #source/kernel/gen_system #intern/string #intern/moto/include #source/gameengine/Rasterizer #source/gameengine/BlenderRoutines ' incs += ' #source/blender/gpu #extern/glew/include ' + env['BF_OPENGL_INC'] -env.BlenderLib ( 'bf_oglrasterizer', Split(sources), Split(incs), [], libtype=['game','player'], priority=[40, 120] ) +cxxflags = [] +if env['OURPLATFORM']=='win32-vc': + cxxflags.append ('/GR') + cxxflags.append ('/O2') + +env.BlenderLib ( 'bf_oglrasterizer', Split(sources), Split(incs), [], libtype=['game','player'], priority=[40, 120], cxx_compileflags = cxxflags ) diff --git a/source/gameengine/Rasterizer/SConscript b/source/gameengine/Rasterizer/SConscript index a024f7e0ee6..a16a04b8514 100644 --- a/source/gameengine/Rasterizer/SConscript +++ b/source/gameengine/Rasterizer/SConscript @@ -7,9 +7,9 @@ sources = env.Glob('*.cpp') incs = '. #source/kernel/gen_system #intern/string #intern/moto/include #source/gameengine/BlenderRoutines #extern/glew/include #source/gameengine/Expressions #source/blender/blenkernel #source/blender/makesdna' incs += ' ' + env['BF_PYTHON_INC'] +cxxflags = [] if env['OURPLATFORM']=='win32-vc': - cflags = [] - cflags.append('/Ox') - env.BlenderLib ( 'bf_rasterizer', sources, Split(incs), [], libtype=['game','player'], priority=[35,115], compileflags = cflags ) -else: - env.BlenderLib ( 'bf_rasterizer', sources, Split(incs), [], libtype=['game','player'], priority=[35,115] ) + cxxflags.append ('/GR') + cxxflags.append ('/O2') + +env.BlenderLib ( 'bf_rasterizer', sources, Split(incs), [], libtype=['game','player'], priority=[35,115], cxx_compileflags = cxxflags ) diff --git a/source/gameengine/SceneGraph/SConscript b/source/gameengine/SceneGraph/SConscript index 23c1c24c297..8ebf9c0b850 100644 --- a/source/gameengine/SceneGraph/SConscript +++ b/source/gameengine/SceneGraph/SConscript @@ -6,4 +6,9 @@ sources = env.Glob('*.cpp') #'SG_BBox.cpp SG_Controller.cpp SG_IObject.cpp SG_No incs = '. #intern/moto/include' -env.BlenderLib ( 'bf_scenegraph', sources, Split(incs), [], libtype=['game','player'], priority=[50,130] ) +cxxflags = [] +if env['OURPLATFORM']=='win32-vc': + cxxflags.append ('/GR') + cxxflags.append ('/O2') + +env.BlenderLib ( 'bf_scenegraph', sources, Split(incs), [], libtype=['game','player'], priority=[50,130], cxx_compileflags = cxxflags ) diff --git a/source/gameengine/VideoTexture/Exception.cpp b/source/gameengine/VideoTexture/Exception.cpp index 3f939de6bc2..8704d49f2a7 100644 --- a/source/gameengine/VideoTexture/Exception.cpp +++ b/source/gameengine/VideoTexture/Exception.cpp @@ -204,6 +204,12 @@ void registerAllExceptions(void) ImageSizesNotMatchDesc.registerDesc(); SceneInvalidDesc.registerDesc(); CameraInvalidDesc.registerDesc(); + ObserverInvalidDesc.registerDesc(); + MirrorInvalidDesc.registerDesc(); + MirrorSizeInvalidDesc.registerDesc(); + MirrorNormalInvalidDesc.registerDesc(); + MirrorHorizontalDesc.registerDesc(); + MirrorTooSmallDesc.registerDesc(); SourceVideoEmptyDesc.registerDesc(); SourceVideoCreationDesc.registerDesc(); } diff --git a/source/gameengine/VideoTexture/Exception.h b/source/gameengine/VideoTexture/Exception.h index 5345e87f199..1a3c25071b1 100644 --- a/source/gameengine/VideoTexture/Exception.h +++ b/source/gameengine/VideoTexture/Exception.h @@ -202,6 +202,12 @@ extern ExpDesc MaterialNotAvailDesc; extern ExpDesc ImageSizesNotMatchDesc; extern ExpDesc SceneInvalidDesc; extern ExpDesc CameraInvalidDesc; +extern ExpDesc ObserverInvalidDesc; +extern ExpDesc MirrorInvalidDesc; +extern ExpDesc MirrorSizeInvalidDesc; +extern ExpDesc MirrorNormalInvalidDesc; +extern ExpDesc MirrorHorizontalDesc; +extern ExpDesc MirrorTooSmallDesc; extern ExpDesc SourceVideoEmptyDesc; extern ExpDesc SourceVideoCreationDesc; diff --git a/source/gameengine/VideoTexture/ImageRender.cpp b/source/gameengine/VideoTexture/ImageRender.cpp index a8f7871fa21..58697ed3cc7 100644 --- a/source/gameengine/VideoTexture/ImageRender.cpp +++ b/source/gameengine/VideoTexture/ImageRender.cpp @@ -24,96 +24,238 @@ http://www.gnu.org/copyleft/lesser.txt. #include <PyObjectPlus.h> #include <structmember.h> +#include <float.h> +#include <math.h> -#include <KX_BlenderCanvas.h> -#include <KX_BlenderRenderTools.h> -#include <RAS_IRasterizer.h> -#include <RAS_OpenGLRasterizer.h> -#include <KX_WorldInfo.h> -#include <KX_Light.h> -#include "ImageRender.h" +#include <BIF_gl.h> + +#include "KX_PythonInit.h" +#include "DNA_scene_types.h" +#include "RAS_CameraData.h" +#include "RAS_MeshObject.h" +#include "BLI_arithb.h" +#include "ImageRender.h" #include "ImageBase.h" #include "BlendType.h" #include "Exception.h" +#include "Texture.h" -ExceptionID SceneInvalid, CameraInvalid; +ExceptionID SceneInvalid, CameraInvalid, ObserverInvalid; +ExceptionID MirrorInvalid, MirrorSizeInvalid, MirrorNormalInvalid, MirrorHorizontal, MirrorTooSmall; ExpDesc SceneInvalidDesc (SceneInvalid, "Scene object is invalid"); ExpDesc CameraInvalidDesc (CameraInvalid, "Camera object is invalid"); - -#if 0 // not yet supported +ExpDesc ObserverInvalidDesc (ObserverInvalid, "Observer object is invalid"); +ExpDesc MirrorInvalidDesc (MirrorInvalid, "Mirror object is invalid"); +ExpDesc MirrorSizeInvalidDesc (MirrorSizeInvalid, "Mirror has no vertex or no size"); +ExpDesc MirrorNormalInvalidDesc (MirrorNormalInvalid, "Cannot determine mirror plane"); +ExpDesc MirrorHorizontalDesc (MirrorHorizontal, "Mirror is horizontal in local space"); +ExpDesc MirrorTooSmallDesc (MirrorTooSmall, "Mirror is too small"); // constructor -ImageRender::ImageRender (KX_Scene * scene, KX_Camera * camera) : m_scene(scene), -m_camera(camera) +ImageRender::ImageRender (KX_Scene * scene, KX_Camera * camera) : + ImageViewport(), + m_render(true), + m_scene(scene), + m_camera(camera), + m_owncamera(false), + m_observer(NULL), + m_mirror(NULL), + m_clip(100.f) { - // create screen area - m_area.winrct.xmin = m_upLeft[0]; - m_area.winrct.ymin = m_upLeft[1]; - m_area.winx = m_size[0]; - m_area.winy = m_size[1]; - // create canvas - m_canvas = new KX_BlenderCanvas(&m_area); - // create render tools - m_rendertools = new KX_BlenderRenderTools(); - // create rasterizer - m_rasterizer = new RAS_OpenGLRasterizer(m_canvas); - m_rasterizer->Init(); // initialize background colour - setBackground(0, 0, 255); - // refresh lights - refreshLights(); + setBackground(0, 0, 255, 255); + // retrieve rendering objects + m_engine = KX_GetActiveEngine(); + m_rasterizer = m_engine->GetRasterizer(); + m_canvas = m_engine->GetCanvas(); + m_rendertools = m_engine->GetRenderTools(); } // destructor ImageRender::~ImageRender (void) { - // release allocated objects - delete m_rasterizer; - delete m_rendertools; - delete m_canvas; + if (m_owncamera) + m_camera->Release(); } // set background color -void ImageRender::setBackground (unsigned char red, unsigned char green, unsigned char blue) +void ImageRender::setBackground (int red, int green, int blue, int alpha) { - m_background[0] = red; - m_background[1] = green; - m_background[2] = blue; - m_rasterizer->SetBackColor(m_background[0], m_background[1], m_background[2], 1.0); + m_background[0] = (red < 0) ? 0.f : (red > 255) ? 1.f : float(red)/255.f; + m_background[1] = (green < 0) ? 0.f : (green > 255) ? 1.f : float(green)/255.f; + m_background[2] = (blue < 0) ? 0.f : (blue > 255) ? 1.f : float(blue)/255.f; + m_background[3] = (alpha < 0) ? 0.f : (alpha > 255) ? 1.f : float(alpha)/255.f; } // capture image from viewport void ImageRender::calcImage (unsigned int texId) { - // setup camera - bool cameraPasive = !m_camera->GetViewport(); - // render scene - Render(); - // reset camera - if (cameraPasive) m_camera->EnableViewport(false); + if (m_rasterizer->GetDrawingMode() != RAS_IRasterizer::KX_TEXTURED || // no need for texture + m_camera->GetViewport() || // camera must be inactive + m_camera == m_scene->GetActiveCamera()) + { + // no need to compute texture in non texture rendering + m_avail = false; + return; + } + // render the scene from the camera + Render(); // get image from viewport ImageViewport::calcImage(texId); + // restore OpenGL state + m_canvas->EndFrame(); } void ImageRender::Render() { - // -} + RAS_FrameFrustum frustrum; + + if (!m_render) + return; + + if (m_mirror) + { + // mirror mode, compute camera frustrum, position and orientation + // convert mirror position and normal in world space + const MT_Matrix3x3 & mirrorObjWorldOri = m_mirror->GetSGNode()->GetWorldOrientation(); + const MT_Point3 & mirrorObjWorldPos = m_mirror->GetSGNode()->GetWorldPosition(); + const MT_Vector3 & mirrorObjWorldScale = m_mirror->GetSGNode()->GetWorldScaling(); + MT_Point3 mirrorWorldPos = + mirrorObjWorldPos + mirrorObjWorldScale * (mirrorObjWorldOri * m_mirrorPos); + MT_Vector3 mirrorWorldZ = mirrorObjWorldOri * m_mirrorZ; + // get observer world position + const MT_Point3 & observerWorldPos = m_observer->GetSGNode()->GetWorldPosition(); + // get plane D term = mirrorPos . normal + MT_Scalar mirrorPlaneDTerm = mirrorWorldPos.dot(mirrorWorldZ); + // compute distance of observer to mirror = D - observerPos . normal + MT_Scalar observerDistance = mirrorPlaneDTerm - observerWorldPos.dot(mirrorWorldZ); + // if distance < 0.01 => observer is on wrong side of mirror, don't render + if (observerDistance < 0.01f) + return; + // set camera world position = observerPos + normal * 2 * distance + MT_Point3 cameraWorldPos = observerWorldPos + (MT_Scalar(2.0)*observerDistance)*mirrorWorldZ; + m_camera->GetSGNode()->SetLocalPosition(cameraWorldPos); + // set camera orientation: z=normal, y=mirror_up in world space, x= y x z + MT_Vector3 mirrorWorldY = mirrorObjWorldOri * m_mirrorY; + MT_Vector3 mirrorWorldX = mirrorObjWorldOri * m_mirrorX; + MT_Matrix3x3 cameraWorldOri( + mirrorWorldX[0], mirrorWorldY[0], mirrorWorldZ[0], + mirrorWorldX[1], mirrorWorldY[1], mirrorWorldZ[1], + mirrorWorldX[2], mirrorWorldY[2], mirrorWorldZ[2]); + m_camera->GetSGNode()->SetLocalOrientation(cameraWorldOri); + m_camera->GetSGNode()->UpdateWorldData(0.0); + // compute camera frustrum: + // get position of mirror relative to camera: offset = mirrorPos-cameraPos + MT_Vector3 mirrorOffset = mirrorWorldPos - cameraWorldPos; + // convert to camera orientation + mirrorOffset = mirrorOffset * cameraWorldOri; + // scale mirror size to world scale: + // get closest local axis for mirror Y and X axis and scale height and width by local axis scale + MT_Scalar x, y; + x = fabs(m_mirrorY[0]); + y = fabs(m_mirrorY[1]); + float height = (x > y) ? + ((x > fabs(m_mirrorY[2])) ? mirrorObjWorldScale[0] : mirrorObjWorldScale[2]): + ((y > fabs(m_mirrorY[2])) ? mirrorObjWorldScale[1] : mirrorObjWorldScale[2]); + x = fabs(m_mirrorX[0]); + y = fabs(m_mirrorX[1]); + float width = (x > y) ? + ((x > fabs(m_mirrorX[2])) ? mirrorObjWorldScale[0] : mirrorObjWorldScale[2]): + ((y > fabs(m_mirrorX[2])) ? mirrorObjWorldScale[1] : mirrorObjWorldScale[2]); + width *= m_mirrorHalfWidth; + height *= m_mirrorHalfHeight; + // left = offsetx-width + // right = offsetx+width + // top = offsety+height + // bottom = offsety-height + // near = -offsetz + // far = near+100 + frustrum.x1 = mirrorOffset[0]-width; + frustrum.x2 = mirrorOffset[0]+width; + frustrum.y1 = mirrorOffset[1]-height; + frustrum.y2 = mirrorOffset[1]+height; + frustrum.camnear = -mirrorOffset[2]; + frustrum.camfar = -mirrorOffset[2]+m_clip; + } + const float ortho = 100.0; + const RAS_IRasterizer::StereoMode stereomode = m_rasterizer->GetStereoMode(); + + // The screen area that ImageViewport will copy is also the rendering zone + m_canvas->SetViewPort(m_position[0], m_position[1], m_position[0]+m_capSize[0]-1, m_position[1]+m_capSize[1]-1); + m_canvas->ClearColor(m_background[0], m_background[1], m_background[2], m_background[3]); + m_canvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER|RAS_ICanvas::DEPTH_BUFFER); + m_rasterizer->BeginFrame(RAS_IRasterizer::KX_TEXTURED,m_engine->GetClockTime()); + m_rendertools->BeginFrame(m_rasterizer); + m_engine->SetWorldSettings(m_scene->GetWorldInfo()); + m_rendertools->SetAuxilaryClientInfo(m_scene); + m_rasterizer->DisplayFog(); + // matrix calculation, don't apply any of the stereo mode + m_rasterizer->SetStereoMode(RAS_IRasterizer::RAS_STEREO_NOSTEREO); + if (m_mirror) + { + // frustrum was computed above + // get frustrum matrix and set projection matrix + MT_Matrix4x4 projmat = m_rasterizer->GetFrustumMatrix( + frustrum.x1, frustrum.x2, frustrum.y1, frustrum.y2, frustrum.camnear, frustrum.camfar); + + m_camera->SetProjectionMatrix(projmat); + } else if (m_camera->hasValidProjectionMatrix()) + { + m_rasterizer->SetProjectionMatrix(m_camera->GetProjectionMatrix()); + } else + { + float lens = m_camera->GetLens(); + bool orthographic = !m_camera->GetCameraData()->m_perspective; + float nearfrust = m_camera->GetCameraNear(); + float farfrust = m_camera->GetCameraFar(); + float aspect_ratio = 1.0f; + Scene *blenderScene = m_scene->GetBlenderScene(); + + if (orthographic) { + lens *= ortho; + nearfrust = (nearfrust + 1.0)*ortho; + farfrust *= ortho; + } + // compute the aspect ratio from frame blender scene settings so that render to texture + // works the same in Blender and in Blender player + if (blenderScene->r.ysch != 0) + aspect_ratio = float(blenderScene->r.xsch) / float(blenderScene->r.ysch); + + RAS_FramingManager::ComputeDefaultFrustum( + nearfrust, + farfrust, + lens, + aspect_ratio, + frustrum); + + MT_Matrix4x4 projmat = m_rasterizer->GetFrustumMatrix( + frustrum.x1, frustrum.x2, frustrum.y1, frustrum.y2, frustrum.camnear, frustrum.camfar); + + m_camera->SetProjectionMatrix(projmat); + } -// refresh lights -void ImageRender::refreshLights (void) -{ - // clear lights list - //m_rendertools->RemoveAllLights(); - // set lights - //for (int idx = 0; idx < scene->GetLightList()->GetCount(); ++idx) - // m_rendertools->AddLight(((KX_LightObject*)(scene->GetLightList()->GetValue(idx)))->GetLightData()); -} + MT_Transform camtrans(m_camera->GetWorldToCamera()); + if (!m_camera->GetCameraData()->m_perspective) + camtrans.getOrigin()[2] *= ortho; + MT_Matrix4x4 viewmat(camtrans); + + m_rasterizer->SetViewMatrix(viewmat, m_camera->NodeGetWorldPosition(), + m_camera->GetCameraLocation(), m_camera->GetCameraOrientation()); + m_camera->SetModelviewMatrix(viewmat); + // restore the stereo mode now that the matrix is computed + m_rasterizer->SetStereoMode(stereomode); + + // do not update the mesh, we don't want to do it more than once per frame + //m_scene->UpdateMeshTransformations(); + m_scene->CalculateVisibleMeshes(m_rasterizer,m_camera); + + m_scene->RenderBuckets(camtrans, m_rasterizer, m_rendertools); +} // cast Image pointer to ImageRender @@ -174,26 +316,31 @@ static int ImageRender_init (PyObject * pySelf, PyObject * args, PyObject * kwds // get background color PyObject * getBackground (PyImage * self, void * closure) { - return Py_BuildValue("[BBB]", getImageRender(self)->getBackground()[0], - getImageRender(self)->getBackground()[1], getImageRender(self)->getBackground()[2]); + return Py_BuildValue("[BBBB]", + getImageRender(self)->getBackground(0), + getImageRender(self)->getBackground(1), + getImageRender(self)->getBackground(2), + getImageRender(self)->getBackground(3)); } // set color static int setBackground (PyImage * self, PyObject * value, void * closure) { // check validity of parameter - if (value == NULL || !PySequence_Check(value) || PySequence_Length(value) != 3 + if (value == NULL || !PySequence_Check(value) || PySequence_Length(value) != 4 || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 0)) || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 1)) - || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 2))) + || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 2)) + || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 3))) { - PyErr_SetString(PyExc_TypeError, "The value must be a sequence of 3 ints"); + PyErr_SetString(PyExc_TypeError, "The value must be a sequence of 4 integer between 0 and 255"); return -1; } // set background color getImageRender(self)->setBackground((unsigned char)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 0))), (unsigned char)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 1))), - (unsigned char)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 2)))); + (unsigned char)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 2))), + (unsigned char)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 3)))); // success return 0; } @@ -209,6 +356,10 @@ static PyMethodDef imageRenderMethods[] = static PyGetSetDef imageRenderGetSets[] = { {(char*)"background", (getter)getBackground, (setter)setBackground, (char*)"background color", NULL}, + // attribute from ImageViewport + {(char*)"capsize", (getter)ImageViewport_getCaptureSize, (setter)ImageViewport_setCaptureSize, (char*)"size of render area", NULL}, + {(char*)"alpha", (getter)ImageViewport_getAlpha, (setter)ImageViewport_setAlpha, (char*)"use alpha in texture", NULL}, + {(char*)"whole", (getter)ImageViewport_getWhole, (setter)ImageViewport_setWhole, (char*)"use whole viewport to render", NULL}, // attributes from ImageBase class {(char*)"image", (getter)Image_getImage, NULL, (char*)"image data", NULL}, {(char*)"size", (getter)Image_getSize, NULL, (char*)"image size", NULL}, @@ -263,5 +414,329 @@ PyTypeObject ImageRenderType = Image_allocNew, /* tp_new */ }; +// object initialization +static int ImageMirror_init (PyObject * pySelf, PyObject * args, PyObject * kwds) +{ + // parameters - scene object + PyObject * scene; + // reference object for mirror + PyObject * observer; + // object holding the mirror + PyObject * mirror; + // material of the mirror + short materialID = 0; + // parameter keywords + static char *kwlist[] = {"scene", "observer", "mirror", "material", NULL}; + // get parameters + if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOO|h", kwlist, &scene, &observer, &mirror, &materialID)) + return -1; + try + { + // get scene pointer + KX_Scene * scenePtr (NULL); + if (scene != NULL && PyObject_TypeCheck(scene, &KX_Scene::Type)) + scenePtr = static_cast<KX_Scene*>(scene); + else + THRWEXCP(SceneInvalid, S_OK); + + // get observer pointer + KX_GameObject * observerPtr (NULL); + if (observer != NULL && PyObject_TypeCheck(observer, &KX_GameObject::Type)) + observerPtr = static_cast<KX_GameObject*>(observer); + else if (observer != NULL && PyObject_TypeCheck(observer, &KX_Camera::Type)) + observerPtr = static_cast<KX_Camera*>(observer); + else + THRWEXCP(ObserverInvalid, S_OK); + + // get mirror pointer + KX_GameObject * mirrorPtr (NULL); + if (mirror != NULL && PyObject_TypeCheck(mirror, &KX_GameObject::Type)) + mirrorPtr = static_cast<KX_GameObject*>(mirror); + else + THRWEXCP(MirrorInvalid, S_OK); + + // locate the material in the mirror + RAS_IPolyMaterial * material = getMaterial(mirror, materialID); + if (material == NULL) + THRWEXCP(MaterialNotAvail, S_OK); + + // get pointer to image structure + PyImage * self = reinterpret_cast<PyImage*>(pySelf); + + // create source object + if (self->m_image != NULL) + { + delete self->m_image; + self->m_image = NULL; + } + self->m_image = new ImageRender(scenePtr, observerPtr, mirrorPtr, material); + } + catch (Exception & exp) + { + exp.report(); + return -1; + } + // initialization succeded + return 0; +} + +// get background color +PyObject * getClip (PyImage * self, void * closure) +{ + return PyFloat_FromDouble(getImageRender(self)->getClip()); +} + +// set clip +static int setClip (PyImage * self, PyObject * value, void * closure) +{ + // check validity of parameter + double clip; + if (value == NULL || !PyFloat_Check(value) || (clip = PyFloat_AsDouble(value)) < 0.01 || clip > 5000.0) + { + PyErr_SetString(PyExc_TypeError, "The value must be an float between 0.01 and 5000"); + return -1; + } + // set background color + getImageRender(self)->setClip(float(clip)); + // success + return 0; +} + +// attributes structure +static PyGetSetDef imageMirrorGetSets[] = +{ + {(char*)"clip", (getter)getClip, (setter)setClip, (char*)"clipping distance", NULL}, + // attribute from ImageRender + {(char*)"background", (getter)getBackground, (setter)setBackground, (char*)"background color", NULL}, + // attribute from ImageViewport + {(char*)"capsize", (getter)ImageViewport_getCaptureSize, (setter)ImageViewport_setCaptureSize, (char*)"size of render area", NULL}, + {(char*)"alpha", (getter)ImageViewport_getAlpha, (setter)ImageViewport_setAlpha, (char*)"use alpha in texture", NULL}, + {(char*)"whole", (getter)ImageViewport_getWhole, (setter)ImageViewport_setWhole, (char*)"use whole viewport to render", NULL}, + // attributes from ImageBase class + {(char*)"image", (getter)Image_getImage, NULL, (char*)"image data", NULL}, + {(char*)"size", (getter)Image_getSize, NULL, (char*)"image size", NULL}, + {(char*)"scale", (getter)Image_getScale, (setter)Image_setScale, (char*)"fast scale of image (near neighbour)", NULL}, + {(char*)"flip", (getter)Image_getFlip, (setter)Image_setFlip, (char*)"flip image vertically", NULL}, + {(char*)"filter", (getter)Image_getFilter, (setter)Image_setFilter, (char*)"pixel filter", NULL}, + {NULL} +}; + + +// constructor +ImageRender::ImageRender (KX_Scene * scene, KX_GameObject * observer, KX_GameObject * mirror, RAS_IPolyMaterial * mat) : + ImageViewport(), + m_render(false), + m_scene(scene), + m_observer(observer), + m_mirror(mirror), + m_clip(100.f) +{ + // this constructor is used for automatic planar mirror + // create a camera, take all data by default, in any case we will recompute the frustrum on each frame + RAS_CameraData camdata; + vector<RAS_TexVert*> mirrorVerts; + vector<RAS_TexVert*>::iterator it; + float mirrorArea = 0.f; + float mirrorNormal[3] = {0.f, 0.f, 0.f}; + float mirrorUp[3]; + float dist, vec[3], axis[3]; + float zaxis[3] = {0.f, 0.f, 1.f}; + float yaxis[3] = {0.f, 1.f, 0.f}; + float mirrorMat[3][3]; + float left, right, top, bottom, back; + + m_camera= new KX_Camera(scene, KX_Scene::m_callbacks, camdata); + m_camera->SetName("__mirror__cam__"); + // don't add the camera to the scene object list, it doesn't need to be accessible + m_owncamera = true; + // retrieve rendering objects + m_engine = KX_GetActiveEngine(); + m_rasterizer = m_engine->GetRasterizer(); + m_canvas = m_engine->GetCanvas(); + m_rendertools = m_engine->GetRenderTools(); + // locate the vertex assigned to mat and do following calculation in mesh coordinates + for (int meshIndex = 0; meshIndex < mirror->GetMeshCount(); meshIndex++) + { + RAS_MeshObject* mesh = mirror->GetMesh(meshIndex); + int numPolygons = mesh->NumPolygons(); + for (int polygonIndex=0; polygonIndex < numPolygons; polygonIndex++) + { + RAS_Polygon* polygon = mesh->GetPolygon(polygonIndex); + if (polygon->GetMaterial()->GetPolyMaterial() == mat) + { + RAS_TexVert *v1, *v2, *v3, *v4; + float normal[3]; + float area; + // this polygon is part of the mirror, + v1 = polygon->GetVertex(0); + v2 = polygon->GetVertex(1); + v3 = polygon->GetVertex(2); + mirrorVerts.push_back(v1); + mirrorVerts.push_back(v2); + mirrorVerts.push_back(v3); + if (polygon->VertexCount() == 4) + { + v4 = polygon->GetVertex(3); + mirrorVerts.push_back(v4); + area = CalcNormFloat4((float*)v1->getXYZ(), (float*)v2->getXYZ(), (float*)v3->getXYZ(), (float*)v4->getXYZ(), normal); + } else + { + area = CalcNormFloat((float*)v1->getXYZ(), (float*)v2->getXYZ(), (float*)v3->getXYZ(), normal); + } + area = fabs(area); + mirrorArea += area; + VecMulf(normal, area); + VecAddf(mirrorNormal, mirrorNormal, normal); + } + } + } + if (mirrorVerts.size() == 0 || mirrorArea < FLT_EPSILON) + { + // no vertex or zero size mirror + THRWEXCP(MirrorSizeInvalid, S_OK); + } + // compute average normal of mirror faces + VecMulf(mirrorNormal, 1.0f/mirrorArea); + if (Normalize(mirrorNormal) == 0.f) + { + // no normal + THRWEXCP(MirrorNormalInvalid, S_OK); + } + // the mirror plane has an equation of the type ax+by+cz = d where (a,b,c) is the normal vector + // if the mirror is more vertical then horizontal, the Z axis is the up direction. + // otherwise the Y axis is the up direction. + // If the mirror is not perfectly vertical(horizontal), the Z(Y) axis projection on the mirror + // plan by the normal will be the up direction. + if (fabs(mirrorNormal[2]) > fabs(mirrorNormal[1]) && + fabs(mirrorNormal[2]) > fabs(mirrorNormal[0])) + { + // the mirror is more horizontal than vertical + VecCopyf(axis, yaxis); + } + else + { + // the mirror is more vertical than horizontal + VecCopyf(axis, zaxis); + } + dist = Inpf(mirrorNormal, axis); + if (fabs(dist) < FLT_EPSILON) + { + // the mirror is already fully aligned with up axis + VecCopyf(mirrorUp, axis); + } + else + { + // projection of axis to mirror plane through normal + VecCopyf(vec, mirrorNormal); + VecMulf(vec, dist); + VecSubf(mirrorUp, axis, vec); + if (Normalize(mirrorUp) == 0.f) + { + // should not happen + THRWEXCP(MirrorHorizontal, S_OK); + return; + } + } + // compute rotation matrix between local coord and mirror coord + // to match camera orientation, we select mirror z = -normal, y = up, x = y x z + VecCopyf(mirrorMat[2], mirrorNormal); + VecMulf(mirrorMat[2], -1.0f); + VecCopyf(mirrorMat[1], mirrorUp); + Crossf(mirrorMat[0], mirrorMat[1], mirrorMat[2]); + // transpose to make it a orientation matrix from local space to mirror space + Mat3Transp(mirrorMat); + // transform all vertex to plane coordinates and determine mirror position + left = FLT_MAX; + right = -FLT_MAX; + bottom = FLT_MAX; + top = -FLT_MAX; + back = -FLT_MAX; // most backward vertex (=highest Z coord in mirror space) + for (it = mirrorVerts.begin(); it != mirrorVerts.end(); it++) + { + VecCopyf(vec, (float*)(*it)->getXYZ()); + Mat3MulVecfl(mirrorMat, vec); + if (vec[0] < left) + left = vec[0]; + if (vec[0] > right) + right = vec[0]; + if (vec[1] < bottom) + bottom = vec[1]; + if (vec[1] > top) + top = vec[1]; + if (vec[2] > back) + back = vec[2]; + } + // now store this information in the object for later rendering + m_mirrorHalfWidth = (right-left)*0.5f; + m_mirrorHalfHeight = (top-bottom)*0.5f; + if (m_mirrorHalfWidth < 0.01f || m_mirrorHalfHeight < 0.01f) + { + // mirror too small + THRWEXCP(MirrorTooSmall, S_OK); + } + // mirror position in mirror coord + vec[0] = (left+right)*0.5f; + vec[1] = (top+bottom)*0.5f; + vec[2] = back; + // convert it in local space: transpose again the matrix to get back to mirror to local transform + Mat3Transp(mirrorMat); + Mat3MulVecfl(mirrorMat, vec); + // mirror position in local space + m_mirrorPos.setValue(vec[0], vec[1], vec[2]); + // mirror normal vector (pointed towards the back of the mirror) in local space + m_mirrorZ.setValue(-mirrorNormal[0], -mirrorNormal[1], -mirrorNormal[2]); + m_mirrorY.setValue(mirrorUp[0], mirrorUp[1], mirrorUp[2]); + m_mirrorX = m_mirrorY.cross(m_mirrorZ); + m_render = true; + + setBackground(0, 0, 255, 255); +} + + + + +// define python type +PyTypeObject ImageMirrorType = +{ + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "VideoTexture.ImageMirror", /*tp_name*/ + sizeof(PyImage), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)Image_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT, /*tp_flags*/ + "Image source from mirror", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + imageRenderMethods, /* tp_methods */ + 0, /* tp_members */ + imageMirrorGetSets, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)ImageMirror_init, /* tp_init */ + 0, /* tp_alloc */ + Image_allocNew, /* tp_new */ +}; + -#endif // #if 0 diff --git a/source/gameengine/VideoTexture/ImageRender.h b/source/gameengine/VideoTexture/ImageRender.h index 66255f04d2c..c94e2f1e718 100644 --- a/source/gameengine/VideoTexture/ImageRender.h +++ b/source/gameengine/VideoTexture/ImageRender.h @@ -42,42 +42,56 @@ class ImageRender : public ImageViewport public: /// constructor ImageRender (KX_Scene * scene, KX_Camera * camera); + ImageRender (KX_Scene * scene, KX_GameObject * observer, KX_GameObject * mirror, RAS_IPolyMaterial * mat); /// destructor virtual ~ImageRender (void); /// get background color - unsigned char * getBackground (void) { return m_background; } + int getBackground (int idx) { return (idx < 0 || idx > 3) ? 0 : int(m_background[idx]*255.f); } /// set background color - void setBackground (unsigned char red, unsigned char green, unsigned char blue); + void setBackground (int red, int green, int blue, int alpha); + + /// clipping distance + float getClip (void) { return m_clip; } + /// set whole buffer use + void setClip (float clip) { m_clip = clip; } protected: + /// true if ready to render + bool m_render; /// rendered scene KX_Scene * m_scene; /// camera for render KX_Camera * m_camera; - - /// screen area for rendering - ScrArea m_area; - /// rendering device - RAS_ICanvas * m_canvas; - /// rasterizer - RAS_IRasterizer * m_rasterizer; - /// render tools - RAS_IRenderTools * m_rendertools; + /// do we own the camera? + bool m_owncamera; + /// for mirror operation + KX_GameObject * m_observer; + KX_GameObject * m_mirror; + float m_clip; // clipping distance + float m_mirrorHalfWidth; // mirror width in mirror space + float m_mirrorHalfHeight; // mirror height in mirror space + MT_Point3 m_mirrorPos; // mirror center position in local space + MT_Vector3 m_mirrorZ; // mirror Z axis in local space + MT_Vector3 m_mirrorY; // mirror Y axis in local space + MT_Vector3 m_mirrorX; // mirror X axis in local space + /// canvas + RAS_ICanvas* m_canvas; + /// rasterizer + RAS_IRasterizer* m_rasterizer; + /// render tools + RAS_IRenderTools* m_rendertools; + /// engine + KX_KetsjiEngine* m_engine; /// background colour - unsigned char m_background[3]; + float m_background[4]; /// render 3d scene to image virtual void calcImage (unsigned int texId); - /// refresh lights - void refreshLights (void); - /// methods from KX_KetsjiEngine - bool BeginFrame(); - void EndFrame(); void Render(); void SetupRenderFrame(KX_Scene *scene, KX_Camera* cam); void RenderFrame(KX_Scene* scene, KX_Camera* cam); diff --git a/source/gameengine/VideoTexture/ImageViewport.cpp b/source/gameengine/VideoTexture/ImageViewport.cpp index deb66ffb6ba..4c2c81e2208 100644 --- a/source/gameengine/VideoTexture/ImageViewport.cpp +++ b/source/gameengine/VideoTexture/ImageViewport.cpp @@ -34,12 +34,12 @@ http://www.gnu.org/copyleft/lesser.txt. // constructor -ImageViewport::ImageViewport (void) : m_texInit(false) +ImageViewport::ImageViewport (void) : m_alpha(false), m_texInit(false) { // get viewport rectangle glGetIntegerv(GL_VIEWPORT, m_viewport); // create buffer for viewport image - m_viewportImage = new BYTE [3 * getViewportSize()[0] * getViewportSize()[1]]; + m_viewportImage = new BYTE [4 * getViewportSize()[0] * getViewportSize()[1]]; // set attributes setWhole(false); } @@ -62,7 +62,7 @@ void ImageViewport::setWhole (bool whole) m_capSize[idx] = whole ? short(getViewportSize()[idx]) : calcSize(short(getViewportSize()[idx])); // position - m_position[idx] = whole ? 0 : (getViewportSize()[idx] - m_capSize[idx]) >> 1; + m_position[idx] = whole ? 0 : ((getViewportSize()[idx] - m_capSize[idx]) >> 1); } // init image init(m_capSize[0], m_capSize[1]); @@ -123,20 +123,31 @@ void ImageViewport::calcImage (unsigned int texId) && m_capSize[1] == calcSize(m_capSize[1]) && !m_flip) { // just copy current viewport to texture - glBindTexture(GL_TEXTURE_2D, texId); - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_upLeft[0], m_upLeft[1], (GLsizei)m_capSize[0], (GLsizei)m_capSize[1]); - // image is not available - m_avail = false; + glBindTexture(GL_TEXTURE_2D, texId); + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_upLeft[0], m_upLeft[1], (GLsizei)m_capSize[0], (GLsizei)m_capSize[1]); + // image is not available + m_avail = false; } // otherwise copy viewport to buffer, if image is not available else if (!m_avail) { // get frame buffer data - glReadPixels(m_upLeft[0], m_upLeft[1], (GLsizei)m_capSize[0], (GLsizei)m_capSize[1], GL_RGB, - GL_UNSIGNED_BYTE, m_viewportImage); - // filter loaded data - FilterRGB24 filt; - filterImage(filt, m_viewportImage, m_capSize); + if (m_alpha) + { + glReadPixels(m_upLeft[0], m_upLeft[1], (GLsizei)m_capSize[0], (GLsizei)m_capSize[1], GL_RGBA, + GL_UNSIGNED_BYTE, m_viewportImage); + // filter loaded data + FilterRGBA32 filt; + filterImage(filt, m_viewportImage, m_capSize); + } + else + { + glReadPixels(m_upLeft[0], m_upLeft[1], (GLsizei)m_capSize[0], (GLsizei)m_capSize[1], GL_RGB, + GL_UNSIGNED_BYTE, m_viewportImage); + // filter loaded data + FilterRGB24 filt; + filterImage(filt, m_viewportImage, m_capSize); + } } } @@ -151,14 +162,14 @@ inline ImageViewport * getImageViewport (PyImage * self) // get whole -static PyObject * ImageViewport_getWhole (PyImage * self, void * closure) +PyObject * ImageViewport_getWhole (PyImage * self, void * closure) { if (self->m_image != NULL && getImageViewport(self)->getWhole()) Py_RETURN_TRUE; else Py_RETURN_FALSE; } // set whole -static int ImageViewport_setWhole (PyImage * self, PyObject * value, void * closure) +int ImageViewport_setWhole (PyImage * self, PyObject * value, void * closure) { // check parameter, report failure if (value == NULL || !PyBool_Check(value)) @@ -172,6 +183,28 @@ static int ImageViewport_setWhole (PyImage * self, PyObject * value, void * clos return 0; } +// get alpha +PyObject * ImageViewport_getAlpha (PyImage * self, void * closure) +{ + if (self->m_image != NULL && getImageViewport(self)->getAlpha()) Py_RETURN_TRUE; + else Py_RETURN_FALSE; +} + +// set whole +int ImageViewport_setAlpha (PyImage * self, PyObject * value, void * closure) +{ + // check parameter, report failure + if (value == NULL || !PyBool_Check(value)) + { + PyErr_SetString(PyExc_TypeError, "The value must be a bool"); + return -1; + } + // set alpha + if (self->m_image != NULL) getImageViewport(self)->setAlpha(value == Py_True); + // success + return 0; +} + // get position static PyObject * ImageViewport_getPosition (PyImage * self, void * closure) @@ -202,14 +235,14 @@ static int ImageViewport_setPosition (PyImage * self, PyObject * value, void * c } // get capture size -static PyObject * ImageViewport_getCaptureSize (PyImage * self, void * closure) +PyObject * ImageViewport_getCaptureSize (PyImage * self, void * closure) { return Py_BuildValue("(ii)", getImageViewport(self)->getCaptureSize()[0], getImageViewport(self)->getCaptureSize()[1]); } // set capture size -static int ImageViewport_setCaptureSize (PyImage * self, PyObject * value, void * closure) +int ImageViewport_setCaptureSize (PyImage * self, PyObject * value, void * closure) { // check validity of parameter if (value == NULL || !PySequence_Check(value) || PySequence_Length(value) != 2 @@ -242,6 +275,7 @@ static PyGetSetDef imageViewportGetSets[] = {(char*)"whole", (getter)ImageViewport_getWhole, (setter)ImageViewport_setWhole, (char*)"use whole viewport to capture", NULL}, {(char*)"position", (getter)ImageViewport_getPosition, (setter)ImageViewport_setPosition, (char*)"upper left corner of captured area", NULL}, {(char*)"capsize", (getter)ImageViewport_getCaptureSize, (setter)ImageViewport_setCaptureSize, (char*)"size of viewport area being captured", NULL}, + {(char*)"alpha", (getter)ImageViewport_getAlpha, (setter)ImageViewport_setAlpha, (char*)"use alpha in texture", NULL}, // attributes from ImageBase class {(char*)"image", (getter)Image_getImage, NULL, (char*)"image data", NULL}, {(char*)"size", (getter)Image_getSize, NULL, (char*)"image size", NULL}, diff --git a/source/gameengine/VideoTexture/ImageViewport.h b/source/gameengine/VideoTexture/ImageViewport.h index 4265906b8f5..0449249cf95 100644 --- a/source/gameengine/VideoTexture/ImageViewport.h +++ b/source/gameengine/VideoTexture/ImageViewport.h @@ -43,6 +43,12 @@ public: bool getWhole (void) { return m_whole; } /// set whole buffer use void setWhole (bool whole); + + /// is alpha channel used + bool getAlpha (void) { return m_alpha; } + /// set whole buffer use + void setAlpha (bool alpha) { m_alpha = alpha; } + /// get capture size in viewport short * getCaptureSize (void) { return m_capSize; } /// set capture size in viewport @@ -61,6 +67,8 @@ protected: short m_capSize[2]; /// use whole viewport bool m_whole; + /// use alpha channel + bool m_alpha; /// position of capture rectangle in viewport GLint m_position[2]; @@ -79,6 +87,12 @@ protected: GLint * getViewportSize (void) { return m_viewport + 2; } }; +PyObject * ImageViewport_getCaptureSize (PyImage * self, void * closure); +int ImageViewport_setCaptureSize (PyImage * self, PyObject * value, void * closure); +PyObject * ImageViewport_getWhole (PyImage * self, void * closure); +int ImageViewport_setWhole (PyImage * self, PyObject * value, void * closure); +PyObject * ImageViewport_getAlpha (PyImage * self, void * closure); +int ImageViewport_setAlpha (PyImage * self, PyObject * value, void * closure); #endif diff --git a/source/gameengine/VideoTexture/SConscript b/source/gameengine/VideoTexture/SConscript index f3fe0dab6ad..28737ed06e5 100644 --- a/source/gameengine/VideoTexture/SConscript +++ b/source/gameengine/VideoTexture/SConscript @@ -15,11 +15,12 @@ incs += ' #source/blender/gpu #source/kernel/gen_system #intern/string #intern/m incs += ' #intern/guardedalloc #intern/SoundSystem' incs += ' #extern/glew/include' -cflags = [] defs = '' -if env['OURPLATFORM'] == 'win32-vc': - cflags.append('/GR') - cflags.append('/Ox') +cxxflags = [] +if env['OURPLATFORM']=='win32-vc': + cxxflags.append ('/GR') + cxxflags.append ('/O2') + incs += ' ' + env['BF_PYTHON_INC'] #incs += ' ' + env['BF_OPENGL_INC'] @@ -29,4 +30,4 @@ if env['WITH_BF_FFMPEG']: incs += ' ' + env['BF_FFMPEG_INC'] defs += ' __STDC_CONSTANT_MACROS' -env.BlenderLib ( 'bf_videotex', sources, Split(incs), Split(defs), libtype=['game','player'], priority=[25, 72], compileflags = cflags ) +env.BlenderLib ( 'bf_videotex', sources, Split(incs), Split(defs), libtype=['game','player'], priority=[25, 72], cxx_compileflags = cxxflags ) diff --git a/source/gameengine/VideoTexture/Texture.h b/source/gameengine/VideoTexture/Texture.h index 3c371e51537..1bbef8f0f9e 100644 --- a/source/gameengine/VideoTexture/Texture.h +++ b/source/gameengine/VideoTexture/Texture.h @@ -32,6 +32,7 @@ http://www.gnu.org/copyleft/lesser.txt. #include "ImageBase.h" #include "BlendType.h" +#include "Exception.h" // type Texture declaration @@ -82,5 +83,10 @@ RAS_IPolyMaterial * getMaterial (PyObject *obj, short matID); // get material ID short getMaterialID (PyObject * obj, char * name); +// Exceptions +extern ExceptionID MaterialNotAvail; + +// object type +extern BlendType<KX_GameObject> gameObjectType; #endif diff --git a/source/gameengine/VideoTexture/blendVideoTex.cpp b/source/gameengine/VideoTexture/blendVideoTex.cpp index b38882f8164..ec066811a52 100644 --- a/source/gameengine/VideoTexture/blendVideoTex.cpp +++ b/source/gameengine/VideoTexture/blendVideoTex.cpp @@ -132,6 +132,7 @@ extern PyTypeObject FilterBGR24Type; extern PyTypeObject ImageBuffType; extern PyTypeObject ImageMixType; extern PyTypeObject ImageRenderType; +extern PyTypeObject ImageMirrorType; extern PyTypeObject ImageViewportType; extern PyTypeObject ImageViewportType; @@ -144,7 +145,8 @@ static void registerAllTypes(void) #endif pyImageTypes.add(&ImageBuffType, "ImageBuff"); pyImageTypes.add(&ImageMixType, "ImageMix"); - //pyImageTypes.add(&ImageRenderType, "ImageRender"); + pyImageTypes.add(&ImageRenderType, "ImageRender"); + pyImageTypes.add(&ImageMirrorType, "ImageMirror"); pyImageTypes.add(&ImageViewportType, "ImageViewport"); pyFilterTypes.add(&FilterBlueScreenType, "FilterBlueScreen"); diff --git a/source/nan_compile.mk b/source/nan_compile.mk index 4b13ef8f678..19d833b5b0d 100644 --- a/source/nan_compile.mk +++ b/source/nan_compile.mk @@ -120,22 +120,34 @@ ifeq ($(OS),freebsd) endif ifeq ($(OS),irix) - CC = cc - CCC = CC - CFLAGS += -n32 -mips3 -Xcpluscomm - CCFLAGS += -n32 -mips3 -Xcpluscomm -LANG:std -ifdef MIPS73_ISOHEADERS - CCFLAGS += -LANG:libc_in_namespace_std=off -I$(MIPS73_ISOHEADERS) -else - CCFLAGS += -LANG:libc_in_namespace_std=off -endif - REL_CFLAGS += -n32 -mips3 -O2 -OPT:Olimit=0 - REL_CCFLAGS += -n32 -mips3 -O2 -OPT:Olimit=0 + ifeq ($(IRIX_USE_GCC),true) + CC = gcc + CCC = g++ + CFLAGS += -fPIC -funsigned-char -fno-strict-aliasing -mabi=n32 -mips4 + CCFLAGS += -fPIC -fpermissive -funsigned-char -fno-strict-aliasing -mabi=n32 -mips4 + REL_CFLAGS += -O2 + REL_CCFLAGS += -O2 + CPPFLAGS += -DXP_UNIX + DBG_CFLAGS += -g3 -gdwarf-2 -ggdb + DBG_CCFLAGS += -g3 -gdwarf-2 -ggdb + else + CC = cc + CCC = CC + CFLAGS += -n32 -mips3 -Xcpluscomm + CCFLAGS += -n32 -mips3 -Xcpluscomm -LANG:std + ifdef MIPS73_ISOHEADERS + CCFLAGS += -LANG:libc_in_namespace_std=off -I$(MIPS73_ISOHEADERS) + else + CCFLAGS += -LANG:libc_in_namespace_std=off + endif + REL_CFLAGS += -n32 -mips3 -O2 -OPT:Olimit=0 + REL_CCFLAGS += -n32 -mips3 -O2 -OPT:Olimit=0 + endif OPENGL_HEADERS = /usr/include NAN_DEPEND = true AR = CC ARFLAGS = -ar -o - ARFLAGSQUIET = -ar -o + ARFLAGSQUIET = -ar -o endif ifeq ($(OS),linux) diff --git a/source/nan_definitions.mk b/source/nan_definitions.mk index 424a7c558d7..3961e153cea 100644 --- a/source/nan_definitions.mk +++ b/source/nan_definitions.mk @@ -75,6 +75,7 @@ else export NAN_SOLID ?= $(LCGDIR)/solid export NAN_QHULL ?= $(LCGDIR)/qhull endif + export NAN_USE_BULLET ?= true export NAN_BULLET2 ?= $(LCGDIR)/bullet2 export NAN_SUMO ?= $(SRCHOME)/gameengine/Physics/Sumo export NAN_FUZZICS ?= $(SRCHOME)/gameengine/Physics/Sumo/Fuzzics @@ -83,7 +84,7 @@ endif export NAN_GUARDEDALLOC ?= $(LCGDIR)/guardedalloc export NAN_IKSOLVER ?= $(LCGDIR)/iksolver export NAN_BSP ?= $(LCGDIR)/bsp - export NAN_BOOLOP ?= $(LCGDIR)/boolop + export NAN_BOOLOP ?= $(LCGDIR)/boolop export NAN_SOUNDSYSTEM ?= $(LCGDIR)/SoundSystem export NAN_STRING ?= $(LCGDIR)/string export NAN_MEMUTIL ?= $(LCGDIR)/memutil @@ -99,13 +100,13 @@ endif ifeq ($(FREE_WINDOWS), true) export NAN_FTGL ?= $(LCGDIR)/gcc/ftgl export NAN_FFMPEG ?= $(LCGDIR)/gcc/ffmpeg - export NAN_FFMPEGLIBS ?= $(NAN_FFMPEG)/lib/libavformat.a $(NAN_FFMPEG)/lib/libavutil.a $(NAN_FFMPEG)/lib/libavcodec.a - export NAN_FFMPEGCFLAGS ?= -I$(NAN_FFMPEG)/include + export NAN_FFMPEGLIBS ?= $(NAN_FFMPEG)/lib/libavformat.a $(NAN_FFMPEG)/lib/libavutil.a $(NAN_FFMPEG)/lib/libavcodec.a $(NAN_FFMPEG)/lib/libavdevice.a + export NAN_FFMPEGCFLAGS ?= -I$(NAN_FFMPEG)/include -I$(NANBLENDERHOME)/extern/ffmpeg else export NAN_FTGL ?= $(LCGDIR)/ftgl export NAN_FFMPEG ?= $(LCGDIR)/ffmpeg - export NAN_FFMPEGLIBS ?= $(NAN_FFMPEG)/lib/libavformat.a $(NAN_FFMPEG)/lib/libavcodec.a $(NAN_FFMPEG)/lib/libswscale.a $(NAN_FFMPEG)/lib/libavutil.a - export NAN_FFMPEGCFLAGS ?= -I$(NAN_FFMPEG)/include + export NAN_FFMPEGLIBS ?= $(NAN_FFMPEG)/lib/libavformat.a $(NAN_FFMPEG)/lib/libavcodec.a $(NAN_FFMPEG)/lib/libswscale.a $(NAN_FFMPEG)/lib/libavutil.a $(NAN_FFMPEG)/lib/libavdevice.a + export NAN_FFMPEGCFLAGS ?= -I$(NAN_FFMPEG)/include -I$(NANBLENDERHOME)/extern/ffmpeg endif ifeq ($(WITH_VERSE), true) @@ -116,7 +117,7 @@ endif export WITH_DDS ?= true ifeq ($(OS),windows) - export NAN_WINTAB ?= $(LCGDIR)/wintab + export NAN_WINTAB ?= $(LCGDIR)/wintab ifeq ($(FREE_WINDOWS), true) export NAN_PTHREADS ?= $(LCGDIR)/pthreads export NAN_OPENEXR ?= $(LCGDIR)/gcc/openexr @@ -129,28 +130,34 @@ endif endif else ifeq ($(OS),darwin) - export NAN_OPENEXR ?= $(LCGDIR)/openexr - ifeq ($(CPU),powerpc) - export NAN_OPENEXR_LIBS ?= $(NAN_OPENEXR)/lib/libIlmImf.a $(NAN_OPENEXR)/lib/libHalf.a $(NAN_OPENEXR)/lib/libIex.a - else - export NAN_OPENEXR_LIBS ?= $(NAN_OPENEXR)/lib/libIlmImf.a $(NAN_OPENEXR)/lib/libHalf.a $(NAN_OPENEXR)/lib/libIex.a $(NAN_OPENEXR)/lib/libIlmThread.a - endif + export NAN_OPENEXR ?= $(LCGDIR)/openexr + ifeq ($(CPU),powerpc) + export NAN_OPENEXR_LIBS ?= $(NAN_OPENEXR)/lib/libIlmImf.a $(NAN_OPENEXR)/lib/libHalf.a $(NAN_OPENEXR)/lib/libIex.a + else + export NAN_OPENEXR_LIBS ?= $(NAN_OPENEXR)/lib/libIlmImf.a $(NAN_OPENEXR)/lib/libHalf.a $(NAN_OPENEXR)/lib/libIex.a $(NAN_OPENEXR)/lib/libIlmThread.a + endif else ifeq ($(OS),linux) - ifeq ($(WITH_OPENEXR), true) - NAN_OPENEXR?=$(shell pkg-config --variable=prefix OpenEXR ) - NAN_OPENEXR_INC?=$(shell pkg-config --cflags OpenEXR ) - NAN_OPENEXR_LIBS?=$(addprefix ${NAN_OPENEXR}/lib/lib,$(addsuffix .a,$(shell pkg-config --libs-only-l OpenEXR | sed -s "s/-l//g" ))) - endif + ifeq ($(WITH_OPENEXR), true) + NAN_OPENEXR?=$(shell pkg-config --variable=prefix OpenEXR ) + NAN_OPENEXR_INC?=$(shell pkg-config --cflags OpenEXR ) + NAN_OPENEXR_LIBS?=$(addprefix ${NAN_OPENEXR}/lib/lib,$(addsuffix .a,$(shell pkg-config --libs-only-l OpenEXR | sed -s "s/-l//g" ))) + endif else ifeq ($(OS), solaris) # this only exists at the moment for i386-64 CPU Types at the moment export NAN_OPENEXR ?= $(LCGDIR)/openexr - export NAN_OPENEXR_LIBS ?= $(NAN_OPENEXR)/lib/libIlmImf.a $(NAN_OPENEXR)/lib/libHalf.a $(NAN_OPENEXR)/lib/libIex.a $(NAN_OPENEXR)/lib/libIlmThread.a -lrt else - export NAN_OPENEXR ?= /usr/local - export NAN_OPENEXR_LIBS ?= $(NAN_OPENEXR)/lib/libIlmImf.a $(NAN_OPENEXR)/lib/libHalf.a $(NAN_OPENEXR)/lib/libIex.a + ifeq ($(OS), irix) + ifeq ($(IRIX_USE_GCC), true) + export NAN_OPENEXR ?= $(LCGDIR)/openexr/gcc + else + export NAN_OPENEXR ?= $(LCGDIR)/openexr + endif + endif + export NAN_OPENEXR_INC ?= -I$(NAN_OPENEXR)/include -I$(NAN_OPENEXR)/include/OpenEXR + export NAN_OPENEXR_LIBS ?= $(NAN_OPENEXR)/lib/libIlmImf.a $(NAN_OPENEXR)/lib/libHalf.a $(NAN_OPENEXR)/lib/libIex.a $(NAN_OPENEXR)/lib/libIlmThread.a endif endif endif @@ -331,23 +338,27 @@ endif export NAN_PYTHON ?= $(LCGDIR)/python export NAN_PYTHON_VERSION ?= 2.3 export NAN_PYTHON_BINARY ?= $(NAN_PYTHON)/bin/python$(NAN_PYTHON_VERSION) - export NAN_PYTHON_LIB ?= $(NAN_PYTHON)/lib/python$(NAN_PYTHON_VERSION)/config/libpython$(NAN_PYTHON_VERSION).a + export NAN_PYTHON_LIB ?= $(NAN_PYTHON)/lib/python$(NAN_PYTHON_VERSION)/config/libpython$(NAN_PYTHON_VERSION).a -lpthread export NAN_OPENAL ?= $(LCGDIR)/openal export NAN_FMOD ?= $(LCGDIR)/fmod export NAN_JPEG ?= $(LCGDIR)/jpeg export NAN_PNG ?= $(LCGDIR)/png - export NAN_TIFF ?= /usr/freeware + export NAN_TIFF ?= $(LCGDIR)/tiff export NAN_ODE ?= $(LCGDIR)/ode export NAN_TERRAPLAY ?= $(LCGDIR)/terraplay export NAN_MESA ?= /usr/src/Mesa-3.1 - export NAN_ZLIB ?= /usr/freeware + export NAN_ZLIB ?= $(LCGDIR)/zlib export NAN_NSPR ?= $(LCGDIR)/nspr - export NAN_FREETYPE ?= /usr/freeware - export NAN_GETTEXT ?= /usr/freeware - export NAN_GETTEXT_LIB ?= $(NAN_GETTEXT)/lib32/libintl.a + export NAN_FREETYPE ?= $(LCGDIR)/freetype + export NAN_ICONV ?= $(LCGDIR)/iconv + export NAN_GETTEXT ?= $(LCGDIR)/gettext + export NAN_GETTEXT_LIB ?= $(NAN_GETTEXT)/lib/libintl.a $(NAN_ICONV)/lib/libiconv.a export NAN_SDL ?= $(LCGDIR)/sdl - export NAN_SDLLIBS ?= -L$(NAN_SDL)/lib -lSDL + export NAN_SDLLIBS ?= $(NAN_SDL)/lib/libSDL.a export NAN_SDLCFLAGS ?= -I$(NAN_SDL)/include/SDL + export NAN_FFMPEG ?= $(LCGDIR)/ffmpeg + export NAN_FFMPEGLIBS = $(NAN_FFMPEG)/lib/libavformat.a $(NAN_FFMPEG)/lib/libavcodec.a $(NAN_FFMPEG)/lib/libswscale.a $(NAN_FFMPEG)/lib/libavutil.a $(NAN_FFMPEG)/lib/libavdevice.a $(NAN_FFMPEG)/lib/libogg.a $(NAN_FFMPEG)/lib/libfaad.a $(NAN_FFMPEG)/lib/libmp3lame.a $(NAN_FFMPEG)/lib/libvorbis.a $(NAN_FFMPEG)/lib/libx264.a $(NAN_FFMPEG)/lib/libfaac.a $(NAN_ZLIB)/lib/libz.a + export NAN_FFMPEGCFLAGS ?= -I$(NAN_FFMPEG)/include -I$(NANBLENDERHOME)/extern/ffmpeg # Uncomment the following line to use Mozilla inplace of netscape # CPPFLAGS +=-DMOZ_NOT_NET @@ -396,7 +407,7 @@ endif ifneq ($(NAN_USE_FFMPEG_CONFIG), true) export NAN_FFMPEG ?= /usr - export NAN_FFMPEGLIBS ?= -L$(NAN_FFMPEG)/lib -lavformat -lavcodec -lavutil -lswscale -ldts -lz + export NAN_FFMPEGLIBS ?= -L$(NAN_FFMPEG)/lib -lavformat -lavcodec -lavutil -lswscale -lavdevice -ldts -lz export NAN_FFMPEGCFLAGS ?= -I$(NAN_FFMPEG)/include endif diff --git a/source/nan_link.mk b/source/nan_link.mk index 8dda3b8c2df..186fe07e09a 100644 --- a/source/nan_link.mk +++ b/source/nan_link.mk @@ -72,11 +72,19 @@ ifeq ($(OS),freebsd) endif ifeq ($(OS),irix) - LDFLAGS += -mips3 - LLIBS = -lmovieGL -lGLU -lGL -lXmu -lXext -lX11 -lc -lm -ldmedia - LLIBS += -lcl -laudio -ldb -lCio -lz - LLIBS += -lpthread - LLIBS += -woff 84,171 + ifeq ($(IRIX_USE_GCC), true) + LDFLAGS += -mabi=n32 -mips4 + DBG_LDFLAGS += -LD_LAYOUT:lgot_buffer=40 + else + LDFLAGS += -n32 -mips3 + LDFLAGS += -woff 84,171 + endif + LLIBS = -lmovieGL -lGLU -lGL -lXmu -lXext -lXi -lX11 -lc -lm -ldmedia + LLIBS += -lcl -laudio + ifneq ($(IRIX_USE_GCC), true) + LLIBS += -lCio -ldb + endif + LLIBS += -lz -lpthread DYNLDFLAGS = -shared $(LDFLAGS) endif @@ -90,7 +98,7 @@ ifeq ($(OS),linux) ifeq ($(CPU),$(findstring $(CPU), "i386 x86_64 ia64 parisc64 powerpc sparc64")) COMMENT = "MESA 3.1" LLIBS = -L$(NAN_MESA)/lib -L/usr/X11R6/lib -lXmu -lXext -lX11 -lXi - LLIBS += -lutil -lc -lm -ldl -lpthread + LLIBS += -lutil -lc -lm -ldl -lpthread # LLIBS += -L$(NAN_ODE)/lib -lode LOPTS = -export-dynamic DADD = -lGL -lGLU diff --git a/tools/Blender.py b/tools/Blender.py index 1c54e98f177..9c978fccf49 100644 --- a/tools/Blender.py +++ b/tools/Blender.py @@ -434,11 +434,11 @@ class BlenderEnvironment(SConsEnvironment): lenv.Append(CCFLAGS = lenv['BF_PROFILE_CCFLAGS']) lenv.Append(CXXFLAGS = lenv['BF_PROFILE_CXXFLAGS']) if compileflags: - lenv.Append(CFLAGS = compileflags) + lenv.Replace(CFLAGS = compileflags) if cc_compileflags: - lenv.Append(CCFLAGS = cc_compileflags) + lenv.Replace(CCFLAGS = cc_compileflags) if cxx_compileflags: - lenv.Append(CXXFLAGS = cxx_compileflags) + lenv.Replace(CXXFLAGS = cxx_compileflags) lenv.Append(CFLAGS = lenv['C_WARN']) lenv.Append(CCFLAGS = lenv['CC_WARN']) lenv.Append(CXXFLAGS = lenv['CXX_WARN']) diff --git a/tools/btools.py b/tools/btools.py index e07b6184abc..21ab547b11a 100755 --- a/tools/btools.py +++ b/tools/btools.py @@ -555,8 +555,10 @@ def NSIS_Installer(target=None, source=None, env=None): new_nsis = open(tmpnsi, 'w') new_nsis.write(ns_cnt) new_nsis.close() + print "Preparing nsis file looks ok\n" os.chdir(start_dir) + print "try to launch 'makensis' ...make sure it is on the path \n" cmdline = "makensis " + "\""+tmpnsi+"\"" |