forked from bartvdbraak/blender
Sculpt Branch:
svn merge https://svn.blender.org/svnroot/bf-blender/trunk/blender -r24889:25180
This commit is contained in:
commit
82ddfbf99f
@ -216,8 +216,8 @@ IF(UNIX AND NOT APPLE)
|
||||
|
||||
IF (WITH_OPENCOLLADA)
|
||||
SET(OPENCOLLADA /usr/local/opencollada CACHE FILEPATH "OpenCollada Directory")
|
||||
SET(OPENCOLLADA_LIBPATH ${OPENCOLLADA})
|
||||
SET(OPENCOLLADA_LIB OpenCollada)
|
||||
SET(OPENCOLLADA_LIBPATH ${OPENCOLLADA}/lib)
|
||||
SET(OPENCOLLADA_LIB OpenCOLLADAStreamWriter OpenCOLLADASaxFrameworkLoader OpenCOLLADAFramework OpenCOLLADABaseUtils GeneratedSaxParser UTF MathMLSolver pcre ftoa Buffer)
|
||||
SET(OPENCOLLADA_INC ${OPENCOLLADA})
|
||||
SET(PCRE /usr CACHE FILEPATH "PCRE Directory")
|
||||
SET(PCRE_LIBPATH ${PCRE}/lib)
|
||||
@ -437,7 +437,7 @@ IF(APPLE)
|
||||
IF(CMAKE_OSX_ARCHITECTURES MATCHES i386)
|
||||
SET(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/darwin-8.x.i386)
|
||||
ELSE(CMAKE_OSX_ARCHITECTURES MATCHES i386)
|
||||
SET(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/darwin-6.1-powerpc)
|
||||
SET(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/darwin-8.0.0-powerpc)
|
||||
ENDIF(CMAKE_OSX_ARCHITECTURES MATCHES i386)
|
||||
ENDIF(WITH_LIBS10.5)
|
||||
|
||||
@ -531,18 +531,20 @@ IF(APPLE)
|
||||
SET(LLIBS stdc++ SystemStubs)
|
||||
|
||||
IF (WITH_COCOA)
|
||||
SET(PLATFORM_CFLAGS "-pipe -fPIC -funsigned-char -fno-strict-aliasing -DGHOST_COCOA")
|
||||
SET(PLATFORM_CFLAGS "-pipe -funsigned-char -DGHOST_COCOA")
|
||||
SET(PLATFORM_LINKFLAGS "-fexceptions -framework CoreServices -framework Foundation -framework IOKit -framework AppKit -framework Cocoa -framework Carbon -framework AudioUnit -framework AudioToolbox -framework CoreAudio")
|
||||
IF(USE_QTKIT)
|
||||
SET(PLATFORM_CFLAGS "${PLATFORM_CFLAGS} -DUSE_QTKIT")
|
||||
SET(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -framework QTKit")
|
||||
ELSE(USE_QTKIT)
|
||||
IF(WITH_QUICKTIME)
|
||||
IF(CMAKE_OSX_ARCHITECTURES MATCHES i386)
|
||||
SET(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -framework QuickTime")
|
||||
#libSDL still needs 32bit carbon quicktime
|
||||
ENDIF(CMAKE_OSX_ARCHITECTURES MATCHES i386)
|
||||
ELSEIF(WITH_QUICKTIME)
|
||||
SET(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -framework QuickTime")
|
||||
ENDIF(WITH_QUICKTIME)
|
||||
ENDIF(USE_QTKIT)
|
||||
ELSE (WITH_COCOA)
|
||||
SET(PLATFORM_CFLAGS "-pipe -fPIC -funsigned-char -fno-strict-aliasing")
|
||||
SET(PLATFORM_CFLAGS "-pipe -funsigned-char")
|
||||
SET(PLATFORM_LINKFLAGS "-fexceptions -framework CoreServices -framework Foundation -framework IOKit -framework AppKit -framework Carbon -framework AGL -framework AudioUnit -framework AudioToolbox -framework CoreAudio -framework QuickTime")
|
||||
ENDIF (WITH_COCOA)
|
||||
|
||||
@ -585,13 +587,17 @@ IF(APPLE)
|
||||
|
||||
SET(EXETYPE MACOSX_BUNDLE)
|
||||
|
||||
|
||||
SET(CMAKE_C_FLAGS_DEBUG "-fno-strict-aliasing -g")
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "-fno-strict-aliasing -g")
|
||||
IF(CMAKE_OSX_ARCHITECTURES MATCHES "i386")
|
||||
SET(CMAKE_CXX_FLAGS_RELEASE "-O3 -ftree-vectorize -msse -msse2 -fvariable-expansion-in-unroller")
|
||||
SET(CMAKE_C_FLAGS_RELEASE "-O3 -ftree-vectorize -msse -msse2 -fvariable-expansion-in-unroller")
|
||||
SET(CMAKE_CXX_FLAGS_RELEASE "-O3 -mdynamic-no-pic -ftree-vectorize -msse -msse2 -fvariable-expansion-in-unroller")
|
||||
SET(CMAKE_C_FLAGS_RELEASE "-O3 -mdynamic-no-pic -ftree-vectorize -msse -msse2 -fvariable-expansion-in-unroller")
|
||||
ELSEIF(CMAKE_OSX_ARCHITECTURES MATCHES "x86_64")
|
||||
SET(CMAKE_CXX_FLAGS_RELEASE "-O3 -ftree-vectorize -msse -msse2 -msse3 -mssse3 -fvariable-expansion-in-unroller")
|
||||
SET(CMAKE_C_FLAGS_RELEASE "-O3 -ftree-vectorize -msse -msse2 -msse3 -mssse3 -fvariable-expansion-in-unroller")
|
||||
SET(CMAKE_CXX_FLAGS_RELEASE "-O3 -mdynamic-no-pic -ftree-vectorize -msse -msse2 -msse3 -mssse3 -fvariable-expansion-in-unroller")
|
||||
SET(CMAKE_C_FLAGS_RELEASE "-O3 -mdynamic-no-pic -ftree-vectorize -msse -msse2 -msse3 -mssse3 -fvariable-expansion-in-unroller")
|
||||
ELSE(CMAKE_OSX_ARCHITECTURES MATCHES "x86_64")
|
||||
SET(CMAKE_C_FLAGS_RELEASE "-mdynamic-no-pic -fno-strict-aliasing")
|
||||
SET(CMAKE_CXX_FLAGS_RELEASE "-mdynamic-no-pic -fno-strict-aliasing")
|
||||
ENDIF(CMAKE_OSX_ARCHITECTURES MATCHES "i386")
|
||||
|
||||
# Better warnings
|
||||
|
@ -40,11 +40,17 @@ if MACOSX_ARCHITECTURE == 'x86_64' or MACOSX_ARCHITECTURE == 'ppc64':
|
||||
# Can be customized
|
||||
|
||||
if MACOSX_ARCHITECTURE == 'ppc':
|
||||
MAC_MIN_VERS = '10.3'
|
||||
MACOSX_SDK='/Developer/SDKs/MacOSX10.3.9.sdk'
|
||||
LCGDIR = '#../lib/darwin-6.1-powerpc'
|
||||
CC = 'gcc-3.3'
|
||||
CXX = 'g++-3.3'
|
||||
# ppc release are now made for 10.4
|
||||
# MAC_MIN_VERS = '10.3'
|
||||
# MACOSX_SDK='/Developer/SDKs/MacOSX10.3.9.sdk'
|
||||
# LCGDIR = '#../lib/darwin-6.1-powerpc'
|
||||
# CC = 'gcc-3.3'
|
||||
# CXX = 'g++-3.3'
|
||||
MAC_MIN_VERS = '10.4'
|
||||
MACOSX_SDK='/Developer/SDKs/MacOSX10.4u.sdk'
|
||||
LCGDIR = '#../lib/darwin-8.0.0-powerpc'
|
||||
CC = 'gcc-4.0'
|
||||
CXX = 'g++-4.0'
|
||||
elif MACOSX_ARCHITECTURE == 'i386':
|
||||
MAC_MIN_VERS = '10.4'
|
||||
MACOSX_SDK='/Developer/SDKs/MacOSX10.4u.sdk'
|
||||
@ -147,7 +153,7 @@ BF_JACK_INC = '${BF_JACK}/include/jack'
|
||||
BF_JACK_LIB = 'jack'
|
||||
BF_JACK_LIBPATH = '${BF_JACK}/lib'
|
||||
|
||||
WITH_BF_SNDFILE = False
|
||||
WITH_BF_SNDFILE = True
|
||||
BF_SNDFILE = LIBDIR + '/sndfile'
|
||||
BF_SNDFILE_INC = '${BF_SNDFILE}/include'
|
||||
BF_SNDFILE_LIB = 'sndfile'
|
||||
@ -205,7 +211,7 @@ BF_BULLET = '#extern/bullet2/src'
|
||||
BF_BULLET_INC = '${BF_BULLET}'
|
||||
BF_BULLET_LIB = 'extern_bullet'
|
||||
|
||||
WITH_BF_FFTW3 = False
|
||||
WITH_BF_FFTW3 = True
|
||||
BF_FFTW3 = LIBDIR + '/fftw3'
|
||||
BF_FFTW3_INC = '${BF_FFTW3}/include'
|
||||
BF_FFTW3_LIB = 'libfftw3'
|
||||
@ -249,7 +255,7 @@ BF_OPENGL_LIBPATH = '/System/Library/Frameworks/OpenGL.framework/Libraries'
|
||||
BF_OPENGL_LINKFLAGS = ['-framework', 'OpenGL']
|
||||
|
||||
#OpenCollada flags
|
||||
WITH_BF_COLLADA = True
|
||||
WITH_BF_COLLADA = False
|
||||
BF_COLLADA = '#source/blender/collada'
|
||||
BF_COLLADA_INC = '${BF_COLLADA}'
|
||||
BF_COLLADA_LIB = 'bf_collada'
|
||||
@ -303,8 +309,8 @@ if MAC_MIN_VERS == '10.3':
|
||||
LLIBS.append('crt3.o')
|
||||
|
||||
if USE_SDK==True:
|
||||
SDK_FLAGS=['-isysroot', MACOSX_SDK,'-mmacosx-version-min='+MAC_MIN_VERS]
|
||||
PLATFORM_LINKFLAGS = ['-mmacosx-version-min='+MAC_MIN_VERS,'-Wl','-syslibroot '+MACOSX_SDK]+PLATFORM_LINKFLAGS
|
||||
SDK_FLAGS=['-isysroot', MACOSX_SDK,'-mmacosx-version-min='+MAC_MIN_VERS,'-arch',MACOSX_ARCHITECTURE]
|
||||
PLATFORM_LINKFLAGS = ['-mmacosx-version-min='+MAC_MIN_VERS,'-Wl','-syslibroot '+MACOSX_SDK,'-arch',MACOSX_ARCHITECTURE]+PLATFORM_LINKFLAGS
|
||||
CCFLAGS=SDK_FLAGS+CCFLAGS
|
||||
CXXFLAGS=SDK_FLAGS+CXXFLAGS
|
||||
|
||||
|
@ -155,9 +155,9 @@ WITH_BF_COLLADA = False
|
||||
BF_COLLADA = '#source/blender/collada'
|
||||
BF_COLLADA_INC = '${BF_COLLADA}'
|
||||
BF_COLLADA_LIB = 'bf_collada'
|
||||
BF_OPENCOLLADA = ''
|
||||
BF_OPENCOLLADA_LIB = 'OpenCollada'
|
||||
BF_OPENCOLLADA_LIBPATH = '/usr/lib'
|
||||
BF_OPENCOLLADA = '/usr'
|
||||
BF_OPENCOLLADA_LIB = 'OpenCOLLADAStreamWriter OpenCOLLADASaxFrameworkLoader OpenCOLLADAFramework OpenCOLLADABaseUtils GeneratedSaxParser UTF MathMLSolver pcre Buffer ftoa'
|
||||
BF_OPENCOLLADA_LIBPATH = '${BF_OPENCOLLADA}/lib'
|
||||
BF_PCRE = ''
|
||||
BF_PCRE_LIB = 'pcre'
|
||||
BF_PCRE_LIBPATH = '/usr/lib'
|
||||
|
@ -127,8 +127,15 @@ BF_OPENGL_LIB_STATIC = [ '${BF_OPENGL}/lib/libGL.a', '${BF_OPENGL}/lib/libGLU.a'
|
||||
'${BF_OPENGL}/lib/libXmu.a', '${BF_OPENGL}/lib/libXext.a',
|
||||
'${BF_OPENGL}/lib/libX11.a', '${BF_OPENGL}/lib/libXi.a' ]
|
||||
|
||||
# Disable Collada by default
|
||||
WITH_BF_COLLADA = False
|
||||
WITH_BF_COLLADA = True
|
||||
BF_COLLADA = '#source/blender/collada'
|
||||
BF_COLLADA_INC = '${BF_COLLADA}'
|
||||
BF_COLLADA_LIB = 'bf_collada'
|
||||
|
||||
BF_OPENCOLLADA = LIBDIR + '/opencollada'
|
||||
BF_OPENCOLLADA_INC = '${BF_OPENCOLLADA}/include'
|
||||
BF_OPENCOLLADA_LIB = 'OpenCOLLADAStreamWriter OpenCOLLADASaxFrameworkLoader OpenCOLLADAFramework OpenCOLLADABaseUtils GeneratedSaxParser UTF MathMLSolver xml2 pcre'
|
||||
BF_OPENCOLLADA_LIBPATH = '${BF_OPENCOLLADA}/lib'
|
||||
|
||||
##
|
||||
CC = 'gcc'
|
||||
@ -145,7 +152,7 @@ C_WARN = [ '-Wno-char-subscripts', '-Wdeclaration-after-statement' ]
|
||||
|
||||
CC_WARN = [ '-Wall' ]
|
||||
|
||||
LLIBS = ['-lshell32', '-lshfolder', '-lgdi32', '-lmsvcrt', '-lwinmm', '-lmingw32', '-lm', '-lws2_32', '-lz', '-lstdc++']
|
||||
LLIBS = ['-lshell32', '-lshfolder', '-lgdi32', '-lmsvcrt', '-lwinmm', '-lmingw32', '-lm', '-lws2_32', '-lz', '-lstdc++','-lole32','-luuid']
|
||||
|
||||
BF_DEBUG = False
|
||||
BF_DEBUG_CCFLAGS= ['-g']
|
||||
|
2
extern/Eigen2/Eigen/src/Core/util/Macros.h
vendored
2
extern/Eigen2/Eigen/src/Core/util/Macros.h
vendored
@ -39,7 +39,7 @@
|
||||
// 16 byte alignment is only useful for vectorization. Since it affects the ABI, we need to enable 16 byte alignment on all
|
||||
// platforms where vectorization might be enabled. In theory we could always enable alignment, but it can be a cause of problems
|
||||
// on some platforms, so we just disable it in certain common platform (compiler+architecture combinations) to avoid these problems.
|
||||
#if defined(__GNUC__) && !(defined(__i386__) || defined(__x86_64__) || defined(__powerpc__) || defined(__ia64__))
|
||||
#if defined(__GNUC__) && !(defined(__i386__) || defined(__x86_64__) || defined(__powerpc__) || defined(__ia64__) || defined(__ppc__))
|
||||
#define EIGEN_GCC_AND_ARCH_DOESNT_WANT_ALIGNMENT 1
|
||||
#else
|
||||
#define EIGEN_GCC_AND_ARCH_DOESNT_WANT_ALIGNMENT 0
|
||||
|
@ -152,6 +152,10 @@ BT_DECLARE_ALIGNED_ALLOCATOR();
|
||||
{
|
||||
return (proxyType == STATIC_PLANE_PROXYTYPE);
|
||||
}
|
||||
static SIMD_FORCE_INLINE bool isSoftBody(int proxyType)
|
||||
{
|
||||
return (proxyType == SOFTBODY_SHAPE_PROXYTYPE);
|
||||
}
|
||||
|
||||
}
|
||||
;
|
||||
|
@ -31,6 +31,7 @@ subject to the following restrictions:
|
||||
#include "LinearMath/btAabbUtil2.h"
|
||||
#include "LinearMath/btQuickprof.h"
|
||||
#include "LinearMath/btStackAlloc.h"
|
||||
#include "BulletSoftBody/btSoftBody.h"
|
||||
|
||||
//#define USE_BRUTEFORCE_RAYBROADPHASE 1
|
||||
//RECALCULATE_AABB is slower, but benefit is that you don't need to call 'stepSimulation' or 'updateAabbs' before using a rayTest
|
||||
@ -411,6 +412,31 @@ void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTra
|
||||
// restore
|
||||
collisionObject->internalSetTemporaryCollisionShape(saveCollisionShape);
|
||||
}
|
||||
} else {
|
||||
if (collisionShape->isSoftBody()) {
|
||||
btSoftBody* softBody = static_cast<btSoftBody*>(collisionObject);
|
||||
btSoftBody::sRayCast softResult;
|
||||
if (softBody->rayTest(rayFromTrans.getOrigin(), rayToTrans.getOrigin(), softResult))
|
||||
{
|
||||
btCollisionWorld::LocalShapeInfo shapeInfo;
|
||||
shapeInfo.m_shapePart = 0;
|
||||
shapeInfo.m_triangleIndex = softResult.index;
|
||||
// get the normal
|
||||
btVector3 normal = softBody->m_faces[softResult.index].m_normal;
|
||||
btVector3 rayDir = rayToTrans.getOrigin() - rayFromTrans.getOrigin();
|
||||
if (normal.dot(rayDir) > 0) {
|
||||
// normal always point toward origin of the ray
|
||||
normal = -normal;
|
||||
}
|
||||
btCollisionWorld::LocalRayResult rayResult
|
||||
(collisionObject,
|
||||
&shapeInfo,
|
||||
normal,
|
||||
softResult.fraction);
|
||||
bool normalInWorldSpace = true;
|
||||
resultCallback.addSingleResult(rayResult,normalInWorldSpace);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -72,6 +72,10 @@ public:
|
||||
{
|
||||
return btBroadphaseProxy::isCompound(getShapeType());
|
||||
}
|
||||
SIMD_FORCE_INLINE bool isSoftBody() const
|
||||
{
|
||||
return btBroadphaseProxy::isSoftBody(getShapeType());
|
||||
}
|
||||
|
||||
///isInfinite is used to catch simulation error (aabb check)
|
||||
SIMD_FORCE_INLINE bool isInfinite() const
|
||||
|
@ -828,7 +828,8 @@ btSoftBody* btSoftBodyHelpers::CreateFromTriMesh(btSoftBodyWorldInfo& worldInfo
|
||||
#undef IDX
|
||||
psb->appendFace(idx[0],idx[1],idx[2]);
|
||||
}
|
||||
psb->randomizeConstraints();
|
||||
// don't randomize now, let's give a chance to the application to set face data
|
||||
//psb->randomizeConstraints();
|
||||
return(psb);
|
||||
}
|
||||
|
||||
|
2
extern/bullet2/src/SConscript
vendored
2
extern/bullet2/src/SConscript
vendored
@ -42,4 +42,4 @@ env.BlenderLib ( libname = 'extern_bullet2collision_dispatch', sources=collision
|
||||
env.BlenderLib ( libname = 'extern_bullet2collision_gimpact', sources=collision_gimpact_src, includes=Split(incs), defines=Split(defs), libtype=['extern','player'], priority=[20,138], compileflags=cflags )
|
||||
env.BlenderLib ( libname = 'extern_bullet2collision_shapes', sources=collision_shapes_src, includes=Split(incs), defines=Split(defs), libtype=['extern','player'], priority=[20,138], compileflags=cflags )
|
||||
env.BlenderLib ( libname = 'extern_bullet2collision_narrowphase', sources=collision_narrowphase_src, includes=Split(incs), defines=Split(defs), libtype=['extern','player'], priority=[20,138], compileflags=cflags )
|
||||
env.BlenderLib ( libname = 'extern_bullet2softbody', sources=softbody_src, includes=Split(incs), defines=Split(defs), libtype=['extern','player'], priority=[18,135], compileflags=cflags )
|
||||
env.BlenderLib ( libname = 'extern_bullet2softbody', sources=softbody_src, includes=Split(incs), defines=Split(defs), libtype=['extern','player'], priority=[30,135], compileflags=cflags )
|
||||
|
@ -310,7 +310,7 @@ void BOP_intersectCoplanarFaces(BOP_Mesh* mesh,
|
||||
}
|
||||
|
||||
MT_Vector3 p3p1 = p1-p3;
|
||||
MT_Plane3 plane3((p3p1.cross(normal).normalized()),p3);
|
||||
MT_Plane3 plane3((p3p1.cross(normal).safe_normalized()),p3);
|
||||
|
||||
sA.m_cfg1 = BOP_Segment::createVertexCfg(3);
|
||||
sA.m_v1 = faceA->getVertex(2);
|
||||
@ -528,7 +528,7 @@ void BOP_mergeSort(MT_Point3 *points, unsigned int *face, unsigned int &size, bo
|
||||
invertB = false;
|
||||
if (face[1] == 1) {
|
||||
|
||||
// invertA¿?
|
||||
// invertAø?
|
||||
for(i=0;i<size;i++) {
|
||||
if (position[i] == 1) {
|
||||
invertA = true;
|
||||
@ -537,7 +537,7 @@ void BOP_mergeSort(MT_Point3 *points, unsigned int *face, unsigned int &size, bo
|
||||
else if (position[i] == 0) break;
|
||||
}
|
||||
|
||||
// invertB¿?
|
||||
// invertBø?
|
||||
if (size == 4) {
|
||||
for(i=0;i<size;i++) {
|
||||
if (position[i] == 3) {
|
||||
@ -549,7 +549,7 @@ void BOP_mergeSort(MT_Point3 *points, unsigned int *face, unsigned int &size, bo
|
||||
}
|
||||
}
|
||||
else if (face[1] == 2) {
|
||||
// invertB¿?
|
||||
// invertBø?
|
||||
for(i=0;i<size;i++) {
|
||||
if (position[i] == 2) {
|
||||
invertB = true;
|
||||
|
@ -41,9 +41,14 @@ IF(APPLE)
|
||||
LIST(REMOVE_ITEM SRC "${CMAKE_CURRENT_SOURCE_DIR}/intern/GHOST_DisplayManagerWin32.cpp")
|
||||
LIST(REMOVE_ITEM SRC "${CMAKE_CURRENT_SOURCE_DIR}/intern/GHOST_SystemWin32.cpp")
|
||||
LIST(REMOVE_ITEM SRC "${CMAKE_CURRENT_SOURCE_DIR}/intern/GHOST_WindowWin32.cpp")
|
||||
LIST(REMOVE_ITEM SRC "${CMAKE_CURRENT_SOURCE_DIR}/intern/GHOST_DropTargetWin32.cpp")
|
||||
LIST(REMOVE_ITEM SRC "${CMAKE_CURRENT_SOURCE_DIR}/intern/GHOST_DisplayManagerX11.cpp")
|
||||
LIST(REMOVE_ITEM SRC "${CMAKE_CURRENT_SOURCE_DIR}/intern/GHOST_SystemX11.cpp")
|
||||
LIST(REMOVE_ITEM SRC "${CMAKE_CURRENT_SOURCE_DIR}/intern/GHOST_WindowX11.cpp")
|
||||
|
||||
IF(WITH_QUICKTIME)
|
||||
ADD_DEFINITIONS(-DWITH_QUICKTIME)
|
||||
ENDIF(WITH_QUICKTIME)
|
||||
ELSE(APPLE)
|
||||
IF(WIN32)
|
||||
SET(INC ${INC} ${WINTAB_INC})
|
||||
@ -59,6 +64,7 @@ ELSE(APPLE)
|
||||
ELSE(WIN32)
|
||||
SET(INC ${INC} ${X11_X11_INCLUDE_PATH})
|
||||
LIST(REMOVE_ITEM SRC "${CMAKE_CURRENT_SOURCE_DIR}/intern/GHOST_DisplayManagerWin32.cpp")
|
||||
LIST(REMOVE_ITEM SRC "${CMAKE_CURRENT_SOURCE_DIR}/intern/GHOST_DropTargetWin32.cpp")
|
||||
LIST(REMOVE_ITEM SRC "${CMAKE_CURRENT_SOURCE_DIR}/intern/GHOST_SystemWin32.cpp")
|
||||
LIST(REMOVE_ITEM SRC "${CMAKE_CURRENT_SOURCE_DIR}/intern/GHOST_WindowWin32.cpp")
|
||||
LIST(REMOVE_ITEM SRC "${CMAKE_CURRENT_SOURCE_DIR}/intern/GHOST_DisplayManagerCarbon.cpp")
|
||||
|
@ -11,34 +11,54 @@ if window_system == 'darwin':
|
||||
sources += env.Glob('intern/*.mm')
|
||||
|
||||
|
||||
pf = ['GHOST_DisplayManager', 'GHOST_System', 'GHOST_Window']
|
||||
pf = ['GHOST_DisplayManager', 'GHOST_System', 'GHOST_Window', 'GHOST_DropTarget']
|
||||
defs=['_USE_MATH_DEFINES']
|
||||
|
||||
if window_system in ('linux2', 'openbsd3', 'sunos5', 'freebsd6', 'irix6'):
|
||||
for f in pf:
|
||||
try:
|
||||
sources.remove('intern' + os.sep + f + 'Win32.cpp')
|
||||
sources.remove('intern' + os.sep + f + 'Carbon.cpp')
|
||||
except ValueError:
|
||||
pass
|
||||
elif window_system in ('win32-vc', 'win32-mingw', 'cygwin', 'linuxcross', 'win64-vc'):
|
||||
for f in pf:
|
||||
try:
|
||||
sources.remove('intern' + os.sep + f + 'X11.cpp')
|
||||
sources.remove('intern' + os.sep + f + 'Carbon.cpp')
|
||||
except ValueError:
|
||||
pass
|
||||
elif window_system == 'darwin':
|
||||
if env['WITH_GHOST_COCOA']:
|
||||
if env['WITH_BF_QUICKTIME']:
|
||||
defs.append('WITH_QUICKTIME')
|
||||
if env['USE_QTKIT']:
|
||||
defs.append('USE_QTKIT')
|
||||
for f in pf:
|
||||
try:
|
||||
sources.remove('intern' + os.sep + f + 'Win32.cpp')
|
||||
sources.remove('intern' + os.sep + f + 'X11.cpp')
|
||||
sources.remove('intern' + os.sep + f + 'Carbon.cpp')
|
||||
except ValueError:
|
||||
pass
|
||||
else:
|
||||
for f in pf:
|
||||
try:
|
||||
sources.remove('intern' + os.sep + f + 'Win32.cpp')
|
||||
sources.remove('intern' + os.sep + f + 'X11.cpp')
|
||||
sources.remove('intern' + os.sep + f + 'Cocoa.mm')
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
else:
|
||||
print "Unknown window system specified."
|
||||
Exit()
|
||||
|
||||
if env['BF_GHOST_DEBUG']:
|
||||
defs.append('BF_GHOST_DEBUG')
|
||||
|
||||
incs = '. ../string ' + env['BF_OPENGL_INC']
|
||||
if window_system in ('win32-vc', 'win32-mingw', 'cygwin', 'linuxcross', 'win64-vc'):
|
||||
incs = env['BF_WINTAB_INC'] + ' ' + incs
|
||||
env.BlenderLib ('bf_ghost', sources, Split(incs), defines=['_USE_MATH_DEFINES'], libtype=['intern','player'], priority = [40,15] )
|
||||
env.BlenderLib ('bf_ghost', sources, Split(incs), defines=defs, libtype=['intern','player'], priority = [40,15] )
|
||||
|
||||
|
@ -37,12 +37,17 @@
|
||||
#ifdef WIN32
|
||||
#ifdef _DEBUG
|
||||
#pragma warning (disable:4786) // suppress stl-MSVC debug info warning
|
||||
#define GHOST_DEBUG
|
||||
// #define GHOST_DEBUG
|
||||
#endif // _DEBUG
|
||||
#endif // WIN32
|
||||
|
||||
#ifdef BF_GHOST_DEBUG
|
||||
#define GHOST_DEBUG // spit ghost events to stdout
|
||||
#endif // BF_GHOST_DEBUG
|
||||
|
||||
#ifdef GHOST_DEBUG
|
||||
#include <iostream>
|
||||
#include <stdio.h> //for printf()
|
||||
#endif // GHOST_DEBUG
|
||||
|
||||
|
||||
|
426
intern/ghost/intern/GHOST_DropTargetWin32.cpp
Normal file
426
intern/ghost/intern/GHOST_DropTargetWin32.cpp
Normal file
@ -0,0 +1,426 @@
|
||||
/**
|
||||
* $Id$
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 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 *****
|
||||
*/
|
||||
|
||||
#include "GHOST_Debug.h"
|
||||
#include "GHOST_DropTargetWin32.h"
|
||||
|
||||
#ifdef GHOST_DEBUG
|
||||
// utility
|
||||
void printLastError(void);
|
||||
#endif // GHOST_DEBUG
|
||||
|
||||
|
||||
GHOST_DropTargetWin32::GHOST_DropTargetWin32(GHOST_WindowWin32 * window, GHOST_SystemWin32 * system)
|
||||
:
|
||||
m_window(window),
|
||||
m_system(system)
|
||||
{
|
||||
m_cRef = 1;
|
||||
m_hWnd = window->getHWND();
|
||||
m_draggedObjectType = GHOST_kDragnDropTypeUnknown;
|
||||
|
||||
// register our window as drop target
|
||||
::RegisterDragDrop(m_hWnd, this);
|
||||
}
|
||||
|
||||
GHOST_DropTargetWin32::~GHOST_DropTargetWin32()
|
||||
{
|
||||
::RevokeDragDrop(m_hWnd);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* IUnknown::QueryInterface
|
||||
*/
|
||||
HRESULT __stdcall GHOST_DropTargetWin32::QueryInterface (REFIID riid, void ** ppvObj)
|
||||
{
|
||||
|
||||
if (!ppvObj)
|
||||
return E_INVALIDARG;
|
||||
*ppvObj = NULL;
|
||||
|
||||
if(riid == IID_IUnknown || riid == IID_IDropTarget)
|
||||
{
|
||||
AddRef();
|
||||
*ppvObj = (void*)this;
|
||||
return S_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
*ppvObj = 0;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* IUnknown::AddRef
|
||||
*/
|
||||
|
||||
ULONG __stdcall GHOST_DropTargetWin32::AddRef(void)
|
||||
{
|
||||
return ::InterlockedIncrement(&m_cRef);
|
||||
}
|
||||
|
||||
/*
|
||||
* IUnknown::Release
|
||||
*/
|
||||
ULONG __stdcall GHOST_DropTargetWin32::Release(void)
|
||||
{
|
||||
ULONG refs = ::InterlockedDecrement(&m_cRef);
|
||||
|
||||
if(refs == 0)
|
||||
{
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return refs;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Implementation of IDropTarget::DragEnter
|
||||
*/
|
||||
HRESULT __stdcall GHOST_DropTargetWin32::DragEnter(IDataObject * pDataObject, DWORD grfKeyState, POINTL pt, DWORD * pdwEffect)
|
||||
{
|
||||
// we don't know yet if we accept the drop.
|
||||
m_window->setAcceptDragOperation(false);
|
||||
*pdwEffect = DROPEFFECT_NONE;
|
||||
|
||||
m_draggedObjectType = getGhostType(pDataObject);
|
||||
m_system->pushDragDropEvent(GHOST_kEventDraggingEntered, m_draggedObjectType, m_window, pt.x, pt.y, NULL);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Implementation of IDropTarget::DragOver
|
||||
*/
|
||||
HRESULT __stdcall GHOST_DropTargetWin32::DragOver(DWORD grfKeyState, POINTL pt, DWORD * pdwEffect)
|
||||
{
|
||||
if(m_window->canAcceptDragOperation())
|
||||
{
|
||||
*pdwEffect = allowedDropEffect(*pdwEffect);
|
||||
}
|
||||
else
|
||||
{
|
||||
*pdwEffect = DROPEFFECT_NONE;
|
||||
//*pdwEffect = DROPEFFECT_COPY; // XXX Uncomment to test drop. Drop will not be called if pdwEffect == DROPEFFECT_NONE.
|
||||
}
|
||||
m_system->pushDragDropEvent(GHOST_kEventDraggingUpdated, m_draggedObjectType, m_window, pt.x, pt.y, NULL);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Implementation of IDropTarget::DragLeave
|
||||
*/
|
||||
HRESULT __stdcall GHOST_DropTargetWin32::DragLeave(void)
|
||||
{
|
||||
m_system->pushDragDropEvent(GHOST_kEventDraggingExited, m_draggedObjectType, m_window, 0, 0, NULL);
|
||||
m_draggedObjectType = GHOST_kDragnDropTypeUnknown;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/* Implementation of IDropTarget::Drop
|
||||
* This function will not be called if pdwEffect is set to DROPEFFECT_NONE in
|
||||
* the implementation of IDropTarget::DragOver
|
||||
*/
|
||||
HRESULT __stdcall GHOST_DropTargetWin32::Drop(IDataObject * pDataObject, DWORD grfKeyState, POINTL pt, DWORD * pdwEffect)
|
||||
{
|
||||
void * data = getGhostData(pDataObject);
|
||||
if(m_window->canAcceptDragOperation())
|
||||
{
|
||||
*pdwEffect = allowedDropEffect(*pdwEffect);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
*pdwEffect = DROPEFFECT_NONE;
|
||||
}
|
||||
if (data)
|
||||
m_system->pushDragDropEvent(GHOST_kEventDraggingDropDone, m_draggedObjectType, m_window, pt.x, pt.y, data );
|
||||
|
||||
m_draggedObjectType = GHOST_kDragnDropTypeUnknown;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Helpers
|
||||
*/
|
||||
|
||||
DWORD GHOST_DropTargetWin32::allowedDropEffect(DWORD dwAllowed)
|
||||
{
|
||||
DWORD dwEffect = DROPEFFECT_NONE;
|
||||
if(dwAllowed & DROPEFFECT_COPY)
|
||||
dwEffect = DROPEFFECT_COPY;
|
||||
|
||||
return dwEffect;
|
||||
}
|
||||
|
||||
GHOST_TDragnDropTypes GHOST_DropTargetWin32::getGhostType(IDataObject * pDataObject)
|
||||
{
|
||||
/* Text
|
||||
* Note: Unicode text is aviable as CF_TEXT too, the system can do the
|
||||
* conversion, but we do the conversion ourself with WC_NO_BEST_FIT_CHARS.
|
||||
*/
|
||||
FORMATETC fmtetc = { CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
|
||||
if(pDataObject->QueryGetData(&fmtetc) == S_OK)
|
||||
{
|
||||
return GHOST_kDragnDropTypeString;
|
||||
}
|
||||
|
||||
// Filesnames
|
||||
fmtetc.cfFormat = CF_HDROP;
|
||||
if(pDataObject->QueryGetData(&fmtetc) == S_OK)
|
||||
{
|
||||
return GHOST_kDragnDropTypeFilenames;
|
||||
}
|
||||
|
||||
return GHOST_kDragnDropTypeUnknown;
|
||||
}
|
||||
|
||||
void * GHOST_DropTargetWin32::getGhostData(IDataObject * pDataObject)
|
||||
{
|
||||
GHOST_TDragnDropTypes type = getGhostType(pDataObject);
|
||||
switch(type)
|
||||
{
|
||||
case GHOST_kDragnDropTypeFilenames:
|
||||
return getDropDataAsFilenames(pDataObject);
|
||||
break;
|
||||
case GHOST_kDragnDropTypeString:
|
||||
return getDropDataAsString(pDataObject);
|
||||
break;
|
||||
case GHOST_kDragnDropTypeBitmap:
|
||||
//return getDropDataAsBitmap(pDataObject);
|
||||
break;
|
||||
default:
|
||||
#ifdef GHOST_DEBUG
|
||||
::printf("\nGHOST_kDragnDropTypeUnknown");
|
||||
#endif // GHOST_DEBUG
|
||||
return NULL;
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void * GHOST_DropTargetWin32::getDropDataAsFilenames(IDataObject * pDataObject)
|
||||
{
|
||||
UINT totfiles, nvalid=0;
|
||||
WCHAR fpath [MAX_PATH];
|
||||
char * temp_path;
|
||||
GHOST_TStringArray *strArray = NULL;
|
||||
FORMATETC fmtetc = { CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
|
||||
STGMEDIUM stgmed;
|
||||
HDROP hdrop;
|
||||
|
||||
// Check if dataobject supplies the format we want.
|
||||
// Double checking here, first in getGhostType.
|
||||
if(pDataObject->QueryGetData(&fmtetc) == S_OK)
|
||||
{
|
||||
if(pDataObject->GetData(&fmtetc, &stgmed) == S_OK)
|
||||
{
|
||||
hdrop = (HDROP)::GlobalLock(stgmed.hGlobal);
|
||||
|
||||
totfiles = ::DragQueryFileW ( hdrop, -1, NULL, 0 );
|
||||
if (!totfiles)
|
||||
{
|
||||
::GlobalUnlock(stgmed.hGlobal);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strArray = (GHOST_TStringArray*) ::malloc(sizeof(GHOST_TStringArray));
|
||||
strArray->count = 0;
|
||||
strArray->strings = (GHOST_TUns8**) ::malloc(totfiles*sizeof(GHOST_TUns8*));
|
||||
|
||||
for ( UINT nfile = 0; nfile < totfiles; nfile++ )
|
||||
{
|
||||
if ( ::DragQueryFileW ( hdrop, nfile, fpath, MAX_PATH ) > 0 )
|
||||
{
|
||||
if ( !WideCharToANSI(fpath, temp_path) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
// Just ignore paths that could not be converted verbatim.
|
||||
if (strpbrk(temp_path, "?"))
|
||||
{
|
||||
#ifdef GHOST_DEBUG
|
||||
::printf("\ndiscarding path that contains illegal characters: %s", temp_path);
|
||||
#endif // GHOST_DEBUG
|
||||
::free(temp_path);
|
||||
temp_path = NULL;
|
||||
continue;
|
||||
}
|
||||
strArray->strings[nvalid] = (GHOST_TUns8*) temp_path;
|
||||
strArray->count = nvalid+1;
|
||||
nvalid++;
|
||||
}
|
||||
}
|
||||
// Free up memory.
|
||||
::GlobalUnlock(stgmed.hGlobal);
|
||||
::ReleaseStgMedium(&stgmed);
|
||||
|
||||
return strArray;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void * GHOST_DropTargetWin32::getDropDataAsString(IDataObject * pDataObject)
|
||||
{
|
||||
char* tmp_string;
|
||||
FORMATETC fmtetc = { CF_UNICODETEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
|
||||
STGMEDIUM stgmed;
|
||||
|
||||
// Try unicode first.
|
||||
// Check if dataobject supplies the format we want.
|
||||
if(pDataObject->QueryGetData(&fmtetc) == S_OK)
|
||||
{
|
||||
if(pDataObject->GetData(&fmtetc, &stgmed) == S_OK)
|
||||
{
|
||||
LPCWSTR wstr = (LPCWSTR)::GlobalLock(stgmed.hGlobal);
|
||||
if ( !WideCharToANSI(wstr, tmp_string) )
|
||||
{
|
||||
::GlobalUnlock(stgmed.hGlobal);
|
||||
return NULL;
|
||||
}
|
||||
// Free memory
|
||||
::GlobalUnlock(stgmed.hGlobal);
|
||||
::ReleaseStgMedium(&stgmed);
|
||||
#ifdef GHOST_DEBUG
|
||||
::printf("\n<converted droped unicode string>\n%s\n</droped converted unicode string>\n",tmp_string);
|
||||
#endif // GHOST_DEBUG
|
||||
return tmp_string;
|
||||
}
|
||||
}
|
||||
|
||||
fmtetc.cfFormat = CF_TEXT;
|
||||
|
||||
if(pDataObject->QueryGetData(&fmtetc) == S_OK)
|
||||
{
|
||||
if(pDataObject->GetData(&fmtetc, &stgmed) == S_OK)
|
||||
{
|
||||
char * str = (char*)::GlobalLock(stgmed.hGlobal);
|
||||
|
||||
tmp_string = (char*)::malloc(::strlen(str)+1);
|
||||
if ( !tmp_string )
|
||||
{
|
||||
::GlobalUnlock(stgmed.hGlobal);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( !::strcpy(tmp_string, str) )
|
||||
{
|
||||
::free(tmp_string);
|
||||
::GlobalUnlock(stgmed.hGlobal);
|
||||
return NULL;
|
||||
}
|
||||
// Free memory
|
||||
::GlobalUnlock(stgmed.hGlobal);
|
||||
::ReleaseStgMedium(&stgmed);
|
||||
|
||||
return tmp_string;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int GHOST_DropTargetWin32::WideCharToANSI(LPCWSTR in, char * &out)
|
||||
{
|
||||
int size;
|
||||
out = NULL; //caller should free if != NULL
|
||||
|
||||
// Get the required size.
|
||||
size = ::WideCharToMultiByte(CP_ACP, //System Default Codepage
|
||||
0x00000400, // WC_NO_BEST_FIT_CHARS
|
||||
in,
|
||||
-1, //-1 null terminated, makes output null terminated too.
|
||||
NULL,
|
||||
0,
|
||||
NULL,NULL
|
||||
);
|
||||
|
||||
if(!size)
|
||||
{
|
||||
#ifdef GHOST_DEBUG
|
||||
::printLastError();
|
||||
#endif // GHOST_DEBUG
|
||||
return 0;
|
||||
}
|
||||
|
||||
out = (char*)::malloc(size);
|
||||
if (!out)
|
||||
{
|
||||
::printf("\nmalloc failed!!!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
size = ::WideCharToMultiByte(CP_ACP,
|
||||
0x00000400,
|
||||
in,
|
||||
-1,
|
||||
(LPSTR) out,
|
||||
size,
|
||||
NULL,NULL
|
||||
);
|
||||
|
||||
if(!size)
|
||||
{
|
||||
#ifdef GHOST_DEBUG
|
||||
::printLastError();
|
||||
#endif //GHOST_DEBUG
|
||||
::free(out);
|
||||
out = NULL;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
#ifdef GHOST_DEBUG
|
||||
void printLastError(void)
|
||||
{
|
||||
LPTSTR s;
|
||||
DWORD err;
|
||||
|
||||
err = GetLastError();
|
||||
if(FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM,
|
||||
NULL,
|
||||
err,
|
||||
0,
|
||||
(LPTSTR)&s,
|
||||
0,
|
||||
NULL)
|
||||
)
|
||||
{
|
||||
printf("\nLastError: (%d) %s\n", (int)err, s);
|
||||
LocalFree(s);
|
||||
}
|
||||
}
|
||||
#endif // GHOST_DEBUG
|
||||
|
155
intern/ghost/intern/GHOST_DropTargetWin32.h
Normal file
155
intern/ghost/intern/GHOST_DropTargetWin32.h
Normal file
@ -0,0 +1,155 @@
|
||||
/**
|
||||
* $Id$
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 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 *****
|
||||
*/
|
||||
#ifndef _GHOST_DROP_TARGET_WIN32_H_
|
||||
#define _GHOST_DROP_TARGET_WIN32_H_
|
||||
|
||||
#include <windows.h>
|
||||
#include <string.h>
|
||||
#include <GHOST_Types.h>
|
||||
#include "GHOST_WindowWin32.h"
|
||||
#include "GHOST_SystemWin32.h"
|
||||
|
||||
class GHOST_DropTargetWin32 : public IDropTarget
|
||||
{
|
||||
public:
|
||||
/* IUnknownd implementation.
|
||||
* Enables clients to get pointers to other interfaces on a given object
|
||||
* through the QueryInterface method, and manage the existence of the object
|
||||
* through the AddRef and Release methods. All other COM interfaces are
|
||||
* inherited, directly or indirectly, from IUnknown. Therefore, the three
|
||||
* methods in IUnknown are the first entries in the VTable for every interface.
|
||||
*/
|
||||
HRESULT __stdcall QueryInterface (REFIID riid, void ** ppvObj);
|
||||
ULONG __stdcall AddRef (void);
|
||||
ULONG __stdcall Release (void);
|
||||
|
||||
/* IDropTarget implementation
|
||||
+ The IDropTarget interface is one of the interfaces you implement to
|
||||
provide drag-and-drop operations in your application. It contains methods
|
||||
used in any application that can be a target for data during a
|
||||
drag-and-drop operation. A drop-target application is responsible for:
|
||||
*
|
||||
* - Determining the effect of the drop on the target application.
|
||||
* - Incorporating any valid dropped data when the drop occurs.
|
||||
* - Communicating target feedback to the source so the source application
|
||||
* can provide appropriate visual feedback such as setting the cursor.
|
||||
* - Implementing drag scrolling.
|
||||
* - Registering and revoking its application windows as drop targets.
|
||||
*
|
||||
* The IDropTarget interface contains methods that handle all these
|
||||
* responsibilities except registering and revoking the application window
|
||||
* as a drop target, for which you must call the RegisterDragDrop and the
|
||||
* RevokeDragDrop functions.
|
||||
*/
|
||||
|
||||
HRESULT __stdcall DragEnter (IDataObject * pDataObject, DWORD grfKeyState, POINTL pt, DWORD * pdwEffect);
|
||||
HRESULT __stdcall DragOver (DWORD grfKeyState, POINTL pt, DWORD * pdwEffect);
|
||||
HRESULT __stdcall DragLeave (void);
|
||||
HRESULT __stdcall Drop (IDataObject * pDataObject, DWORD grfKeyState, POINTL pt, DWORD * pdwEffect);
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* With the modifier keys, we want to distinguish left and right keys.
|
||||
* Sometimes this is not possible (Windows ME for instance). Then, we want
|
||||
* events generated for both keys.
|
||||
* @param window The window to register as drop target.
|
||||
* @param system The associated system.
|
||||
*/
|
||||
GHOST_DropTargetWin32(GHOST_WindowWin32 * window, GHOST_SystemWin32 * system);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
* Do NOT destroy directly. Use Release() instead to make COM happy.
|
||||
*/
|
||||
~GHOST_DropTargetWin32();
|
||||
|
||||
private:
|
||||
|
||||
/* Internal helper functions */
|
||||
|
||||
/**
|
||||
* Base the effect on those allowed by the dropsource.
|
||||
* @param dwAllowed Drop sources allowed drop effect.
|
||||
* @return The allowed drop effect.
|
||||
*/
|
||||
DWORD allowedDropEffect(DWORD dwAllowed);
|
||||
|
||||
/**
|
||||
* Query DataObject for the data types it supports.
|
||||
* @param pDataObject Pointer to the DataObject.
|
||||
* @return GHOST data type.
|
||||
*/
|
||||
GHOST_TDragnDropTypes getGhostType(IDataObject * pDataObject);
|
||||
|
||||
/**
|
||||
* Get data to pass in event.
|
||||
* It checks the type and calls specific functions for each type.
|
||||
* @param pDataObject Pointer to the DataObject.
|
||||
* @return Pointer to data.
|
||||
*/
|
||||
void * getGhostData(IDataObject * pDataObject);
|
||||
|
||||
/**
|
||||
* Allocate data as file array to pass in event.
|
||||
* @param pDataObject Pointer to the DataObject.
|
||||
* @return Pointer to data.
|
||||
*/
|
||||
void * getDropDataAsFilenames(IDataObject * pDataObject);
|
||||
|
||||
/**
|
||||
* Allocate data as string to pass in event.
|
||||
* @param pDataObject Pointer to the DataObject.
|
||||
* @return Pointer to data.
|
||||
*/
|
||||
void * getDropDataAsString(IDataObject * pDataObject);
|
||||
|
||||
/**
|
||||
* Convert Unicode to ANSI, replacing unconvertable chars with '?'.
|
||||
* The ANSI codepage is the system default codepage,
|
||||
* and can change from system to system.
|
||||
* @param in LPCWSTR.
|
||||
* @param out char *. Is set to NULL on failure.
|
||||
* @return 0 on failure. Else the size of the string including '\0'.
|
||||
*/
|
||||
int WideCharToANSI(LPCWSTR in, char * &out);
|
||||
|
||||
/* Private member variables */
|
||||
/* COM reference count. */
|
||||
LONG m_cRef;
|
||||
/* Handle of the associated window. */
|
||||
HWND m_hWnd;
|
||||
/* The associated GHOST_WindowWin32. */
|
||||
GHOST_WindowWin32 * m_window;
|
||||
/* The System. */
|
||||
GHOST_SystemWin32 * m_system;
|
||||
/* Data type of the dragged object */
|
||||
GHOST_TDragnDropTypes m_draggedObjectType;
|
||||
|
||||
};
|
||||
|
||||
#endif // _GHOST_DROP_TARGET_WIN32_H_
|
@ -49,7 +49,7 @@ bool GHOST_EventPrinter::processEvent(GHOST_IEvent* event)
|
||||
|
||||
if (event->getType() == GHOST_kEventWindowUpdate) return false;
|
||||
|
||||
std::cout << "GHOST_EventPrinter::processEvent, time: " << (GHOST_TInt32)event->getTime() << ", type: ";
|
||||
std::cout << "\nGHOST_EventPrinter::processEvent, time: " << (GHOST_TInt32)event->getTime() << ", type: ";
|
||||
switch (event->getType()) {
|
||||
case GHOST_kEventUnknown:
|
||||
std::cout << "GHOST_kEventUnknown"; handled = false;
|
||||
@ -125,19 +125,21 @@ bool GHOST_EventPrinter::processEvent(GHOST_IEvent* event)
|
||||
case GHOST_kEventDraggingDropDone:
|
||||
{
|
||||
GHOST_TEventDragnDropData* dragnDropData = (GHOST_TEventDragnDropData*)((GHOST_IEvent*)event)->getData();
|
||||
std::cout << "GHOST_kEventDraggingDropDone, dragged object type : " << dragnDropData->dataType;
|
||||
std::cout << "GHOST_kEventDraggingDropDone,";
|
||||
std::cout << " mouse at x=" << dragnDropData->x << " y=" << dragnDropData->y;
|
||||
switch (dragnDropData->dataType) {
|
||||
case GHOST_kDragnDropTypeString:
|
||||
std::cout << " string received = " << (char*)dragnDropData->data;
|
||||
std::cout << " type : GHOST_kDragnDropTypeString,";
|
||||
std::cout << "\n String received = " << (char*)dragnDropData->data;
|
||||
break;
|
||||
case GHOST_kDragnDropTypeFilenames:
|
||||
{
|
||||
GHOST_TStringArray *strArray = (GHOST_TStringArray*)dragnDropData->data;
|
||||
int i;
|
||||
std::cout << "\nReceived " << strArray->count << " filenames";
|
||||
std::cout << " type : GHOST_kDragnDropTypeFilenames,";
|
||||
std::cout << "\n Received " << strArray->count << " filename" << (strArray->count > 1 ? "s:" : ":");
|
||||
for (i=0;i<strArray->count;i++)
|
||||
std::cout << " Filename #" << i << ": " << strArray->strings[i];
|
||||
std::cout << "\n File[" << i << "] : " << strArray->strings[i];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -192,7 +194,6 @@ bool GHOST_EventPrinter::processEvent(GHOST_IEvent* event)
|
||||
std::cout << "not found"; handled = false;
|
||||
break;
|
||||
}
|
||||
std::cout << "\n";
|
||||
return handled;
|
||||
}
|
||||
|
||||
|
@ -200,6 +200,12 @@ public:
|
||||
*/
|
||||
GHOST_TSuccess handleWindowEvent(GHOST_TEventType eventType, GHOST_WindowCocoa* window);
|
||||
|
||||
/**
|
||||
* Handles the Cocoa event telling the application has become active (again)
|
||||
* @return Indication whether the event was handled.
|
||||
*/
|
||||
GHOST_TSuccess handleApplicationBecomeActiveEvent();
|
||||
|
||||
|
||||
/**
|
||||
* Handles a drag'n'drop destination event. Called by GHOST_WindowCocoa window subclass
|
||||
|
@ -389,6 +389,28 @@ extern "C" int GHOST_HACK_getFirstFile(char buf[FIRSTFILEBUFLG]) {
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(WITH_QUICKTIME) && !defined(USE_QTKIT)
|
||||
//Need to place this quicktime function in an ObjC file
|
||||
//It is used to avoid memory leak when raising the quicktime "compression settings" standard dialog
|
||||
extern "C" {
|
||||
struct bContext;
|
||||
struct wmOperator;
|
||||
extern int fromcocoa_request_qtcodec_settings(bContext *C, wmOperator *op);
|
||||
|
||||
|
||||
int cocoa_request_qtcodec_settings(bContext *C, wmOperator *op)
|
||||
{
|
||||
int result;
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
result = fromcocoa_request_qtcodec_settings(C, op);
|
||||
|
||||
[pool drain];
|
||||
return result;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
#pragma mark Cocoa objects
|
||||
|
||||
@ -403,6 +425,7 @@ extern "C" int GHOST_HACK_getFirstFile(char buf[FIRSTFILEBUFLG]) {
|
||||
- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename;
|
||||
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender;
|
||||
- (void)applicationWillTerminate:(NSNotification *)aNotification;
|
||||
- (void)applicationWillBecomeActive:(NSNotification *)aNotification;
|
||||
@end
|
||||
|
||||
@implementation CocoaAppDelegate : NSObject
|
||||
@ -436,6 +459,11 @@ extern "C" int GHOST_HACK_getFirstFile(char buf[FIRSTFILEBUFLG]) {
|
||||
/*G.afbreek = 0; //Let Cocoa perform the termination at the end
|
||||
WM_exit(C);*/
|
||||
}
|
||||
|
||||
- (void)applicationWillBecomeActive:(NSNotification *)aNotification
|
||||
{
|
||||
systemCocoa->handleApplicationBecomeActiveEvent();
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
@ -530,6 +558,9 @@ GHOST_TSuccess GHOST_SystemCocoa::init()
|
||||
|
||||
[windowMenu addItemWithTitle:@"Zoom" action:@selector(performZoom:) keyEquivalent:@""];
|
||||
|
||||
menuItem = [windowMenu addItemWithTitle:@"Close" action:@selector(performClose:) keyEquivalent:@"w"];
|
||||
[menuItem setKeyEquivalentModifierMask:NSCommandKeyMask];
|
||||
|
||||
menuItem = [[NSMenuItem alloc] init];
|
||||
[menuItem setSubmenu:windowMenu];
|
||||
|
||||
@ -706,13 +737,10 @@ GHOST_TSuccess GHOST_SystemCocoa::setCursorPosition(GHOST_TInt32 x, GHOST_TInt32
|
||||
|
||||
GHOST_TSuccess GHOST_SystemCocoa::getModifierKeys(GHOST_ModifierKeys& keys) const
|
||||
{
|
||||
unsigned int modifiers = [[NSApp currentEvent] modifierFlags];
|
||||
//Direct query to modifierFlags can be used in 10.6
|
||||
|
||||
keys.set(GHOST_kModifierKeyCommand, (modifiers & NSCommandKeyMask) ? true : false);
|
||||
keys.set(GHOST_kModifierKeyLeftAlt, (modifiers & NSAlternateKeyMask) ? true : false);
|
||||
keys.set(GHOST_kModifierKeyLeftShift, (modifiers & NSShiftKeyMask) ? true : false);
|
||||
keys.set(GHOST_kModifierKeyLeftControl, (modifiers & NSControlKeyMask) ? true : false);
|
||||
keys.set(GHOST_kModifierKeyCommand, (m_modifierMask & NSCommandKeyMask) ? true : false);
|
||||
keys.set(GHOST_kModifierKeyLeftAlt, (m_modifierMask & NSAlternateKeyMask) ? true : false);
|
||||
keys.set(GHOST_kModifierKeyLeftShift, (m_modifierMask & NSShiftKeyMask) ? true : false);
|
||||
keys.set(GHOST_kModifierKeyLeftControl, (m_modifierMask & NSControlKeyMask) ? true : false);
|
||||
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
@ -740,8 +768,6 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent)
|
||||
bool anyProcessed = false;
|
||||
NSEvent *event;
|
||||
|
||||
m_outsideLoopEventProcessed = false;
|
||||
|
||||
// SetMouseCoalescingEnabled(false, NULL);
|
||||
//TODO : implement timer ??
|
||||
|
||||
@ -838,9 +864,55 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent)
|
||||
} while (event!= nil);
|
||||
//} while (waitForEvent && !anyProcessed); Needed only for timer implementation
|
||||
|
||||
if (m_outsideLoopEventProcessed) {
|
||||
m_outsideLoopEventProcessed = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
return anyProcessed;
|
||||
}
|
||||
|
||||
return anyProcessed || m_outsideLoopEventProcessed;
|
||||
//Note: called from NSApplication delegate
|
||||
GHOST_TSuccess GHOST_SystemCocoa::handleApplicationBecomeActiveEvent()
|
||||
{
|
||||
//Update the modifiers key mask, as its status may have changed when the application was not active
|
||||
//(that is when update events are sent to another application)
|
||||
unsigned int modifiers;
|
||||
GHOST_IWindow* window = m_windowManager->getActiveWindow();
|
||||
|
||||
#ifdef MAC_OS_X_VERSION_10_6
|
||||
modifiers = [NSEvent modifierFlags];
|
||||
#else
|
||||
//If build against an older SDK, check if running on 10.6 to use the correct function
|
||||
if ([NSEvent respondsToSelector:@selector(modifierFlags)]) {
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4
|
||||
modifiers = (unsigned int)[NSEvent modifierFlags];
|
||||
#else
|
||||
modifiers = (NSUInteger)[NSEvent modifierFlags];
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
//TODO: need to find a better workaround for the missing cocoa "getModifierFlag" function in 10.4/10.5
|
||||
modifiers = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((modifiers & NSShiftKeyMask) != (m_modifierMask & NSShiftKeyMask)) {
|
||||
pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & NSShiftKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftShift) );
|
||||
}
|
||||
if ((modifiers & NSControlKeyMask) != (m_modifierMask & NSControlKeyMask)) {
|
||||
pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & NSControlKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftControl) );
|
||||
}
|
||||
if ((modifiers & NSAlternateKeyMask) != (m_modifierMask & NSAlternateKeyMask)) {
|
||||
pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & NSAlternateKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftAlt) );
|
||||
}
|
||||
if ((modifiers & NSCommandKeyMask) != (m_modifierMask & NSCommandKeyMask)) {
|
||||
pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & NSCommandKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyCommand) );
|
||||
}
|
||||
|
||||
m_modifierMask = modifiers;
|
||||
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
//Note: called from NSWindow delegate
|
||||
|
@ -39,6 +39,7 @@
|
||||
#endif
|
||||
|
||||
#include "GHOST_SystemWin32.h"
|
||||
#include "GHOST_EventDragnDrop.h"
|
||||
|
||||
// win64 doesn't define GWL_USERDATA
|
||||
#ifdef WIN32
|
||||
@ -138,10 +139,15 @@ GHOST_SystemWin32::GHOST_SystemWin32()
|
||||
m_displayManager = new GHOST_DisplayManagerWin32 ();
|
||||
GHOST_ASSERT(m_displayManager, "GHOST_SystemWin32::GHOST_SystemWin32(): m_displayManager==0\n");
|
||||
m_displayManager->initialize();
|
||||
|
||||
// Require COM for GHOST_DropTargetWin32 created in GHOST_WindowWin32.
|
||||
OleInitialize(0);
|
||||
}
|
||||
|
||||
GHOST_SystemWin32::~GHOST_SystemWin32()
|
||||
{
|
||||
// Shutdown COM
|
||||
OleUninitialize();
|
||||
}
|
||||
|
||||
|
||||
@ -187,7 +193,7 @@ GHOST_IWindow* GHOST_SystemWin32::createWindow(
|
||||
bool stereoVisual, const GHOST_TEmbedderWindowID parentWindow )
|
||||
{
|
||||
GHOST_Window* window = 0;
|
||||
window = new GHOST_WindowWin32 (title, left, top, width, height, state, type, stereoVisual);
|
||||
window = new GHOST_WindowWin32 (this, title, left, top, width, height, state, type, stereoVisual);
|
||||
if (window) {
|
||||
if (window->getValid()) {
|
||||
// Store the pointer to the window
|
||||
@ -248,11 +254,13 @@ bool GHOST_SystemWin32::processEvents(bool waitForEvent)
|
||||
GHOST_TSuccess GHOST_SystemWin32::getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const
|
||||
{
|
||||
POINT point;
|
||||
::GetCursorPos(&point);
|
||||
if(::GetCursorPos(&point)){
|
||||
x = point.x;
|
||||
y = point.y;
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_SystemWin32::setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) const
|
||||
@ -499,11 +507,56 @@ GHOST_EventButton* GHOST_SystemWin32::processButtonEvent(GHOST_TEventType type,
|
||||
}
|
||||
|
||||
|
||||
GHOST_EventCursor* GHOST_SystemWin32::processCursorEvent(GHOST_TEventType type, GHOST_IWindow *window)
|
||||
GHOST_EventCursor* GHOST_SystemWin32::processCursorEvent(GHOST_TEventType type, GHOST_IWindow *Iwindow)
|
||||
{
|
||||
GHOST_TInt32 x, y;
|
||||
getSystem()->getCursorPosition(x, y);
|
||||
return new GHOST_EventCursor (getSystem()->getMilliSeconds(), type, window, x, y);
|
||||
GHOST_TInt32 x_screen, y_screen;
|
||||
GHOST_SystemWin32 * system = ((GHOST_SystemWin32 * ) getSystem());
|
||||
GHOST_WindowWin32 * window = ( GHOST_WindowWin32 * ) Iwindow;
|
||||
|
||||
system->getCursorPosition(x_screen, y_screen);
|
||||
|
||||
if(window->getCursorGrabMode() != GHOST_kGrabDisable && window->getCursorGrabMode() != GHOST_kGrabNormal)
|
||||
{
|
||||
GHOST_TInt32 x_new= x_screen;
|
||||
GHOST_TInt32 y_new= y_screen;
|
||||
GHOST_TInt32 x_accum, y_accum;
|
||||
GHOST_Rect bounds;
|
||||
|
||||
/* fallback to window bounds */
|
||||
if(window->getCursorGrabBounds(bounds)==GHOST_kFailure){
|
||||
window->getClientBounds(bounds);
|
||||
}
|
||||
|
||||
/* could also clamp to screen bounds
|
||||
* wrap with a window outside the view will fail atm */
|
||||
|
||||
bounds.wrapPoint(x_new, y_new, 2); /* offset of one incase blender is at screen bounds */
|
||||
|
||||
window->getCursorGrabAccum(x_accum, y_accum);
|
||||
if(x_new != x_screen|| y_new != y_screen) {
|
||||
/* when wrapping we don't need to add an event because the
|
||||
* setCursorPosition call will cause a new event after */
|
||||
system->setCursorPosition(x_new, y_new); /* wrap */
|
||||
window->setCursorGrabAccum(x_accum + (x_screen - x_new), y_accum + (y_screen - y_new));
|
||||
}else{
|
||||
return new GHOST_EventCursor(system->getMilliSeconds(),
|
||||
GHOST_kEventCursorMove,
|
||||
window,
|
||||
x_screen + x_accum,
|
||||
y_screen + y_accum
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
return new GHOST_EventCursor(system->getMilliSeconds(),
|
||||
GHOST_kEventCursorMove,
|
||||
window,
|
||||
x_screen,
|
||||
y_screen
|
||||
);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@ -549,6 +602,26 @@ GHOST_Event* GHOST_SystemWin32::processWindowEvent(GHOST_TEventType type, GHOST_
|
||||
return new GHOST_Event(getSystem()->getMilliSeconds(), type, window);
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_SystemWin32::pushDragDropEvent(GHOST_TEventType eventType,
|
||||
GHOST_TDragnDropTypes draggedObjectType,
|
||||
GHOST_IWindow* window,
|
||||
int mouseX, int mouseY,
|
||||
void* data)
|
||||
{
|
||||
GHOST_SystemWin32* system = ((GHOST_SystemWin32*)getSystem());
|
||||
return system->pushEvent(new GHOST_EventDragnDrop(system->getMilliSeconds(),
|
||||
eventType,
|
||||
draggedObjectType,
|
||||
window,mouseX,mouseY,data)
|
||||
);
|
||||
}
|
||||
|
||||
void GHOST_SystemWin32::processMinMaxInfo(MINMAXINFO * minmax)
|
||||
{
|
||||
minmax->ptMinTrackSize.x=320;
|
||||
minmax->ptMinTrackSize.y=240;
|
||||
}
|
||||
|
||||
|
||||
LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
@ -793,6 +866,15 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
|
||||
event = processWindowEvent(GHOST_kEventWindowUpdate, window);
|
||||
::ValidateRect(hwnd, NULL);
|
||||
break;
|
||||
case WM_GETMINMAXINFO:
|
||||
/* The WM_GETMINMAXINFO message is sent to a window when the size or
|
||||
* position of the window is about to change. An application can use
|
||||
* this message to override the window's default maximized size and
|
||||
* position, or its default minimum or maximum tracking size.
|
||||
*/
|
||||
processMinMaxInfo((MINMAXINFO *) lParam);
|
||||
/* Let DefWindowProc handle it. */
|
||||
break;
|
||||
case WM_SIZE:
|
||||
/* The WM_SIZE message is sent to a window after its size has changed.
|
||||
* The WM_SIZE and WM_MOVE messages are not sent if an application handles the
|
||||
|
@ -51,6 +51,7 @@ class GHOST_EventCursor;
|
||||
class GHOST_EventKey;
|
||||
class GHOST_EventWheel;
|
||||
class GHOST_EventWindow;
|
||||
class GHOST_EventDragnDrop;
|
||||
|
||||
/**
|
||||
* WIN32 Implementation of GHOST_System class.
|
||||
@ -182,6 +183,18 @@ public:
|
||||
*/
|
||||
virtual void putClipboard(GHOST_TInt8 *buffer, bool selection) const;
|
||||
|
||||
/**
|
||||
* Creates a drag'n'drop event and pushes it immediately onto the event queue.
|
||||
* Called by GHOST_DropTargetWin32 class.
|
||||
* @param eventType The type of drag'n'drop event
|
||||
* @param draggedObjectType The type object concerned (currently array of file names, string, ?bitmap)
|
||||
* @param mouseX x mouse coordinate (in window coordinates)
|
||||
* @param mouseY y mouse coordinate
|
||||
* @param window The window on which the event occured
|
||||
* @return Indication whether the event was handled.
|
||||
*/
|
||||
static GHOST_TSuccess pushDragDropEvent(GHOST_TEventType eventType, GHOST_TDragnDropTypes draggedObjectType,GHOST_IWindow* window, int mouseX, int mouseY, void* data);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Initializes the system.
|
||||
@ -228,7 +241,7 @@ protected:
|
||||
* @param window The window receiving the event (the active window).
|
||||
* @return The event created.
|
||||
*/
|
||||
static GHOST_EventCursor* processCursorEvent(GHOST_TEventType type, GHOST_IWindow *window);
|
||||
static GHOST_EventCursor* processCursorEvent(GHOST_TEventType type, GHOST_IWindow *Iwindow);
|
||||
|
||||
/**
|
||||
* Creates a mouse wheel event.
|
||||
@ -255,6 +268,11 @@ protected:
|
||||
* @return The event created.
|
||||
*/
|
||||
static GHOST_Event* processWindowEvent(GHOST_TEventType type, GHOST_IWindow* window);
|
||||
/**
|
||||
* Handles minimum window size.
|
||||
* @param minmax The MINMAXINFO structure.
|
||||
*/
|
||||
static void processMinMaxInfo(MINMAXINFO * minmax);
|
||||
|
||||
/**
|
||||
* Returns the local state of the modifier keys (from the message queue).
|
||||
|
@ -66,8 +66,10 @@
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <stdio.h> // for fprintf only
|
||||
#include <cstdlib> // for exit
|
||||
|
||||
typedef struct NDOFPlatformInfo {
|
||||
Display *display;
|
||||
@ -96,7 +98,10 @@ GHOST_SystemX11(
|
||||
{
|
||||
m_display = XOpenDisplay(NULL);
|
||||
|
||||
if (!m_display) return;
|
||||
if (!m_display) {
|
||||
std::cerr << "Unable to open a display" << std::endl;
|
||||
abort(); //was return before, but this would just mean it will crash later
|
||||
}
|
||||
|
||||
#ifdef __sgi
|
||||
m_delete_window_atom
|
||||
|
@ -109,6 +109,8 @@ GHOST_TSuccess GHOST_Window::setCursorGrab(GHOST_TGrabCursorMode mode, GHOST_Rec
|
||||
m_cursorGrabBounds.m_l= m_cursorGrabBounds.m_r= -1;
|
||||
else if (bounds) {
|
||||
m_cursorGrabBounds= *bounds;
|
||||
} else { /* if bounds not defined, use window */
|
||||
getClientBounds(m_cursorGrabBounds);
|
||||
}
|
||||
m_cursorGrab = mode;
|
||||
return GHOST_kSuccess;
|
||||
|
@ -230,6 +230,28 @@ extern "C" {
|
||||
- (void)keyDown:(NSEvent *)theEvent
|
||||
{}
|
||||
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4
|
||||
//Cmd+key are handled differently before 10.5
|
||||
- (BOOL)performKeyEquivalent:(NSEvent *)theEvent
|
||||
{
|
||||
NSString *chars = [theEvent charactersIgnoringModifiers];
|
||||
|
||||
if ([chars length] <1)
|
||||
return NO;
|
||||
|
||||
//Let cocoa handle menu shortcuts
|
||||
switch ([chars characterAtIndex:0]) {
|
||||
case 'q':
|
||||
case 'w':
|
||||
case 'h':
|
||||
case 'm':
|
||||
return NO;
|
||||
default:
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
- (BOOL)isOpaque
|
||||
{
|
||||
return YES;
|
||||
|
@ -40,6 +40,8 @@
|
||||
|
||||
#include <string.h>
|
||||
#include "GHOST_WindowWin32.h"
|
||||
#include "GHOST_SystemWin32.h"
|
||||
#include "GHOST_DropTargetWin32.h"
|
||||
#include <GL/gl.h>
|
||||
#include <math.h>
|
||||
|
||||
@ -95,6 +97,7 @@ static PIXELFORMATDESCRIPTOR sPreferredFormat = {
|
||||
};
|
||||
|
||||
GHOST_WindowWin32::GHOST_WindowWin32(
|
||||
GHOST_SystemWin32 * system,
|
||||
const STR_String& title,
|
||||
GHOST_TInt32 left,
|
||||
GHOST_TInt32 top,
|
||||
@ -106,6 +109,7 @@ GHOST_WindowWin32::GHOST_WindowWin32(
|
||||
:
|
||||
GHOST_Window(title, left, top, width, height, state, GHOST_kDrawingContextTypeNone,
|
||||
stereoVisual),
|
||||
m_system(system),
|
||||
m_hDC(0),
|
||||
m_hGlRc(0),
|
||||
m_hasMouseCaptured(false),
|
||||
@ -167,6 +171,9 @@ GHOST_WindowWin32::GHOST_WindowWin32(
|
||||
0); // pointer to window-creation data
|
||||
}
|
||||
if (m_hWnd) {
|
||||
// Register this window as a droptarget. Requires m_hWnd to be valid.
|
||||
// Note that OleInitialize(0) has to be called prior to this. Done in GHOST_SystemWin32.
|
||||
m_dropTarget = new GHOST_DropTargetWin32(this, m_system);
|
||||
// Store a pointer to this class in the window structure
|
||||
::SetWindowLongPtr(m_hWnd, GWL_USERDATA, (LONG_PTR)this);
|
||||
|
||||
@ -275,6 +282,7 @@ GHOST_WindowWin32::~GHOST_WindowWin32()
|
||||
m_hDC = 0;
|
||||
}
|
||||
if (m_hWnd) {
|
||||
m_dropTarget->Release(); // frees itself.
|
||||
::DestroyWindow(m_hWnd);
|
||||
m_hWnd = 0;
|
||||
}
|
||||
@ -285,6 +293,10 @@ bool GHOST_WindowWin32::getValid() const
|
||||
return m_hWnd != 0;
|
||||
}
|
||||
|
||||
HWND GHOST_WindowWin32::getHWND() const
|
||||
{
|
||||
return m_hWnd;
|
||||
}
|
||||
|
||||
void GHOST_WindowWin32::setTitle(const STR_String& title)
|
||||
{
|
||||
@ -663,6 +675,41 @@ GHOST_TSuccess GHOST_WindowWin32::setWindowCursorVisibility(bool visible)
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_WindowWin32::setWindowCursorGrab(GHOST_TGrabCursorMode mode)
|
||||
{
|
||||
if(mode != GHOST_kGrabDisable) {
|
||||
if(mode != GHOST_kGrabNormal) {
|
||||
m_system->getCursorPosition(m_cursorGrabInitPos[0], m_cursorGrabInitPos[1]);
|
||||
setCursorGrabAccum(0, 0);
|
||||
|
||||
if(mode == GHOST_kGrabHide)
|
||||
setWindowCursorVisibility(false);
|
||||
}
|
||||
registerMouseClickEvent(true);
|
||||
}
|
||||
else {
|
||||
if (m_cursorGrab==GHOST_kGrabHide) {
|
||||
m_system->setCursorPosition(m_cursorGrabInitPos[0], m_cursorGrabInitPos[1]);
|
||||
setWindowCursorVisibility(true);
|
||||
}
|
||||
if(m_cursorGrab != GHOST_kGrabNormal) {
|
||||
/* use to generate a mouse move event, otherwise the last event
|
||||
* blender gets can be outside the screen causing menus not to show
|
||||
* properly unless the user moves the mouse */
|
||||
GHOST_TInt32 pos[2];
|
||||
m_system->getCursorPosition(pos[0], pos[1]);
|
||||
m_system->setCursorPosition(pos[0], pos[1]);
|
||||
}
|
||||
|
||||
/* Almost works without but important otherwise the mouse GHOST location can be incorrect on exit */
|
||||
setCursorGrabAccum(0, 0);
|
||||
m_cursorGrabBounds.m_l= m_cursorGrabBounds.m_r= -1; /* disable */
|
||||
registerMouseClickEvent(false);
|
||||
}
|
||||
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_WindowWin32::setWindowCursorShape(GHOST_TStandardCursor cursorShape)
|
||||
{
|
||||
if (m_customCursor) {
|
||||
@ -676,6 +723,7 @@ GHOST_TSuccess GHOST_WindowWin32::setWindowCursorShape(GHOST_TStandardCursor cur
|
||||
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
void GHOST_WindowWin32::processWin32TabletInitEvent()
|
||||
{
|
||||
if (m_wintab) {
|
||||
|
@ -47,6 +47,9 @@
|
||||
#define PACKETMODE PK_BUTTONS
|
||||
#include <pktdef.h>
|
||||
|
||||
class GHOST_SystemWin32;
|
||||
class GHOST_DropTargetWin32;
|
||||
|
||||
// typedefs for WinTab functions to allow dynamic loading
|
||||
typedef UINT (API * GHOST_WIN32_WTInfo) ( UINT, UINT, LPVOID );
|
||||
typedef HCTX (API * GHOST_WIN32_WTOpen) (HWND, LPLOGCONTEXTA, BOOL);
|
||||
@ -74,6 +77,7 @@ public:
|
||||
* @param stereoVisual Stereo visual for quad buffered stereo.
|
||||
*/
|
||||
GHOST_WindowWin32(
|
||||
GHOST_SystemWin32 * system,
|
||||
const STR_String& title,
|
||||
GHOST_TInt32 left,
|
||||
GHOST_TInt32 top,
|
||||
@ -96,6 +100,12 @@ public:
|
||||
*/
|
||||
virtual bool getValid() const;
|
||||
|
||||
/**
|
||||
* Access to the handle of the window.
|
||||
* @return The handle of the window.
|
||||
*/
|
||||
virtual HWND getHWND() const;
|
||||
|
||||
/**
|
||||
* Sets the title displayed in the title bar.
|
||||
* @param title The title to display in the title bar.
|
||||
@ -250,6 +260,13 @@ protected:
|
||||
*/
|
||||
virtual GHOST_TSuccess setWindowCursorVisibility(bool visible);
|
||||
|
||||
/**
|
||||
* Sets the cursor grab on the window using native window system calls.
|
||||
* Using registerMouseClickEvent.
|
||||
* @param mode GHOST_TGrabCursorMode.
|
||||
*/
|
||||
virtual GHOST_TSuccess setWindowCursorGrab(GHOST_TGrabCursorMode mode);
|
||||
|
||||
/**
|
||||
* Sets the cursor shape on the window using
|
||||
* native window system calls.
|
||||
@ -273,6 +290,10 @@ protected:
|
||||
int bg_color
|
||||
);
|
||||
|
||||
/** Pointer to system */
|
||||
GHOST_SystemWin32 * m_system;
|
||||
/** Pointer to COM IDropTarget implementor */
|
||||
GHOST_DropTargetWin32 * m_dropTarget;
|
||||
/** Window handle. */
|
||||
HWND m_hWnd;
|
||||
/** Device context handle. */
|
||||
|
@ -352,6 +352,10 @@
|
||||
RelativePath="..\..\intern\GHOST_DisplayManagerWin32.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\intern\GHOST_DropTargetWin32.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\intern\GHOST_Event.h"
|
||||
>
|
||||
@ -489,6 +493,10 @@
|
||||
RelativePath="..\..\intern\GHOST_DisplayManagerWin32.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\intern\GHOST_DropTargetWin32.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\intern\GHOST_EventManager.cpp"
|
||||
>
|
||||
|
@ -43,7 +43,7 @@
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..\..\..\..\lib\windows\jpeg\include;..\..\..\..\lib\windows\zlib\include;..\..\..\..\lib\windows\png\include;..\..\..\..\lib\windows\tiff\include;..\..\..\..\lib\windows\openexr\include;..\..\..\..\lib\windows\openexr\include\Iex;..\..\..\..\lib\windows\openexr\include\Imath;..\..\..\..\lib\windows\openexr\include\IlmImf;..\..\..\..\lib\windows\QTDevWin\CIncludes;..\..\..\..\lib\windows\ffmpeg\include;..\..\..\..\lib\windows\ffmpeg\include\msvc;..\..\..\..\build\msvc_9\intern\memutil\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\source\blender\avi;..\..\..\source\blender\imbuf;..\..\..\source\blender\blenlib;..\..\..\source\blender\include;..\..\..\source\blender\quicktime;..\..\..\source\blender\blenkernel;..\..\..\source\blender\blenloader;..\..\..\source\blender\makesdna;..\..\..\source\blender\imbuf\intern;..\..\..\source\blender\readstreamglue;..\..\..\source\blender\render\extern\include;..\..\..\source\blender\imbuf\intern\openexr;..\..\..\source\blender\imbuf\intern\dds"
|
||||
AdditionalIncludeDirectories="..\..\..\..\lib\windows\jpeg\include;..\..\..\..\lib\windows\zlib\include;..\..\..\..\lib\windows\png\include;..\..\..\..\lib\windows\tiff\include;..\..\..\..\lib\windows\openexr\include;..\..\..\..\lib\windows\openexr\include\Iex;..\..\..\..\lib\windows\openexr\include\Imath;..\..\..\..\lib\windows\openexr\include\IlmImf;..\..\..\..\lib\windows\QTDevWin\CIncludes;..\..\..\..\lib\windows\ffmpeg\include;..\..\..\..\lib\windows\ffmpeg\include\msvc;..\..\..\..\build\msvc_9\intern\memutil\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\source\blender\avi;..\..\..\source\blender\imbuf;..\..\..\source\blender\blenlib;..\..\..\source\blender\include;..\..\..\source\blender\quicktime;..\..\..\source\blender\blenkernel;..\..\..\source\blender\blenloader;..\..\..\source\blender\makesdna;..\..\..\source\blender\imbuf\intern;..\..\..\source\blender\readstreamglue;..\..\..\source\blender\render\extern\include;..\..\..\source\blender\imbuf\intern\openexr;..\..\..\source\blender\imbuf\intern\dds;..\..\..\source\blender\windowmanager;..\..\..\source\blender\makesrna"
|
||||
PreprocessorDefinitions="_DEBUG;WIN32;_LIB;WITH_QUICKTIME;WITH_OPENEXR;WITH_DDS;WITH_FFMPEG"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
@ -118,7 +118,7 @@
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..\..\..\..\lib\windows\jpeg\include;..\..\..\..\lib\windows\zlib\include;..\..\..\..\lib\windows\png\include;..\..\..\..\lib\windows\tiff\include;..\..\..\..\lib\windows\openexr\include;..\..\..\..\lib\windows\openexr\include\Iex;..\..\..\..\lib\windows\openexr\include\Imath;..\..\..\..\lib\windows\openexr\include\IlmImf;..\..\..\..\lib\windows\QTDevWin\CIncludes;..\..\..\..\lib\windows\ffmpeg\include;..\..\..\..\lib\windows\ffmpeg\include\msvc;..\..\..\..\build\msvc_9\intern\memutil\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\source\blender\avi;..\..\..\source\blender\imbuf;..\..\..\source\blender\blenlib;..\..\..\source\blender\include;..\..\..\source\blender\quicktime;..\..\..\source\blender\blenkernel;..\..\..\source\blender\blenloader;..\..\..\source\blender\makesdna;..\..\..\source\blender\imbuf\intern;..\..\..\source\blender\readstreamglue;..\..\..\source\blender\render\extern\include;..\..\..\source\blender\imbuf\intern\openexr;..\..\..\source\blender\imbuf\intern\dds"
|
||||
AdditionalIncludeDirectories="..\..\..\..\lib\windows\jpeg\include;..\..\..\..\lib\windows\zlib\include;..\..\..\..\lib\windows\png\include;..\..\..\..\lib\windows\tiff\include;..\..\..\..\lib\windows\openexr\include;..\..\..\..\lib\windows\openexr\include\Iex;..\..\..\..\lib\windows\openexr\include\Imath;..\..\..\..\lib\windows\openexr\include\IlmImf;..\..\..\..\lib\windows\QTDevWin\CIncludes;..\..\..\..\lib\windows\ffmpeg\include;..\..\..\..\lib\windows\ffmpeg\include\msvc;..\..\..\..\build\msvc_9\intern\memutil\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\source\blender\avi;..\..\..\source\blender\imbuf;..\..\..\source\blender\blenlib;..\..\..\source\blender\include;..\..\..\source\blender\quicktime;..\..\..\source\blender\blenkernel;..\..\..\source\blender\blenloader;..\..\..\source\blender\makesdna;..\..\..\source\blender\imbuf\intern;..\..\..\source\blender\readstreamglue;..\..\..\source\blender\render\extern\include;..\..\..\source\blender\imbuf\intern\openexr;..\..\..\source\blender\imbuf\intern\dds;..\..\..\source\blender\windowmanager;..\..\..\source\blender\makesrna"
|
||||
PreprocessorDefinitions="_DEBUG,WIN32,_LIB"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
@ -192,7 +192,7 @@
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
InlineFunctionExpansion="1"
|
||||
AdditionalIncludeDirectories="..\..\..\..\lib\windows\jpeg\include;..\..\..\..\lib\windows\zlib\include;..\..\..\..\lib\windows\png\include;..\..\..\..\lib\windows\tiff\include;..\..\..\..\lib\windows\openexr\include;..\..\..\..\lib\windows\openexr\include\Iex;..\..\..\..\lib\windows\openexr\include\Imath;..\..\..\..\lib\windows\openexr\include\IlmImf;..\..\..\..\lib\windows\QTDevWin\CIncludes;..\..\..\..\lib\windows\ffmpeg\include;..\..\..\..\lib\windows\ffmpeg\include\msvc;..\..\..\..\build\msvc_9\intern\memutil\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\source\blender\avi;..\..\..\source\blender\imbuf;..\..\..\source\blender\blenlib;..\..\..\source\blender\include;..\..\..\source\blender\quicktime;..\..\..\source\blender\blenkernel;..\..\..\source\blender\blenloader;..\..\..\source\blender\makesdna;..\..\..\source\blender\imbuf\intern;..\..\..\source\blender\readstreamglue;..\..\..\source\blender\render\extern\include;..\..\..\source\blender\imbuf\intern\openexr;..\..\..\source\blender\imbuf\intern\dds"
|
||||
AdditionalIncludeDirectories="..\..\..\..\lib\windows\jpeg\include;..\..\..\..\lib\windows\zlib\include;..\..\..\..\lib\windows\png\include;..\..\..\..\lib\windows\tiff\include;..\..\..\..\lib\windows\openexr\include;..\..\..\..\lib\windows\openexr\include\Iex;..\..\..\..\lib\windows\openexr\include\Imath;..\..\..\..\lib\windows\openexr\include\IlmImf;..\..\..\..\lib\windows\QTDevWin\CIncludes;..\..\..\..\lib\windows\ffmpeg\include;..\..\..\..\lib\windows\ffmpeg\include\msvc;..\..\..\..\build\msvc_9\intern\memutil\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\source\blender\avi;..\..\..\source\blender\imbuf;..\..\..\source\blender\blenlib;..\..\..\source\blender\include;..\..\..\source\blender\quicktime;..\..\..\source\blender\blenkernel;..\..\..\source\blender\blenloader;..\..\..\source\blender\makesdna;..\..\..\source\blender\imbuf\intern;..\..\..\source\blender\readstreamglue;..\..\..\source\blender\render\extern\include;..\..\..\source\blender\imbuf\intern\openexr;..\..\..\source\blender\imbuf\intern\dds;..\..\..\source\blender\windowmanager;..\..\..\source\blender\makesrna"
|
||||
PreprocessorDefinitions="NDEBUG,WIN32,_LIB,WITH_QUICKTIME"
|
||||
StringPooling="true"
|
||||
RuntimeLibrary="2"
|
||||
@ -268,7 +268,7 @@
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
InlineFunctionExpansion="1"
|
||||
AdditionalIncludeDirectories="..\..\..\..\lib\windows\jpeg\include;..\..\..\..\lib\windows\zlib\include;..\..\..\..\lib\windows\png\include;..\..\..\..\lib\windows\tiff\include;..\..\..\..\lib\windows\openexr\include;..\..\..\..\lib\windows\openexr\include\Iex;..\..\..\..\lib\windows\openexr\include\Imath;..\..\..\..\lib\windows\openexr\include\IlmImf;..\..\..\..\lib\windows\QTDevWin\CIncludes;..\..\..\..\lib\windows\ffmpeg\include;..\..\..\..\lib\windows\ffmpeg\include\msvc;..\..\..\..\build\msvc_9\intern\memutil\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\source\blender\avi;..\..\..\source\blender\imbuf;..\..\..\source\blender\blenlib;..\..\..\source\blender\include;..\..\..\source\blender\quicktime;..\..\..\source\blender\blenkernel;..\..\..\source\blender\blenloader;..\..\..\source\blender\makesdna;..\..\..\source\blender\imbuf\intern;..\..\..\source\blender\readstreamglue;..\..\..\source\blender\render\extern\include;..\..\..\source\blender\imbuf\intern\openexr;..\..\..\source\blender\imbuf\intern\dds"
|
||||
AdditionalIncludeDirectories="..\..\..\..\lib\windows\jpeg\include;..\..\..\..\lib\windows\zlib\include;..\..\..\..\lib\windows\png\include;..\..\..\..\lib\windows\tiff\include;..\..\..\..\lib\windows\openexr\include;..\..\..\..\lib\windows\openexr\include\Iex;..\..\..\..\lib\windows\openexr\include\Imath;..\..\..\..\lib\windows\openexr\include\IlmImf;..\..\..\..\lib\windows\QTDevWin\CIncludes;..\..\..\..\lib\windows\ffmpeg\include;..\..\..\..\lib\windows\ffmpeg\include\msvc;..\..\..\..\build\msvc_9\intern\memutil\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\source\blender\avi;..\..\..\source\blender\imbuf;..\..\..\source\blender\blenlib;..\..\..\source\blender\include;..\..\..\source\blender\quicktime;..\..\..\source\blender\blenkernel;..\..\..\source\blender\blenloader;..\..\..\source\blender\makesdna;..\..\..\source\blender\imbuf\intern;..\..\..\source\blender\readstreamglue;..\..\..\source\blender\render\extern\include;..\..\..\source\blender\imbuf\intern\openexr;..\..\..\source\blender\imbuf\intern\dds;..\..\..\source\blender\windowmanager;..\..\..\source\blender\makesrna"
|
||||
PreprocessorDefinitions="NDEBUG;WIN32;_LIB;WITH_QUICKTIME;WITH_OPENEXR;WITH_DDS;WITH_FFMPEG"
|
||||
StringPooling="true"
|
||||
RuntimeLibrary="0"
|
||||
@ -343,7 +343,7 @@
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..\..\..\..\lib\windows\jpeg\include;..\..\..\..\lib\windows\zlib\include;..\..\..\..\lib\windows\png\include;..\..\..\..\lib\windows\tiff\include;..\..\..\..\lib\windows\openexr\include;..\..\..\..\lib\windows\openexr\include\Iex;..\..\..\..\lib\windows\openexr\include\Imath;..\..\..\..\lib\windows\openexr\include\IlmImf;..\..\..\..\lib\windows\QTDevWin\CIncludes;..\..\..\..\lib\windows\ffmpeg\include;..\..\..\..\lib\windows\ffmpeg\include\msvc;..\..\..\..\build\msvc_9\intern\memutil\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\source\blender\avi;..\..\..\source\blender\imbuf;..\..\..\source\blender\blenlib;..\..\..\source\blender\include;..\..\..\source\blender\quicktime;..\..\..\source\blender\blenkernel;..\..\..\source\blender\blenloader;..\..\..\source\blender\makesdna;..\..\..\source\blender\imbuf\intern;..\..\..\source\blender\readstreamglue;..\..\..\source\blender\render\extern\include;..\..\..\source\blender\imbuf\intern\openexr;..\..\..\source\blender\imbuf\intern\dds"
|
||||
AdditionalIncludeDirectories="..\..\..\..\lib\windows\jpeg\include;..\..\..\..\lib\windows\zlib\include;..\..\..\..\lib\windows\png\include;..\..\..\..\lib\windows\tiff\include;..\..\..\..\lib\windows\openexr\include;..\..\..\..\lib\windows\openexr\include\Iex;..\..\..\..\lib\windows\openexr\include\Imath;..\..\..\..\lib\windows\openexr\include\IlmImf;..\..\..\..\lib\windows\QTDevWin\CIncludes;..\..\..\..\lib\windows\ffmpeg\include;..\..\..\..\lib\windows\ffmpeg\include\msvc;..\..\..\..\build\msvc_9\intern\memutil\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\source\blender\avi;..\..\..\source\blender\imbuf;..\..\..\source\blender\blenlib;..\..\..\source\blender\include;..\..\..\source\blender\quicktime;..\..\..\source\blender\blenkernel;..\..\..\source\blender\blenloader;..\..\..\source\blender\makesdna;..\..\..\source\blender\imbuf\intern;..\..\..\source\blender\readstreamglue;..\..\..\source\blender\render\extern\include;..\..\..\source\blender\imbuf\intern\openexr;..\..\..\source\blender\imbuf\intern\dds;..\..\..\source\blender\windowmanager;..\..\..\source\blender\makesrna"
|
||||
PreprocessorDefinitions="_DEBUG;WIN32;_LIB;WITH_QUICKTIME;WITH_DDS;WITH_FFMPEG"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
@ -418,7 +418,7 @@
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
InlineFunctionExpansion="1"
|
||||
AdditionalIncludeDirectories="..\..\..\..\lib\windows\jpeg\include;..\..\..\..\lib\windows\zlib\include;..\..\..\..\lib\windows\png\include;..\..\..\..\lib\windows\tiff\include;..\..\..\..\lib\windows\openexr\include;..\..\..\..\lib\windows\openexr\include\Iex;..\..\..\..\lib\windows\openexr\include\Imath;..\..\..\..\lib\windows\openexr\include\IlmImf;..\..\..\..\lib\windows\QTDevWin\CIncludes;..\..\..\..\lib\windows\ffmpeg\include;..\..\..\..\lib\windows\ffmpeg\include\msvc;..\..\..\..\build\msvc_9\intern\memutil\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\source\blender\avi;..\..\..\source\blender\imbuf;..\..\..\source\blender\blenlib;..\..\..\source\blender\include;..\..\..\source\blender\quicktime;..\..\..\source\blender\blenkernel;..\..\..\source\blender\blenloader;..\..\..\source\blender\makesdna;..\..\..\source\blender\imbuf\intern;..\..\..\source\blender\readstreamglue;..\..\..\source\blender\render\extern\include;..\..\..\source\blender\imbuf\intern\openexr;..\..\..\source\blender\imbuf\intern\dds"
|
||||
AdditionalIncludeDirectories="..\..\..\..\lib\windows\jpeg\include;..\..\..\..\lib\windows\zlib\include;..\..\..\..\lib\windows\png\include;..\..\..\..\lib\windows\tiff\include;..\..\..\..\lib\windows\openexr\include;..\..\..\..\lib\windows\openexr\include\Iex;..\..\..\..\lib\windows\openexr\include\Imath;..\..\..\..\lib\windows\openexr\include\IlmImf;..\..\..\..\lib\windows\QTDevWin\CIncludes;..\..\..\..\lib\windows\ffmpeg\include;..\..\..\..\lib\windows\ffmpeg\include\msvc;..\..\..\..\build\msvc_9\intern\memutil\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\source\blender\avi;..\..\..\source\blender\imbuf;..\..\..\source\blender\blenlib;..\..\..\source\blender\include;..\..\..\source\blender\quicktime;..\..\..\source\blender\blenkernel;..\..\..\source\blender\blenloader;..\..\..\source\blender\makesdna;..\..\..\source\blender\imbuf\intern;..\..\..\source\blender\readstreamglue;..\..\..\source\blender\render\extern\include;..\..\..\source\blender\imbuf\intern\openexr;..\..\..\source\blender\imbuf\intern\dds;..\..\..\source\blender\windowmanager;..\..\..\source\blender\makesrna"
|
||||
PreprocessorDefinitions="NDEBUG;WIN32;_LIB;WITH_QUICKTIME;WITH_DDS;WITH_FFMPEG"
|
||||
StringPooling="true"
|
||||
RuntimeLibrary="0"
|
||||
|
@ -141,7 +141,7 @@
|
||||
Optimization="2"
|
||||
InlineFunctionExpansion="1"
|
||||
AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\source\blender;..\..\..\source\blender\blenlib;..\..\..\source\blender\makesdna;..\..\..\source\blender\makesrna;..\..\..\source\blender\editors\include;..\..\..\source\blender\blenkernel;..\..\..\..\lib\windows\pthreads\include;..\..\..\source\blender\render\extern\include;..\..\..\source\blender\windowmanager;..\..\..\source\blender\imbuf"
|
||||
PreprocessorDefinitions="NDEBUG,WIN32,_CONSOLE"
|
||||
PreprocessorDefinitions="NDEBUG,WIN32,_CONSOLE;GAMEBLENDER=1"
|
||||
StringPooling="true"
|
||||
RuntimeLibrary="0"
|
||||
EnableFunctionLevelLinking="true"
|
||||
@ -327,7 +327,7 @@
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\source\blender;..\..\..\source\blender\blenlib;..\..\..\source\blender\makesdna;..\..\..\source\blender\makesrna;..\..\..\source\blender\editors\include;..\..\..\source\blender\blenkernel;..\..\..\..\lib\windows\pthreads\include;..\..\..\source\blender\render\extern\include;..\..\..\source\blender\windowmanager;..\..\..\source\blender\imbuf"
|
||||
PreprocessorDefinitions="_DEBUG;WIN32;_CONSOLE"
|
||||
PreprocessorDefinitions="_DEBUG;WIN32;_CONSOLE;GAMEBLENDER=1"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
DefaultCharIsUnsigned="true"
|
||||
@ -423,7 +423,7 @@
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\source\blender;..\..\..\source\blender\blenlib;..\..\..\source\blender\makesdna;..\..\..\source\blender\makesrna;..\..\..\source\blender\editors\include;..\..\..\source\blender\blenkernel;..\..\..\..\lib\windows\pthreads\include;..\..\..\source\blender\render\extern\include;..\..\..\source\blender\windowmanager;..\..\..\source\blender\imbuf"
|
||||
PreprocessorDefinitions="_DEBUG,WIN32,_CONSOLE"
|
||||
PreprocessorDefinitions="_DEBUG,WIN32,_CONSOLE;GAMEBLENDER=1"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
DefaultCharIsUnsigned="true"
|
||||
@ -519,7 +519,7 @@
|
||||
Name="VCCLCompilerTool"
|
||||
InlineFunctionExpansion="1"
|
||||
AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\source\blender;..\..\..\source\blender\blenlib;..\..\..\source\blender\makesdna;..\..\..\source\blender\makesrna;..\..\..\source\blender\editors\include;..\..\..\source\blender\blenkernel;..\..\..\..\lib\windows\pthreads\include;..\..\..\source\blender\render\extern\include;..\..\..\source\blender\windowmanager;..\..\..\source\blender\imbuf"
|
||||
PreprocessorDefinitions="NDEBUG,WIN32,_CONSOLE"
|
||||
PreprocessorDefinitions="NDEBUG,WIN32,_CONSOLE;GAMEBLENDER=1"
|
||||
StringPooling="true"
|
||||
RuntimeLibrary="0"
|
||||
EnableFunctionLevelLinking="true"
|
||||
@ -617,6 +617,10 @@
|
||||
RelativePath="..\..\..\source\blender\makesrna\intern\rna_armature.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\source\blender\makesrna\intern\rna_armature_api.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\source\blender\makesrna\intern\rna_boid.c"
|
||||
>
|
||||
|
@ -44,7 +44,7 @@
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\..\lib\windows\pthreads\include;..\..\..\source\blender\imbuf;..\..\..\source\blender\makesdna;..\..\..\source\blender\makesrna;..\..\..\source\blender\blenlib;..\..\..\source\blender\blenkernel;..\..\..\source\blender\ikplugin;..\..\..\source\blender\windowmanager;..\..\..\source\blender\editors\include;..\..\..\source\blender\render\extern\include"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;GAMEBLENDER=1"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
@ -115,7 +115,7 @@
|
||||
Optimization="2"
|
||||
EnableIntrinsicFunctions="true"
|
||||
AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\..\lib\windows\pthreads\include;..\..\..\source\blender\imbuf;..\..\..\source\blender\makesdna;..\..\..\source\blender\makesrna;..\..\..\source\blender\blenlib;..\..\..\source\blender\blenkernel;..\..\..\source\blender\ikplugin;..\..\..\source\blender\windowmanager;..\..\..\source\blender\editors\include;..\..\..\source\blender\render\extern\include"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;GAMEBLENDER=1"
|
||||
MinimalRebuild="true"
|
||||
RuntimeLibrary="0"
|
||||
EnableFunctionLevelLinking="false"
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 190 KiB After Width: | Height: | Size: 204 KiB |
@ -757,6 +757,7 @@ class PovrayRender(bpy.types.RenderEngine):
|
||||
pov_binary = winreg.QueryValueEx(regKey, 'Home')[0] + '\\bin\\pvengine'
|
||||
|
||||
if 1:
|
||||
# TODO, when povray isnt found this gives a cryptic error, would be nice to be able to detect if it exists
|
||||
self._process = subprocess.Popen([pov_binary, self._temp_file_ini]) # stdout=subprocess.PIPE, stderr=subprocess.PIPE
|
||||
else:
|
||||
# This works too but means we have to wait until its done
|
||||
|
@ -486,7 +486,7 @@ def write(filename, batch_objects = None, \
|
||||
self.blenBone = blenBone
|
||||
self.blenMeshes = {} # fbxMeshObName : mesh
|
||||
self.fbxArm = fbxArm
|
||||
self.restMatrix = blenBone.armature_matrix
|
||||
self.restMatrix = blenBone.matrix_local
|
||||
# self.restMatrix = blenBone.matrix['ARMATURESPACE']
|
||||
|
||||
# not used yet
|
||||
@ -664,13 +664,13 @@ def write(filename, batch_objects = None, \
|
||||
|
||||
# we know we have a matrix
|
||||
# matrix = mtx4_z90 * (ob.matrix['ARMATURESPACE'] * matrix_mod)
|
||||
matrix = mtx4_z90 * ob.armature_matrix # dont apply armature matrix anymore
|
||||
matrix = mtx4_z90 * ob.matrix_local # dont apply armature matrix anymore
|
||||
# matrix = mtx4_z90 * ob.matrix['ARMATURESPACE'] # dont apply armature matrix anymore
|
||||
|
||||
parent = ob.parent
|
||||
if parent:
|
||||
#par_matrix = mtx4_z90 * (parent.matrix['ARMATURESPACE'] * matrix_mod)
|
||||
par_matrix = mtx4_z90 * parent.armature_matrix # dont apply armature matrix anymore
|
||||
par_matrix = mtx4_z90 * parent.matrix_local # dont apply armature matrix anymore
|
||||
# par_matrix = mtx4_z90 * parent.matrix['ARMATURESPACE'] # dont apply armature matrix anymore
|
||||
matrix = matrix * par_matrix.copy().invert()
|
||||
|
||||
@ -841,7 +841,7 @@ def write(filename, batch_objects = None, \
|
||||
"""
|
||||
|
||||
file.write('\n\t\t\tProperty: "LimbLength", "double", "",%.6f' %
|
||||
(my_bone.blenBone.armature_head - my_bone.blenBone.armature_tail).length)
|
||||
(my_bone.blenBone.head_local - my_bone.blenBone.tail_local).length)
|
||||
# (my_bone.blenBone.head['ARMATURESPACE'] - my_bone.blenBone.tail['ARMATURESPACE']).length)
|
||||
|
||||
#file.write('\n\t\t\tProperty: "LimbLength", "double", "",1')
|
||||
|
@ -85,19 +85,6 @@ def fixName(name):
|
||||
else:
|
||||
return name.replace(' ', '_')
|
||||
|
||||
|
||||
# this used to be in BPySys module
|
||||
# frankly, I don't understand how it works
|
||||
def BPySys_cleanName(name):
|
||||
|
||||
v = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,46,47,58,59,60,61,62,63,64,91,92,93,94,96,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254]
|
||||
|
||||
invalid = ''.join([chr(i) for i in v])
|
||||
|
||||
for ch in invalid:
|
||||
name = name.replace(ch, '_')
|
||||
return name
|
||||
|
||||
# A Dict of Materials
|
||||
# (material.name, image.name):matname_imagename # matname_imagename has gaps removed.
|
||||
MTL_DICT = {}
|
||||
@ -884,7 +871,7 @@ def do_export(filename, context,
|
||||
orig_frame = scn.current_frame
|
||||
|
||||
if EXPORT_ALL_SCENES: # Add scene name into the context_name
|
||||
context_name[1] = '_%s' % BPySys_cleanName(scn.name) # WARNING, its possible that this could cause a collision. we could fix if were feeling parranoied.
|
||||
context_name[1] = '_%s' % bpy.utils.clean_name(scn.name) # WARNING, its possible that this could cause a collision. we could fix if were feeling parranoied.
|
||||
|
||||
# Export an animation?
|
||||
if EXPORT_ANIMATION:
|
||||
@ -998,9 +985,9 @@ class ExportOBJ(bpy.types.Operator):
|
||||
wm.add_fileselect(self)
|
||||
return ('RUNNING_MODAL',)
|
||||
|
||||
def poll(self, context): # Poll isnt working yet
|
||||
print("Poll")
|
||||
return context.active_object != None
|
||||
|
||||
|
||||
|
||||
|
||||
bpy.ops.add(ExportOBJ)
|
||||
|
||||
@ -1021,4 +1008,4 @@ if __name__ == "__main__":
|
||||
# - NURBS - needs API additions
|
||||
# - all scenes export
|
||||
# + normals calculation
|
||||
# - get rid of cleanName somehow
|
||||
|
||||
|
@ -263,9 +263,9 @@ class ExportPLY(bpy.types.Operator):
|
||||
|
||||
path = StringProperty(name="File Path", description="File path used for exporting the PLY file", maxlen= 1024, default= "")
|
||||
use_modifiers = BoolProperty(name="Apply Modifiers", description="Apply Modifiers to the exported mesh", default= True)
|
||||
use_normals = BoolProperty(name="Export Normals", description="Export Normals for smooth and hard shaded faces", default= True)
|
||||
use_uvs = BoolProperty(name="Export UVs", description="Exort the active UV layer", default= True)
|
||||
use_colors = BoolProperty(name="Export Vertex Colors", description="Exort the active vertex color layer", default= True)
|
||||
use_normals = BoolProperty(name="Normals", description="Export Normals for smooth and hard shaded faces", default= True)
|
||||
use_uvs = BoolProperty(name="UVs", description="Exort the active UV layer", default= True)
|
||||
use_colors = BoolProperty(name="Vertex Colors", description="Exort the active vertex color layer", default= True)
|
||||
|
||||
|
||||
def poll(self, context):
|
||||
@ -291,6 +291,17 @@ class ExportPLY(bpy.types.Operator):
|
||||
wm.add_fileselect(self)
|
||||
return ('RUNNING_MODAL',)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
props = self.properties
|
||||
|
||||
row = layout.row()
|
||||
row.prop(props, "use_modifiers")
|
||||
row.prop(props, "use_normals")
|
||||
row = layout.row()
|
||||
row.prop(props, "use_uvs")
|
||||
row.prop(props, "use_colors")
|
||||
|
||||
|
||||
bpy.ops.add(ExportPLY)
|
||||
|
||||
|
@ -227,8 +227,6 @@ def read_bvh(context, file_path, GLOBAL_SCALE=1.0):
|
||||
if ROT_STYLE != 'NATIVE':
|
||||
rx, ry, rz = eulerRotate(rx, ry, rz, bvh_node.rot_order)
|
||||
|
||||
#x,y,z = x/10.0, y/10.0, z/10.0 # For IPO's 36 is 360d
|
||||
|
||||
# Make interpolation not cross between 180d, thjis fixes sub frame interpolation and time scaling.
|
||||
# Will go from (355d to 365d) rather then to (355d to 5d) - inbetween these 2 there will now be a correct interpolation.
|
||||
|
||||
@ -337,7 +335,7 @@ def bvh_node_dict2objects(context, bvh_nodes, IMPORT_START_FRAME= 1, IMPORT_LOOP
|
||||
|
||||
bvh_node.temp.rot= rx*DEG2RAD,ry*DEG2RAD,rz*DEG2RAD
|
||||
|
||||
bvh_node.temp.insertIpoKey(Blender.Object.IpoKeyTypes.LOCROT)
|
||||
bvh_node.temp.insertIpoKey(Blender.Object.IpoKeyTypes.LOCROT) # XXX invalid
|
||||
|
||||
scn.update(1)
|
||||
return objects
|
||||
@ -401,7 +399,7 @@ def bvh_node_dict2armature(context, bvh_nodes, IMPORT_START_FRAME= 1, IMPORT_LOO
|
||||
#XXX - sloppy operator code
|
||||
|
||||
bpy.ops.armature.delete()
|
||||
bpy.ops.armature.select_all_toggle()
|
||||
bpy.ops.armature.select_all()
|
||||
bpy.ops.armature.delete()
|
||||
|
||||
ZERO_AREA_BONES= []
|
||||
@ -486,8 +484,8 @@ def bvh_node_dict2armature(context, bvh_nodes, IMPORT_START_FRAME= 1, IMPORT_LOO
|
||||
pass
|
||||
|
||||
|
||||
bpy.ops.pose.select_all_toggle() # set
|
||||
bpy.ops.anim.insert_keyframe_menu(type=-4) # XXX - -4 ???
|
||||
bpy.ops.pose.select_all() # set
|
||||
bpy.ops.anim.keyframe_insert_menu(type=-4) # XXX - -4 ???
|
||||
|
||||
|
||||
|
||||
@ -500,7 +498,7 @@ def bvh_node_dict2armature(context, bvh_nodes, IMPORT_START_FRAME= 1, IMPORT_LOO
|
||||
#XXX action = Blender.Armature.NLA.NewAction("Action")
|
||||
#XXX action.setActive(arm_ob)
|
||||
|
||||
#bpy.ops.act.new()
|
||||
#bpy.ops.action.new()
|
||||
#action = bpy.data.actions[-1]
|
||||
|
||||
# arm_ob.animation_data.action = action
|
||||
@ -540,6 +538,7 @@ def bvh_node_dict2armature(context, bvh_nodes, IMPORT_START_FRAME= 1, IMPORT_LOO
|
||||
'''
|
||||
|
||||
# KEYFRAME METHOD, SLOW, USE IPOS DIRECT
|
||||
# TODO: use f-point samples instead (Aligorith)
|
||||
|
||||
# Animate the data, the last used bvh_node will do since they all have the same number of frames
|
||||
for current_frame in range(len(bvh_node.anim_data)-1): # skip the first frame (rest frame)
|
||||
@ -618,7 +617,7 @@ def bvh_node_dict2armature(context, bvh_nodes, IMPORT_START_FRAME= 1, IMPORT_LOO
|
||||
|
||||
|
||||
|
||||
# bpy.ops.anim.insert_keyframe_menu(type=-4) # XXX - -4 ???
|
||||
# bpy.ops.anim.keyframe_insert_menu(type=-4) # XXX - -4 ???
|
||||
bpy.ops.screen.frame_offset(delta=1)
|
||||
|
||||
# First time, set the IPO's to linear
|
||||
|
@ -807,7 +807,7 @@ def create_mesh(scn, new_objects, has_ngons, CREATE_FGONS, CREATE_EDGES, verts_l
|
||||
blender_tface.uv2= verts_tex[face_vert_tex_indicies[1]]
|
||||
blender_tface.uv3= verts_tex[face_vert_tex_indicies[2]]
|
||||
|
||||
if blender_face.verts[3] != 0:
|
||||
if len(face_vert_loc_indicies)==4:
|
||||
blender_tface.uv4= verts_tex[face_vert_tex_indicies[3]]
|
||||
|
||||
# for ii, uv in enumerate(blender_face.uv):
|
||||
@ -1277,7 +1277,7 @@ def load_obj(filepath,
|
||||
|
||||
# deselect all
|
||||
# if context.selected_objects:
|
||||
# bpy.ops.OBJECT_OT_select_all_toggle()
|
||||
# bpy.ops.OBJECT_OT_select_all()
|
||||
|
||||
scene = context.scene
|
||||
# scn = bpy.data.scenes.active
|
||||
@ -1640,5 +1640,5 @@ menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_import, menu_func)
|
||||
# search image in bpy.config.textureDir - load_image
|
||||
# replaced BPyImage.comprehensiveImageLoad with a simplified version that only checks additional directory specified, but doesn't search dirs recursively (obj_image_load)
|
||||
# bitmask won't work? - 132
|
||||
# uses operator bpy.ops.OBJECT_OT_select_all_toggle() to deselect all (not necessary?)
|
||||
# uses operator bpy.ops.OBJECT_OT_select_all() to deselect all (not necessary?)
|
||||
# uses bpy.sys.time()
|
||||
|
@ -127,7 +127,7 @@ def clientSendJob(conn, scene, anim = False):
|
||||
# FLUID + POINT CACHE
|
||||
###########################
|
||||
root, ext = os.path.splitext(name)
|
||||
default_path = path + "blendcache_" + root + os.sep # need an API call for that
|
||||
default_path = path + os.sep + "blendcache_" + root + os.sep # need an API call for that
|
||||
|
||||
for object in bpy.data.objects:
|
||||
for modifier in object.modifiers:
|
||||
|
@ -26,6 +26,64 @@ from netrender.utils import *
|
||||
import netrender.client as client
|
||||
import netrender.model
|
||||
|
||||
@rnaOperator
|
||||
class RENDER_OT_netslave_bake(bpy.types.Operator):
|
||||
'''NEED DESCRIPTION'''
|
||||
bl_idname = "render.netslavebake"
|
||||
bl_label = "Bake all in file"
|
||||
|
||||
def poll(self, context):
|
||||
return True
|
||||
|
||||
def execute(self, context):
|
||||
scene = context.scene
|
||||
netsettings = scene.network_render
|
||||
|
||||
filename = bpy.data.filename
|
||||
path, name = os.path.split(filename)
|
||||
root, ext = os.path.splitext(name)
|
||||
default_path = path + os.sep + "blendcache_" + root + os.sep # need an API call for that
|
||||
relative_path = os.sep + os.sep + "blendcache_" + root + os.sep
|
||||
|
||||
# Force all point cache next to the blend file
|
||||
for object in bpy.data.objects:
|
||||
for modifier in object.modifiers:
|
||||
if modifier.type == 'FLUID_SIMULATION' and modifier.settings.type == "DOMAIN":
|
||||
modifier.settings.path = relative_path
|
||||
bpy.ops.fluid.bake({"active_object": object, "scene": scene})
|
||||
elif modifier.type == "CLOTH":
|
||||
modifier.point_cache.step = 1
|
||||
modifier.point_cache.disk_cache = True
|
||||
modifier.point_cache.external = False
|
||||
elif modifier.type == "SOFT_BODY":
|
||||
modifier.point_cache.step = 1
|
||||
modifier.point_cache.disk_cache = True
|
||||
modifier.point_cache.external = False
|
||||
elif modifier.type == "SMOKE" and modifier.smoke_type == "TYPE_DOMAIN":
|
||||
modifier.domain_settings.point_cache_low.step = 1
|
||||
modifier.domain_settings.point_cache_low.disk_cache = True
|
||||
modifier.domain_settings.point_cache_low.external = False
|
||||
modifier.domain_settings.point_cache_high.step = 1
|
||||
modifier.domain_settings.point_cache_high.disk_cache = True
|
||||
modifier.domain_settings.point_cache_high.external = False
|
||||
|
||||
# particles modifier are stupid and don't contain data
|
||||
# we have to go through the object property
|
||||
for psys in object.particle_systems:
|
||||
psys.point_cache.step = 1
|
||||
psys.point_cache.disk_cache = True
|
||||
psys.point_cache.external = False
|
||||
psys.point_cache.filepath = relative_path
|
||||
|
||||
bpy.ops.ptcache.bake_all()
|
||||
|
||||
#bpy.ops.wm.save_mainfile(path = path + os.sep + root + "_baked.blend")
|
||||
|
||||
return ('FINISHED',)
|
||||
|
||||
def invoke(self, context, event):
|
||||
return self.execute(context)
|
||||
|
||||
@rnaOperator
|
||||
class RENDER_OT_netclientanim(bpy.types.Operator):
|
||||
'''Start rendering an animation on network'''
|
||||
|
@ -16,6 +16,8 @@
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
# internal blender C module
|
||||
import _bpy
|
||||
from _bpy import types, props
|
||||
@ -31,21 +33,33 @@ from bpy import ops as _ops_module
|
||||
# fake operator module
|
||||
ops = _ops_module.ops_fake_module
|
||||
|
||||
import sys
|
||||
DEBUG = ("-d" in sys.argv)
|
||||
|
||||
def load_scripts(reload_scripts=False):
|
||||
import os
|
||||
import sys
|
||||
import traceback
|
||||
import time
|
||||
|
||||
|
||||
t_main = time.time()
|
||||
|
||||
def test_import(module_name):
|
||||
try:
|
||||
return __import__(module_name)
|
||||
t = time.time()
|
||||
ret= __import__(module_name)
|
||||
if DEBUG:
|
||||
print("time %s %.4f" % (module_name, time.time() - t))
|
||||
return ret
|
||||
except:
|
||||
traceback.print_exc()
|
||||
return None
|
||||
|
||||
|
||||
for base_path in utils.script_paths():
|
||||
for path_subdir in ("ui", "op", "io"):
|
||||
path = os.path.join(base_path, path_subdir)
|
||||
if os.path.isdir(path):
|
||||
sys.path.insert(0, path)
|
||||
for f in sorted(os.listdir(path)):
|
||||
if f.endswith(".py"):
|
||||
@ -61,6 +75,9 @@ def load_scripts(reload_scripts=False):
|
||||
print("Reloading:", mod)
|
||||
reload(mod)
|
||||
|
||||
if DEBUG:
|
||||
print("Time %.4f" % (time.time() - t_main))
|
||||
|
||||
def _main():
|
||||
|
||||
# a bit nasty but this prevents help() and input() from locking blender
|
||||
@ -69,7 +86,8 @@ def _main():
|
||||
import sys
|
||||
sys.stdin = None
|
||||
|
||||
if "-d" in sys.argv and False: # Enable this to measure startup speed
|
||||
# if "-d" in sys.argv: # Enable this to measure startup speed
|
||||
if 0:
|
||||
import cProfile
|
||||
cProfile.run('import bpy; bpy.load_scripts()', 'blender.prof')
|
||||
|
||||
|
@ -23,6 +23,7 @@ from _bpy import ops as ops_module
|
||||
|
||||
op_add = ops_module.add
|
||||
op_remove = ops_module.remove
|
||||
op_add_macro = ops_module.add_macro
|
||||
op_dir = ops_module.dir
|
||||
op_call = ops_module.call
|
||||
op_as_string = ops_module.as_string
|
||||
@ -59,6 +60,9 @@ class bpy_ops(object):
|
||||
def add(self, pyop):
|
||||
op_add(pyop)
|
||||
|
||||
def add_macro(self, pyop):
|
||||
op_add_macro(pyop)
|
||||
|
||||
def remove(self, pyop):
|
||||
op_remove(pyop)
|
||||
|
||||
|
@ -16,6 +16,8 @@
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
import bpy
|
||||
import os
|
||||
|
||||
@ -25,18 +27,61 @@ def expandpath(path):
|
||||
|
||||
return path
|
||||
|
||||
|
||||
_unclean_chars = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, \
|
||||
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, \
|
||||
35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 46, 47, 58, 59, 60, 61, 62, 63, \
|
||||
64, 91, 92, 93, 94, 96, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, \
|
||||
133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, \
|
||||
147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, \
|
||||
161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, \
|
||||
175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, \
|
||||
189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, \
|
||||
203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, \
|
||||
217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, \
|
||||
231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, \
|
||||
245, 246, 247, 248, 249, 250, 251, 252, 253, 254]
|
||||
|
||||
_unclean_chars = ''.join([chr(i) for i in _unclean_chars])
|
||||
|
||||
def clean_name(name, replace="_"):
|
||||
'''
|
||||
All characters besides A-Z/a-z, 0-9 are replaced with "_"
|
||||
or the replace argumet if defined.
|
||||
'''
|
||||
for ch in _unclean_chars:
|
||||
name = name.replace(ch, replace)
|
||||
return name
|
||||
|
||||
|
||||
# base scripts
|
||||
_scripts = os.path.join(os.path.dirname(__file__), os.path.pardir, os.path.pardir)
|
||||
_scripts = (os.path.normpath(_scripts), )
|
||||
|
||||
def script_paths(*args):
|
||||
scripts = list(_scripts)
|
||||
|
||||
# add user scripts dir
|
||||
user_script_path = bpy.context.user_preferences.filepaths.python_scripts_directory
|
||||
|
||||
if not user_script_path:
|
||||
# XXX - WIN32 needs checking, perhaps better call a blender internal function.
|
||||
user_script_path = os.path.join(os.path.expanduser("~"), ".blender", "scripts")
|
||||
|
||||
user_script_path = os.path.normpath(user_script_path)
|
||||
|
||||
if user_script_path not in scripts and os.path.isdir(user_script_path):
|
||||
scripts.append(user_script_path)
|
||||
|
||||
if not args:
|
||||
return _scripts
|
||||
return scripts
|
||||
|
||||
subdir = os.path.join(*args)
|
||||
script_paths = []
|
||||
for path in _scripts:
|
||||
script_paths.append(os.path.join(path, subdir))
|
||||
for path in scripts:
|
||||
path_subdir = os.path.join(path, subdir)
|
||||
if os.path.isdir(path_subdir):
|
||||
script_paths.append(path_subdir)
|
||||
|
||||
return script_paths
|
||||
|
||||
|
@ -15,6 +15,9 @@
|
||||
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
from _bpy import types as bpy_types
|
||||
|
||||
StructRNA = bpy_types.Struct.__bases__[0]
|
||||
@ -22,6 +25,7 @@ StructRNA = bpy_types.Struct.__bases__[0]
|
||||
|
||||
|
||||
class Context(StructRNA):
|
||||
__slots__ = ()
|
||||
|
||||
def copy(self):
|
||||
new_context = {}
|
||||
@ -34,6 +38,7 @@ class Context(StructRNA):
|
||||
|
||||
|
||||
class Object(bpy_types.ID):
|
||||
__slots__ = ()
|
||||
|
||||
@property
|
||||
def children(self):
|
||||
@ -46,6 +51,12 @@ class _GenericBone:
|
||||
functions for bones, common between Armature/Pose/Edit bones.
|
||||
internal subclassing use only.
|
||||
'''
|
||||
__slots__ = ()
|
||||
|
||||
def translate(self, vec):
|
||||
self.head += vec
|
||||
self.tail += vec
|
||||
|
||||
def parent_index(self, parent_test):
|
||||
'''
|
||||
The same as 'bone in other_bone.parent_recursive' but saved generating a list.
|
||||
@ -63,6 +74,11 @@ class _GenericBone:
|
||||
|
||||
return 0
|
||||
|
||||
@property
|
||||
def basename(self):
|
||||
#return self.name.rsplit(".", 1)[0]
|
||||
return self.name.split(".")[0]
|
||||
|
||||
@property
|
||||
def parent_recursive(self):
|
||||
parent_list = []
|
||||
@ -80,6 +96,11 @@ class _GenericBone:
|
||||
def length(self):
|
||||
return (self.head - self.tail).length
|
||||
|
||||
@length.setter
|
||||
def length(self, value):
|
||||
"""The distance from head to tail"""
|
||||
self.tail = self.head + ((self.tail - self.head).normalize() * value)
|
||||
|
||||
@property
|
||||
def children(self):
|
||||
return [child for child in self._other_bones if child.parent == self]
|
||||
@ -96,6 +117,35 @@ class _GenericBone:
|
||||
bones_children.sort(key=lambda bone_pair: bone_pair[0])
|
||||
return [bone for index, bone in bones_children]
|
||||
|
||||
@property
|
||||
def children_recursive_basename(self):
|
||||
'''
|
||||
Returns a chain of children with the same base name as this bone
|
||||
Only direct chains are supported, forks caused by multiple children with matching basenames will.
|
||||
'''
|
||||
basename = self.basename
|
||||
chain = []
|
||||
|
||||
child = self
|
||||
while True:
|
||||
children = child.children
|
||||
children_basename = []
|
||||
|
||||
for child in children:
|
||||
if basename == child.basename:
|
||||
children_basename.append(child)
|
||||
|
||||
if len(children_basename) == 1:
|
||||
child = children_basename[0]
|
||||
chain.append(child)
|
||||
else:
|
||||
if len(children_basename):
|
||||
print("multiple basenames found, this is probably not what you want!", bone.name, children_basename)
|
||||
|
||||
break
|
||||
|
||||
return chain
|
||||
|
||||
@property
|
||||
def _other_bones(self):
|
||||
id_data = self.id_data
|
||||
@ -112,22 +162,51 @@ class _GenericBone:
|
||||
|
||||
|
||||
class PoseBone(StructRNA, _GenericBone):
|
||||
pass
|
||||
__slots__ = ()
|
||||
|
||||
|
||||
class Bone(StructRNA, _GenericBone):
|
||||
pass
|
||||
__slots__ = ()
|
||||
|
||||
|
||||
class EditBone(StructRNA, _GenericBone):
|
||||
pass
|
||||
__slots__ = ()
|
||||
|
||||
|
||||
def ord_ind(i1, i2):
|
||||
if i1<i2: return i1,i2
|
||||
if i1 < i2:
|
||||
return i1, i2
|
||||
return i2, i1
|
||||
|
||||
|
||||
class Mesh(bpy_types.ID):
|
||||
__slots__ = ()
|
||||
|
||||
def from_pydata(self, verts, edges, faces):
|
||||
'''
|
||||
Make a mesh from a list of verts/edges/faces
|
||||
Until we have a nicer way to make geometry, use this.
|
||||
'''
|
||||
self.add_geometry(len(verts), len(edges), len(faces))
|
||||
|
||||
verts_flat = [f for v in verts for f in v]
|
||||
self.verts.foreach_set("co", verts_flat)
|
||||
del verts_flat
|
||||
|
||||
edges_flat = [i for e in edges for i in e]
|
||||
self.edges.foreach_set("verts", edges_flat)
|
||||
del edges_flat
|
||||
|
||||
def treat_face(f):
|
||||
if len(f) == 3:
|
||||
return f[0], f[1], f[2], 0
|
||||
elif f[3] == 0:
|
||||
return f[3], f[0], f[1], f[2]
|
||||
return f
|
||||
|
||||
faces_flat = [v for f in faces for v in treat_face(f)]
|
||||
self.faces.foreach_set("verts_raw", faces_flat)
|
||||
del faces_flat
|
||||
|
||||
@property
|
||||
def edge_keys(self):
|
||||
@ -153,6 +232,7 @@ class Mesh(bpy_types.ID):
|
||||
|
||||
|
||||
class MeshEdge(StructRNA):
|
||||
__slots__ = ()
|
||||
|
||||
@property
|
||||
def key(self):
|
||||
@ -160,6 +240,7 @@ class MeshEdge(StructRNA):
|
||||
|
||||
|
||||
class MeshFace(StructRNA):
|
||||
__slots__ = ()
|
||||
|
||||
@property
|
||||
def edge_keys(self):
|
||||
@ -171,20 +252,36 @@ class MeshFace(StructRNA):
|
||||
|
||||
|
||||
import collections
|
||||
|
||||
|
||||
class OrderedMeta(type):
|
||||
|
||||
def __init__(cls, name, bases, attributes):
|
||||
super(OrderedMeta, cls).__init__(name, bases, attributes)
|
||||
cls.order = list(attributes.keys())
|
||||
|
||||
def __prepare__(name, bases, **kwargs):
|
||||
return collections.OrderedDict()
|
||||
|
||||
|
||||
# Only defined so operators members can be used by accessing self.order
|
||||
class Operator(StructRNA, metaclass=OrderedMeta):
|
||||
pass
|
||||
__slots__ = ()
|
||||
|
||||
|
||||
class Macro(StructRNA, metaclass=OrderedMeta):
|
||||
# bpy_types is imported before ops is defined
|
||||
# so we have to do a local import on each run
|
||||
__slots__ = ()
|
||||
|
||||
@classmethod
|
||||
def define(self, opname):
|
||||
from _bpy import ops
|
||||
return ops.macro_define(self, opname)
|
||||
|
||||
|
||||
class Menu(StructRNA):
|
||||
__slots__ = ()
|
||||
|
||||
def path_menu(self, searchpaths, operator):
|
||||
layout = self.layout
|
||||
|
@ -69,10 +69,13 @@ def get_root_modules():
|
||||
|
||||
modules += sys.builtin_module_names
|
||||
|
||||
# needed for modules defined in C
|
||||
modules += sys.modules.keys()
|
||||
|
||||
modules = list(set(modules))
|
||||
if '__init__' in modules:
|
||||
modules.remove('__init__')
|
||||
modules = sorted(set(modules))
|
||||
modules = sorted(modules)
|
||||
if store:
|
||||
ROOT_MODULES = modules
|
||||
return modules
|
||||
|
@ -16,8 +16,11 @@
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
import bpy
|
||||
|
||||
|
||||
def collect_baseclasses(_class, bases):
|
||||
|
||||
if _class is type or _class is object:
|
||||
@ -29,6 +32,7 @@ def collect_baseclasses(_class, bases):
|
||||
|
||||
return bases
|
||||
|
||||
|
||||
def collect_subclasses(_class, subs):
|
||||
|
||||
if _class is type or _class is object:
|
||||
@ -40,6 +44,7 @@ def collect_subclasses(_class, subs):
|
||||
|
||||
return subs
|
||||
|
||||
|
||||
class DynMenu(bpy.types.Menu):
|
||||
|
||||
def draw(self, context):
|
||||
@ -61,6 +66,7 @@ class DynMenu(bpy.types.Menu):
|
||||
subclass.internal_draw(self, context)
|
||||
# print("subclass.internal_draw", subclass.internal_draw)
|
||||
|
||||
|
||||
def setup(menu_class):
|
||||
'''
|
||||
Setup subclasses (not needed when self.add() is used)
|
||||
@ -88,6 +94,7 @@ def setup(menu_class):
|
||||
|
||||
root_class.draw = DynMenu.draw
|
||||
|
||||
|
||||
def add(menu_class, func):
|
||||
'''
|
||||
Add a single function directly without having to make a class
|
||||
|
187
release/scripts/modules/graphviz_export.py
Normal file
187
release/scripts/modules/graphviz_export.py
Normal file
@ -0,0 +1,187 @@
|
||||
# ##### 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.
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
import bpy
|
||||
|
||||
header = '''
|
||||
digraph ancestors {
|
||||
graph [fontsize=30 labelloc="t" label="" splines=false overlap=true, rankdir=BT];
|
||||
ratio = "auto" ;
|
||||
'''
|
||||
|
||||
footer = '''
|
||||
}
|
||||
'''
|
||||
|
||||
|
||||
def compat_str(text, line_length=0):
|
||||
|
||||
if line_length:
|
||||
text_ls = []
|
||||
while len(text) > line_length:
|
||||
text_ls.append(text[:line_length])
|
||||
text = text[line_length:]
|
||||
|
||||
if text:
|
||||
text_ls.append(text)
|
||||
text = '\n '.join(text_ls)
|
||||
|
||||
|
||||
#text = text.replace('.', '.\n')
|
||||
#text = text.replace(']', ']\n')
|
||||
text = text.replace("\n", "\\n")
|
||||
text = text.replace('"', '\\"')
|
||||
return "* " + text
|
||||
|
||||
|
||||
def graph_armature(obj, path, FAKE_PARENT=True, CONSTRAINTS=True, DRIVERS=True, XTRA_INFO=False):
|
||||
CONSTRAINTS = DRIVERS = True
|
||||
|
||||
fileobject = open(path, "w")
|
||||
fw = fileobject.write
|
||||
fw(header)
|
||||
fw('label = "%s::%s" ;' % (bpy.data.filename.split("/")[-1].split("\\")[-1], obj.name))
|
||||
|
||||
arm = obj.data
|
||||
|
||||
bones = [bone.name for bone in arm.bones]
|
||||
bones.sort()
|
||||
print("")
|
||||
for bone in bones:
|
||||
b = arm.bones[bone]
|
||||
print(">>", bone, ["*>", "->"][b.connected], getattr(getattr(b, "parent", ""), "name", ""))
|
||||
label = [bone]
|
||||
bone = arm.bones[bone]
|
||||
|
||||
for key, value in obj.pose.bones[bone.name].items():
|
||||
if key.startswith("_"):
|
||||
continue
|
||||
|
||||
if type(value) == float:
|
||||
value = "%.3f" % value
|
||||
elif type(value) == str:
|
||||
value = compat_str(value)
|
||||
|
||||
label.append("%s = %s" % (key, value))
|
||||
|
||||
opts = ["shape=box", "regular=1", "style=filled", "fixedsize=false", 'label="%s"' % compat_str('\n'.join(label))]
|
||||
|
||||
if bone.name.startswith('ORG'):
|
||||
opts.append("fillcolor=yellow")
|
||||
else:
|
||||
opts.append("fillcolor=white")
|
||||
|
||||
|
||||
fw('"%s" [%s];\n' % (bone.name, ','.join(opts)))
|
||||
|
||||
fw('\n\n# Hierarchy:\n')
|
||||
|
||||
# Root node.
|
||||
if FAKE_PARENT:
|
||||
fw('"Object::%s" [];\n' % obj.name)
|
||||
|
||||
for bone in bones:
|
||||
bone = arm.bones[bone]
|
||||
|
||||
parent = bone.parent
|
||||
if parent:
|
||||
parent_name = parent.name
|
||||
connected = bone.connected
|
||||
elif FAKE_PARENT:
|
||||
parent_name = 'Object::%s' % obj.name
|
||||
connected = False
|
||||
else:
|
||||
continue
|
||||
|
||||
opts = ["dir=forward", "weight=2", "arrowhead=normal"]
|
||||
if not connected:
|
||||
opts.append("style=dotted")
|
||||
|
||||
fw('"%s" -> "%s" [%s] ;\n' % (bone.name, parent_name, ','.join(opts)))
|
||||
del bone
|
||||
|
||||
# constraints
|
||||
if CONSTRAINTS:
|
||||
fw('\n\n# Constraints:\n')
|
||||
for bone in bones:
|
||||
pbone = obj.pose.bones[bone]
|
||||
# must be ordered
|
||||
for constraint in pbone.constraints:
|
||||
subtarget = getattr(constraint, "subtarget", "")
|
||||
if subtarget:
|
||||
# TODO, not internal links
|
||||
opts = ['dir=forward', "weight=1", "arrowhead=normal", "arrowtail=none", "constraint=false", 'color="red"', 'labelfontsize=4']
|
||||
if XTRA_INFO:
|
||||
label = "%s\n%s" % (constraint.type, constraint.name)
|
||||
opts.append('label="%s"' % compat_str(label))
|
||||
fw('"%s" -> "%s" [%s] ;\n' % (subtarget, pbone.name, ','.join(opts)))
|
||||
|
||||
# Drivers
|
||||
if DRIVERS:
|
||||
fw('\n\n# Drivers:\n')
|
||||
|
||||
def rna_path_as_pbone(rna_path):
|
||||
if not rna_path.startswith("pose.bones["):
|
||||
return None
|
||||
|
||||
#rna_path_bone = rna_path[:rna_path.index("]") + 1]
|
||||
#return obj.path_resolve(rna_path_bone)
|
||||
bone_name = rna_path.split("[")[1].split("]")[0]
|
||||
return obj.pose.bones[bone_name[1:-1]]
|
||||
|
||||
animation_data = obj.animation_data
|
||||
if animation_data:
|
||||
|
||||
fcurve_drivers = [fcurve_driver for fcurve_driver in animation_data.drivers]
|
||||
fcurve_drivers.sort(key=lambda fcurve_driver: fcurve_driver.rna_path)
|
||||
|
||||
for fcurve_driver in fcurve_drivers:
|
||||
rna_path = fcurve_driver.rna_path
|
||||
pbone = rna_path_as_pbone(rna_path)
|
||||
|
||||
if pbone:
|
||||
for target in fcurve_driver.driver.targets:
|
||||
pbone_target = rna_path_as_pbone(target.rna_path)
|
||||
rna_path_target = target.rna_path
|
||||
if pbone_target:
|
||||
opts = ['dir=forward', "weight=1", "arrowhead=normal", "arrowtail=none", "constraint=false", 'color="blue"', "labelfontsize=4"] # ,
|
||||
display_source = rna_path.replace("pose.bones", "")
|
||||
display_target = rna_path_target.replace("pose.bones", "")
|
||||
if XTRA_INFO:
|
||||
label = "%s\\n%s" % (display_source, display_target)
|
||||
opts.append('label="%s"' % compat_str(label))
|
||||
fw('"%s" -> "%s" [%s] ;\n' % (pbone_target.name, pbone.name, ','.join(opts)))
|
||||
|
||||
fw(footer)
|
||||
fileobject.close()
|
||||
|
||||
'''
|
||||
print(".", end='')
|
||||
import sys
|
||||
sys.stdout.flush()
|
||||
'''
|
||||
print("\nSaved:", path)
|
||||
return True
|
||||
|
||||
if __name__ == "__main__":
|
||||
import os
|
||||
tmppath = "/tmp/test.dot"
|
||||
graph_armature(bpy.context.object, tmppath, CONSTRAINTS=True, DRIVERS=True)
|
||||
os.system("dot -Tpng %s > %s; eog %s &" % (tmppath, tmppath + '.png', tmppath + '.png'))
|
301
release/scripts/modules/retopo.py
Normal file
301
release/scripts/modules/retopo.py
Normal file
@ -0,0 +1,301 @@
|
||||
# ##### 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.
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
import bpy
|
||||
|
||||
EPS_SPLINE_DIV = 15.0 # remove doubles is ~15th the length of the spline
|
||||
|
||||
|
||||
def get_hub(co, _hubs, EPS_SPLINE):
|
||||
|
||||
if 1:
|
||||
for hub in _hubs.values():
|
||||
if (hub.co - co).length < EPS_SPLINE:
|
||||
return hub
|
||||
|
||||
key = co.toTuple(3)
|
||||
hub = _hubs[key] = Hub(co, key, len(_hubs))
|
||||
return hub
|
||||
else:
|
||||
pass
|
||||
|
||||
'''
|
||||
key = co.toTuple(3)
|
||||
try:
|
||||
return _hubs[key]
|
||||
except:
|
||||
hub = _hubs[key] = Hub(co, key, len(_hubs))
|
||||
return hub
|
||||
'''
|
||||
|
||||
|
||||
class Hub(object):
|
||||
__slots__ = "co", "key", "index", "links"
|
||||
|
||||
def __init__(self, co, key, index):
|
||||
self.co = co.copy()
|
||||
self.key = key
|
||||
self.index = index
|
||||
self.links = []
|
||||
|
||||
def get_weight(self):
|
||||
f = 0.0
|
||||
|
||||
for hub_other in self.links:
|
||||
f += (self.co - hub_other.co).length
|
||||
|
||||
def replace(self, other):
|
||||
for hub in self.links:
|
||||
try:
|
||||
hub.links.remove(self)
|
||||
except:
|
||||
pass
|
||||
if other not in hub.links:
|
||||
hub.links.append(other)
|
||||
|
||||
def dist(self, other):
|
||||
return (self.co - other.co).length
|
||||
|
||||
def calc_faces(self, hub_ls):
|
||||
faces = []
|
||||
# first tris
|
||||
for l_a in self.links:
|
||||
for l_b in l_a.links:
|
||||
if l_b is not self and l_b in self.links:
|
||||
# will give duplicates
|
||||
faces.append((self.index, l_a.index, l_b.index))
|
||||
|
||||
# now quads, check which links share 2 different verts directly
|
||||
def validate_quad(face):
|
||||
if len(set(face)) != len(face):
|
||||
return False
|
||||
if hub_ls[face[0]] in hub_ls[face[2]].links:
|
||||
return False
|
||||
if hub_ls[face[2]] in hub_ls[face[0]].links:
|
||||
return False
|
||||
|
||||
if hub_ls[face[1]] in hub_ls[face[3]].links:
|
||||
return False
|
||||
if hub_ls[face[3]] in hub_ls[face[1]].links:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
for i, l_a in enumerate(self.links):
|
||||
links_a = set([l.index for l in l_a.links])
|
||||
for j in range(i):
|
||||
l_b = self.links[j]
|
||||
|
||||
links_b = set([l.index for l in l_b.links])
|
||||
|
||||
isect = links_a.intersection(links_b)
|
||||
if len(isect) == 2:
|
||||
isect = list(isect)
|
||||
|
||||
# check there are no diagonal lines
|
||||
face = (isect[0], l_a.index, isect[1], l_b.index)
|
||||
if validate_quad(face):
|
||||
|
||||
faces.append(face)
|
||||
|
||||
return faces
|
||||
|
||||
|
||||
class Spline(object):
|
||||
__slots__ = "points", "hubs", "length"
|
||||
|
||||
def __init__(self, points):
|
||||
self.points = points
|
||||
self.hubs = []
|
||||
|
||||
# calc length
|
||||
f = 0.0
|
||||
co_prev = self.points[0]
|
||||
for co in self.points[1:]:
|
||||
f += (co - co_prev).length
|
||||
co_prev = co
|
||||
self.length = f
|
||||
|
||||
def link(self):
|
||||
if len(self.hubs) < 2:
|
||||
return
|
||||
|
||||
edges = list(set([i for i, hub in self.hubs]))
|
||||
edges.sort()
|
||||
|
||||
edges_order = {}
|
||||
for i in edges:
|
||||
edges_order[i] = []
|
||||
|
||||
|
||||
# self.hubs.sort()
|
||||
for i, hub in self.hubs:
|
||||
edges_order[i].append(hub)
|
||||
|
||||
hubs_order = []
|
||||
for i in edges:
|
||||
ls = edges_order[i]
|
||||
edge_start = self.points[i]
|
||||
ls.sort(key=lambda hub: (hub.co - edge_start).length)
|
||||
hubs_order.extend(ls)
|
||||
|
||||
# Now we have the order, connect the hubs
|
||||
hub_prev = hubs_order[0]
|
||||
|
||||
for hub in hubs_order[1:]:
|
||||
hub.links.append(hub_prev)
|
||||
hub_prev.links.append(hub)
|
||||
hub_prev = hub
|
||||
|
||||
|
||||
def get_points(stroke):
|
||||
return [point.co.copy() for point in stroke.points]
|
||||
|
||||
|
||||
def get_splines(gp):
|
||||
l = None
|
||||
for l in gp.layers:
|
||||
if l.active: # XXX - should be layers.active
|
||||
break
|
||||
if l:
|
||||
frame = l.active_frame
|
||||
return [Spline(get_points(stroke)) for stroke in frame.strokes]
|
||||
else:
|
||||
return []
|
||||
|
||||
|
||||
def xsect_spline(sp_a, sp_b, _hubs):
|
||||
from Mathutils import LineIntersect
|
||||
from Mathutils import MidpointVecs
|
||||
from Geometry import ClosestPointOnLine
|
||||
pt_a_prev = pt_b_prev = None
|
||||
EPS_SPLINE = (sp_a.length + sp_b.length) / (EPS_SPLINE_DIV * 2)
|
||||
pt_a_prev = sp_a.points[0]
|
||||
for a, pt_a in enumerate(sp_a.points[1:]):
|
||||
pt_b_prev = sp_b.points[0]
|
||||
for b, pt_b in enumerate(sp_b.points[1:]):
|
||||
|
||||
# Now we have 2 edges
|
||||
# print(pt_a, pt_a_prev, pt_b, pt_b_prev)
|
||||
xsect = LineIntersect(pt_a, pt_a_prev, pt_b, pt_b_prev)
|
||||
if xsect is not None:
|
||||
if (xsect[0] - xsect[1]).length <= EPS_SPLINE:
|
||||
f = ClosestPointOnLine(xsect[1], pt_a, pt_a_prev)[1]
|
||||
# if f >= 0.0-EPS_SPLINE and f <= 1.0+EPS_SPLINE: # for some reason doesnt work so well, same below
|
||||
if f >= 0.0 and f <= 1.0:
|
||||
f = ClosestPointOnLine(xsect[0], pt_b, pt_b_prev)[1]
|
||||
# if f >= 0.0-EPS_SPLINE and f <= 1.0+EPS_SPLINE:
|
||||
if f >= 0.0 and f <= 1.0:
|
||||
# This wont happen often
|
||||
co = MidpointVecs(xsect[0], xsect[1])
|
||||
hub = get_hub(co, _hubs, EPS_SPLINE)
|
||||
|
||||
sp_a.hubs.append((a, hub))
|
||||
sp_b.hubs.append((b, hub))
|
||||
|
||||
pt_b_prev = pt_b
|
||||
|
||||
pt_a_prev = pt_a
|
||||
|
||||
|
||||
def calculate(gp):
|
||||
splines = get_splines(gp)
|
||||
_hubs = {}
|
||||
|
||||
for i, sp in enumerate(splines):
|
||||
for j, sp_other in enumerate(splines):
|
||||
if j <= i:
|
||||
continue
|
||||
|
||||
xsect_spline(sp, sp_other, _hubs)
|
||||
|
||||
for sp in splines:
|
||||
sp.link()
|
||||
|
||||
# remove these
|
||||
hubs_ls = [hub for hub in _hubs.values() if hub.index != -1]
|
||||
|
||||
_hubs.clear()
|
||||
_hubs = None
|
||||
|
||||
for i, hub in enumerate(hubs_ls):
|
||||
hub.index = i
|
||||
|
||||
# Now we have connected hubs, write all edges!
|
||||
def order(i1, i2):
|
||||
if i1 > i2:
|
||||
return i2, i1
|
||||
return i1, i2
|
||||
|
||||
edges = {}
|
||||
|
||||
for hub in hubs_ls:
|
||||
i1 = hub.index
|
||||
for hub_other in hub.links:
|
||||
i2 = hub_other.index
|
||||
edges[order(i1, i2)] = None
|
||||
|
||||
verts = []
|
||||
edges = edges.keys()
|
||||
faces = []
|
||||
|
||||
for hub in hubs_ls:
|
||||
verts.append(hub.co)
|
||||
faces.extend(hub.calc_faces(hubs_ls))
|
||||
|
||||
# remove double faces
|
||||
faces = dict([(tuple(sorted(f)), f) for f in faces]).values()
|
||||
|
||||
mesh = bpy.data.add_mesh("Retopo")
|
||||
mesh.from_pydata(verts, [], faces)
|
||||
|
||||
scene = bpy.context.scene
|
||||
mesh.update()
|
||||
obj_new = bpy.data.add_object('MESH', "Torus")
|
||||
obj_new.data = mesh
|
||||
scene.objects.link(obj_new)
|
||||
|
||||
return obj_new
|
||||
|
||||
|
||||
def main():
|
||||
scene = bpy.context.scene
|
||||
obj = bpy.context.object
|
||||
|
||||
gp = None
|
||||
|
||||
if obj:
|
||||
gp = obj.grease_pencil
|
||||
|
||||
if not gp:
|
||||
gp = scene.grease_pencil
|
||||
|
||||
if not gp:
|
||||
raise Exception("no active grease pencil")
|
||||
|
||||
obj_new = calculate(gp)
|
||||
|
||||
scene.objects.active = obj_new
|
||||
obj_new.selected = True
|
||||
|
||||
# nasty, recalc normals
|
||||
bpy.ops.object.mode_set(mode='EDIT', toggle=False)
|
||||
bpy.ops.mesh.normals_make_consistent(inside=False)
|
||||
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
|
@ -1,385 +0,0 @@
|
||||
# ##### BEGIN GPL LICENSE BLOCK #####
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
import bpy
|
||||
from functools import reduce
|
||||
|
||||
# TODO, have these in a more general module
|
||||
from rna_prop_ui import rna_idprop_ui_get, rna_idprop_ui_prop_get
|
||||
|
||||
empty_layer = [False] * 16
|
||||
|
||||
|
||||
def gen_none(obj, orig_bone_name):
|
||||
pass
|
||||
|
||||
def get_bone_data(obj, bone_name):
|
||||
arm = obj.data
|
||||
pbone = obj.pose.bones[bone_name]
|
||||
if obj.mode == 'EDIT':
|
||||
bone = arm.edit_bones[bone_name]
|
||||
else:
|
||||
bone = arm.bones[bone_name]
|
||||
|
||||
return obj, arm, pbone, bone
|
||||
|
||||
def bone_basename(name):
|
||||
return name.split(".")[0]
|
||||
|
||||
def add_stretch_to(obj, from_name, to_name, name):
|
||||
'''
|
||||
Adds a bone that stretches from one to another
|
||||
'''
|
||||
|
||||
is_editmode = (obj.mode == 'EDIT')
|
||||
if not is_editmode:
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
|
||||
arm = obj.data
|
||||
stretch_ebone = arm.edit_bones.new(name)
|
||||
stretch_name = stretch_ebone.name
|
||||
head = stretch_ebone.head = arm.edit_bones[from_name].head.copy()
|
||||
tail = stretch_ebone.tail = arm.edit_bones[to_name].head.copy()
|
||||
|
||||
|
||||
# Now for the constraint
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
from_pbone = obj.pose.bones[from_name]
|
||||
to_pbone = obj.pose.bones[to_name]
|
||||
stretch_pbone = obj.pose.bones[stretch_name]
|
||||
|
||||
con = stretch_pbone.constraints.new('COPY_LOCATION')
|
||||
con.target = obj
|
||||
con.subtarget = from_name
|
||||
|
||||
con = stretch_pbone.constraints.new('STRETCH_TO')
|
||||
con.target = obj
|
||||
con.subtarget = to_name
|
||||
con.original_length = (head-tail).length
|
||||
con.keep_axis = 'PLANE_X'
|
||||
con.volume = 'NO_VOLUME'
|
||||
|
||||
if is_editmode:
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
#else:
|
||||
# bpy.ops.object.mode_set(mode='OBJECT')
|
||||
|
||||
|
||||
def gen_finger(obj, orig_bone_name):
|
||||
|
||||
# *** EDITMODE
|
||||
|
||||
# get assosiated data
|
||||
obj, arm, orig_pbone, orig_ebone = get_bone_data(obj, orig_bone_name)
|
||||
|
||||
obj.animation_data_create() # needed if its a new armature with no keys
|
||||
|
||||
arm.layer[0] = arm.layer[8] = True
|
||||
|
||||
children = orig_pbone.children_recursive
|
||||
tot_len = reduce(lambda f, pbone: f + pbone.bone.length, children, orig_pbone.bone.length)
|
||||
|
||||
base_name = bone_basename(orig_pbone.name)
|
||||
|
||||
# first make a new bone at the location of the finger
|
||||
control_ebone = arm.edit_bones.new(base_name)
|
||||
control_bone_name = control_ebone.name # we dont know if we get the name requested
|
||||
|
||||
# Place the finger bone
|
||||
head = orig_ebone.head.copy()
|
||||
tail = orig_ebone.tail.copy()
|
||||
|
||||
control_ebone.head = head
|
||||
control_ebone.tail = head + ((tail - head).normalize() * tot_len)
|
||||
control_ebone.roll = orig_ebone.roll
|
||||
|
||||
# now add bones inbetween this and its children recursively
|
||||
|
||||
# switching modes so store names only!
|
||||
children = [pbone.name for pbone in children]
|
||||
|
||||
# set an alternate layer for driver bones
|
||||
other_layer = empty_layer[:]
|
||||
other_layer[8] = True
|
||||
|
||||
|
||||
driver_bone_pairs = []
|
||||
|
||||
for child_bone_name in children:
|
||||
obj, arm, pbone_child, child_ebone = get_bone_data(obj, child_bone_name)
|
||||
|
||||
# finger.02 --> finger_driver.02
|
||||
driver_bone_name = child_bone_name.split('.')
|
||||
driver_bone_name = driver_bone_name[0] + "_driver." + ".".join(driver_bone_name[1:])
|
||||
|
||||
driver_ebone = arm.edit_bones.new(driver_bone_name)
|
||||
driver_bone_name = driver_ebone.name # cant be too sure!
|
||||
driver_ebone.layer = other_layer
|
||||
|
||||
new_len = pbone_child.bone.length / 2.0
|
||||
|
||||
head = child_ebone.head.copy()
|
||||
tail = child_ebone.tail.copy()
|
||||
|
||||
driver_ebone.head = head
|
||||
driver_ebone.tail = head + ((tail - head).normalize() * new_len)
|
||||
driver_ebone.roll = child_ebone.roll
|
||||
|
||||
# Insert driver_ebone in the chain without connected parents
|
||||
driver_ebone.connected = False
|
||||
driver_ebone.parent = child_ebone.parent
|
||||
|
||||
child_ebone.connected = False
|
||||
child_ebone.parent = driver_ebone
|
||||
|
||||
# Add the drivers to these when in posemode.
|
||||
driver_bone_pairs.append((child_bone_name, driver_bone_name))
|
||||
|
||||
del control_ebone
|
||||
|
||||
|
||||
# *** POSEMODE
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
|
||||
|
||||
obj, arm, orig_pbone, orig_bone = get_bone_data(obj, orig_bone_name)
|
||||
obj, arm, control_pbone, control_bone= get_bone_data(obj, control_bone_name)
|
||||
|
||||
|
||||
# only allow Y scale
|
||||
control_pbone.lock_scale = (True, False, True)
|
||||
|
||||
control_pbone["bend_ratio"]= 0.4
|
||||
prop = rna_idprop_ui_prop_get(control_pbone, "bend_ratio", create=True)
|
||||
prop["min"] = 0.0
|
||||
prop["max"] = 1.0
|
||||
|
||||
con = orig_pbone.constraints.new('COPY_LOCATION')
|
||||
con.target = obj
|
||||
con.subtarget = control_bone_name
|
||||
|
||||
con = orig_pbone.constraints.new('COPY_ROTATION')
|
||||
con.target = obj
|
||||
con.subtarget = control_bone_name
|
||||
|
||||
|
||||
|
||||
# setup child drivers on each new smaller bone added. assume 2 for now.
|
||||
|
||||
# drives the bones
|
||||
controller_path = control_pbone.path_to_id() # 'pose.bones["%s"]' % control_bone_name
|
||||
|
||||
i = 0
|
||||
for child_bone_name, driver_bone_name in driver_bone_pairs:
|
||||
|
||||
# XXX - todo, any number
|
||||
if i==2:
|
||||
break
|
||||
|
||||
obj, arm, driver_pbone, driver_bone = get_bone_data(obj, driver_bone_name)
|
||||
|
||||
driver_pbone.rotation_mode = 'YZX'
|
||||
fcurve_driver = driver_pbone.driver_add("rotation_euler", 0)
|
||||
|
||||
#obj.driver_add('pose.bones["%s"].scale', 1)
|
||||
#obj.animation_data.drivers[-1] # XXX, WATCH THIS
|
||||
driver = fcurve_driver.driver
|
||||
|
||||
# scale target
|
||||
tar = driver.targets.new()
|
||||
tar.name = "scale"
|
||||
tar.id_type = 'OBJECT'
|
||||
tar.id = obj
|
||||
tar.array_index = 1 # Y scale
|
||||
tar.rna_path = controller_path + '.scale'
|
||||
|
||||
# bend target
|
||||
tar = driver.targets.new()
|
||||
tar.name = "br"
|
||||
tar.id_type = 'OBJECT'
|
||||
tar.id = obj
|
||||
tar.rna_path = controller_path + '["bend_ratio"]'
|
||||
|
||||
# XXX - todo, any number
|
||||
if i==0:
|
||||
driver.expression = '(-scale+1.0)*pi*2.0*(1.0-br)'
|
||||
elif i==1:
|
||||
driver.expression = '(-scale+1.0)*pi*2.0*br'
|
||||
|
||||
obj, arm, child_pbone, child_bone = get_bone_data(obj, child_bone_name)
|
||||
|
||||
# only allow X rotation
|
||||
driver_pbone.lock_rotation = child_pbone.lock_rotation = (False, True, True)
|
||||
|
||||
i += 1
|
||||
|
||||
|
||||
def gen_delta(obj, delta_name):
|
||||
'''
|
||||
Use this bone to define a delta thats applied to its child in pose mode.
|
||||
'''
|
||||
|
||||
mode_orig = obj.mode
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
|
||||
delta_pbone = obj.pose.bones[delta_name]
|
||||
children = delta_pbone.children
|
||||
|
||||
if len(children) != 1:
|
||||
print("only 1 child supported for delta")
|
||||
|
||||
child_name = children[0].name
|
||||
|
||||
delta_head = delta_pbone.head.copy()
|
||||
delta_tail = delta_pbone.tail.copy()
|
||||
delta_matrix = delta_pbone.matrix.copy()
|
||||
|
||||
children = delta_pbone.children
|
||||
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
|
||||
arm = obj.data
|
||||
|
||||
# XXX -probably should allow via the UI
|
||||
for ebone in arm.edit_bones:
|
||||
ebone.selected = ebone.head_selected = ebone.tail_selected = False
|
||||
|
||||
# Select for deleting
|
||||
delta_ebone = arm.edit_bones[delta_name]
|
||||
delta_ebone.selected = delta_ebone.head_selected = delta_ebone.tail_selected = True
|
||||
|
||||
bpy.ops.armature.delete()
|
||||
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
|
||||
|
||||
# Move the child bone to the deltas location
|
||||
obj.animation_data_create()
|
||||
child_pbone = obj.pose[child_name]
|
||||
|
||||
# ------------------- drivers
|
||||
fcurve_driver = child_pbone.driver_add("rotation_euler", 0)
|
||||
#fcurve_driver = obj.animation_data.drivers[-1] # XXX, WATCH THIS
|
||||
driver = fcurve_driver.driver
|
||||
driver.type = 'AVERAGE'
|
||||
mod = driver.modifiers.new('GENERATOR')
|
||||
|
||||
|
||||
|
||||
obj, arm, parent_pbone, parent_bone = get_bone_data(obj, delta_name)
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
|
||||
|
||||
bpy.ops.object.mode_set(mode=mode_orig)
|
||||
|
||||
|
||||
def gen_arm(obj, orig_bone_name):
|
||||
"""
|
||||
the bone with the 'arm' property is the upper arm, this assumes a chain as follows.
|
||||
[shoulder, upper_arm, forearm, hand]
|
||||
...where this bone is 'upper_arm'
|
||||
"""
|
||||
|
||||
def validate_chain():
|
||||
'''
|
||||
Sanity check and return the arm as a list of bone names.
|
||||
'''
|
||||
# do a sanity check
|
||||
obj, arm, orig_pbone, orig_ebone = get_bone_data(obj, orig_bone_name)
|
||||
shoulder_pbone = arm_pbone.parent
|
||||
|
||||
if not shoulder_pbone:
|
||||
print("could not find 'arm' parent, skipping:", orig_bone_name)
|
||||
return
|
||||
|
||||
# We could have some bones attached, find the bone that has this as its 2nd parent
|
||||
hands = []
|
||||
for pbone in obj.pose.bones:
|
||||
index = pbone.parent_index(orig_pbone)
|
||||
if index == 2:
|
||||
hands.append(pbone)
|
||||
|
||||
if len(hands) > 1:
|
||||
print("more then 1 hand found on:", orig_bone_name)
|
||||
return
|
||||
|
||||
# first add the 2 new bones
|
||||
hand_pbone = hands[0]
|
||||
forearm_pbone = hand_pbone.parent
|
||||
|
||||
return shoulder_pbone.name, orig_pbone.name, forearm_pbone.name, hand_pbone.name
|
||||
|
||||
shoulder_name, arm_name, forearm_name, hand_name = validate_chain()
|
||||
|
||||
|
||||
obj, arm, hand_pbone, hand_ebone = get_bone_data(obj, hand_name)
|
||||
|
||||
# Add the edit bones
|
||||
hand_ik_ebone = arm.edit_bones.new(hand_name + "_ik")
|
||||
|
||||
hand_ik_ebone.head = hand_ebone.head
|
||||
hand_ik_ebone.tail = hand_ebone.tail
|
||||
hand_ik_ebone.roll = hand_ebone.roll
|
||||
|
||||
|
||||
gen_table = {
|
||||
"":gen_none, \
|
||||
"finger":gen_finger, \
|
||||
"delta":gen_delta, \
|
||||
"arm":gen_arm, \
|
||||
}
|
||||
|
||||
|
||||
def generate_rig(context, ob):
|
||||
|
||||
# add_stretch_to(ob, "a", "b", "c")
|
||||
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
|
||||
|
||||
# copy object and data
|
||||
ob.selected = False
|
||||
ob_new = ob.copy()
|
||||
ob_new.data = ob.data.copy()
|
||||
scene = context.scene
|
||||
scene.objects.link(ob_new)
|
||||
scene.objects.active = ob_new
|
||||
ob_new.selected = True
|
||||
|
||||
# enter armature editmode
|
||||
|
||||
|
||||
for pbone_name in ob_new.pose.bones.keys():
|
||||
bone_type = ob_new.pose.bones[pbone_name].get("type", "")
|
||||
|
||||
try:
|
||||
func = gen_table[bone_type]
|
||||
except KeyError:
|
||||
print("\tunknown type '%s', bone '%s'" % (bone_type, pbone_name))
|
||||
|
||||
|
||||
# Toggle editmode so the pose data is always up to date
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
func(ob_new, pbone_name)
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
|
||||
# needed to update driver deps
|
||||
# context.scene.update()
|
||||
|
||||
if __name__ == "__main__":
|
||||
generate_rig(bpy.context, bpy.context.object)
|
625
release/scripts/modules/rigify/__init__.py
Normal file
625
release/scripts/modules/rigify/__init__.py
Normal file
@ -0,0 +1,625 @@
|
||||
# ##### 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.
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
import bpy
|
||||
from Mathutils import Vector
|
||||
|
||||
# TODO, have these in a more general module
|
||||
from rna_prop_ui import rna_idprop_ui_prop_get
|
||||
|
||||
empty_layer = [False] * 32
|
||||
|
||||
|
||||
def auto_class(slots, name="ContainerClass", class_dict=None):
|
||||
|
||||
if class_dict:
|
||||
class_dict = class_dict.copy()
|
||||
else:
|
||||
class_dict = {}
|
||||
|
||||
class_dict["__slots__"] = tuple(slots)
|
||||
|
||||
return type(name, (object,), class_dict)
|
||||
|
||||
|
||||
def auto_class_instance(slots, name="ContainerClass", class_dict=None):
|
||||
return auto_class(slots, name, class_dict)()
|
||||
|
||||
|
||||
def _bone_class_instance_update(self):
|
||||
''' Re-Assigns bones from the blender data
|
||||
'''
|
||||
arm = self.obj.data
|
||||
bbones = arm.bones
|
||||
pbones = self.obj.pose.bones
|
||||
ebones = arm.edit_bones
|
||||
|
||||
for member in self.attr_names:
|
||||
name = getattr(self, member, None)
|
||||
if name is not None:
|
||||
setattr(self, member + "_b", bbones.get(name, None))
|
||||
setattr(self, member + "_p", pbones.get(name, None))
|
||||
setattr(self, member + "_e", ebones.get(name, None))
|
||||
|
||||
|
||||
def _bone_class_instance_rename(self, attr, new_name):
|
||||
''' Rename bones, editmode only
|
||||
'''
|
||||
|
||||
if self.obj.mode != 'EDIT':
|
||||
raise Exception("Only rename in editmode supported")
|
||||
|
||||
ebone = getattr(self, attr + "_e")
|
||||
ebone.name = new_name
|
||||
|
||||
# we may not get what is asked for so get the name from the editbone
|
||||
setattr(self, attr, ebone.name)
|
||||
|
||||
|
||||
def _bone_class_instance_copy(self, from_prefix="", to_prefix=""):
|
||||
from_name_ls = []
|
||||
new_name_ls = []
|
||||
new_slot_ls = []
|
||||
|
||||
for attr in self.attr_names:
|
||||
bone_name_orig = getattr(self, attr)
|
||||
ebone = getattr(self, attr + "_e")
|
||||
# orig_names[attr] = bone_name_orig
|
||||
|
||||
# insert prefix
|
||||
if from_prefix:
|
||||
bone_name = from_prefix + bone_name_orig
|
||||
ebone.name = bone_name
|
||||
bone_name = ebone.name # cant be sure we get what we ask for
|
||||
else:
|
||||
bone_name = bone_name_orig
|
||||
|
||||
setattr(self, attr, bone_name)
|
||||
|
||||
new_slot_ls.append(attr)
|
||||
from_name_ls.append(bone_name)
|
||||
bone_name_orig = bone_name_orig.replace("ORG-", "") # XXX - we need a better way to do this
|
||||
new_name_ls.append(to_prefix + bone_name_orig)
|
||||
|
||||
new_bones = copy_bone_simple_list(self.obj.data, from_name_ls, new_name_ls, True)
|
||||
new_bc = bone_class_instance(self.obj, new_slot_ls)
|
||||
|
||||
for i, attr in enumerate(new_slot_ls):
|
||||
ebone = new_bones[i]
|
||||
setattr(new_bc, attr + "_e", ebone)
|
||||
setattr(new_bc, attr, ebone.name)
|
||||
|
||||
return new_bc
|
||||
|
||||
|
||||
def _bone_class_instance_names(self):
|
||||
return [getattr(self, attr) for attr in self.attr_names]
|
||||
|
||||
|
||||
def _bone_class_instance_blend(self, from_bc, to_bc, target_bone=None, target_prop="blend"):
|
||||
'''
|
||||
Use for blending bone chains.
|
||||
|
||||
blend_target = (bone_name, bone_property)
|
||||
default to the last bone, blend prop
|
||||
|
||||
XXX - toggles editmode, need to re-validate all editbones :(
|
||||
'''
|
||||
|
||||
if self.attr_names != from_bc.attr_names or self.attr_names != to_bc.attr_names:
|
||||
raise Exception("can only blend between matching chains")
|
||||
|
||||
apply_bones = [getattr(self, attr) for attr in self.attr_names]
|
||||
from_bones = [getattr(from_bc, attr) for attr in from_bc.attr_names]
|
||||
to_bones = [getattr(to_bc, attr) for attr in to_bc.attr_names]
|
||||
|
||||
blend_bone_list(self.obj, apply_bones, from_bones, to_bones, target_bone, target_prop)
|
||||
|
||||
|
||||
def bone_class_instance(obj, slots, name="BoneContainer"):
|
||||
attr_names = tuple(slots) # dont modify the original
|
||||
slots = list(slots) # dont modify the original
|
||||
for i in range(len(slots)):
|
||||
member = slots[i]
|
||||
slots.append(member + "_b") # bone bone
|
||||
slots.append(member + "_p") # pose bone
|
||||
slots.append(member + "_e") # edit bone
|
||||
|
||||
class_dict = { \
|
||||
"obj": obj, \
|
||||
"attr_names": attr_names, \
|
||||
"update": _bone_class_instance_update, \
|
||||
"rename": _bone_class_instance_rename, \
|
||||
"names": _bone_class_instance_names, \
|
||||
"copy": _bone_class_instance_copy, \
|
||||
"blend": _bone_class_instance_blend, \
|
||||
}
|
||||
|
||||
instance = auto_class_instance(slots, name, class_dict)
|
||||
return instance
|
||||
|
||||
|
||||
def get_bone_data(obj, bone_name):
|
||||
arm = obj.data
|
||||
pbone = obj.pose.bones[bone_name]
|
||||
if obj.mode == 'EDIT':
|
||||
bone = arm.edit_bones[bone_name]
|
||||
else:
|
||||
bone = arm.bones[bone_name]
|
||||
|
||||
return arm, pbone, bone
|
||||
|
||||
|
||||
def copy_bone_simple(arm, from_bone, name, parent=False):
|
||||
ebone = arm.edit_bones[from_bone]
|
||||
ebone_new = arm.edit_bones.new(name)
|
||||
|
||||
if parent:
|
||||
ebone_new.connected = ebone.connected
|
||||
ebone_new.parent = ebone.parent
|
||||
|
||||
ebone_new.head = ebone.head
|
||||
ebone_new.tail = ebone.tail
|
||||
ebone_new.roll = ebone.roll
|
||||
return ebone_new
|
||||
|
||||
|
||||
def copy_bone_simple_list(arm, from_bones, to_bones, parent=False):
|
||||
|
||||
if len(from_bones) != len(to_bones):
|
||||
raise Exception("bone list sizes must match")
|
||||
|
||||
copy_bones = [copy_bone_simple(arm, bone_name, to_bones[i], True) for i, bone_name in enumerate(from_bones)]
|
||||
|
||||
# now we need to re-parent
|
||||
for ebone in copy_bones:
|
||||
parent = ebone.parent
|
||||
if parent:
|
||||
try:
|
||||
i = from_bones.index(parent.name)
|
||||
except:
|
||||
i = -1
|
||||
|
||||
if i == -1:
|
||||
ebone.parent = None
|
||||
else:
|
||||
ebone.parent = copy_bones[i]
|
||||
|
||||
return copy_bones
|
||||
|
||||
|
||||
def blend_bone_list(obj, apply_bones, from_bones, to_bones, target_bone=None, target_prop="blend"):
|
||||
|
||||
if obj.mode == 'EDIT':
|
||||
raise Exception("blending cant be called in editmode")
|
||||
|
||||
# setup the blend property
|
||||
if target_bone is None:
|
||||
target_bone = apply_bones[-1] # default to the last bone
|
||||
|
||||
prop_pbone = obj.pose.bones[target_bone]
|
||||
if prop_pbone.get(target_bone, None) is None:
|
||||
prop = rna_idprop_ui_prop_get(prop_pbone, target_prop, create=True)
|
||||
prop_pbone[target_prop] = 0.5
|
||||
prop["soft_min"] = 0.0
|
||||
prop["soft_max"] = 1.0
|
||||
|
||||
driver_path = prop_pbone.path_to_id() + ('["%s"]' % target_prop)
|
||||
|
||||
def blend_target(driver):
|
||||
tar = driver.targets.new()
|
||||
tar.name = target_bone
|
||||
tar.id_type = 'OBJECT'
|
||||
tar.id = obj
|
||||
tar.rna_path = driver_path
|
||||
|
||||
def blend_location(new_pbone, from_bone_name, to_bone_name):
|
||||
con = new_pbone.constraints.new('COPY_LOCATION')
|
||||
con.target = obj
|
||||
con.subtarget = from_bone_name
|
||||
|
||||
con = new_pbone.constraints.new('COPY_LOCATION')
|
||||
con.target = obj
|
||||
con.subtarget = to_bone_name
|
||||
|
||||
fcurve = con.driver_add("influence", 0)
|
||||
driver = fcurve.driver
|
||||
driver.type = 'AVERAGE'
|
||||
fcurve.modifiers.remove(0) # grr dont need a modifier
|
||||
|
||||
blend_target(driver)
|
||||
|
||||
def blend_rotation(new_pbone, from_bone_name, to_bone_name):
|
||||
con = new_pbone.constraints.new('COPY_ROTATION')
|
||||
con.target = obj
|
||||
con.subtarget = from_bone_name
|
||||
|
||||
con = new_pbone.constraints.new('COPY_ROTATION')
|
||||
con.target = obj
|
||||
con.subtarget = to_bone_name
|
||||
|
||||
fcurve = con.driver_add("influence", 0)
|
||||
driver = fcurve.driver
|
||||
driver.type = 'AVERAGE'
|
||||
fcurve.modifiers.remove(0) # grr dont need a modifier
|
||||
|
||||
blend_target(driver)
|
||||
|
||||
for i, new_bone_name in enumerate(apply_bones):
|
||||
from_bone_name = from_bones[i]
|
||||
to_bone_name = to_bones[i]
|
||||
|
||||
# allow skipping some bones by having None in the list
|
||||
if None in (new_bone_name, from_bone_name, to_bone_name):
|
||||
continue
|
||||
|
||||
new_pbone = obj.pose.bones[new_bone_name]
|
||||
|
||||
if not new_pbone.bone.connected:
|
||||
blend_location(new_pbone, from_bone_name, to_bone_name)
|
||||
|
||||
blend_rotation(new_pbone, from_bone_name, to_bone_name)
|
||||
|
||||
|
||||
def add_stretch_to(obj, from_name, to_name, name):
|
||||
'''
|
||||
Adds a bone that stretches from one to another
|
||||
'''
|
||||
|
||||
mode_orig = obj.mode
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
|
||||
arm = obj.data
|
||||
stretch_ebone = arm.edit_bones.new(name)
|
||||
stretch_name = stretch_ebone.name
|
||||
del name
|
||||
|
||||
head = stretch_ebone.head = arm.edit_bones[from_name].head.copy()
|
||||
#tail = stretch_ebone.tail = arm.edit_bones[to_name].head.copy()
|
||||
|
||||
# annoying exception for zero length bones, since its using stretch_to the rest pose doesnt really matter
|
||||
#if (head - tail).length < 0.1:
|
||||
if 1:
|
||||
tail = stretch_ebone.tail = arm.edit_bones[from_name].tail.copy()
|
||||
|
||||
|
||||
# Now for the constraint
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
|
||||
stretch_pbone = obj.pose.bones[stretch_name]
|
||||
|
||||
con = stretch_pbone.constraints.new('COPY_LOCATION')
|
||||
con.target = obj
|
||||
con.subtarget = from_name
|
||||
|
||||
con = stretch_pbone.constraints.new('STRETCH_TO')
|
||||
con.target = obj
|
||||
con.subtarget = to_name
|
||||
con.original_length = (head - tail).length
|
||||
con.keep_axis = 'PLANE_X'
|
||||
con.volume = 'NO_VOLUME'
|
||||
|
||||
bpy.ops.object.mode_set(mode=mode_orig)
|
||||
|
||||
|
||||
def add_pole_target_bone(obj, base_name, name, mode='CROSS'):
|
||||
'''
|
||||
Does not actually create a poll target, just the bone to use as a poll target
|
||||
'''
|
||||
mode_orig = obj.mode
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
|
||||
arm = obj.data
|
||||
|
||||
poll_ebone = arm.edit_bones.new(base_name + "_poll")
|
||||
base_ebone = arm.edit_bones[base_name]
|
||||
poll_name = poll_ebone.name
|
||||
parent_ebone = base_ebone.parent
|
||||
|
||||
base_head = base_ebone.head.copy()
|
||||
base_tail = base_ebone.tail.copy()
|
||||
base_dir = base_head - base_tail
|
||||
|
||||
parent_head = parent_ebone.head.copy()
|
||||
parent_tail = parent_ebone.tail.copy()
|
||||
parent_dir = parent_head - parent_tail
|
||||
|
||||
distance = (base_dir.length + parent_dir.length)
|
||||
|
||||
if mode == 'CROSS':
|
||||
offset = base_dir.copy().normalize() - parent_dir.copy().normalize()
|
||||
offset.length = distance
|
||||
else:
|
||||
offset = Vector(0, 0, 0)
|
||||
if mode[0] == "+":
|
||||
val = distance
|
||||
else:
|
||||
val = - distance
|
||||
|
||||
setattr(offset, mode[1].lower(), val)
|
||||
|
||||
poll_ebone.head = base_head + offset
|
||||
poll_ebone.tail = base_head + (offset * (1.0 - (1.0 / 4.0)))
|
||||
|
||||
bpy.ops.object.mode_set(mode=mode_orig)
|
||||
|
||||
return poll_name
|
||||
|
||||
|
||||
def generate_rig(context, obj_orig, prefix="ORG-"):
|
||||
from collections import OrderedDict
|
||||
|
||||
global_undo = context.user_preferences.edit.global_undo
|
||||
context.user_preferences.edit.global_undo = False
|
||||
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
|
||||
|
||||
# copy object and data
|
||||
obj_orig.selected = False
|
||||
obj = obj_orig.copy()
|
||||
obj.data = obj_orig.data.copy()
|
||||
scene = context.scene
|
||||
scene.objects.link(obj)
|
||||
scene.objects.active = obj
|
||||
obj.selected = True
|
||||
|
||||
arm = obj.data
|
||||
|
||||
# original name mapping
|
||||
base_names = {}
|
||||
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
for bone in arm.edit_bones:
|
||||
bone_name = bone.name
|
||||
bone.name = prefix + bone_name
|
||||
base_names[bone.name] = bone_name # new -> old mapping
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
|
||||
# key: bone name
|
||||
# value: {type:definition, ...}
|
||||
# where type is the submodule name - leg, arm etc
|
||||
# and definition is a list of bone names
|
||||
bone_definitions = {}
|
||||
|
||||
# key: bone name
|
||||
# value: [functions, ...]
|
||||
# each function is from the module. eg leg.ik, arm.main
|
||||
bone_typeinfos = {}
|
||||
|
||||
# inspect all bones and assign their definitions before modifying
|
||||
for pbone in obj.pose.bones:
|
||||
bone_name = pbone.name
|
||||
bone_type = obj.pose.bones[bone_name].get("type", "")
|
||||
bone_type_list = [bt for bt in bone_type.replace(",", " ").split()]
|
||||
|
||||
for bone_type in bone_type_list:
|
||||
type_pair = bone_type.split(".")
|
||||
|
||||
# 'leg.ik' will look for an ik function in the leg module
|
||||
# 'leg' will look up leg.main
|
||||
if len(type_pair) == 1:
|
||||
type_pair = type_pair[0], "main"
|
||||
|
||||
submod_name, func_name = type_pair
|
||||
|
||||
# from rigify import leg
|
||||
submod = __import__(name="%s.%s" % (__package__, submod_name), fromlist=[submod_name])
|
||||
reload(submod)
|
||||
|
||||
bone_def_dict = bone_definitions.setdefault(bone_name, {})
|
||||
|
||||
# Only calculate bone definitions once
|
||||
if submod_name not in bone_def_dict:
|
||||
metarig_definition_func = getattr(submod, "metarig_definition")
|
||||
bone_def_dict[submod_name] = metarig_definition_func(obj, bone_name)
|
||||
|
||||
|
||||
bone_typeinfo = bone_typeinfos.setdefault(bone_name, [])
|
||||
|
||||
type_func = getattr(submod, func_name)
|
||||
bone_typeinfo.append((submod_name, type_func))
|
||||
|
||||
|
||||
# sort bones, not needed but gives more pradictable execution which may be useful in rare cases
|
||||
bones_sorted = obj.pose.bones.values()
|
||||
bones_sorted.sort(key=lambda pbone: pbone.name) # first sort by names
|
||||
bones_sorted.sort(key=lambda pbone: - len(pbone.parent_recursive)) # children before parents
|
||||
|
||||
# now we have all the info about bones we can start operating on them
|
||||
# for pbone in obj.pose.bones:
|
||||
for pbone in bones_sorted:
|
||||
bone_name = pbone.name
|
||||
|
||||
if bone_name not in bone_typeinfos:
|
||||
continue
|
||||
|
||||
bone_def_dict = bone_definitions[bone_name]
|
||||
|
||||
# Only blend results from the same submodule, eg.
|
||||
# leg.ik and arm.fk could not be blended.
|
||||
results = OrderedDict()
|
||||
|
||||
for submod_name, type_func in bone_typeinfos[bone_name]:
|
||||
# this bones definition of the current typeinfo
|
||||
definition = bone_def_dict[submod_name]
|
||||
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
ret = type_func(obj, definition, base_names)
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
|
||||
if ret:
|
||||
result_submod = results.setdefault(submod_name, [])
|
||||
|
||||
if result_submod and len(result_submod[-1]) != len(ret):
|
||||
raise Exception("bone lists not compatible: %s, %s" % (result_submod[-1], ret))
|
||||
|
||||
result_submod.append(ret)
|
||||
|
||||
for result_submod in results.values():
|
||||
# blend 2 chains
|
||||
definition = bone_def_dict[submod_name]
|
||||
|
||||
if len(result_submod) == 2:
|
||||
blend_bone_list(obj, definition, result_submod[0], result_submod[1])
|
||||
|
||||
# needed to update driver deps
|
||||
# context.scene.update()
|
||||
|
||||
# Only for demo'ing
|
||||
|
||||
# obj.restrict_view = True
|
||||
obj.data.draw_axes = False
|
||||
|
||||
context.user_preferences.edit.global_undo = global_undo
|
||||
|
||||
return obj
|
||||
|
||||
|
||||
def write_meta_rig(obj, func_name="metarig_template"):
|
||||
''' Must be in editmode
|
||||
'''
|
||||
code = []
|
||||
|
||||
code.append("def %s():" % func_name)
|
||||
code.append(" # generated by rigify.write_meta_rig")
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
code.append(" bpy.ops.object.mode_set(mode='EDIT')")
|
||||
|
||||
code.append(" obj = bpy.context.object")
|
||||
code.append(" arm = obj.data")
|
||||
|
||||
arm = obj.data
|
||||
# write parents first
|
||||
bones = [(len(bone.parent_recursive), bone.name) for bone in arm.edit_bones]
|
||||
bones.sort(key=lambda item: item[0])
|
||||
bones = [item[1] for item in bones]
|
||||
|
||||
|
||||
for bone_name in bones:
|
||||
bone = arm.edit_bones[bone_name]
|
||||
code.append(" bone = arm.edit_bones.new('%s')" % bone.name)
|
||||
code.append(" bone.head[:] = %.4f, %.4f, %.4f" % bone.head.toTuple(4))
|
||||
code.append(" bone.tail[:] = %.4f, %.4f, %.4f" % bone.tail.toTuple(4))
|
||||
code.append(" bone.roll = %.4f" % bone.roll)
|
||||
code.append(" bone.connected = %s" % str(bone.connected))
|
||||
if bone.parent:
|
||||
code.append(" bone.parent = arm.edit_bones['%s']" % bone.parent.name)
|
||||
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
code.append("")
|
||||
code.append(" bpy.ops.object.mode_set(mode='OBJECT')")
|
||||
|
||||
for bone_name in bones:
|
||||
pbone = obj.pose.bones[bone_name]
|
||||
pbone_written = False
|
||||
|
||||
# Only 1 level of props, simple types supported
|
||||
for key, value in pbone.items():
|
||||
if key.startswith("_"):
|
||||
continue
|
||||
|
||||
if type(value) not in (float, str, int):
|
||||
print("Unsupported ID Prop:", str((key, value)))
|
||||
continue
|
||||
|
||||
if type(value) == str:
|
||||
value = "'" + value + "'"
|
||||
|
||||
if not pbone_written: # only write bones we need
|
||||
code.append(" pbone = obj.pose.bones['%s']" % bone_name)
|
||||
|
||||
code.append(" pbone['%s'] = %s" % (key, value))
|
||||
|
||||
return "\n".join(code)
|
||||
|
||||
|
||||
def generate_test(context):
|
||||
import os
|
||||
new_objects = []
|
||||
|
||||
scene = context.scene
|
||||
|
||||
def create_empty_armature(name):
|
||||
obj_new = bpy.data.add_object('ARMATURE', name)
|
||||
armature = bpy.data.add_armature(name)
|
||||
obj_new.data = armature
|
||||
scene.objects.link(obj_new)
|
||||
scene.objects.active = obj_new
|
||||
|
||||
files = os.listdir(os.path.dirname(__file__))
|
||||
for f in files:
|
||||
if f.startswith("_"):
|
||||
continue
|
||||
|
||||
if not f.endswith(".py"):
|
||||
continue
|
||||
|
||||
module_name = f[:-3]
|
||||
submodule = __import__(name="%s.%s" % (__package__, module_name), fromlist=[module_name])
|
||||
|
||||
metarig_template = getattr(submodule, "metarig_template", None)
|
||||
|
||||
if metarig_template:
|
||||
create_empty_armature("meta_" + module_name) # sets active
|
||||
metarig_template()
|
||||
obj = context.object
|
||||
obj_new = generate_rig(context, obj)
|
||||
|
||||
new_objects.append((obj, obj_new))
|
||||
else:
|
||||
print("note: rig type '%s' has no metarig_template(), can't test this", module_name)
|
||||
|
||||
return new_objects
|
||||
|
||||
|
||||
def generate_test_all(context):
|
||||
import rigify
|
||||
import graphviz_export
|
||||
import os
|
||||
reload(rigify)
|
||||
reload(graphviz_export)
|
||||
|
||||
new_objects = rigify.generate_test(context)
|
||||
|
||||
base_name = os.path.splitext(bpy.data.filename)[0]
|
||||
for obj, obj_new in new_objects:
|
||||
for obj in (obj, obj_new):
|
||||
fn = base_name + "-" + bpy.utils.clean_name(obj.name)
|
||||
|
||||
path_dot = fn + ".dot"
|
||||
path_png = fn + ".png"
|
||||
saved = graphviz_export.graph_armature(obj, path_dot, CONSTRAINTS=True, DRIVERS=True)
|
||||
|
||||
#if saved:
|
||||
# os.system("dot -Tpng %s > %s; eog %s" % (path_dot, path_png, path_png))
|
||||
|
||||
i = 0
|
||||
for obj, obj_new in new_objects:
|
||||
obj.data.drawtype = 'STICK'
|
||||
obj.location[1] += i
|
||||
obj_new.location[1] += i
|
||||
obj_new.selected = False
|
||||
obj.selected = True
|
||||
i += 4
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
generate_rig(bpy.context, bpy.context.object)
|
345
release/scripts/modules/rigify/arm.py
Normal file
345
release/scripts/modules/rigify/arm.py
Normal file
@ -0,0 +1,345 @@
|
||||
# ##### 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.
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
import bpy
|
||||
from rigify import bone_class_instance, copy_bone_simple, add_pole_target_bone, add_stretch_to
|
||||
from rna_prop_ui import rna_idprop_ui_prop_get
|
||||
|
||||
METARIG_NAMES = "shoulder", "arm", "forearm", "hand"
|
||||
|
||||
|
||||
def metarig_template():
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
obj = bpy.context.object
|
||||
arm = obj.data
|
||||
bone = arm.edit_bones.new('shoulder')
|
||||
bone.head[:] = 0.0000, -0.4515, 0.0000
|
||||
bone.tail[:] = 1.0000, -0.0794, 0.3540
|
||||
bone.roll = -0.2227
|
||||
bone.connected = False
|
||||
bone = arm.edit_bones.new('upper_arm')
|
||||
bone.head[:] = 1.1319, -0.0808, -0.0101
|
||||
bone.tail[:] = 3.0319, 0.2191, -0.1101
|
||||
bone.roll = 1.6152
|
||||
bone.connected = False
|
||||
bone.parent = arm.edit_bones['shoulder']
|
||||
bone = arm.edit_bones.new('forearm')
|
||||
bone.head[:] = 3.0319, 0.2191, -0.1101
|
||||
bone.tail[:] = 4.8319, -0.0809, -0.0242
|
||||
bone.roll = 1.5153
|
||||
bone.connected = True
|
||||
bone.parent = arm.edit_bones['upper_arm']
|
||||
bone = arm.edit_bones.new('hand')
|
||||
bone.head[:] = 4.8319, -0.0809, -0.0242
|
||||
bone.tail[:] = 5.7590, -0.1553, -0.1392
|
||||
bone.roll = -3.0083
|
||||
bone.connected = True
|
||||
bone.parent = arm.edit_bones['forearm']
|
||||
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
pbone = obj.pose.bones['upper_arm']
|
||||
pbone['type'] = 'arm'
|
||||
|
||||
|
||||
def metarig_definition(obj, orig_bone_name):
|
||||
mt = bone_class_instance(obj, METARIG_NAMES) # meta
|
||||
mt.arm = orig_bone_name
|
||||
mt.update()
|
||||
|
||||
mt.shoulder_p = mt.arm_p.parent
|
||||
|
||||
if not mt.shoulder_p:
|
||||
raise Exception("could not find 'arm' parent, skipping:", orig_bone_name)
|
||||
print(mt.shoulder_p)
|
||||
mt.shoulder = mt.shoulder_p.name
|
||||
|
||||
# We could have some bones attached, find the bone that has this as its 2nd parent
|
||||
hands = []
|
||||
for pbone in obj.pose.bones:
|
||||
index = pbone.parent_index(mt.arm_p)
|
||||
if index == 2:
|
||||
hands.append(pbone)
|
||||
|
||||
if len(hands) > 1:
|
||||
raise Exception("more then 1 hand found on:", orig_bone_name)
|
||||
|
||||
# first add the 2 new bones
|
||||
mt.hand_p = hands[0]
|
||||
mt.hand = mt.hand_p.name
|
||||
|
||||
mt.forearm_p = mt.hand_p.parent
|
||||
mt.forearm = mt.forearm_p.name
|
||||
|
||||
return mt.names()
|
||||
|
||||
|
||||
def main(obj, definitions, base_names):
|
||||
"""
|
||||
the bone with the 'arm' property is the upper arm, this assumes a chain as follows.
|
||||
[shoulder, upper_arm, forearm, hand]
|
||||
...where this bone is 'upper_arm'
|
||||
|
||||
there are 3 chains
|
||||
- Original
|
||||
- IK, MCH-%s_ik
|
||||
- IKSwitch, MCH-%s ()
|
||||
|
||||
|
||||
"""
|
||||
|
||||
# Since there are 3 chains, this gets confusing so divide into 3 chains
|
||||
# Initialize container classes for convenience
|
||||
mt = bone_class_instance(obj, METARIG_NAMES) # meta
|
||||
mt.shoulder, mt.arm, mt.forearm, mt.hand = definitions
|
||||
|
||||
ik = bone_class_instance(obj, ["arm", "forearm", "pole", "hand"]) # ik
|
||||
sw = bone_class_instance(obj, ["socket", "shoulder", "arm", "forearm", "hand"]) # hinge
|
||||
ex = bone_class_instance(obj, ["arm_hinge"]) # hinge & extras
|
||||
|
||||
arm = obj.data
|
||||
|
||||
def chain_ik(prefix="MCH-%s_ik"):
|
||||
|
||||
mt.update()
|
||||
|
||||
# Add the edit bones
|
||||
ik.hand_e = copy_bone_simple(arm, mt.hand, prefix % base_names[mt.hand])
|
||||
ik.hand = ik.hand_e.name
|
||||
|
||||
ik.arm_e = copy_bone_simple(arm, mt.arm, prefix % base_names[mt.arm])
|
||||
ik.arm = ik.arm_e.name
|
||||
|
||||
ik.forearm_e = copy_bone_simple(arm, mt.forearm, prefix % base_names[mt.forearm])
|
||||
ik.forearm = ik.forearm_e.name
|
||||
|
||||
ik.arm_e.parent = mt.arm_e.parent
|
||||
ik.forearm_e.connected = mt.arm_e.connected
|
||||
|
||||
ik.forearm_e.parent = ik.arm_e
|
||||
ik.forearm_e.connected = True
|
||||
|
||||
|
||||
# Add the bone used for the arms poll target
|
||||
ik.pole = add_pole_target_bone(obj, mt.forearm, "elbow_poll", mode='+Z')
|
||||
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
|
||||
ik.update()
|
||||
|
||||
con = ik.forearm_p.constraints.new('IK')
|
||||
con.target = obj
|
||||
con.subtarget = ik.hand
|
||||
con.pole_target = obj
|
||||
con.pole_subtarget = ik.pole
|
||||
|
||||
con.use_tail = True
|
||||
con.use_stretch = True
|
||||
con.use_target = True
|
||||
con.use_rotation = False
|
||||
con.chain_length = 2
|
||||
con.pole_angle = -90.0 # XXX, RAD2DEG
|
||||
|
||||
# ID Propery on the hand for IK/FK switch
|
||||
|
||||
prop = rna_idprop_ui_prop_get(ik.hand_p, "ik", create=True)
|
||||
ik.hand_p["ik"] = 0.5
|
||||
prop["soft_min"] = 0.0
|
||||
prop["soft_max"] = 1.0
|
||||
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
|
||||
def chain_switch(prefix="MCH-%s"):
|
||||
print(mt.obj.mode)
|
||||
sw.update()
|
||||
mt.update()
|
||||
|
||||
sw.shoulder_e = copy_bone_simple(arm, mt.shoulder, prefix % base_names[mt.shoulder])
|
||||
sw.shoulder = sw.shoulder_e.name
|
||||
sw.shoulder_e.parent = mt.shoulder_e.parent
|
||||
sw.shoulder_e.connected = mt.shoulder_e.connected
|
||||
|
||||
sw.arm_e = copy_bone_simple(arm, mt.arm, prefix % base_names[mt.arm])
|
||||
sw.arm = sw.arm_e.name
|
||||
sw.arm_e.parent = sw.shoulder_e
|
||||
sw.arm_e.connected = arm.edit_bones[mt.shoulder].connected
|
||||
|
||||
sw.forearm_e = copy_bone_simple(arm, mt.forearm, prefix % base_names[mt.forearm])
|
||||
sw.forearm = sw.forearm_e.name
|
||||
sw.forearm_e.parent = sw.arm_e
|
||||
sw.forearm_e.connected = arm.edit_bones[mt.forearm].connected
|
||||
|
||||
sw.hand_e = copy_bone_simple(arm, mt.hand, prefix % base_names[mt.hand])
|
||||
sw.hand = sw.hand_e.name
|
||||
sw.hand_e.parent = sw.forearm_e
|
||||
sw.hand_e.connected = arm.edit_bones[mt.hand].connected
|
||||
|
||||
# The sw.hand_e needs to own all the children on the metarig's hand
|
||||
for child in mt.hand_e.children:
|
||||
child.parent = sw.hand_e
|
||||
|
||||
|
||||
# These are made the children of sw.shoulder_e
|
||||
|
||||
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
|
||||
# Add constraints
|
||||
sw.update()
|
||||
|
||||
#dummy, ik.arm, ik.forearm, ik.hand, ik.pole = ik_chain_tuple
|
||||
|
||||
ik_driver_path = obj.pose.bones[ik.hand].path_to_id() + '["ik"]'
|
||||
|
||||
def ik_fk_driver(con):
|
||||
'''
|
||||
3 bones use this for ik/fk switching
|
||||
'''
|
||||
fcurve = con.driver_add("influence", 0)
|
||||
driver = fcurve.driver
|
||||
tar = driver.targets.new()
|
||||
driver.type = 'AVERAGE'
|
||||
tar.name = "ik"
|
||||
tar.id_type = 'OBJECT'
|
||||
tar.id = obj
|
||||
tar.rna_path = ik_driver_path
|
||||
|
||||
# ***********
|
||||
con = sw.arm_p.constraints.new('COPY_ROTATION')
|
||||
con.name = "FK"
|
||||
con.target = obj
|
||||
con.subtarget = mt.arm
|
||||
|
||||
con = sw.arm_p.constraints.new('COPY_ROTATION')
|
||||
|
||||
con.target = obj
|
||||
con.subtarget = ik.arm
|
||||
con.influence = 0.5
|
||||
ik_fk_driver(con)
|
||||
|
||||
# ***********
|
||||
con = sw.forearm_p.constraints.new('COPY_ROTATION')
|
||||
con.name = "FK"
|
||||
con.target = obj
|
||||
con.subtarget = mt.forearm
|
||||
|
||||
con = sw.forearm_p.constraints.new('COPY_ROTATION')
|
||||
con.name = "IK"
|
||||
con.target = obj
|
||||
con.subtarget = ik.forearm
|
||||
con.influence = 0.5
|
||||
ik_fk_driver(con)
|
||||
|
||||
# ***********
|
||||
con = sw.hand_p.constraints.new('COPY_ROTATION')
|
||||
con.name = "FK"
|
||||
con.target = obj
|
||||
con.subtarget = mt.hand
|
||||
|
||||
con = sw.hand_p.constraints.new('COPY_ROTATION')
|
||||
con.name = "IK"
|
||||
con.target = obj
|
||||
con.subtarget = ik.hand
|
||||
con.influence = 0.5
|
||||
ik_fk_driver(con)
|
||||
|
||||
|
||||
add_stretch_to(obj, sw.forearm, ik.pole, "VIS-elbow_ik_poll")
|
||||
add_stretch_to(obj, sw.hand, ik.hand, "VIS-hand_ik")
|
||||
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
|
||||
def chain_shoulder(prefix="MCH-%s"):
|
||||
|
||||
sw.socket_e = copy_bone_simple(arm, mt.arm, (prefix % base_names[mt.arm]) + "_socket")
|
||||
sw.socket = sw.socket_e.name
|
||||
sw.socket_e.tail = arm.edit_bones[mt.shoulder].tail
|
||||
|
||||
|
||||
# Set the shoulder as parent
|
||||
ik.update()
|
||||
sw.update()
|
||||
mt.update()
|
||||
|
||||
sw.socket_e.parent = sw.shoulder_e
|
||||
ik.arm_e.parent = sw.shoulder_e
|
||||
|
||||
|
||||
# ***** add the shoulder hinge
|
||||
# yes this is correct, the shoulder copy gets the arm's name
|
||||
ex.arm_hinge_e = copy_bone_simple(arm, mt.shoulder, (prefix % base_names[mt.arm]) + "_hinge")
|
||||
ex.arm_hinge = ex.arm_hinge_e.name
|
||||
offset = ex.arm_hinge_e.length / 2.0
|
||||
|
||||
ex.arm_hinge_e.head.y += offset
|
||||
ex.arm_hinge_e.tail.y += offset
|
||||
|
||||
# Note: meta arm becomes child of hinge
|
||||
mt.arm_e.parent = ex.arm_hinge_e
|
||||
|
||||
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
|
||||
ex.update()
|
||||
|
||||
con = mt.arm_p.constraints.new('COPY_LOCATION')
|
||||
con.target = obj
|
||||
con.subtarget = sw.socket
|
||||
|
||||
|
||||
# Hinge constraint & driver
|
||||
con = ex.arm_hinge_p.constraints.new('COPY_ROTATION')
|
||||
con.name = "hinge"
|
||||
con.target = obj
|
||||
con.subtarget = sw.shoulder
|
||||
driver_fcurve = con.driver_add("influence", 0)
|
||||
driver = driver_fcurve.driver
|
||||
|
||||
|
||||
controller_path = mt.arm_p.path_to_id()
|
||||
# add custom prop
|
||||
mt.arm_p["hinge"] = 0.0
|
||||
prop = rna_idprop_ui_prop_get(mt.arm_p, "hinge", create=True)
|
||||
prop["soft_min"] = 0.0
|
||||
prop["soft_max"] = 1.0
|
||||
|
||||
|
||||
# *****
|
||||
driver = driver_fcurve.driver
|
||||
driver.type = 'AVERAGE'
|
||||
|
||||
tar = driver.targets.new()
|
||||
tar.name = "hinge"
|
||||
tar.id_type = 'OBJECT'
|
||||
tar.id = obj
|
||||
tar.rna_path = controller_path + '["hinge"]'
|
||||
|
||||
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
|
||||
# remove the shoulder and re-parent
|
||||
|
||||
chain_ik()
|
||||
chain_switch()
|
||||
chain_shoulder()
|
||||
|
||||
# Shoulder with its delta and hinge.
|
||||
|
||||
# TODO - return a list for fk and IK
|
||||
return None
|
134
release/scripts/modules/rigify/delta.py
Normal file
134
release/scripts/modules/rigify/delta.py
Normal file
@ -0,0 +1,134 @@
|
||||
# ##### 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.
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
import bpy
|
||||
from rigify import get_bone_data
|
||||
|
||||
# not used, defined for completeness
|
||||
METARIG_NAMES = tuple()
|
||||
|
||||
|
||||
def metarig_definition(obj, orig_bone_name):
|
||||
'''
|
||||
The bone given is the head, its parent is the body,
|
||||
# its only child the first of a chain with matching basenames.
|
||||
eg.
|
||||
body -> head -> neck_01 -> neck_02 -> neck_03.... etc
|
||||
'''
|
||||
arm = obj.data
|
||||
delta = arm.bones[orig_bone_name]
|
||||
children = delta.children
|
||||
|
||||
if len(children) != 1:
|
||||
print("only 1 child supported for delta")
|
||||
|
||||
bone_definition = [delta.name, children[0].name]
|
||||
|
||||
return bone_definition
|
||||
|
||||
|
||||
def main(obj, bone_definition, base_names):
|
||||
'''
|
||||
Use this bone to define a delta thats applied to its child in pose mode.
|
||||
'''
|
||||
|
||||
mode_orig = obj.mode
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
|
||||
delta_name, child_name = bone_definition
|
||||
|
||||
delta_pbone = obj.pose.bones[delta_name]
|
||||
|
||||
arm, child_pbone, child_bone = get_bone_data(obj, child_name)
|
||||
|
||||
delta_phead = delta_pbone.head.copy()
|
||||
delta_ptail = delta_pbone.tail.copy()
|
||||
delta_pmatrix = delta_pbone.matrix.copy()
|
||||
|
||||
child_phead = child_pbone.head.copy()
|
||||
child_ptail = child_pbone.tail.copy()
|
||||
child_pmatrix = child_pbone.matrix.copy()
|
||||
|
||||
|
||||
children = delta_pbone.children
|
||||
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
|
||||
delta_ebone = arm.edit_bones[delta_name]
|
||||
child_ebone = arm.edit_bones[child_name]
|
||||
|
||||
delta_head = delta_ebone.head.copy()
|
||||
delta_tail = delta_ebone.tail.copy()
|
||||
|
||||
# arm, parent_pbone, parent_bone = get_bone_data(obj, delta_name)
|
||||
child_head = child_ebone.head.copy()
|
||||
child_tail = child_ebone.tail.copy()
|
||||
|
||||
#arm.edit_bones.remove(delta_ebone)
|
||||
#del delta_ebone # cant use this
|
||||
del child_pbone
|
||||
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
|
||||
|
||||
|
||||
# Move the child bone to the deltas location
|
||||
obj.animation_data_create()
|
||||
delta_pbone = obj.pose.bones[delta_name]
|
||||
# child_pbone = obj.pose.bones[child_name]
|
||||
|
||||
# ------------------- drivers
|
||||
|
||||
delta_pbone.rotation_mode = 'XYZ'
|
||||
|
||||
rot = delta_pmatrix.invert().rotationPart() * child_pmatrix.rotationPart()
|
||||
rot = rot.invert().toEuler()
|
||||
|
||||
fcurve_drivers = delta_pbone.driver_add("rotation_euler", -1)
|
||||
for i, fcurve_driver in enumerate(fcurve_drivers):
|
||||
driver = fcurve_driver.driver
|
||||
driver.type = 'AVERAGE'
|
||||
#mod = fcurve_driver.modifiers.new('GENERATOR')
|
||||
mod = fcurve_driver.modifiers[0]
|
||||
mod.poly_order = 1
|
||||
mod.coefficients[0] = rot[i]
|
||||
mod.coefficients[1] = 0.0
|
||||
|
||||
# tricky, find the transform to drive the bone to this location.
|
||||
delta_head_offset = child_pmatrix.rotationPart() * (delta_phead - child_phead)
|
||||
|
||||
fcurve_drivers = delta_pbone.driver_add("location", -1)
|
||||
for i, fcurve_driver in enumerate(fcurve_drivers):
|
||||
driver = fcurve_driver.driver
|
||||
driver.type = 'AVERAGE'
|
||||
#mod = fcurve_driver.modifiers.new('GENERATOR')
|
||||
mod = fcurve_driver.modifiers[0]
|
||||
mod.poly_order = 1
|
||||
mod.coefficients[0] = delta_head_offset[i]
|
||||
mod.coefficients[1] = 0.0
|
||||
|
||||
|
||||
# arm, parent_pbone, parent_bone = get_bone_data(obj, delta_name)
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
|
||||
bpy.ops.object.mode_set(mode=mode_orig)
|
||||
|
||||
# no blendeing
|
||||
return None
|
223
release/scripts/modules/rigify/finger.py
Normal file
223
release/scripts/modules/rigify/finger.py
Normal file
@ -0,0 +1,223 @@
|
||||
# ##### 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.
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
import bpy
|
||||
from rigify import get_bone_data, empty_layer, copy_bone_simple
|
||||
from rna_prop_ui import rna_idprop_ui_prop_get
|
||||
from functools import reduce
|
||||
|
||||
METARIG_NAMES = "finger_01", "finger_02", "finger_03"
|
||||
|
||||
|
||||
def metarig_template():
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
obj = bpy.context.object
|
||||
arm = obj.data
|
||||
bone = arm.edit_bones.new('finger.01')
|
||||
bone.head[:] = 0.0000, 0.0000, 0.0000
|
||||
bone.tail[:] = 0.8788, -0.4584, -0.1327
|
||||
bone.roll = -2.8722
|
||||
bone.connected = False
|
||||
bone = arm.edit_bones.new('finger.02')
|
||||
bone.head[:] = 0.8788, -0.4584, -0.1327
|
||||
bone.tail[:] = 1.7483, -0.9059, -0.3643
|
||||
bone.roll = -2.7099
|
||||
bone.connected = True
|
||||
bone.parent = arm.edit_bones['finger.01']
|
||||
bone = arm.edit_bones.new('finger.03')
|
||||
bone.head[:] = 1.7483, -0.9059, -0.3643
|
||||
bone.tail[:] = 2.2478, -1.1483, -0.7408
|
||||
bone.roll = -2.1709
|
||||
bone.connected = True
|
||||
bone.parent = arm.edit_bones['finger.02']
|
||||
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
pbone = obj.pose.bones['finger.01']
|
||||
pbone['type'] = 'finger'
|
||||
|
||||
|
||||
def metarig_definition(obj, orig_bone_name):
|
||||
'''
|
||||
The bone given is the first in a chain
|
||||
Expects a chain of at least 2 children.
|
||||
eg.
|
||||
finger -> finger_01 -> finger_02
|
||||
'''
|
||||
|
||||
bone_definition = []
|
||||
|
||||
orig_bone = obj.data.bones[orig_bone_name]
|
||||
|
||||
bone_definition.append(orig_bone.name)
|
||||
|
||||
bone = orig_bone
|
||||
chain = 0
|
||||
while chain < 2: # first 2 bones only have 1 child
|
||||
children = bone.children
|
||||
|
||||
if len(children) != 1:
|
||||
raise Exception("expected the chain to have 2 children without a fork")
|
||||
bone = children[0]
|
||||
bone_definition.append(bone.name) # finger_02, finger_03
|
||||
chain += 1
|
||||
|
||||
if len(bone_definition) != len(METARIG_NAMES):
|
||||
raise Exception("internal problem, expected %d bones" % len(METARIG_NAMES))
|
||||
|
||||
return bone_definition
|
||||
|
||||
|
||||
def main(obj, bone_definition, base_names):
|
||||
|
||||
# *** EDITMODE
|
||||
|
||||
# get assosiated data
|
||||
arm, orig_pbone, orig_ebone = get_bone_data(obj, bone_definition[0])
|
||||
|
||||
obj.animation_data_create() # needed if its a new armature with no keys
|
||||
|
||||
arm.layer[0] = arm.layer[8] = True
|
||||
|
||||
children = orig_pbone.children_recursive
|
||||
tot_len = reduce(lambda f, pbone: f + pbone.bone.length, children, orig_pbone.bone.length)
|
||||
|
||||
base_name = base_names[bone_definition[0]].rsplit(".", 1)[0]
|
||||
|
||||
# first make a new bone at the location of the finger
|
||||
#control_ebone = arm.edit_bones.new(base_name)
|
||||
control_ebone = copy_bone_simple(arm, bone_definition[0], base_name)
|
||||
control_bone_name = control_ebone.name # we dont know if we get the name requested
|
||||
|
||||
control_ebone.connected = orig_ebone.connected
|
||||
control_ebone.parent = orig_ebone.parent
|
||||
control_ebone.length = tot_len
|
||||
|
||||
# now add bones inbetween this and its children recursively
|
||||
|
||||
# switching modes so store names only!
|
||||
children = [pbone.name for pbone in children]
|
||||
|
||||
# set an alternate layer for driver bones
|
||||
other_layer = empty_layer[:]
|
||||
other_layer[8] = True
|
||||
|
||||
|
||||
driver_bone_pairs = []
|
||||
|
||||
for child_bone_name in children:
|
||||
child_ebone = arm.edit_bones[child_bone_name]
|
||||
|
||||
# finger.02 --> finger_driver.02
|
||||
driver_bone_name = child_bone_name.split('.')
|
||||
driver_bone_name = driver_bone_name[0] + "_driver." + ".".join(driver_bone_name[1:])
|
||||
|
||||
driver_ebone = copy_bone_simple(arm, child_ebone.name, driver_bone_name)
|
||||
driver_ebone.length *= 0.5
|
||||
driver_ebone.layer = other_layer
|
||||
|
||||
# Insert driver_ebone in the chain without connected parents
|
||||
driver_ebone.connected = False
|
||||
driver_ebone.parent = child_ebone.parent
|
||||
|
||||
child_ebone.connected = False
|
||||
child_ebone.parent = driver_ebone
|
||||
|
||||
# Add the drivers to these when in posemode.
|
||||
driver_bone_pairs.append((child_bone_name, driver_bone_name))
|
||||
|
||||
del control_ebone
|
||||
|
||||
|
||||
# *** POSEMODE
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
|
||||
|
||||
orig_pbone = obj.pose.bones[bone_definition[0]]
|
||||
control_pbone = obj.pose.bones[control_bone_name]
|
||||
|
||||
|
||||
# only allow Y scale
|
||||
control_pbone.lock_scale = (True, False, True)
|
||||
|
||||
control_pbone["bend_ratio"] = 0.4
|
||||
prop = rna_idprop_ui_prop_get(control_pbone, "bend_ratio", create=True)
|
||||
prop["soft_min"] = 0.0
|
||||
prop["soft_max"] = 1.0
|
||||
|
||||
con = orig_pbone.constraints.new('COPY_LOCATION')
|
||||
con.target = obj
|
||||
con.subtarget = control_bone_name
|
||||
|
||||
con = orig_pbone.constraints.new('COPY_ROTATION')
|
||||
con.target = obj
|
||||
con.subtarget = control_bone_name
|
||||
|
||||
|
||||
|
||||
# setup child drivers on each new smaller bone added. assume 2 for now.
|
||||
|
||||
# drives the bones
|
||||
controller_path = control_pbone.path_to_id() # 'pose.bones["%s"]' % control_bone_name
|
||||
|
||||
i = 0
|
||||
for child_bone_name, driver_bone_name in driver_bone_pairs:
|
||||
|
||||
# XXX - todo, any number
|
||||
if i == 2:
|
||||
break
|
||||
|
||||
driver_pbone = obj.pose.bones[driver_bone_name]
|
||||
|
||||
driver_pbone.rotation_mode = 'YZX'
|
||||
fcurve_driver = driver_pbone.driver_add("rotation_euler", 0)
|
||||
|
||||
#obj.driver_add('pose.bones["%s"].scale', 1)
|
||||
#obj.animation_data.drivers[-1] # XXX, WATCH THIS
|
||||
driver = fcurve_driver.driver
|
||||
|
||||
# scale target
|
||||
tar = driver.targets.new()
|
||||
tar.name = "scale"
|
||||
tar.id_type = 'OBJECT'
|
||||
tar.id = obj
|
||||
tar.rna_path = controller_path + '.scale[1]'
|
||||
|
||||
# bend target
|
||||
tar = driver.targets.new()
|
||||
tar.name = "br"
|
||||
tar.id_type = 'OBJECT'
|
||||
tar.id = obj
|
||||
tar.rna_path = controller_path + '["bend_ratio"]'
|
||||
|
||||
# XXX - todo, any number
|
||||
if i == 0:
|
||||
driver.expression = '(-scale+1.0)*pi*2.0*(1.0-br)'
|
||||
elif i == 1:
|
||||
driver.expression = '(-scale+1.0)*pi*2.0*br'
|
||||
|
||||
child_pbone = obj.pose.bones[child_bone_name]
|
||||
|
||||
# only allow X rotation
|
||||
driver_pbone.lock_rotation = child_pbone.lock_rotation = (False, True, True)
|
||||
|
||||
i += 1
|
||||
|
||||
# no blending the result of this
|
||||
return None
|
341
release/scripts/modules/rigify/leg.py
Normal file
341
release/scripts/modules/rigify/leg.py
Normal file
@ -0,0 +1,341 @@
|
||||
# ##### 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.
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
import bpy
|
||||
from rigify import bone_class_instance, copy_bone_simple, blend_bone_list
|
||||
from rna_prop_ui import rna_idprop_ui_prop_get
|
||||
|
||||
METARIG_NAMES = "hips", "thigh", "shin", "foot", "toe", "heel"
|
||||
|
||||
|
||||
def metarig_template():
|
||||
# generated by rigify.write_meta_rig
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
obj = bpy.context.object
|
||||
arm = obj.data
|
||||
bone = arm.edit_bones.new('hips')
|
||||
bone.head[:] = 0.0000, 0.0000, 0.0000
|
||||
bone.tail[:] = 0.0000, 0.0000, 1.0000
|
||||
bone.roll = 0.0000
|
||||
bone.connected = False
|
||||
bone = arm.edit_bones.new('thigh')
|
||||
bone.head[:] = 0.5000, 0.0000, 0.0000
|
||||
bone.tail[:] = 0.3000, -0.1000, -1.7000
|
||||
bone.roll = 0.1171
|
||||
bone.connected = False
|
||||
bone.parent = arm.edit_bones['hips']
|
||||
bone = arm.edit_bones.new('shin')
|
||||
bone.head[:] = 0.3000, -0.1000, -1.7000
|
||||
bone.tail[:] = 0.3000, 0.0000, -3.5000
|
||||
bone.roll = -0.0000
|
||||
bone.connected = True
|
||||
bone.parent = arm.edit_bones['thigh']
|
||||
bone = arm.edit_bones.new('foot')
|
||||
bone.head[:] = 0.3000, 0.0000, -3.5000
|
||||
bone.tail[:] = 0.4042, -0.5909, -3.9000
|
||||
bone.roll = -0.4662
|
||||
bone.connected = True
|
||||
bone.parent = arm.edit_bones['shin']
|
||||
bone = arm.edit_bones.new('toe')
|
||||
bone.head[:] = 0.4042, -0.5909, -3.9000
|
||||
bone.tail[:] = 0.4391, -0.9894, -3.9000
|
||||
bone.roll = -3.1416
|
||||
bone.connected = True
|
||||
bone.parent = arm.edit_bones['foot']
|
||||
bone = arm.edit_bones.new('heel')
|
||||
bone.head[:] = 0.2600, 0.2000, -4.0000
|
||||
bone.tail[:] = 0.3700, -0.4000, -4.0000
|
||||
bone.roll = 0.0000
|
||||
bone.connected = False
|
||||
bone.parent = arm.edit_bones['foot']
|
||||
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
pbone = obj.pose.bones['thigh']
|
||||
pbone['type'] = 'leg'
|
||||
|
||||
|
||||
def metarig_definition(obj, orig_bone_name):
|
||||
'''
|
||||
The bone given is the first in a chain
|
||||
Expects a chain of at least 3 children.
|
||||
eg.
|
||||
thigh -> shin -> foot -> [toe, heel]
|
||||
'''
|
||||
|
||||
bone_definition = []
|
||||
|
||||
orig_bone = obj.data.bones[orig_bone_name]
|
||||
orig_bone_parent = orig_bone.parent
|
||||
|
||||
if orig_bone_parent is None:
|
||||
raise Exception("expected the thigh bone to have a parent hip bone")
|
||||
|
||||
bone_definition.append(orig_bone_parent.name)
|
||||
bone_definition.append(orig_bone.name)
|
||||
|
||||
|
||||
bone = orig_bone
|
||||
chain = 0
|
||||
while chain < 2: # first 2 bones only have 1 child
|
||||
children = bone.children
|
||||
|
||||
if len(children) != 1:
|
||||
raise Exception("expected the thigh bone to have 3 children without a fork")
|
||||
bone = children[0]
|
||||
bone_definition.append(bone.name) # shin, foot
|
||||
chain += 1
|
||||
|
||||
children = bone.children
|
||||
# Now there must be 2 children, only one connected
|
||||
if len(children) != 2:
|
||||
raise Exception("expected the foot bone:'%s' to have 2 children" % bone.name )
|
||||
|
||||
if children[0].connected == children[1].connected:
|
||||
raise Exception("expected one bone to be connected")
|
||||
|
||||
toe, heel = children
|
||||
if heel.connected:
|
||||
toe, heel = heel, toe
|
||||
|
||||
|
||||
bone_definition.append(toe.name)
|
||||
bone_definition.append(heel.name)
|
||||
|
||||
if len(bone_definition) != len(METARIG_NAMES):
|
||||
raise Exception("internal problem, expected %d bones" % len(METARIG_NAMES))
|
||||
|
||||
return bone_definition
|
||||
|
||||
|
||||
def ik(obj, bone_definition, base_names):
|
||||
arm = obj.data
|
||||
|
||||
# setup the existing bones
|
||||
mt_chain = bone_class_instance(obj, ["thigh", "shin", "foot", "toe"])
|
||||
mt = bone_class_instance(obj, ["hips", "heel"])
|
||||
#ex = bone_class_instance(obj, [""])
|
||||
ex = bone_class_instance(obj, ["thigh_socket", "thigh_hinge", "foot_roll_1", "foot_roll_2", "foot_roll_3"])
|
||||
# children of ik_foot
|
||||
ik = bone_class_instance(obj, ["foot", "foot_roll", "foot_roll_01", "foot_roll_02", "knee_target"])
|
||||
|
||||
# XXX - duplicate below
|
||||
for bone_class in (mt, mt_chain):
|
||||
for attr in bone_class.attr_names:
|
||||
i = METARIG_NAMES.index(attr)
|
||||
ebone = arm.edit_bones[bone_definition[i]]
|
||||
setattr(bone_class, attr, ebone.name)
|
||||
bone_class.update()
|
||||
# XXX - end dupe
|
||||
|
||||
|
||||
# Make a new chain, ORG are the original bones renamed.
|
||||
ik_chain = mt_chain.copy(to_prefix="MCH-")
|
||||
|
||||
# simple rename
|
||||
ik_chain.rename("thigh", ik_chain.thigh + "_ik")
|
||||
ik_chain.rename("shin", ik_chain.shin + "_ik")
|
||||
|
||||
# ik foot, no parents
|
||||
base_foot_name = base_names[mt_chain.foot] # whatever the foot is called, use that!, XXX - ORG!
|
||||
ik.foot_e = copy_bone_simple(arm, mt_chain.foot, "%s_ik" % base_foot_name)
|
||||
ik.foot = ik.foot_e.name
|
||||
ik.foot_e.tail.z = ik.foot_e.head.z
|
||||
ik.foot_e.roll = 0.0
|
||||
|
||||
# heel pointing backwards, half length
|
||||
ik.foot_roll_e = copy_bone_simple(arm, mt.heel, "%s_roll" % base_foot_name)
|
||||
ik.foot_roll = ik.foot_roll_e.name
|
||||
ik.foot_roll_e.tail = ik.foot_roll_e.head + (ik.foot_roll_e.head - ik.foot_roll_e.tail) / 2.0
|
||||
ik.foot_roll_e.parent = ik.foot_e # heel is disconnected
|
||||
|
||||
# heel pointing forwards to the toe base, parent of the following 2 bones
|
||||
ik.foot_roll_01_e = copy_bone_simple(arm, mt.heel, "MCH-%s_roll.01" % base_foot_name)
|
||||
ik.foot_roll_01 = ik.foot_roll_01_e.name
|
||||
ik.foot_roll_01_e.tail = mt_chain.foot_e.tail
|
||||
ik.foot_roll_01_e.parent = ik.foot_e # heel is disconnected
|
||||
|
||||
# same as above but reverse direction
|
||||
ik.foot_roll_02_e = copy_bone_simple(arm, mt.heel, "MCH-%s_roll.02" % base_foot_name)
|
||||
ik.foot_roll_02 = ik.foot_roll_02_e.name
|
||||
ik.foot_roll_02_e.parent = ik.foot_roll_01_e # heel is disconnected
|
||||
ik.foot_roll_02_e.head = mt_chain.foot_e.tail
|
||||
ik.foot_roll_02_e.tail = mt.heel_e.head
|
||||
|
||||
del base_foot_name
|
||||
|
||||
# rename 'MCH-toe' --> to 'toe_ik' and make the child of ik.foot_roll_01
|
||||
# ------------------ FK or IK?
|
||||
ik_chain.rename("toe", base_names[mt_chain.toe] + "_ik")
|
||||
ik_chain.toe_e.connected = False
|
||||
ik_chain.toe_e.parent = ik.foot_roll_01_e
|
||||
|
||||
# re-parent ik_chain.foot to the
|
||||
ik_chain.foot_e.connected = False
|
||||
ik_chain.foot_e.parent = ik.foot_roll_02_e
|
||||
|
||||
|
||||
# knee target is the heel moved up and forward on its local axis
|
||||
ik.knee_target_e = copy_bone_simple(arm, mt.heel, "knee_target")
|
||||
ik.knee_target = ik.knee_target_e.name
|
||||
offset = ik.knee_target_e.tail - ik.knee_target_e.head
|
||||
offset.z = 0
|
||||
offset.length = mt_chain.shin_e.head.z - mt.heel_e.head.z
|
||||
offset.z += offset.length
|
||||
ik.knee_target_e.translate(offset)
|
||||
ik.knee_target_e.length *= 0.5
|
||||
ik.knee_target_e.parent = ik.foot_e
|
||||
|
||||
# roll the bone to point up... could also point in the same direction as ik.foot_roll
|
||||
# ik.foot_roll_02_e.matrix * Vector(0.0, 0.0, 1.0) # ACK!, no rest matrix in editmode
|
||||
ik.foot_roll_01_e.align((0.0, 0.0, -1.0))
|
||||
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
|
||||
ik.update()
|
||||
ex.update()
|
||||
mt_chain.update()
|
||||
ik_chain.update()
|
||||
|
||||
# IK
|
||||
con = ik_chain.shin_p.constraints.new('IK')
|
||||
con.chain_length = 2
|
||||
con.iterations = 500
|
||||
con.pole_angle = -90.0 # XXX - in deg!
|
||||
con.use_tail = True
|
||||
con.use_stretch = True
|
||||
con.use_target = True
|
||||
con.use_rotation = False
|
||||
con.weight = 1.0
|
||||
|
||||
con.target = obj
|
||||
con.subtarget = ik.foot
|
||||
|
||||
con.pole_target = obj
|
||||
con.pole_subtarget = ik.knee_target
|
||||
|
||||
# foot roll
|
||||
cons = [ \
|
||||
(ik.foot_roll_01_p.constraints.new('COPY_ROTATION'), ik.foot_roll_01_p.constraints.new('LIMIT_ROTATION')), \
|
||||
(ik.foot_roll_02_p.constraints.new('COPY_ROTATION'), ik.foot_roll_02_p.constraints.new('LIMIT_ROTATION'))]
|
||||
|
||||
for con, con_l in cons:
|
||||
con.target = obj
|
||||
con.subtarget = ik.foot_roll
|
||||
con.use_x, con.use_y, con.use_z = True, False, False
|
||||
con.target_space = con.owner_space = 'LOCAL'
|
||||
|
||||
con = con_l
|
||||
con.use_limit_x, con.use_limit_y, con.use_limit_z = True, False, False
|
||||
con.owner_space = 'LOCAL'
|
||||
|
||||
if con_l is cons[-1][-1]:
|
||||
con.minimum_x = 0.0
|
||||
con.maximum_x = 180.0 # XXX -deg
|
||||
else:
|
||||
con.minimum_x = -180.0 # XXX -deg
|
||||
con.maximum_x = 0.0
|
||||
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
|
||||
return None, ik_chain.thigh, ik_chain.shin, ik_chain.foot, ik_chain.toe, None
|
||||
|
||||
|
||||
def fk(obj, bone_definition, base_names):
|
||||
from Mathutils import Vector
|
||||
arm = obj.data
|
||||
|
||||
# these account for all bones in METARIG_NAMES
|
||||
mt_chain = bone_class_instance(obj, ["thigh", "shin", "foot", "toe"])
|
||||
mt = bone_class_instance(obj, ["hips", "heel"])
|
||||
|
||||
# new bones
|
||||
ex = bone_class_instance(obj, ["thigh_socket", "thigh_hinge"])
|
||||
|
||||
for bone_class in (mt, mt_chain):
|
||||
for attr in bone_class.attr_names:
|
||||
i = METARIG_NAMES.index(attr)
|
||||
ebone = arm.edit_bones[bone_definition[i]]
|
||||
setattr(bone_class, attr, ebone.name)
|
||||
bone_class.update()
|
||||
|
||||
ex.thigh_socket_e = copy_bone_simple(arm, mt_chain.thigh, "MCH-%s_socket" % base_names[mt_chain.thigh], parent=True)
|
||||
ex.thigh_socket = ex.thigh_socket_e.name
|
||||
ex.thigh_socket_e.tail = ex.thigh_socket_e.head + Vector(0.0, 0.0, ex.thigh_socket_e.length / 4.0)
|
||||
|
||||
ex.thigh_hinge_e = copy_bone_simple(arm, mt_chain.thigh, "MCH-%s_hinge" % base_names[mt_chain.thigh], parent=True)
|
||||
ex.thigh_hinge = ex.thigh_hinge_e.name
|
||||
ex.thigh_hinge_e.tail = ex.thigh_hinge_e.head + Vector(0.0, 0.0, mt_chain.thigh_e.head.length)
|
||||
ex.thigh_hinge_e.translate(Vector( - (mt.hips_e.head.x - mt_chain.thigh_e.head.x), 0.0, 0.0))
|
||||
ex.thigh_hinge_e.length = mt.hips_e.length
|
||||
|
||||
fk_chain = mt_chain.copy() # fk has no prefix!
|
||||
|
||||
fk_chain.thigh_e.connected = False
|
||||
fk_chain.thigh_e.parent = ex.thigh_hinge_e
|
||||
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
|
||||
ex.update()
|
||||
mt_chain.update()
|
||||
fk_chain.update()
|
||||
|
||||
con = fk_chain.thigh_p.constraints.new('COPY_LOCATION')
|
||||
con.target = obj
|
||||
con.subtarget = ex.thigh_socket
|
||||
|
||||
# hinge
|
||||
prop = rna_idprop_ui_prop_get(fk_chain.thigh_p, "hinge", create=True)
|
||||
fk_chain.thigh_p["hinge"] = 0.5
|
||||
prop["soft_min"] = 0.0
|
||||
prop["soft_max"] = 1.0
|
||||
|
||||
con = ex.thigh_hinge_p.constraints.new('COPY_ROTATION')
|
||||
con.target = obj
|
||||
con.subtarget = mt.hips
|
||||
|
||||
# add driver
|
||||
hinge_driver_path = fk_chain.thigh_p.path_to_id() + '["hinge"]'
|
||||
|
||||
fcurve = con.driver_add("influence", 0)
|
||||
driver = fcurve.driver
|
||||
tar = driver.targets.new()
|
||||
driver.type = 'AVERAGE'
|
||||
tar.name = "var"
|
||||
tar.id_type = 'OBJECT'
|
||||
tar.id = obj
|
||||
tar.rna_path = hinge_driver_path
|
||||
|
||||
mod = fcurve.modifiers[0]
|
||||
mod.poly_order = 1
|
||||
mod.coefficients[0] = 1.0
|
||||
mod.coefficients[1] = -1.0
|
||||
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
|
||||
# dont blend the hips or heel
|
||||
return None, fk_chain.thigh, fk_chain.shin, fk_chain.foot, fk_chain.toe, None
|
||||
|
||||
|
||||
def main(obj, bone_definition, base_names):
|
||||
bones_ik = ik(obj, bone_definition, base_names)
|
||||
bones_fk = fk(obj, bone_definition, base_names)
|
||||
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
blend_bone_list(obj, bone_definition, bones_ik, bones_fk)
|
267
release/scripts/modules/rigify/neck.py
Normal file
267
release/scripts/modules/rigify/neck.py
Normal file
@ -0,0 +1,267 @@
|
||||
# ##### 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.
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
import bpy
|
||||
from rigify import bone_class_instance, copy_bone_simple
|
||||
from rna_prop_ui import rna_idprop_ui_prop_get
|
||||
|
||||
# not used, defined for completeness
|
||||
METARIG_NAMES = ("body", "head")
|
||||
|
||||
|
||||
def metarig_template():
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
obj = bpy.context.object
|
||||
arm = obj.data
|
||||
bone = arm.edit_bones.new('body')
|
||||
bone.head[:] = -0.0000, -0.2771, -1.3345
|
||||
bone.tail[:] = -0.0000, -0.1708, -0.3984
|
||||
bone.roll = 0.0000
|
||||
bone.connected = False
|
||||
bone = arm.edit_bones.new('head')
|
||||
bone.head[:] = -0.0000, -0.1708, -0.1984
|
||||
bone.tail[:] = 0.0000, -0.1708, 1.6016
|
||||
bone.roll = -0.0000
|
||||
bone.connected = False
|
||||
bone.parent = arm.edit_bones['body']
|
||||
bone = arm.edit_bones.new('neck.01')
|
||||
bone.head[:] = 0.0000, -0.1708, -0.1984
|
||||
bone.tail[:] = -0.0000, -0.0994, 0.1470
|
||||
bone.roll = -0.0000
|
||||
bone.connected = False
|
||||
bone.parent = arm.edit_bones['head']
|
||||
bone = arm.edit_bones.new('neck.02')
|
||||
bone.head[:] = -0.0000, -0.0994, 0.1470
|
||||
bone.tail[:] = 0.0000, -0.2428, 0.5162
|
||||
bone.roll = -0.0000
|
||||
bone.connected = True
|
||||
bone.parent = arm.edit_bones['neck.01']
|
||||
bone = arm.edit_bones.new('neck.03')
|
||||
bone.head[:] = 0.0000, -0.2428, 0.5162
|
||||
bone.tail[:] = 0.0000, -0.4190, 0.8722
|
||||
bone.roll = -0.0000
|
||||
bone.connected = True
|
||||
bone.parent = arm.edit_bones['neck.02']
|
||||
bone = arm.edit_bones.new('neck.04')
|
||||
bone.head[:] = 0.0000, -0.4190, 0.8722
|
||||
bone.tail[:] = 0.0000, -0.5111, 1.1956
|
||||
bone.roll = 0.0000
|
||||
bone.connected = True
|
||||
bone.parent = arm.edit_bones['neck.03']
|
||||
bone = arm.edit_bones.new('neck.05')
|
||||
bone.head[:] = 0.0000, -0.5111, 1.1956
|
||||
bone.tail[:] = 0.0000, -0.5391, 1.6081
|
||||
bone.roll = 0.0000
|
||||
bone.connected = True
|
||||
bone.parent = arm.edit_bones['neck.04']
|
||||
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
pbone = obj.pose.bones['head']
|
||||
pbone['type'] = 'neck'
|
||||
|
||||
|
||||
def metarig_definition(obj, orig_bone_name):
|
||||
'''
|
||||
The bone given is the head, its parent is the body,
|
||||
# its only child the first of a chain with matching basenames.
|
||||
eg.
|
||||
body -> head -> neck_01 -> neck_02 -> neck_03.... etc
|
||||
'''
|
||||
arm = obj.data
|
||||
head = arm.bones[orig_bone_name]
|
||||
body = head.parent
|
||||
|
||||
children = head.children
|
||||
if len(children) != 1:
|
||||
print("expected the head to have only 1 child.")
|
||||
|
||||
child = children[0]
|
||||
bone_definition = [body.name, head.name, child.name]
|
||||
bone_definition.extend([child.name for child in child.children_recursive_basename])
|
||||
return bone_definition
|
||||
|
||||
|
||||
def main(obj, bone_definition, base_names):
|
||||
from Mathutils import Vector
|
||||
|
||||
arm = obj.data
|
||||
|
||||
# Initialize container classes for convenience
|
||||
mt = bone_class_instance(obj, ["body", "head"]) # meta
|
||||
mt.body = bone_definition[0]
|
||||
mt.head = bone_definition[1]
|
||||
mt.update()
|
||||
|
||||
neck_chain = bone_definition[2:]
|
||||
|
||||
mt_chain = bone_class_instance(obj, [("neck_%.2d" % (i + 1)) for i in range(len(neck_chain))]) # 99 bones enough eh?
|
||||
for i, attr in enumerate(mt_chain.attr_names):
|
||||
setattr(mt_chain, attr, neck_chain[i])
|
||||
mt_chain.update()
|
||||
|
||||
neck_chain_basename = mt_chain.neck_01_e.basename
|
||||
neck_chain_segment_length = mt_chain.neck_01_e.length
|
||||
|
||||
ex = bone_class_instance(obj, ["body", "head", "head_hinge", "neck_socket"]) # hinge & extras
|
||||
|
||||
# Add the head hinge at the bodys location, becomes the parent of the original head
|
||||
|
||||
|
||||
# Copy the head bone and offset
|
||||
ex.head_e = copy_bone_simple(arm, mt.head, "MCH_%s" % mt.head, parent=True)
|
||||
ex.head = ex.head_e.name
|
||||
# offset
|
||||
head_length = ex.head_e.length
|
||||
ex.head_e.head.y += head_length / 2.0
|
||||
ex.head_e.tail.y += head_length / 2.0
|
||||
|
||||
# Yes, use the body bone but call it a head hinge
|
||||
ex.head_hinge_e = copy_bone_simple(arm, mt.body, "MCH_%s_hinge" % mt.head, parent=True)
|
||||
ex.head_hinge = ex.head_hinge_e.name
|
||||
ex.head_hinge_e.head.y += head_length / 4.0
|
||||
ex.head_hinge_e.tail.y += head_length / 4.0
|
||||
|
||||
# reparent the head, assume its not connected
|
||||
mt.head_e.parent = ex.head_hinge_e
|
||||
|
||||
# Insert the neck socket, the head copys this loation
|
||||
ex.neck_socket_e = arm.edit_bones.new("MCH-%s_socked" % neck_chain_basename)
|
||||
ex.neck_socket = ex.neck_socket_e.name
|
||||
ex.neck_socket_e.parent = mt.body_e
|
||||
ex.neck_socket_e.head = mt.head_e.head
|
||||
ex.neck_socket_e.tail = mt.head_e.head - Vector(0.0, neck_chain_segment_length / 2.0, 0.0)
|
||||
ex.neck_socket_e.roll = 0.0
|
||||
|
||||
# offset the head, not really needed since it has a copyloc constraint
|
||||
mt.head_e.head.y += head_length / 4.0
|
||||
mt.head_e.tail.y += head_length / 4.0
|
||||
|
||||
for i, attr in enumerate(mt_chain.attr_names):
|
||||
neck_e = getattr(mt_chain, attr + "_e")
|
||||
|
||||
# dont store parent names, re-reference as each chain bones parent.
|
||||
neck_e_parent = arm.edit_bones.new("MCH-rot_%s" % neck_e.name)
|
||||
neck_e_parent.head = neck_e.head
|
||||
neck_e_parent.tail = neck_e.head + ((mt.head_e.tail - mt.head_e.head).normalize() * neck_chain_segment_length / 2.0)
|
||||
neck_e_parent.roll = neck_e.roll
|
||||
|
||||
|
||||
orig_parent = neck_e.parent
|
||||
neck_e.connected = False
|
||||
neck_e.parent = neck_e_parent
|
||||
neck_e_parent.connected = False
|
||||
|
||||
if i == 0:
|
||||
neck_e_parent.parent = mt.body_e
|
||||
else:
|
||||
neck_e_parent.parent = orig_parent
|
||||
|
||||
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
|
||||
mt.update()
|
||||
mt_chain.update()
|
||||
ex.update()
|
||||
|
||||
# Simple one off constraints, no drivers
|
||||
con = mt.head_p.constraints.new('COPY_LOCATION')
|
||||
con.target = obj
|
||||
con.subtarget = ex.neck_socket
|
||||
|
||||
con = ex.head_p.constraints.new('COPY_ROTATION')
|
||||
con.target = obj
|
||||
con.subtarget = mt.head
|
||||
|
||||
# driven hinge
|
||||
prop = rna_idprop_ui_prop_get(mt.head_p, "hinge", create=True)
|
||||
mt.head_p["hinge"] = 0.0
|
||||
prop["soft_min"] = 0.0
|
||||
prop["soft_max"] = 1.0
|
||||
|
||||
con = ex.head_hinge_p.constraints.new('COPY_ROTATION')
|
||||
con.name = "hinge"
|
||||
con.target = obj
|
||||
con.subtarget = mt.body
|
||||
|
||||
# add driver
|
||||
hinge_driver_path = mt.head_p.path_to_id() + '["hinge"]'
|
||||
|
||||
fcurve = con.driver_add("influence", 0)
|
||||
driver = fcurve.driver
|
||||
tar = driver.targets.new()
|
||||
driver.type = 'AVERAGE'
|
||||
tar.name = "var"
|
||||
tar.id_type = 'OBJECT'
|
||||
tar.id = obj
|
||||
tar.rna_path = hinge_driver_path
|
||||
|
||||
#mod = fcurve_driver.modifiers.new('GENERATOR')
|
||||
mod = fcurve.modifiers[0]
|
||||
mod.poly_order = 1
|
||||
mod.coefficients[0] = 1.0
|
||||
mod.coefficients[1] = -1.0
|
||||
|
||||
head_driver_path = mt.head_p.path_to_id()
|
||||
|
||||
# b01/max(0.001,b01+b02+b03+b04+b05)
|
||||
target_names = [("b%.2d" % (i + 1)) for i in range(len(neck_chain))]
|
||||
expression_suffix = "/max(0.001,%s)" % "+".join(target_names)
|
||||
|
||||
|
||||
for i, attr in enumerate(mt_chain.attr_names):
|
||||
neck_p = getattr(mt_chain, attr + "_p")
|
||||
neck_p.lock_location = True, True, True
|
||||
neck_p.lock_location = True, True, True
|
||||
neck_p.lock_rotations_4d = True
|
||||
|
||||
# Add bend prop
|
||||
prop_name = "bend_%.2d" % (i + 1)
|
||||
prop = rna_idprop_ui_prop_get(mt.head_p, prop_name, create=True)
|
||||
mt.head_p[prop_name] = 1.0
|
||||
prop["soft_min"] = 0.0
|
||||
prop["soft_max"] = 1.0
|
||||
|
||||
# add parent constraint
|
||||
neck_p_parent = neck_p.parent
|
||||
|
||||
# add constraint
|
||||
con = neck_p_parent.constraints.new('COPY_ROTATION')
|
||||
con.name = "Copy Rotation"
|
||||
con.target = obj
|
||||
con.subtarget = ex.head
|
||||
con.owner_space = 'LOCAL'
|
||||
con.target_space = 'LOCAL'
|
||||
|
||||
fcurve = con.driver_add("influence", 0)
|
||||
driver = fcurve.driver
|
||||
driver.type = 'SCRIPTED'
|
||||
# b01/max(0.001,b01+b02+b03+b04+b05)
|
||||
driver.expression = target_names[i] + expression_suffix
|
||||
fcurve.modifiers.remove(0) # grr dont need a modifier
|
||||
|
||||
for j in range(len(neck_chain)):
|
||||
tar = driver.targets.new()
|
||||
tar.name = target_names[j]
|
||||
tar.id_type = 'OBJECT'
|
||||
tar.id = obj
|
||||
tar.rna_path = head_driver_path + ('["bend_%.2d"]' % (j + 1))
|
||||
|
||||
# no blending the result of this
|
||||
return None
|
208
release/scripts/modules/rigify/palm.py
Normal file
208
release/scripts/modules/rigify/palm.py
Normal file
@ -0,0 +1,208 @@
|
||||
# ##### 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.
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
import bpy
|
||||
from rigify import get_bone_data, copy_bone_simple
|
||||
from rna_prop_ui import rna_idprop_ui_prop_get
|
||||
|
||||
# not used, defined for completeness
|
||||
METARIG_NAMES = tuple()
|
||||
|
||||
def metarig_template():
|
||||
# generated by rigify.write_meta_rig
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
obj = bpy.context.object
|
||||
arm = obj.data
|
||||
bone = arm.edit_bones.new('hand')
|
||||
bone.head[:] = 0.0082, -1.2492, 0.0000
|
||||
bone.tail[:] = 0.0423, -0.4150, 0.0000
|
||||
bone.roll = 0.0000
|
||||
bone.connected = False
|
||||
bone = arm.edit_bones.new('palm.03')
|
||||
bone.head[:] = 0.0000, 0.0000, -0.0000
|
||||
bone.tail[:] = 0.0506, 1.2781, -0.1299
|
||||
bone.roll = -3.1396
|
||||
bone.connected = False
|
||||
bone.parent = arm.edit_bones['hand']
|
||||
bone = arm.edit_bones.new('palm.04')
|
||||
bone.head[:] = 0.5000, -0.0000, 0.0000
|
||||
bone.tail[:] = 0.6433, 1.2444, -0.1299
|
||||
bone.roll = -3.1357
|
||||
bone.connected = False
|
||||
bone.parent = arm.edit_bones['hand']
|
||||
bone = arm.edit_bones.new('palm.05')
|
||||
bone.head[:] = 1.0000, 0.0000, 0.0000
|
||||
bone.tail[:] = 1.3961, 1.0084, -0.1299
|
||||
bone.roll = -3.1190
|
||||
bone.connected = False
|
||||
bone.parent = arm.edit_bones['hand']
|
||||
bone = arm.edit_bones.new('palm.02')
|
||||
bone.head[:] = -0.5000, 0.0000, -0.0000
|
||||
bone.tail[:] = -0.5674, 1.2022, -0.1299
|
||||
bone.roll = 3.1386
|
||||
bone.connected = False
|
||||
bone.parent = arm.edit_bones['hand']
|
||||
bone = arm.edit_bones.new('palm.01')
|
||||
bone.head[:] = -1.0000, 0.0000, -0.0000
|
||||
bone.tail[:] = -1.3286, 1.0590, -0.1299
|
||||
bone.roll = 3.1239
|
||||
bone.connected = False
|
||||
bone.parent = arm.edit_bones['hand']
|
||||
bone = arm.edit_bones.new('palm.06')
|
||||
bone.head[:] = 1.3536, -0.2941, 0.0000
|
||||
bone.tail[:] = 2.1109, 0.4807, -0.1299
|
||||
bone.roll = -3.0929
|
||||
bone.connected = False
|
||||
bone.parent = arm.edit_bones['hand']
|
||||
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
pbone = obj.pose.bones['palm.05']
|
||||
pbone['type'] = 'palm'
|
||||
|
||||
|
||||
def metarig_definition(obj, orig_bone_name):
|
||||
'''
|
||||
The bone given is the first in an array of siblings with a matching basename
|
||||
sorted with the little finger lowest.
|
||||
eg.
|
||||
[pinky, ring... etc]
|
||||
'''
|
||||
arm = obj.data
|
||||
|
||||
palm_bone = arm.bones[orig_bone_name]
|
||||
palm_parent = palm_bone.parent
|
||||
palm_base = palm_bone.basename
|
||||
bone_definition = [bone.name for bone in palm_parent.children if bone.basename == palm_base]
|
||||
bone_definition.sort()
|
||||
|
||||
return [palm_parent.name] + bone_definition
|
||||
|
||||
|
||||
def main(obj, bone_definition, base_names):
|
||||
arm, palm_pbone, palm_ebone = get_bone_data(obj, bone_definition[0])
|
||||
children = bone_definition[1:]
|
||||
|
||||
# Make a copy of the pinky
|
||||
# simply assume the pinky has the lowest name
|
||||
pinky_ebone = arm.edit_bones[children[0]]
|
||||
ring_ebone = arm.edit_bones[children[1]]
|
||||
|
||||
control_ebone = copy_bone_simple(arm, pinky_ebone.name, "palm_control", parent=True)
|
||||
control_name = control_ebone.name
|
||||
|
||||
offset = (pinky_ebone.head - ring_ebone.head)
|
||||
|
||||
control_ebone.translate(offset)
|
||||
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
|
||||
|
||||
arm, control_pbone, control_ebone = get_bone_data(obj, control_name)
|
||||
arm, pinky_pbone, pinky_ebone = get_bone_data(obj, children[0])
|
||||
|
||||
control_pbone.rotation_mode = 'YZX'
|
||||
control_pbone.lock_rotation = False, True, True
|
||||
|
||||
driver_fcurves = pinky_pbone.driver_add("rotation_euler")
|
||||
|
||||
|
||||
controller_path = control_pbone.path_to_id()
|
||||
|
||||
# add custom prop
|
||||
control_pbone["spread"] = 0.0
|
||||
prop = rna_idprop_ui_prop_get(control_pbone, "spread", create=True)
|
||||
prop["soft_min"] = -1.0
|
||||
prop["soft_max"] = 1.0
|
||||
|
||||
|
||||
# *****
|
||||
driver = driver_fcurves[0].driver
|
||||
driver.type = 'AVERAGE'
|
||||
|
||||
tar = driver.targets.new()
|
||||
tar.name = "x"
|
||||
tar.id_type = 'OBJECT'
|
||||
tar.id = obj
|
||||
tar.rna_path = controller_path + ".rotation_euler[0]"
|
||||
|
||||
|
||||
# *****
|
||||
driver = driver_fcurves[1].driver
|
||||
driver.expression = "-x/4.0"
|
||||
|
||||
tar = driver.targets.new()
|
||||
tar.name = "x"
|
||||
tar.id_type = 'OBJECT'
|
||||
tar.id = obj
|
||||
tar.rna_path = controller_path + ".rotation_euler[0]"
|
||||
|
||||
|
||||
# *****
|
||||
driver = driver_fcurves[2].driver
|
||||
driver.expression = "(1.0-cos(x))-s"
|
||||
tar = driver.targets.new()
|
||||
tar.name = "x"
|
||||
tar.id_type = 'OBJECT'
|
||||
tar.id = obj
|
||||
tar.rna_path = controller_path + ".rotation_euler[0]"
|
||||
|
||||
tar = driver.targets.new()
|
||||
tar.name = "s"
|
||||
tar.id_type = 'OBJECT'
|
||||
tar.id = obj
|
||||
tar.rna_path = controller_path + '["spread"]'
|
||||
|
||||
|
||||
for i, child_name in enumerate(children):
|
||||
child_pbone = obj.pose.bones[child_name]
|
||||
child_pbone.rotation_mode = 'YZX'
|
||||
|
||||
if child_name != children[-1] and child_name != children[0]:
|
||||
|
||||
# this is somewhat arbitrary but seems to look good
|
||||
inf = i / (len(children) + 1)
|
||||
inf = 1.0 - inf
|
||||
inf = ((inf * inf) + inf) / 2.0
|
||||
|
||||
# used for X/Y constraint
|
||||
inf_minor = inf * inf
|
||||
|
||||
con = child_pbone.constraints.new('COPY_ROTATION')
|
||||
con.name = "Copy Z Rot"
|
||||
con.target = obj
|
||||
con.subtarget = children[0] # also pinky_pbone
|
||||
con.owner_space = con.target_space = 'LOCAL'
|
||||
con.use_x, con.use_y, con.use_z = False, False, True
|
||||
con.influence = inf
|
||||
|
||||
con = child_pbone.constraints.new('COPY_ROTATION')
|
||||
con.name = "Copy XY Rot"
|
||||
con.target = obj
|
||||
con.subtarget = children[0] # also pinky_pbone
|
||||
con.owner_space = con.target_space = 'LOCAL'
|
||||
con.use_x, con.use_y, con.use_z = True, True, False
|
||||
con.influence = inf_minor
|
||||
|
||||
|
||||
child_pbone = obj.pose.bones[children[-1]]
|
||||
child_pbone.rotation_mode = 'QUATERNION'
|
||||
|
||||
# no blending the result of this
|
||||
return None
|
472
release/scripts/modules/rigify/spine.py
Normal file
472
release/scripts/modules/rigify/spine.py
Normal file
@ -0,0 +1,472 @@
|
||||
# ##### 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.
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
import bpy
|
||||
from rigify import bone_class_instance, copy_bone_simple
|
||||
from rna_prop_ui import rna_idprop_ui_prop_get
|
||||
|
||||
# not used, defined for completeness
|
||||
METARIG_NAMES = ("pelvis", "ribcage")
|
||||
|
||||
|
||||
def metarig_template():
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
obj = bpy.context.object
|
||||
arm = obj.data
|
||||
bone = arm.edit_bones.new('pelvis')
|
||||
bone.head[:] = -0.0000, -0.2559, 0.8673
|
||||
bone.tail[:] = -0.0000, -0.2559, -0.1327
|
||||
bone.roll = 0.0000
|
||||
bone.connected = False
|
||||
bone = arm.edit_bones.new('rib_cage')
|
||||
bone.head[:] = -0.0000, -0.2559, 0.8673
|
||||
bone.tail[:] = -0.0000, -0.2559, 1.8673
|
||||
bone.roll = -0.0000
|
||||
bone.connected = False
|
||||
bone.parent = arm.edit_bones['pelvis']
|
||||
bone = arm.edit_bones.new('spine.01')
|
||||
bone.head[:] = -0.0000, -0.0000, 0.0000
|
||||
bone.tail[:] = -0.0000, -0.2559, 0.8673
|
||||
bone.roll = -0.0000
|
||||
bone.connected = False
|
||||
bone.parent = arm.edit_bones['rib_cage']
|
||||
bone = arm.edit_bones.new('spine.02')
|
||||
bone.head[:] = -0.0000, -0.2559, 0.8673
|
||||
bone.tail[:] = -0.0000, -0.3321, 1.7080
|
||||
bone.roll = -0.0000
|
||||
bone.connected = True
|
||||
bone.parent = arm.edit_bones['spine.01']
|
||||
bone = arm.edit_bones.new('spine.03')
|
||||
bone.head[:] = -0.0000, -0.3321, 1.7080
|
||||
bone.tail[:] = -0.0000, -0.0787, 2.4160
|
||||
bone.roll = 0.0000
|
||||
bone.connected = True
|
||||
bone.parent = arm.edit_bones['spine.02']
|
||||
bone = arm.edit_bones.new('spine.04')
|
||||
bone.head[:] = -0.0000, -0.0787, 2.4160
|
||||
bone.tail[:] = -0.0000, 0.2797, 3.0016
|
||||
bone.roll = 0.0000
|
||||
bone.connected = True
|
||||
bone.parent = arm.edit_bones['spine.03']
|
||||
bone = arm.edit_bones.new('spine.05')
|
||||
bone.head[:] = -0.0000, 0.2797, 3.0016
|
||||
bone.tail[:] = -0.0000, 0.4633, 3.6135
|
||||
bone.roll = 0.0000
|
||||
bone.connected = True
|
||||
bone.parent = arm.edit_bones['spine.04']
|
||||
bone = arm.edit_bones.new('spine.06')
|
||||
bone.head[:] = -0.0000, 0.4633, 3.6135
|
||||
bone.tail[:] = -0.0000, 0.3671, 4.3477
|
||||
bone.roll = -0.0000
|
||||
bone.connected = True
|
||||
bone.parent = arm.edit_bones['spine.05']
|
||||
bone = arm.edit_bones.new('spine.07')
|
||||
bone.head[:] = -0.0000, 0.3671, 4.3477
|
||||
bone.tail[:] = -0.0000, 0.0175, 5.0033
|
||||
bone.roll = -0.0000
|
||||
bone.connected = True
|
||||
bone.parent = arm.edit_bones['spine.06']
|
||||
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
pbone = obj.pose.bones['rib_cage']
|
||||
pbone['type'] = 'spine'
|
||||
|
||||
|
||||
def metarig_definition(obj, orig_bone_name):
|
||||
'''
|
||||
The bone given is the second in a chain.
|
||||
Expects at least 1 parent and a chain of children withe the same basename
|
||||
eg.
|
||||
pelvis -> rib_cage -> spine.01 -> spine.02 -> spine.03
|
||||
|
||||
note: same as neck.
|
||||
'''
|
||||
arm = obj.data
|
||||
ribcage = arm.bones[orig_bone_name]
|
||||
pelvis = ribcage.parent
|
||||
|
||||
if pelvis is None:
|
||||
raise Exception("expected the ribcage bone:'%s' to have a parent (ribcage)." % ribcage.name)
|
||||
|
||||
children = ribcage.children
|
||||
if len(children) != 1:
|
||||
raise Exception("expected the ribcage to have only 1 child.")
|
||||
|
||||
child = children[0]
|
||||
|
||||
bone_definition = [pelvis.name, ribcage.name, child.name]
|
||||
bone_definition.extend([child.name for child in child.children_recursive_basename])
|
||||
return bone_definition
|
||||
|
||||
|
||||
def fk(*args):
|
||||
main(*args)
|
||||
|
||||
|
||||
def main(obj, bone_definition, base_names):
|
||||
from Mathutils import Vector, RotationMatrix
|
||||
from math import radians, pi
|
||||
|
||||
arm = obj.data
|
||||
|
||||
# Initialize container classes for convenience
|
||||
mt = bone_class_instance(obj, ["pelvis", "ribcage"]) # meta
|
||||
mt.pelvis = bone_definition[0]
|
||||
mt.ribcage = bone_definition[1]
|
||||
mt.update()
|
||||
|
||||
spine_chain_orig = tuple(bone_definition[2:])
|
||||
spine_chain = [arm.edit_bones[child_name] for child_name in spine_chain_orig]
|
||||
spine_chain_basename = base_names[spine_chain[0].name].rsplit(".", 1)[0] # probably 'ORG-spine.01' -> 'spine'
|
||||
spine_chain_len = len(spine_chain_orig)
|
||||
|
||||
child = spine_chain[0]
|
||||
spine_chain_segment_length = child.length
|
||||
child.parent = mt.pelvis_e # was mt.ribcage
|
||||
|
||||
# The first bone in the chain happens to be the basis of others, create them now
|
||||
ex = bone_class_instance(obj, ["pelvis", "ribcage", "ribcage_hinge", "spine_rotate"])
|
||||
df = bone_class_instance(obj, ["pelvis", "ribcage"]) # DEF-wgt_pelvis, DEF-wgt_rib_cage
|
||||
|
||||
|
||||
# copy the pelvis, offset to make MCH-spine_rotate and MCH-ribcage_hinge
|
||||
ex.ribcage_hinge_e = copy_bone_simple(arm, mt.pelvis, "MCH-%s_hinge" % mt.ribcage)
|
||||
ex.ribcage_hinge = ex.ribcage_hinge_e.name
|
||||
ex.ribcage_hinge_e.translate(Vector(0.0, spine_chain_segment_length / 4.0, 0.0))
|
||||
mt.ribcage_e.parent = ex.ribcage_hinge_e
|
||||
|
||||
ex.spine_rotate_e = copy_bone_simple(arm, mt.pelvis, "MCH-%s_rotate" % spine_chain_basename)
|
||||
ex.spine_rotate = ex.spine_rotate_e.name
|
||||
ex.spine_rotate_e.translate(Vector(0.0, spine_chain_segment_length / 2.0, 0.0))
|
||||
# swap head/tail
|
||||
ex.spine_rotate_e.head, ex.spine_rotate_e.tail = ex.spine_rotate_e.tail.copy(), ex.spine_rotate_e.head.copy()
|
||||
ex.spine_rotate_e.parent = mt.pelvis_e
|
||||
|
||||
df.pelvis_e = copy_bone_simple(arm, child.name, "DEF-wgt_%s" % mt.pelvis)
|
||||
df.pelvis = df.pelvis_e.name
|
||||
df.pelvis_e.translate(Vector(spine_chain_segment_length * 2.0, - spine_chain_segment_length, 0.0))
|
||||
|
||||
ex.pelvis_e = copy_bone_simple(arm, child.name, "MCH-wgt_%s" % mt.pelvis)
|
||||
ex.pelvis = ex.pelvis_e.name
|
||||
ex.pelvis_e.translate(Vector(0.0, - spine_chain_segment_length, 0.0))
|
||||
ex.pelvis_e.parent = mt.pelvis_e
|
||||
|
||||
# Copy the last bone now
|
||||
child = spine_chain[-1]
|
||||
|
||||
df.ribcage_e = copy_bone_simple(arm, child.name, "DEF-wgt_%s" % mt.ribcage)
|
||||
df.ribcage = df.ribcage_e.name
|
||||
df.ribcage_e.translate(Vector(spine_chain_segment_length * 2.0, - df.ribcage_e.length / 2.0, 0.0))
|
||||
|
||||
ex.ribcage_e = copy_bone_simple(arm, child.name, "MCH-wgt_%s" % mt.ribcage)
|
||||
ex.ribcage = ex.ribcage_e.name
|
||||
ex.ribcage_e.translate(Vector(0.0, - ex.ribcage_e.length / 2.0, 0.0))
|
||||
ex.ribcage_e.parent = mt.ribcage_e
|
||||
|
||||
spine_chain = [child.name for child in spine_chain]
|
||||
|
||||
# We have 3 spine chains
|
||||
# - original (ORG_*)
|
||||
# - copy (*use original name*)
|
||||
# - reverse (MCH-rev_*)
|
||||
spine_chain_attrs = [("spine_%.2d" % (i + 1)) for i in range(spine_chain_len)]
|
||||
|
||||
mt_chain = bone_class_instance(obj, spine_chain_attrs) # ORG_*
|
||||
rv_chain = bone_class_instance(obj, spine_chain_attrs) # *
|
||||
ex_chain = bone_class_instance(obj, spine_chain_attrs) # MCH-rev_*
|
||||
del spine_chain_attrs
|
||||
|
||||
for i, child_name in enumerate(spine_chain):
|
||||
child_name_orig = base_names[spine_chain_orig[i]]
|
||||
|
||||
attr = mt_chain.attr_names[i] # eg. spine_04
|
||||
|
||||
setattr(mt_chain, attr, spine_chain_orig[i]) # the original bone
|
||||
|
||||
ebone = copy_bone_simple(arm, child_name, child_name_orig) # use the original name
|
||||
setattr(ex_chain, attr, ebone.name)
|
||||
|
||||
ebone = copy_bone_simple(arm, child_name, "MCH-rev_%s" % child_name_orig)
|
||||
setattr(rv_chain, attr, ebone.name)
|
||||
ebone.connected = False
|
||||
|
||||
mt_chain.update()
|
||||
ex_chain.update()
|
||||
rv_chain.update()
|
||||
|
||||
# Now we need to re-parent these chains
|
||||
for i, child_name in enumerate(spine_chain_orig):
|
||||
attr = ex_chain.attr_names[i] + "_e"
|
||||
|
||||
if i == 0:
|
||||
getattr(ex_chain, attr).parent = mt.pelvis_e
|
||||
else:
|
||||
attr_parent = ex_chain.attr_names[i-1] + "_e"
|
||||
getattr(ex_chain, attr).parent = getattr(ex_chain, attr_parent)
|
||||
|
||||
# intentional! get the parent from the other paralelle chain member
|
||||
getattr(rv_chain, attr).parent = getattr(ex_chain, attr)
|
||||
|
||||
|
||||
# ex_chain needs to interlace bones!
|
||||
# Note, skip the first bone
|
||||
for i in range(1, spine_chain_len): # similar to neck
|
||||
child_name_orig = spine_chain_orig[i]
|
||||
spine_e = getattr(mt_chain, mt_chain.attr_names[i] + "_e")
|
||||
|
||||
# dont store parent names, re-reference as each chain bones parent.
|
||||
spine_e_parent = arm.edit_bones.new("MCH-rot_%s" % child_name_orig)
|
||||
spine_e_parent.head = spine_e.head
|
||||
spine_e_parent.tail = spine_e.head + ((mt.ribcage_e.tail - mt.ribcage_e.head).normalize() * spine_chain_segment_length / 2.0)
|
||||
spine_e_parent.roll = mt.ribcage_e.roll
|
||||
|
||||
|
||||
spine_e = getattr(ex_chain, ex_chain.attr_names[i] + "_e")
|
||||
orig_parent = spine_e.parent
|
||||
spine_e.connected = False
|
||||
spine_e.parent = spine_e_parent
|
||||
spine_e_parent.connected = False
|
||||
|
||||
spine_e_parent.parent = orig_parent
|
||||
|
||||
|
||||
# Rotate the rev chain 180 about the by the first bones center point
|
||||
pivot = (rv_chain.spine_01_e.head + rv_chain.spine_01_e.tail) * 0.5
|
||||
matrix = RotationMatrix(radians(180), 3, 'X')
|
||||
for i, attr in enumerate(rv_chain.attr_names): # similar to neck
|
||||
spine_e = getattr(rv_chain, attr + "_e")
|
||||
# use the first bone as the pivot
|
||||
|
||||
spine_e.head = ((spine_e.head - pivot) * matrix) + pivot
|
||||
spine_e.tail = ((spine_e.tail - pivot) * matrix) + pivot
|
||||
spine_e.roll += pi # 180d roll
|
||||
del spine_e
|
||||
|
||||
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
|
||||
# refresh pose bones
|
||||
mt.update()
|
||||
ex.update()
|
||||
df.update()
|
||||
mt_chain.update()
|
||||
ex_chain.update()
|
||||
rv_chain.update()
|
||||
|
||||
# df.pelvis_p / DEF-wgt_pelvis
|
||||
con = df.pelvis_p.constraints.new('COPY_LOCATION')
|
||||
con.target = obj
|
||||
con.subtarget = ex.pelvis
|
||||
con.owner_space = 'LOCAL'
|
||||
con.target_space = 'LOCAL'
|
||||
|
||||
con = df.pelvis_p.constraints.new('COPY_ROTATION')
|
||||
con.target = obj
|
||||
con.subtarget = ex.pelvis
|
||||
con.owner_space = 'LOCAL'
|
||||
con.target_space = 'LOCAL'
|
||||
|
||||
# df.ribcage_p / DEF-wgt_rib_cage
|
||||
con = df.ribcage_p.constraints.new('COPY_ROTATION')
|
||||
con.target = obj
|
||||
con.subtarget = ex.ribcage
|
||||
con.owner_space = 'LOCAL'
|
||||
con.target_space = 'LOCAL'
|
||||
|
||||
con = df.ribcage_p.constraints.new('COPY_LOCATION')
|
||||
con.target = obj
|
||||
con.subtarget = ex.ribcage
|
||||
con.owner_space = 'LOCAL'
|
||||
con.target_space = 'LOCAL'
|
||||
|
||||
con = ex.ribcage_hinge_p.constraints.new('COPY_ROTATION')
|
||||
con.name = "hinge"
|
||||
con.target = obj
|
||||
con.subtarget = mt.pelvis
|
||||
|
||||
# add driver
|
||||
hinge_driver_path = mt.ribcage_p.path_to_id() + '["hinge"]'
|
||||
|
||||
fcurve = con.driver_add("influence", 0)
|
||||
driver = fcurve.driver
|
||||
tar = driver.targets.new()
|
||||
driver.type = 'AVERAGE'
|
||||
tar.name = "var"
|
||||
tar.id_type = 'OBJECT'
|
||||
tar.id = obj
|
||||
tar.rna_path = hinge_driver_path
|
||||
|
||||
mod = fcurve.modifiers[0]
|
||||
mod.poly_order = 1
|
||||
mod.coefficients[0] = 1.0
|
||||
mod.coefficients[1] = -1.0
|
||||
|
||||
|
||||
con = ex.spine_rotate_p.constraints.new('COPY_ROTATION')
|
||||
con.target = obj
|
||||
con.subtarget = mt.ribcage
|
||||
|
||||
|
||||
# ex.pelvis_p / MCH-wgt_pelvis
|
||||
con = ex.pelvis_p.constraints.new('COPY_LOCATION')
|
||||
con.target = obj
|
||||
con.subtarget = mt_chain.spine_01
|
||||
con.owner_space = 'WORLD'
|
||||
con.target_space = 'WORLD'
|
||||
|
||||
con = ex.pelvis_p.constraints.new('COPY_ROTATION')
|
||||
con.target = obj
|
||||
con.subtarget = mt_chain.spine_01
|
||||
con.owner_space = 'WORLD'
|
||||
con.target_space = 'WORLD'
|
||||
|
||||
# ex.ribcage_p / MCH-wgt_rib_cage
|
||||
con = ex.ribcage_p.constraints.new('COPY_LOCATION')
|
||||
con.target = obj
|
||||
con.subtarget = getattr(mt_chain, mt_chain.attr_names[-1])
|
||||
con.head_tail = 0.0
|
||||
|
||||
con = ex.ribcage_p.constraints.new('COPY_ROTATION')
|
||||
con.target = obj
|
||||
con.subtarget = getattr(mt_chain, mt_chain.attr_names[-1])
|
||||
|
||||
# mt.pelvis_p / rib_cage
|
||||
con = mt.ribcage_p.constraints.new('COPY_LOCATION')
|
||||
con.target = obj
|
||||
con.subtarget = mt.pelvis
|
||||
con.head_tail = 0.0
|
||||
|
||||
# This stores all important ID props
|
||||
prop = rna_idprop_ui_prop_get(mt.ribcage_p, "hinge", create=True)
|
||||
mt.ribcage_p["hinge"] = 1.0
|
||||
prop["soft_min"] = 0.0
|
||||
prop["soft_max"] = 1.0
|
||||
|
||||
prop = rna_idprop_ui_prop_get(mt.ribcage_p, "pivot_slide", create=True)
|
||||
mt.ribcage_p["pivot_slide"] = 0.5
|
||||
prop["soft_min"] = 1.0 / spine_chain_len
|
||||
prop["soft_max"] = 1.0
|
||||
|
||||
for i in range(spine_chain_len - 1):
|
||||
prop_name = "bend_%.2d" % (i + 1)
|
||||
prop = rna_idprop_ui_prop_get(mt.ribcage_p, prop_name, create=True)
|
||||
mt.ribcage_p[prop_name] = 1.0
|
||||
prop["soft_min"] = 0.0
|
||||
prop["soft_max"] = 1.0
|
||||
|
||||
# Create a fake connected parent/child relationship with bone location constraints
|
||||
# positioned at the tip.
|
||||
|
||||
# reverse bones / MCH-rev_spine.##
|
||||
for i in range(1, spine_chain_len):
|
||||
spine_p = getattr(rv_chain, rv_chain.attr_names[i] + "_p")
|
||||
spine_fake_parent_name = getattr(rv_chain, rv_chain.attr_names[i - 1])
|
||||
|
||||
con = spine_p.constraints.new('COPY_LOCATION')
|
||||
con.target = obj
|
||||
con.subtarget = spine_fake_parent_name
|
||||
con.head_tail = 1.0
|
||||
del spine_p, spine_fake_parent_name, con
|
||||
|
||||
|
||||
# Constrain 'inbetween' bones
|
||||
|
||||
# b01/max(0.001,b01+b02+b03+b04+b05)
|
||||
target_names = [("b%.2d" % (i + 1)) for i in range(spine_chain_len - 1)]
|
||||
expression_suffix = "/max(0.001,%s)" % "+".join(target_names)
|
||||
|
||||
rib_driver_path = mt.ribcage_p.path_to_id()
|
||||
|
||||
for i in range(1, spine_chain_len):
|
||||
|
||||
spine_p = getattr(ex_chain, ex_chain.attr_names[i] + "_p")
|
||||
spine_p_parent = spine_p.parent # interlaced bone
|
||||
|
||||
con = spine_p_parent.constraints.new('COPY_ROTATION')
|
||||
con.target = obj
|
||||
con.subtarget = ex.spine_rotate
|
||||
con.owner_space = 'LOCAL'
|
||||
con.target_space = 'LOCAL'
|
||||
del spine_p
|
||||
|
||||
# add driver
|
||||
fcurve = con.driver_add("influence", 0)
|
||||
driver = fcurve.driver
|
||||
driver.type = 'SCRIPTED'
|
||||
# b01/max(0.001,b01+b02+b03+b04+b05)
|
||||
driver.expression = target_names[i - 1] + expression_suffix
|
||||
fcurve.modifiers.remove(0) # grr dont need a modifier
|
||||
|
||||
for j in range(spine_chain_len - 1):
|
||||
tar = driver.targets.new()
|
||||
tar.name = target_names[j]
|
||||
tar.id_type = 'OBJECT'
|
||||
tar.id = obj
|
||||
tar.rna_path = rib_driver_path + ('["bend_%.2d"]' % (j + 1))
|
||||
|
||||
|
||||
# original bone drivers
|
||||
# note: the first bone has a lot more constraints, but also this simple one is first.
|
||||
for i, attr in enumerate(mt_chain.attr_names):
|
||||
spine_p = getattr(mt_chain, attr + "_p")
|
||||
|
||||
con = spine_p.constraints.new('COPY_ROTATION')
|
||||
con.target = obj
|
||||
con.subtarget = getattr(ex_chain, attr) # lock to the copy's rotation
|
||||
del spine_p
|
||||
|
||||
# pivot slide: - lots of copy location constraints.
|
||||
|
||||
con = mt_chain.spine_01_p.constraints.new('COPY_LOCATION')
|
||||
con.name = "base"
|
||||
con.target = obj
|
||||
con.subtarget = rv_chain.spine_01 # lock to the reverse location
|
||||
|
||||
for i in range(1, spine_chain_len + 1):
|
||||
con = mt_chain.spine_01_p.constraints.new('COPY_LOCATION')
|
||||
con.name = "slide_%d" % i
|
||||
con.target = obj
|
||||
|
||||
if i == spine_chain_len:
|
||||
attr = mt_chain.attr_names[i - 1]
|
||||
else:
|
||||
attr = mt_chain.attr_names[i]
|
||||
|
||||
con.subtarget = getattr(rv_chain, attr) # lock to the reverse location
|
||||
|
||||
if i == spine_chain_len:
|
||||
con.head_tail = 1.0
|
||||
|
||||
fcurve = con.driver_add("influence", 0)
|
||||
driver = fcurve.driver
|
||||
tar = driver.targets.new()
|
||||
driver.type = 'AVERAGE'
|
||||
tar.name = "var"
|
||||
tar.id_type = 'OBJECT'
|
||||
tar.id = obj
|
||||
tar.rna_path = rib_driver_path + '["pivot_slide"]'
|
||||
|
||||
mod = fcurve.modifiers[0]
|
||||
mod.poly_order = 1
|
||||
mod.coefficients[0] = - (i - 1)
|
||||
mod.coefficients[1] = spine_chain_len
|
||||
|
||||
# no support for blending chains
|
||||
return None
|
@ -20,6 +20,7 @@
|
||||
|
||||
import bpy
|
||||
|
||||
|
||||
def rna_idprop_ui_get(item, create=True):
|
||||
try:
|
||||
return item['_RNA_UI']
|
||||
@ -138,6 +139,7 @@ rna_property = StringProperty(name="Property Name",
|
||||
rna_min = FloatProperty(name="Min", default=0.0, precision=3)
|
||||
rna_max = FloatProperty(name="Max", default=1.0, precision=3)
|
||||
|
||||
|
||||
class WM_OT_properties_edit(bpy.types.Operator):
|
||||
'''Internal use (edit a property path)'''
|
||||
bl_idname = "wm.properties_edit"
|
||||
@ -209,33 +211,15 @@ class WM_OT_properties_edit(bpy.types.Operator):
|
||||
self.properties.max = prop_ui.get("max", 1000000000)
|
||||
self.properties.description = prop_ui.get("description", "")
|
||||
|
||||
if 0:
|
||||
_message= "PyConsole, press Ctrl+D to unlock the BGE"
|
||||
import sys
|
||||
|
||||
# evaluate commands in current namespace
|
||||
frame= sys._getframe()
|
||||
namespace = frame.f_globals.copy()
|
||||
namespace.update(frame.f_locals)
|
||||
|
||||
import code
|
||||
|
||||
# Autocomp in python, not as comprehensive as IPython
|
||||
import rlcompleter
|
||||
|
||||
try: # ick, some pythons dont have this
|
||||
import readline
|
||||
readline.parse_and_bind("tab: complete")
|
||||
except:
|
||||
pass
|
||||
|
||||
code.interact(banner=_message, local=namespace)
|
||||
|
||||
wm = context.manager
|
||||
# This crashes, TODO - fix
|
||||
#return wm.invoke_props_popup(self, event)
|
||||
|
||||
wm.invoke_props_popup(self, event)
|
||||
return ('RUNNING_MODAL',)
|
||||
|
||||
|
||||
|
||||
class WM_OT_properties_add(bpy.types.Operator):
|
||||
'''Internal use (edit a property path)'''
|
||||
bl_idname = "wm.properties_add"
|
||||
@ -261,6 +245,7 @@ class WM_OT_properties_add(bpy.types.Operator):
|
||||
item[property] = 1.0
|
||||
return ('FINISHED',)
|
||||
|
||||
|
||||
class WM_OT_properties_remove(bpy.types.Operator):
|
||||
'''Internal use (edit a property path)'''
|
||||
bl_idname = "wm.properties_remove"
|
||||
@ -273,4 +258,3 @@ class WM_OT_properties_remove(bpy.types.Operator):
|
||||
item = eval("context.%s" % self.properties.path)
|
||||
del item[self.properties.property]
|
||||
return ('FINISHED',)
|
||||
|
||||
|
@ -22,11 +22,13 @@ import bpy
|
||||
|
||||
language_id = 'python'
|
||||
|
||||
|
||||
def add_scrollback(text, text_type):
|
||||
for l in text.split('\n'):
|
||||
bpy.ops.console.scrollback_append(text=l.replace('\t', ' '),
|
||||
type=text_type)
|
||||
|
||||
|
||||
def get_console(console_id):
|
||||
'''
|
||||
helper function for console operators
|
||||
@ -70,6 +72,7 @@ def get_console(console_id):
|
||||
PROMPT = '>>> '
|
||||
PROMPT_MULTI = '... '
|
||||
|
||||
|
||||
def execute(context):
|
||||
sc = context.space_data
|
||||
|
||||
|
@ -25,11 +25,13 @@ import bpy
|
||||
|
||||
language_id = 'shell'
|
||||
|
||||
|
||||
def add_scrollback(text, text_type):
|
||||
for l in text.split('\n'):
|
||||
bpy.ops.console.scrollback_append(text=l.replace('\t', ' '),
|
||||
type=text_type)
|
||||
|
||||
|
||||
def shell_run(text):
|
||||
import subprocess
|
||||
val, output = subprocess.getstatusoutput(text)
|
||||
@ -77,4 +79,3 @@ def banner(context):
|
||||
sc.prompt = os.getcwd() + PROMPT
|
||||
|
||||
return ('FINISHED',)
|
||||
|
||||
|
124
release/scripts/op/object.py
Normal file
124
release/scripts/op/object.py
Normal file
@ -0,0 +1,124 @@
|
||||
# ##### 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.
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
import bpy
|
||||
from bpy.props import *
|
||||
|
||||
|
||||
class SelectPattern(bpy.types.Operator):
|
||||
'''Select object matching a naming pattern.'''
|
||||
bl_idname = "object.select_pattern"
|
||||
bl_label = "Select Pattern"
|
||||
bl_register = True
|
||||
bl_undo = True
|
||||
|
||||
pattern = StringProperty(name="Pattern", description="Name filter using '*' and '?' wildcard chars", maxlen=32, default="*")
|
||||
case_sensitive = BoolProperty(name="Case Sensitive", description="Do a case sensitive compare", default=False)
|
||||
extend = BoolProperty(name="Extend", description="Extend the existing selection", default=True)
|
||||
|
||||
def execute(self, context):
|
||||
|
||||
import fnmatch
|
||||
|
||||
if self.properties.case_sensitive:
|
||||
pattern_match = fnmatch.fnmatchcase
|
||||
else:
|
||||
pattern_match = lambda a, b: fnmatch.fnmatchcase(a.upper(), b.upper())
|
||||
|
||||
obj = context.object
|
||||
if obj and obj.mode == 'POSE':
|
||||
items = obj.data.bones
|
||||
elif obj and obj.type == 'ARMATURE' and obj.mode == 'EDIT':
|
||||
items = obj.data.edit_bones
|
||||
else:
|
||||
items = context.visible_objects
|
||||
|
||||
# Can be pose bones or objects
|
||||
for item in items:
|
||||
if pattern_match(item.name, self.properties.pattern):
|
||||
item.selected = True
|
||||
elif not self.properties.extend:
|
||||
item.selected = False
|
||||
|
||||
return ('FINISHED',)
|
||||
|
||||
def invoke(self, context, event):
|
||||
wm = context.manager
|
||||
# return wm.invoke_props_popup(self, event)
|
||||
wm.invoke_props_popup(self, event)
|
||||
return ('RUNNING_MODAL',)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
props = self.properties
|
||||
|
||||
layout.prop(props, "pattern")
|
||||
row = layout.row()
|
||||
row.prop(props, "case_sensitive")
|
||||
row.prop(props, "extend")
|
||||
|
||||
|
||||
class SubsurfSet(bpy.types.Operator):
|
||||
'''Sets a Subdivision Surface Level (1-5)'''
|
||||
|
||||
bl_idname = "object.subsurf_set"
|
||||
bl_label = "Subsurf Set"
|
||||
bl_register = True
|
||||
bl_undo = True
|
||||
|
||||
level = IntProperty(name="Level",
|
||||
default=1, min=0, max=6)
|
||||
|
||||
def poll(self, context):
|
||||
ob = context.active_object
|
||||
return (ob and ob.type == 'MESH')
|
||||
|
||||
def execute(self, context):
|
||||
level = self.properties.level
|
||||
ob = context.active_object
|
||||
for mod in ob.modifiers:
|
||||
if mod.type == 'SUBSURF':
|
||||
if mod.levels != level:
|
||||
mod.levels = level
|
||||
return ('FINISHED',)
|
||||
|
||||
# adda new modifier
|
||||
mod = ob.modifiers.new("Subsurf", 'SUBSURF')
|
||||
mod.levels = level
|
||||
return ('FINISHED',)
|
||||
|
||||
|
||||
class Retopo(bpy.types.Operator):
|
||||
'''TODO - doc'''
|
||||
|
||||
bl_idname = "object.retopology"
|
||||
bl_label = "Retopology from Grease Pencil"
|
||||
bl_register = True
|
||||
bl_undo = True
|
||||
|
||||
def execute(self, context):
|
||||
import retopo
|
||||
retopo.main()
|
||||
return ('FINISHED',)
|
||||
|
||||
|
||||
bpy.ops.add(SelectPattern)
|
||||
bpy.ops.add(SubsurfSet)
|
||||
bpy.ops.add(Retopo)
|
@ -23,26 +23,12 @@ class AddPresetBase(bpy.types.Operator):
|
||||
'''Base preset class, only for subclassing
|
||||
subclasses must define
|
||||
- preset_values
|
||||
- preset_path '''
|
||||
- preset_subdir '''
|
||||
bl_idname = "render.preset_add"
|
||||
bl_label = "Add Render Preset"
|
||||
|
||||
name = bpy.props.StringProperty(name="Name", description="Name of the preset, used to make the path name", maxlen= 64, default= "")
|
||||
|
||||
'''
|
||||
preset_values = [
|
||||
"bpy.context.scene.render_data.resolution_x",
|
||||
"bpy.context.scene.render_data.resolution_y",
|
||||
"bpy.context.scene.render_data.pixel_aspect_x",
|
||||
"bpy.context.scene.render_data.pixel_aspect_y",
|
||||
"bpy.context.scene.render_data.fps",
|
||||
"bpy.context.scene.render_data.fps_base",
|
||||
"bpy.context.scene.render_data.resolution_percentage",
|
||||
]
|
||||
|
||||
preset_subdir = "render"
|
||||
'''
|
||||
|
||||
def _as_filename(self, name): # could reuse for other presets
|
||||
for char in " !@#$%^&*(){}:\";'[]<>,./?":
|
||||
name = name.replace('.', '_')
|
||||
@ -68,6 +54,9 @@ class AddPresetBase(bpy.types.Operator):
|
||||
|
||||
def invoke(self, context, event):
|
||||
wm = context.manager
|
||||
#crashes, TODO - fix
|
||||
#return wm.invoke_props_popup(self, event)
|
||||
|
||||
wm.invoke_props_popup(self, event)
|
||||
return ('RUNNING_MODAL',)
|
||||
|
||||
@ -136,4 +125,3 @@ bpy.ops.add(AddPresetRender)
|
||||
bpy.ops.add(AddPresetSSS)
|
||||
bpy.ops.add(AddPresetCloth)
|
||||
|
||||
|
||||
|
@ -33,6 +33,7 @@ class MESH_OT_delete_edgeloop(bpy.types.Operator):
|
||||
bpy.ops.tfm.edge_slide(value=1.0)
|
||||
bpy.ops.mesh.select_more()
|
||||
bpy.ops.mesh.remove_doubles()
|
||||
|
||||
return ('FINISHED',)
|
||||
|
||||
rna_path_prop = StringProperty(name="Context Attributes",
|
||||
@ -358,8 +359,7 @@ class WM_OT_doc_edit(bpy.types.Operator):
|
||||
|
||||
def invoke(self, context, event):
|
||||
wm = context.manager
|
||||
wm.invoke_props_popup(self, event)
|
||||
return ('RUNNING_MODAL',)
|
||||
return wm.invoke_props_popup(self, event)
|
||||
|
||||
|
||||
class WM_OT_reload_scripts(bpy.types.Operator):
|
||||
|
@ -41,8 +41,7 @@ class ExportSomeData(bpy.types.Operator):
|
||||
return ('RUNNING_MODAL',)
|
||||
elif 0:
|
||||
# Redo popup
|
||||
wm.invoke_props_popup(self, event) #
|
||||
return ('RUNNING_MODAL',)
|
||||
return wm.invoke_props_popup(self, event) #
|
||||
elif 0:
|
||||
return self.execute(context)
|
||||
|
||||
|
@ -189,6 +189,9 @@ class BONE_PT_relations(BoneButtonsPanel):
|
||||
sub.prop(bone, "connected")
|
||||
sub.prop(bone, "hinge", text="Inherit Rotation")
|
||||
sub.prop(bone, "inherit_scale", text="Inherit Scale")
|
||||
sub = col.column()
|
||||
sub.active = (not bone.parent or not bone.connected)
|
||||
sub.prop(bone, "local_location", text="Local Location")
|
||||
|
||||
|
||||
class BONE_PT_display(BoneButtonsPanel):
|
||||
|
@ -128,6 +128,13 @@ class DATA_PT_shape_curve(DataButtonsPanel):
|
||||
class DATA_PT_geometry_curve(DataButtonsPanel):
|
||||
bl_label = "Geometry"
|
||||
|
||||
def poll(self, context):
|
||||
obj = context.object
|
||||
if obj and obj.type == 'SURFACE':
|
||||
return False
|
||||
|
||||
return context.curve
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
|
@ -365,11 +365,11 @@ class DATA_PT_modifiers(DataButtonsPanel):
|
||||
def MESH_DEFORM(self, layout, ob, md, wide_ui):
|
||||
split = layout.split()
|
||||
col = split.column()
|
||||
col.label(text="Object:")
|
||||
col.prop(md, "object", text="")
|
||||
if md.object and md.object.type == 'ARMATURE':
|
||||
col.label(text="Bone:")
|
||||
col.prop_object(md, "subtarget", md.object.data, "bones", text="")
|
||||
sub = col.column()
|
||||
sub.label(text="Object:")
|
||||
sub.prop(md, "object", text="")
|
||||
sub.prop(md, "mode", text="")
|
||||
sub.active = not md.is_bound
|
||||
if wide_ui:
|
||||
col = split.column()
|
||||
col.label(text="Vertex Group:")
|
||||
@ -385,6 +385,8 @@ class DATA_PT_modifiers(DataButtonsPanel):
|
||||
layout.operator("object.meshdeform_bind", text="Unbind")
|
||||
else:
|
||||
layout.operator("object.meshdeform_bind", text="Bind")
|
||||
|
||||
if md.mode == 'VOLUME':
|
||||
split = layout.split()
|
||||
|
||||
col = split.column()
|
||||
@ -554,7 +556,7 @@ class DATA_PT_modifiers(DataButtonsPanel):
|
||||
col.label(text="Origin:")
|
||||
col.prop(md, "origin", text="")
|
||||
sub = col.column()
|
||||
sub.active = md.origin
|
||||
sub.active = (md.origin != "")
|
||||
sub.prop(md, "relative")
|
||||
|
||||
if wide_ui:
|
||||
|
@ -495,7 +495,7 @@ class MATERIAL_PT_sss(MaterialButtonsPanel):
|
||||
col.prop(sss, "ior")
|
||||
col.prop(sss, "scale")
|
||||
col.prop(sss, "color", text="")
|
||||
col.prop(sss, "radius", text="RGB Radius")
|
||||
col.prop(sss, "radius", text="RGB Radius", expand=True)
|
||||
|
||||
if wide_ui:
|
||||
col = split.column()
|
||||
|
@ -162,7 +162,7 @@ class OBJECT_PT_groups(ObjectButtonsPanel):
|
||||
|
||||
row = col.box().row()
|
||||
row.prop(group, "name", text="")
|
||||
row.operator("object.group_remove", text="", icon='VICON_X')
|
||||
row.operator("object.group_remove", text="", icon='ICON_X')
|
||||
|
||||
split = col.box().split()
|
||||
|
||||
|
@ -21,6 +21,7 @@ import bpy
|
||||
|
||||
narrowui = 180
|
||||
|
||||
|
||||
class ConstraintButtonsPanel(bpy.types.Panel):
|
||||
bl_space_type = 'PROPERTIES'
|
||||
bl_region_type = 'WINDOW'
|
||||
@ -77,7 +78,7 @@ class ConstraintButtonsPanel(bpy.types.Panel):
|
||||
else:
|
||||
layout.prop_object(con, "subtarget", con.target.data, "bones", text="")
|
||||
|
||||
if con.type == 'COPY_LOCATION':
|
||||
if con.type in ('COPY_LOCATION', 'STRETCH_TO', 'TRACK_TO'):
|
||||
row = layout.row()
|
||||
row.label(text="Head/Tail:")
|
||||
row.prop(con, "head_tail", text="")
|
||||
@ -112,21 +113,21 @@ class ConstraintButtonsPanel(bpy.types.Panel):
|
||||
|
||||
col = split.column()
|
||||
col.label(text="Location:")
|
||||
col.prop(con, "locationx", text="X")
|
||||
col.prop(con, "locationy", text="Y")
|
||||
col.prop(con, "locationz", text="Z")
|
||||
col.prop(con, "use_location_x", text="X")
|
||||
col.prop(con, "use_location_y", text="Y")
|
||||
col.prop(con, "use_location_z", text="Z")
|
||||
|
||||
col = split.column()
|
||||
col.label(text="Rotation:")
|
||||
col.prop(con, "rotationx", text="X")
|
||||
col.prop(con, "rotationy", text="Y")
|
||||
col.prop(con, "rotationz", text="Z")
|
||||
col.prop(con, "use_rotation_x", text="X")
|
||||
col.prop(con, "use_rotation_y", text="Y")
|
||||
col.prop(con, "use_rotation_z", text="Z")
|
||||
|
||||
col = split.column()
|
||||
col.label(text="Scale:")
|
||||
col.prop(con, "sizex", text="X")
|
||||
col.prop(con, "sizey", text="Y")
|
||||
col.prop(con, "sizez", text="Z")
|
||||
col.prop(con, "use_scale_x", text="X")
|
||||
col.prop(con, "use_scale_y", text="Y")
|
||||
col.prop(con, "use_scale_z", text="Z")
|
||||
|
||||
split = layout.split()
|
||||
|
||||
@ -187,16 +188,16 @@ class ConstraintButtonsPanel(bpy.types.Panel):
|
||||
col.label(text="Weight:")
|
||||
col.prop(con, "weight", text="Position", slider=True)
|
||||
sub = col.column()
|
||||
sub.active = con.rotation
|
||||
sub.active = con.use_rotation
|
||||
sub.prop(con, "orient_weight", text="Rotation", slider=True)
|
||||
|
||||
if wide_ui:
|
||||
col = split.column()
|
||||
col.prop(con, "tail")
|
||||
col.prop(con, "stretch")
|
||||
col.prop(con, "use_tail")
|
||||
col.prop(con, "use_stretch")
|
||||
col.separator()
|
||||
col.prop(con, "targetless")
|
||||
col.prop(con, "rotation")
|
||||
col.prop(con, "use_target")
|
||||
col.prop(con, "use_rotation")
|
||||
|
||||
def IK_COPY_POSE(self, context, layout, con, wide_ui):
|
||||
self.target_template(layout, con, wide_ui)
|
||||
@ -217,13 +218,13 @@ class ConstraintButtonsPanel(bpy.types.Panel):
|
||||
row.prop(con, "pos_lock_x", text="X")
|
||||
row.prop(con, "pos_lock_y", text="Y")
|
||||
row.prop(con, "pos_lock_z", text="Z")
|
||||
split.active = con.position
|
||||
split.active = con.use_position
|
||||
|
||||
split = layout.split(percentage=0.33)
|
||||
split.row().prop(con, "rotation")
|
||||
row = split.row()
|
||||
row.prop(con, "orient_weight", text="Weight", slider=True)
|
||||
row.active = con.rotation
|
||||
row.active = con.use_rotation
|
||||
split = layout.split(percentage=0.33)
|
||||
row = split.row()
|
||||
row.label(text="Lock:")
|
||||
@ -231,7 +232,7 @@ class ConstraintButtonsPanel(bpy.types.Panel):
|
||||
row.prop(con, "rot_lock_x", text="X")
|
||||
row.prop(con, "rot_lock_y", text="Y")
|
||||
row.prop(con, "rot_lock_z", text="Z")
|
||||
split.active = con.rotation
|
||||
split.active = con.use_rotation
|
||||
|
||||
def IK_DISTANCE(self, context, layout, con, wide_ui):
|
||||
self.target_template(layout, con, wide_ui)
|
||||
@ -402,24 +403,24 @@ class ConstraintButtonsPanel(bpy.types.Panel):
|
||||
split = layout.split()
|
||||
|
||||
col = split.column()
|
||||
col.prop(con, "rotate_like_x", text="X")
|
||||
col.prop(con, "use_x", text="X")
|
||||
sub = col.column()
|
||||
sub.active = con.rotate_like_x
|
||||
sub.active = con.use_x
|
||||
sub.prop(con, "invert_x", text="Invert")
|
||||
|
||||
col = split.column()
|
||||
col.prop(con, "rotate_like_y", text="Y")
|
||||
col.prop(con, "use_y", text="Y")
|
||||
sub = col.column()
|
||||
sub.active = con.rotate_like_y
|
||||
sub.active = con.use_y
|
||||
sub.prop(con, "invert_y", text="Invert")
|
||||
|
||||
col = split.column()
|
||||
col.prop(con, "rotate_like_z", text="Z")
|
||||
col.prop(con, "use_z", text="Z")
|
||||
sub = col.column()
|
||||
sub.active = con.rotate_like_z
|
||||
sub.active = con.use_z
|
||||
sub.prop(con, "invert_z", text="Invert")
|
||||
|
||||
layout.prop(con, "offset")
|
||||
layout.prop(con, "use_offset")
|
||||
|
||||
self.space_template(layout, con, wide_ui)
|
||||
|
||||
@ -429,24 +430,24 @@ class ConstraintButtonsPanel(bpy.types.Panel):
|
||||
split = layout.split()
|
||||
|
||||
col = split.column()
|
||||
col.prop(con, "locate_like_x", text="X")
|
||||
col.prop(con, "use_x", text="X")
|
||||
sub = col.column()
|
||||
sub.active = con.locate_like_x
|
||||
sub.active = con.use_x
|
||||
sub.prop(con, "invert_x", text="Invert")
|
||||
|
||||
col = split.column()
|
||||
col.prop(con, "locate_like_y", text="Y")
|
||||
col.prop(con, "use_y", text="Y")
|
||||
sub = col.column()
|
||||
sub.active = con.locate_like_y
|
||||
sub.active = con.use_y
|
||||
sub.prop(con, "invert_y", text="Invert")
|
||||
|
||||
col = split.column()
|
||||
col.prop(con, "locate_like_z", text="Z")
|
||||
col.prop(con, "use_z", text="Z")
|
||||
sub = col.column()
|
||||
sub.active = con.locate_like_z
|
||||
sub.active = con.use_z
|
||||
sub.prop(con, "invert_z", text="Invert")
|
||||
|
||||
layout.prop(con, "offset")
|
||||
layout.prop(con, "use_offset")
|
||||
|
||||
self.space_template(layout, con, wide_ui)
|
||||
|
||||
@ -454,11 +455,11 @@ class ConstraintButtonsPanel(bpy.types.Panel):
|
||||
self.target_template(layout, con, wide_ui)
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.prop(con, "size_like_x", text="X")
|
||||
row.prop(con, "size_like_y", text="Y")
|
||||
row.prop(con, "size_like_z", text="Z")
|
||||
row.prop(con, "use_x", text="X")
|
||||
row.prop(con, "use_y", text="Y")
|
||||
row.prop(con, "use_z", text="Z")
|
||||
|
||||
layout.prop(con, "offset")
|
||||
layout.prop(con, "use_offset")
|
||||
|
||||
self.space_template(layout, con, wide_ui)
|
||||
|
||||
@ -683,9 +684,9 @@ class ConstraintButtonsPanel(bpy.types.Panel):
|
||||
|
||||
if con.shrinkwrap_type == 'PROJECT':
|
||||
row = layout.row(align=True)
|
||||
row.prop(con, "axis_x")
|
||||
row.prop(con, "axis_y")
|
||||
row.prop(con, "axis_z")
|
||||
row.prop(con, "use_x")
|
||||
row.prop(con, "use_y")
|
||||
row.prop(con, "use_z")
|
||||
|
||||
def DAMPED_TRACK(self, context, layout, con, wide_ui):
|
||||
self.target_template(layout, con, wide_ui)
|
||||
|
@ -208,6 +208,10 @@ class PARTICLE_PT_hair_dynamics(ParticleButtonsPanel):
|
||||
layout = self.layout
|
||||
|
||||
psys = context.particle_system
|
||||
|
||||
if not psys.cloth:
|
||||
return
|
||||
|
||||
#part = psys.settings
|
||||
cloth = psys.cloth.settings
|
||||
|
||||
@ -454,7 +458,7 @@ class PARTICLE_PT_physics(ParticleButtonsPanel):
|
||||
sub = col.row()
|
||||
subsub = sub.column(align=True)
|
||||
subsub.operator("particle.new_target", icon='ICON_ZOOMIN', text="")
|
||||
subsub.operator("particle.remove_target", icon='ICON_ZOOMOUT', text="")
|
||||
subsub.operator("particle.target_remove", icon='ICON_ZOOMOUT', text="")
|
||||
sub = col.row()
|
||||
subsub = sub.column(align=True)
|
||||
subsub.operator("particle.target_move_up", icon='VICON_MOVE_UP', text="")
|
||||
|
@ -83,10 +83,10 @@ class PHYSICS_PT_cloth(PhysicButtonsPanel):
|
||||
if md:
|
||||
cloth = md.settings
|
||||
|
||||
layout.active = cloth_panel_enabled(md)
|
||||
|
||||
split = layout.split()
|
||||
|
||||
split.active = cloth_panel_enabled(md)
|
||||
|
||||
col = split.column()
|
||||
|
||||
col.label(text="Presets:")
|
||||
|
@ -30,7 +30,7 @@ def point_cache_ui(self, context, cache, enabled, particles, smoke):
|
||||
row = layout.row()
|
||||
row.template_list(cache, "point_cache_list", cache, "active_point_cache_index", rows=2)
|
||||
col = row.column(align=True)
|
||||
col.operator("ptcache.add_new", icon='ICON_ZOOMIN', text="")
|
||||
col.operator("ptcache.add", icon='ICON_ZOOMIN', text="")
|
||||
col.operator("ptcache.remove", icon='ICON_ZOOMOUT', text="")
|
||||
|
||||
row = layout.row()
|
||||
|
@ -344,6 +344,10 @@ class RENDER_PT_output(RenderButtonsPanel):
|
||||
split = layout.split()
|
||||
split.prop(rd, "tiff_bit")
|
||||
|
||||
elif rd.file_format == 'QUICKTIME_CARBON':
|
||||
split = layout.split()
|
||||
split.operator("scene.render_data_set_quicktime_codec")
|
||||
|
||||
elif rd.file_format == 'QUICKTIME_QTKIT':
|
||||
split = layout.split()
|
||||
col = split.column()
|
||||
|
@ -219,10 +219,12 @@ class WORLD_PT_ambient_occlusion(WorldButtonsPanel):
|
||||
|
||||
col = split.column()
|
||||
col.prop(ao, "energy")
|
||||
col.prop(ao, "indirect_energy")
|
||||
|
||||
if wide_ui:
|
||||
col = split.column()
|
||||
col.prop(ao, "color")
|
||||
col.prop(ao, "indirect_bounces")
|
||||
|
||||
bpy.types.register(WORLD_PT_context_world)
|
||||
bpy.types.register(WORLD_PT_preview)
|
||||
|
@ -71,6 +71,11 @@ class CONSOLE_MT_console(bpy.types.Menu):
|
||||
layout.menu("CONSOLE_MT_language")
|
||||
layout.itemM("CONSOLE_MT_language")
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("screen.area_dupli")
|
||||
layout.operator("screen.screen_full_area")
|
||||
|
||||
|
||||
class CONSOLE_MT_report(bpy.types.Menu):
|
||||
bl_label = "Report"
|
||||
|
192
release/scripts/ui/space_graph.py
Normal file
192
release/scripts/ui/space_graph.py
Normal file
@ -0,0 +1,192 @@
|
||||
# ##### 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.
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
# <pep8 compliant>
|
||||
import bpy
|
||||
|
||||
|
||||
class GRAPH_HT_header(bpy.types.Header):
|
||||
bl_space_type = 'GRAPH_EDITOR'
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
st = context.space_data
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.template_header()
|
||||
|
||||
if context.area.show_menus:
|
||||
sub = row.row(align=True)
|
||||
|
||||
sub.menu("GRAPH_MT_view")
|
||||
sub.menu("GRAPH_MT_select")
|
||||
sub.menu("GRAPH_MT_channel")
|
||||
sub.menu("GRAPH_MT_key")
|
||||
|
||||
layout.prop(st, "mode", text="")
|
||||
|
||||
layout.template_dopesheet_filter(st.dopesheet)
|
||||
|
||||
layout.prop(st, "autosnap", text="")
|
||||
layout.prop(st, "pivot_point", text="", icon_only=True)
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.operator("graph.copy", text="", icon='ICON_COPYDOWN')
|
||||
row.operator("graph.paste", text="", icon='ICON_PASTEDOWN')
|
||||
|
||||
row = layout.row(align=True)
|
||||
# these likely need new icons
|
||||
row.operator("graph.ghost_curves_create", text="", icon='ICON_GHOST_ENABLED')
|
||||
row.operator("graph.ghost_curves_clear", text="", icon='ICON_GHOST_DISABLED')
|
||||
|
||||
|
||||
class GRAPH_MT_view(bpy.types.Menu):
|
||||
bl_label = "View"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
st = context.space_data
|
||||
|
||||
layout.column()
|
||||
|
||||
layout.separator()
|
||||
layout.operator("graph.properties")
|
||||
|
||||
layout.prop(st, "show_cframe_indicator")
|
||||
layout.prop(st, "show_cursor")
|
||||
layout.prop(st, "show_sliders")
|
||||
layout.prop(st, "automerge_keyframes")
|
||||
|
||||
layout.separator()
|
||||
layout.operator("graph.handles_view_toggle")
|
||||
layout.prop(st, "only_selected_curves_handles")
|
||||
layout.prop(st, "only_selected_keyframe_handles")
|
||||
layout.operator("anim.time_toggle")
|
||||
|
||||
layout.separator()
|
||||
layout.operator("anim.previewrange_set")
|
||||
layout.operator("anim.previewrange_clear")
|
||||
layout.operator("graph.previewrange_set")
|
||||
|
||||
layout.separator()
|
||||
layout.operator("graph.frame_jump")
|
||||
layout.operator("graph.view_all")
|
||||
|
||||
layout.separator()
|
||||
layout.operator("screen.area_dupli")
|
||||
layout.operator("screen.screen_full_area")
|
||||
|
||||
|
||||
class GRAPH_MT_select(bpy.types.Menu):
|
||||
bl_label = "Select"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
layout.column()
|
||||
# This is a bit misleading as the operator's default text is "Select All" while it actually *toggles* All/None
|
||||
layout.operator("graph.select_all_toggle")
|
||||
layout.operator("graph.select_all_toggle", text="Invert Selection").invert = True
|
||||
|
||||
layout.separator()
|
||||
layout.operator("graph.select_border")
|
||||
layout.operator("graph.select_border", text="Border Axis Range").axis_range = True
|
||||
|
||||
layout.separator()
|
||||
layout.operator("graph.select_column", text="Columns on Selected Keys").mode = 'KEYS'
|
||||
layout.operator("graph.select_column", text="Column on Current Frame").mode = 'CFRA'
|
||||
|
||||
layout.operator("graph.select_column", text="Columns on Selected Markers").mode = 'MARKERS_COLUMN'
|
||||
layout.operator("graph.select_column", text="Between Selected Markers").mode = 'MARKERS_BETWEEN'
|
||||
|
||||
|
||||
class GRAPH_MT_channel(bpy.types.Menu):
|
||||
bl_label = "Channel"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
layout.column()
|
||||
layout.operator("anim.channels_setting_toggle")
|
||||
layout.operator("anim.channels_setting_enable")
|
||||
layout.operator("anim.channels_setting_disable")
|
||||
|
||||
layout.separator()
|
||||
layout.operator("anim.channels_editable_toggle")
|
||||
|
||||
layout.separator()
|
||||
layout.operator("anim.channels_expand")
|
||||
layout.operator("anim.channels_collapse")
|
||||
|
||||
|
||||
class GRAPH_MT_key(bpy.types.Menu):
|
||||
bl_label = "Key"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
layout.column()
|
||||
layout.menu("GRAPH_MT_key_transform", text="Transform")
|
||||
|
||||
layout.operator_menu_enum("graph.snap", property="type", text="Snap")
|
||||
layout.operator_menu_enum("graph.mirror", property="type", text="Mirror")
|
||||
|
||||
layout.separator()
|
||||
layout.operator("graph.keyframe_insert")
|
||||
layout.operator("graph.fmodifier_add")
|
||||
|
||||
layout.separator()
|
||||
layout.operator("graph.duplicate")
|
||||
layout.operator("graph.delete")
|
||||
|
||||
layout.separator()
|
||||
layout.operator_menu_enum("graph.handle_type", property="type", text="Handle Type")
|
||||
layout.operator_menu_enum("graph.interpolation_type", property="type", text="Interpolation Mode")
|
||||
layout.operator_menu_enum("graph.extrapolation_type", property="type", text="Extrapolation Mode")
|
||||
|
||||
layout.separator()
|
||||
layout.operator("graph.clean")
|
||||
layout.operator("graph.sample")
|
||||
layout.operator("graph.bake")
|
||||
|
||||
layout.separator()
|
||||
layout.operator("graph.copy")
|
||||
layout.operator("graph.paste")
|
||||
|
||||
|
||||
class GRAPH_MT_key_transform(bpy.types.Menu):
|
||||
bl_label = "Transform"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
layout.column()
|
||||
layout.operator("tfm.translate", text="Grab/Move")
|
||||
layout.operator("tfm.transform", text="Extend").mode = 'TIME_EXTEND'
|
||||
layout.operator("tfm.rotate", text="Rotate")
|
||||
layout.operator("tfm.resize", text="Scale")
|
||||
|
||||
|
||||
bpy.types.register(GRAPH_HT_header) # header/menu classes
|
||||
bpy.types.register(GRAPH_MT_view)
|
||||
bpy.types.register(GRAPH_MT_select)
|
||||
bpy.types.register(GRAPH_MT_channel)
|
||||
bpy.types.register(GRAPH_MT_key)
|
||||
bpy.types.register(GRAPH_MT_key_transform)
|
@ -61,6 +61,10 @@ class IMAGE_MT_view(bpy.types.Menu):
|
||||
layout.operator("image.view_selected")
|
||||
|
||||
layout.operator("image.view_all")
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("screen.area_dupli")
|
||||
layout.operator("screen.screen_full_area")
|
||||
|
||||
|
||||
@ -75,7 +79,7 @@ class IMAGE_MT_select(bpy.types.Menu):
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("uv.select_all_toggle")
|
||||
layout.operator("uv.select_all")
|
||||
layout.operator("uv.select_inverse")
|
||||
layout.operator("uv.unlink_selection")
|
||||
|
||||
@ -151,6 +155,23 @@ class IMAGE_MT_uvs_transform(bpy.types.Menu):
|
||||
layout.operator("tfm.resize")
|
||||
|
||||
|
||||
class IMAGE_MT_uvs_snap(bpy.types.Menu):
|
||||
bl_label = "Snap"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.operator_context = 'EXEC_REGION_WIN'
|
||||
|
||||
layout.operator("uv.snap_selection", text="Selected to Pixels").target = 'PIXELS'
|
||||
layout.operator("uv.snap_selection", text="Selected to Cursor").target = 'CURSOR'
|
||||
layout.operator("uv.snap_selection", text="Selected to Adjacent Unselected").target = 'ADJACENT_UNSELECTED'
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("uv.snap_cursor", text="Cursor to Pixels").target = 'PIXELS'
|
||||
layout.operator("uv.snap_cursor", text="Cursor to Selection").target = 'SELECTION'
|
||||
|
||||
|
||||
class IMAGE_MT_uvs_mirror(bpy.types.Menu):
|
||||
bl_label = "Mirror"
|
||||
|
||||
@ -203,6 +224,7 @@ class IMAGE_MT_uvs(bpy.types.Menu):
|
||||
|
||||
layout.menu("IMAGE_MT_uvs_transform")
|
||||
layout.menu("IMAGE_MT_uvs_mirror")
|
||||
layout.menu("IMAGE_MT_uvs_snap")
|
||||
layout.menu("IMAGE_MT_uvs_weldalign")
|
||||
|
||||
layout.separator()
|
||||
@ -520,6 +542,7 @@ bpy.types.register(IMAGE_MT_select)
|
||||
bpy.types.register(IMAGE_MT_image)
|
||||
bpy.types.register(IMAGE_MT_uvs_showhide)
|
||||
bpy.types.register(IMAGE_MT_uvs_transform)
|
||||
bpy.types.register(IMAGE_MT_uvs_snap)
|
||||
bpy.types.register(IMAGE_MT_uvs_mirror)
|
||||
bpy.types.register(IMAGE_MT_uvs_weldalign)
|
||||
bpy.types.register(IMAGE_MT_uvs)
|
||||
|
@ -83,12 +83,18 @@ class INFO_MT_file(bpy.types.Menu):
|
||||
layout.operator("wm.save_mainfile", text="Save", icon='ICON_FILE_TICK')
|
||||
layout.operator_context = 'INVOKE_AREA'
|
||||
layout.operator("wm.save_as_mainfile", text="Save As...")
|
||||
layout.operator("screen.userpref_show", text="User Preferences...", icon='ICON_PREFERENCES')
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("screen.userpref_show", text="User Preferences...", icon='ICON_PREFERENCES')
|
||||
layout.operator("wm.read_homefile", text="Load Factory Settings").factory = True
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator_context = 'INVOKE_AREA'
|
||||
layout.operator("wm.link_append", text="Link")
|
||||
layout.operator("wm.link_append", text="Append").link = False
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.menu("INFO_MT_file_import")
|
||||
@ -189,7 +195,7 @@ class INFO_MT_add(bpy.types.Menu):
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator_context = 'INVOKE_SCREEN'
|
||||
layout.operator_context = 'INVOKE_REGION_WIN'
|
||||
|
||||
layout.operator("object.armature_add", text="Armature", icon='ICON_OUTLINER_OB_ARMATURE')
|
||||
layout.operator("object.add", text="Lattice", icon='ICON_OUTLINER_OB_LATTICE').type = 'LATTICE'
|
||||
|
@ -82,6 +82,10 @@ class NODE_MT_view(bpy.types.Menu):
|
||||
layout.separator()
|
||||
|
||||
layout.operator("node.view_all")
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("screen.area_dupli")
|
||||
layout.operator("screen.screen_full_area")
|
||||
|
||||
|
||||
|
@ -53,8 +53,8 @@ class OUTLINER_HT_header(bpy.types.Header):
|
||||
row.prop_object(scene, "active_keying_set", scene, "keying_sets", text="")
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.operator("anim.insert_keyframe", text="", icon='ICON_KEY_HLT')
|
||||
row.operator("anim.delete_keyframe", text="", icon='ICON_KEY_DEHLT')
|
||||
row.operator("anim.keyframe_insert", text="", icon='ICON_KEY_HLT')
|
||||
row.operator("anim.keyframe_delete", text="", icon='ICON_KEY_DEHLT')
|
||||
else:
|
||||
row = layout.row(align=False)
|
||||
row.label(text="No Keying Set active")
|
||||
@ -77,6 +77,11 @@ class OUTLINER_MT_view(bpy.types.Menu):
|
||||
col.operator("outliner.show_one_level")
|
||||
col.operator("outliner.show_hierarchy")
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("screen.area_dupli")
|
||||
layout.operator("screen.screen_full_area")
|
||||
|
||||
|
||||
class OUTLINER_MT_edit_datablocks(bpy.types.Menu):
|
||||
bl_label = "Edit"
|
||||
|
@ -100,19 +100,6 @@ class SEQUENCER_MT_view(bpy.types.Menu):
|
||||
layout.separator()
|
||||
layout.operator("sequencer.view_all")
|
||||
layout.operator("sequencer.view_selected")
|
||||
layout.separator()
|
||||
layout.operator("screen.screen_full_area", text="Toggle Full Screen")
|
||||
"""
|
||||
|
||||
|
||||
/* Lock Time */
|
||||
uiDefIconTextBut(block, BUTM, 1, (v2d->flag & V2D_VIEWSYNC_SCREEN_TIME)?ICON_CHECKBOX_HLT:ICON_CHECKBOX_DEHLT,
|
||||
"Lock Time to Other Windows|", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
|
||||
|
||||
/* Draw time or frames.*/
|
||||
uiDefMenuSep(block);
|
||||
"""
|
||||
|
||||
layout.prop(st, "draw_frames")
|
||||
layout.prop(st, "show_cframe_indicator")
|
||||
@ -121,11 +108,10 @@ class SEQUENCER_MT_view(bpy.types.Menu):
|
||||
if st.display_mode == 'WAVEFORM':
|
||||
layout.prop(st, "separate_color_preview")
|
||||
|
||||
"""
|
||||
if(!sa->full) uiDefIconTextBut(block, BUTM, B_FULL, ICON_BLANK1, "Maximize Window|Ctrl UpArrow", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0,0, "");
|
||||
else uiDefIconTextBut(block, BUTM, B_FULL, ICON_BLANK1, "Tile Window|Ctrl DownArrow", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, "");
|
||||
layout.separator()
|
||||
|
||||
"""
|
||||
layout.operator("screen.area_dupli")
|
||||
layout.operator("screen.screen_full_area")
|
||||
|
||||
|
||||
class SEQUENCER_MT_select(bpy.types.Menu):
|
||||
@ -351,7 +337,10 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel):
|
||||
if not strip:
|
||||
return False
|
||||
|
||||
return strip.type in ('COLOR', 'WIPE', 'GLOW', 'SPEED', 'TRANSFORM')
|
||||
return strip.type in ('ADD', 'SUBTRACT', 'ALPHA_OVER', 'ALPHA_UNDER',
|
||||
'GAMMA_CROSS', 'MULTIPLY', 'OVER_DROP',
|
||||
'PLUGIN',
|
||||
'WIPE', 'GLOW', 'TRANSFORM', 'COLOR', 'SPEED')
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
@ -431,6 +420,8 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel):
|
||||
if strip.type == 'SPEED':
|
||||
col.prop(strip, "speed_fader", text="Speed fader")
|
||||
else:
|
||||
col.prop(strip, "use_effect_default_fade", "Default fade")
|
||||
if not strip.use_effect_default_fade:
|
||||
col.prop(strip, "effect_fader", text="Effect fader")
|
||||
|
||||
|
||||
|
@ -160,6 +160,11 @@ class TEXT_MT_text(bpy.types.Menu):
|
||||
|
||||
layout.menu("TEXT_MT_templates")
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("screen.area_dupli")
|
||||
layout.operator("screen.screen_full_area")
|
||||
|
||||
|
||||
class TEXT_MT_templates(bpy.types.Menu):
|
||||
'''
|
||||
@ -168,7 +173,6 @@ class TEXT_MT_templates(bpy.types.Menu):
|
||||
bl_label = "Script Templates"
|
||||
|
||||
def draw(self, context):
|
||||
import os
|
||||
self.path_menu(bpy.utils.script_paths("templates"), "text.open")
|
||||
|
||||
|
||||
|
@ -72,14 +72,14 @@ class TIME_HT_header(bpy.types.Header):
|
||||
subsub = row.row()
|
||||
subsub.prop(tools, "record_with_nla", toggle=True)
|
||||
|
||||
layout.prop(scene, "sync_audio", text="", toggle=True, icon='ICON_SPEAKER')
|
||||
layout.prop(scene, "sync_audio", text="Realtime", toggle=True, icon='ICON_SPEAKER')
|
||||
|
||||
layout.separator()
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.prop_object(scene, "active_keying_set", scene, "keying_sets", text="")
|
||||
row.operator("anim.insert_keyframe", text="", icon='ICON_KEY_HLT')
|
||||
row.operator("anim.delete_keyframe", text="", icon='ICON_KEY_DEHLT')
|
||||
row.operator("anim.keyframe_insert", text="", icon='ICON_KEY_HLT')
|
||||
row.operator("anim.keyframe_delete", text="", icon='ICON_KEY_DEHLT')
|
||||
|
||||
|
||||
class TIME_MT_view(bpy.types.Menu):
|
||||
@ -91,6 +91,7 @@ class TIME_MT_view(bpy.types.Menu):
|
||||
st = context.space_data
|
||||
|
||||
layout.operator("anim.time_toggle")
|
||||
layout.operator("time.view_all")
|
||||
|
||||
layout.separator()
|
||||
|
||||
@ -145,7 +146,7 @@ class TIME_MT_playback(bpy.types.Menu):
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.prop(scene, "sync_audio", icon='ICON_SPEAKER')
|
||||
layout.prop(scene, "sync_audio", text="Realtime Playback", icon='ICON_SPEAKER')
|
||||
layout.prop(scene, "mute_audio")
|
||||
layout.prop(scene, "scrub_audio")
|
||||
|
||||
|
@ -88,7 +88,7 @@ class USERPREF_PT_interface(bpy.types.Panel):
|
||||
sub1.prop(view, "show_playback_fps", text="Playback FPS")
|
||||
sub1.prop(view, "global_scene")
|
||||
sub1.prop(view, "pin_floating_panels")
|
||||
sub1.prop(view, "object_center_size")
|
||||
sub1.prop(view, "object_origin_size")
|
||||
sub1.separator()
|
||||
sub1.separator()
|
||||
sub1.separator()
|
||||
@ -244,7 +244,7 @@ class USERPREF_PT_edit(bpy.types.Panel):
|
||||
sub1.prop(edit, "duplicate_lamp", text="Lamp")
|
||||
sub1.prop(edit, "duplicate_material", text="Material")
|
||||
sub1.prop(edit, "duplicate_texture", text="Texture")
|
||||
sub1.prop(edit, "duplicate_ipo", text="F-Curve")
|
||||
sub1.prop(edit, "duplicate_fcurve", text="F-Curve")
|
||||
sub1.prop(edit, "duplicate_action", text="Action")
|
||||
sub1.prop(edit, "duplicate_particle", text="Particle")
|
||||
|
||||
@ -264,6 +264,9 @@ class USERPREF_PT_system(bpy.types.Panel):
|
||||
|
||||
userpref = context.user_preferences
|
||||
system = userpref.system
|
||||
lamp0 = system.solid_lights[0]
|
||||
lamp1 = system.solid_lights[1]
|
||||
lamp2 = system.solid_lights[2]
|
||||
|
||||
split = layout.split()
|
||||
|
||||
@ -321,6 +324,34 @@ class USERPREF_PT_system(bpy.types.Panel):
|
||||
|
||||
sub1 = sub.column()
|
||||
|
||||
sub1.label(text="Solid OpenGL lights:")
|
||||
|
||||
sub2 = sub1.split()
|
||||
|
||||
col = sub2.column()
|
||||
col.prop(lamp0, "enabled")
|
||||
sub = col.column()
|
||||
sub.active = lamp0.enabled
|
||||
sub.prop(lamp0, "diffuse_color")
|
||||
sub.prop(lamp0, "specular_color")
|
||||
sub.prop(lamp0, "direction")
|
||||
|
||||
col = sub2.column()
|
||||
col.prop(lamp1, "enabled")
|
||||
sub = col.column()
|
||||
sub.active = lamp1.enabled
|
||||
sub.prop(lamp1, "diffuse_color")
|
||||
sub.prop(lamp1, "specular_color")
|
||||
sub.prop(lamp1, "direction")
|
||||
|
||||
col = sub2.column()
|
||||
col.prop(lamp2, "enabled")
|
||||
sub = col.column()
|
||||
sub.active = lamp2.enabled
|
||||
sub.prop(lamp2, "diffuse_color")
|
||||
sub.prop(lamp2, "specular_color")
|
||||
sub.prop(lamp2, "direction")
|
||||
|
||||
sub1.label(text="OpenGL:")
|
||||
sub1.prop(system, "clip_alpha", slider=True)
|
||||
sub1.prop(system, "use_mipmaps")
|
||||
@ -1136,6 +1167,9 @@ class USERPREF_PT_input(bpy.types.Panel):
|
||||
|
||||
sub.label(text="Zoom Style:")
|
||||
sub.row().prop(inputs, "viewport_zoom_style", expand=True)
|
||||
if inputs.viewport_zoom_style == 'DOLLY':
|
||||
sub.row().prop(inputs, "zoom_axis", expand=True)
|
||||
sub.prop(inputs, "invert_zoom_direction")
|
||||
|
||||
#sub.prop(inputs, "use_middle_mouse_paste")
|
||||
|
||||
@ -1143,7 +1177,6 @@ class USERPREF_PT_input(bpy.types.Panel):
|
||||
|
||||
#sub = col.column()
|
||||
#sub.label(text="Mouse Wheel:")
|
||||
#sub.prop(view, "wheel_invert_zoom", text="Invert Zoom")
|
||||
#sub.prop(view, "wheel_scroll_lines", text="Scroll Lines")
|
||||
|
||||
col.separator()
|
||||
@ -1382,9 +1415,9 @@ class WM_OT_keymap_edit(bpy.types.Operator):
|
||||
|
||||
|
||||
class WM_OT_keymap_restore(bpy.types.Operator):
|
||||
"Restore key map"
|
||||
"Restore key map(s)."
|
||||
bl_idname = "wm.keymap_restore"
|
||||
bl_label = "Restore Key Map"
|
||||
bl_label = "Restore Key Map(s)"
|
||||
|
||||
all = BoolProperty(attr="all", name="All Keymaps", description="Restore all keymaps to default.")
|
||||
|
||||
|
@ -27,17 +27,19 @@ class VIEW3D_HT_header(bpy.types.Header):
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
# view = context.space_data
|
||||
view = context.space_data
|
||||
mode_string = context.mode
|
||||
edit_object = context.edit_object
|
||||
object = context.active_object
|
||||
obj = context.active_object
|
||||
toolsettings = context.scene.tool_settings
|
||||
|
||||
row = layout.row(align=True)
|
||||
row = layout.row()
|
||||
row.template_header()
|
||||
|
||||
sub = row.row(align=True)
|
||||
|
||||
# Menus
|
||||
if context.area.show_menus:
|
||||
sub = row.row(align=True)
|
||||
|
||||
sub.menu("VIEW3D_MT_view")
|
||||
|
||||
@ -47,13 +49,56 @@ class VIEW3D_HT_header(bpy.types.Header):
|
||||
|
||||
if edit_object:
|
||||
sub.menu("VIEW3D_MT_edit_%s" % edit_object.type.lower())
|
||||
elif object:
|
||||
if mode_string not in ['PAINT_WEIGHT', 'PAINT_TEXTURE']:
|
||||
elif obj:
|
||||
if mode_string not in ('PAINT_WEIGHT'):
|
||||
sub.menu("VIEW3D_MT_%s" % mode_string.lower())
|
||||
else:
|
||||
sub.menu("VIEW3D_MT_object")
|
||||
|
||||
layout.template_header_3D()
|
||||
row.template_header_3D()
|
||||
|
||||
# Particle edit
|
||||
if obj and obj.mode == 'PARTICLE_EDIT':
|
||||
row.prop(toolsettings.particle_edit, "selection_mode", text="", expand=True, toggle=True)
|
||||
|
||||
# Occlude geometry
|
||||
if obj and view.viewport_shading in ('SOLID', 'SHADED', 'TEXTURED') and (obj.mode == 'PARTICLE_EDIT' or (obj.mode == 'EDIT' and obj.type == 'MESH')):
|
||||
row.prop(view, "occlude_geometry", text="")
|
||||
|
||||
# Proportional editing
|
||||
if obj and obj.mode in ('OBJECT', 'EDIT'):
|
||||
row = layout.row(align=True)
|
||||
row.prop(toolsettings, "proportional_editing", text="", icon_only=True)
|
||||
if toolsettings.proportional_editing != 'DISABLED':
|
||||
row.prop(toolsettings, "proportional_editing_falloff", text="", icon_only=True)
|
||||
|
||||
# Snap
|
||||
row = layout.row(align=True)
|
||||
row.prop(toolsettings, "snap", text="")
|
||||
row.prop(toolsettings, "snap_element", text="", icon_only=True)
|
||||
if toolsettings.snap_element != 'INCREMENT':
|
||||
row.prop(toolsettings, "snap_target", text="")
|
||||
if obj and obj.mode == 'OBJECT':
|
||||
row.prop(toolsettings, "snap_align_rotation", text="")
|
||||
if toolsettings.snap_element == 'VOLUME':
|
||||
row.prop(toolsettings, "snap_peel_object", text="")
|
||||
elif toolsettings.snap_element == 'FACE':
|
||||
row.prop(toolsettings, "snap_project", text="")
|
||||
|
||||
# OpenGL render
|
||||
row = layout.row(align=True)
|
||||
row.operator("screen.opengl_render", text="", icon='ICON_RENDER_STILL')
|
||||
props = row.operator("screen.opengl_render", text="", icon='ICON_RENDER_ANIMATION')
|
||||
props.animation = True
|
||||
|
||||
# Pose
|
||||
if obj and obj.mode == 'POSE':
|
||||
row = layout.row(align=True)
|
||||
row.operator("pose.copy", text="", icon='ICON_COPYDOWN')
|
||||
row.operator("pose.paste", text="", icon='ICON_PASTEDOWN')
|
||||
props = row.operator("pose.paste", text="", icon='ICON_PASTEFLIPDOWN')
|
||||
props.flipped = 1
|
||||
|
||||
|
||||
# ********** Menu **********
|
||||
|
||||
@ -95,16 +140,17 @@ class VIEW3D_MT_transform(bpy.types.Menu):
|
||||
if context.edit_object and context.edit_object.type == 'ARMATURE':
|
||||
layout.operator("armature.align")
|
||||
else:
|
||||
layout.operator_context = 'EXEC_AREA'
|
||||
layout.operator_context = 'EXEC_REGION_WIN'
|
||||
layout.operator("tfm.transform", text="Align to Transform Orientation").mode = 'ALIGN' # XXX see alignmenu() in edit.c of b2.4x to get this working
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator_context = 'EXEC_AREA'
|
||||
|
||||
layout.operator("object.center_set").type = 'CENTER'
|
||||
layout.operator("object.center_set").type = 'CENTER_NEW'
|
||||
layout.operator("object.center_set").type = 'CENTER_CURSOR'
|
||||
layout.operator("object.origin_set", text="Geometry to Origin").type = 'GEOMETRY_ORIGIN'
|
||||
layout.operator("object.origin_set", text="Origin to Geometry").type = 'ORIGIN_GEOMETRY'
|
||||
layout.operator("object.origin_set", text="Origin to 3D Cursor").type = 'ORIGIN_CURSOR'
|
||||
|
||||
|
||||
class VIEW3D_MT_mirror(bpy.types.Menu):
|
||||
bl_label = "Mirror"
|
||||
@ -116,7 +162,7 @@ class VIEW3D_MT_mirror(bpy.types.Menu):
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator_context = 'EXEC_AREA'
|
||||
layout.operator_context = 'INVOKE_REGION_WIN'
|
||||
|
||||
props = layout.operator("tfm.mirror", text="X Global")
|
||||
props.constraint_axis = (True, False, False)
|
||||
@ -141,6 +187,7 @@ class VIEW3D_MT_mirror(bpy.types.Menu):
|
||||
props.constraint_axis = (False, False, True)
|
||||
props.constraint_orientation = 'LOCAL'
|
||||
|
||||
|
||||
class VIEW3D_MT_snap(bpy.types.Menu):
|
||||
bl_label = "Snap"
|
||||
|
||||
@ -149,7 +196,7 @@ class VIEW3D_MT_snap(bpy.types.Menu):
|
||||
|
||||
layout.operator("view3d.snap_selected_to_grid", text="Selection to Grid")
|
||||
layout.operator("view3d.snap_selected_to_cursor", text="Selection to Cursor")
|
||||
layout.operator("view3d.snap_selected_to_center", text="Selection to Center")
|
||||
layout.operator("view3d.snap_selected_to_center", text="Selection to Origin")
|
||||
|
||||
layout.separator()
|
||||
|
||||
@ -188,10 +235,10 @@ class VIEW3D_MT_view(bpy.types.Menu):
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("view3d.viewnumpad").type = 'CAMERA'
|
||||
layout.operator("view3d.viewnumpad").type = 'TOP'
|
||||
layout.operator("view3d.viewnumpad").type = 'FRONT'
|
||||
layout.operator("view3d.viewnumpad").type = 'RIGHT'
|
||||
layout.operator("view3d.viewnumpad", text="Camera").type = 'CAMERA'
|
||||
layout.operator("view3d.viewnumpad", text="Top").type = 'TOP'
|
||||
layout.operator("view3d.viewnumpad", text="Front").type = 'FRONT'
|
||||
layout.operator("view3d.viewnumpad", text="Right").type = 'RIGHT'
|
||||
|
||||
layout.menu("VIEW3D_MT_view_cameras", text="Cameras")
|
||||
|
||||
@ -223,12 +270,13 @@ class VIEW3D_MT_view(bpy.types.Menu):
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("screen.region_foursplit", text="Toggle Quad View")
|
||||
layout.operator("screen.screen_full_area", text="Toggle Full Screen")
|
||||
layout.operator("screen.animation_play", text="Playback Animation")
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("screen.animation_play", text="Playback Animation", icon='ICON_PLAY')
|
||||
layout.operator("screen.area_dupli")
|
||||
layout.operator("screen.region_quadview")
|
||||
layout.operator("screen.screen_full_area")
|
||||
|
||||
|
||||
class VIEW3D_MT_view_navigation(bpy.types.Menu):
|
||||
@ -318,7 +366,7 @@ class VIEW3D_MT_select_object(bpy.types.Menu):
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("object.select_all_toggle", text="Select/Deselect All")
|
||||
layout.operator("object.select_all", text="Select/Deselect All")
|
||||
layout.operator("object.select_inverse", text="Inverse")
|
||||
layout.operator("object.select_random", text="Random")
|
||||
layout.operator("object.select_mirror", text="Mirror")
|
||||
@ -342,15 +390,15 @@ class VIEW3D_MT_select_pose(bpy.types.Menu):
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("pose.select_all_toggle", text="Select/Deselect All")
|
||||
layout.operator("pose.select_all", text="Select/Deselect All")
|
||||
layout.operator("pose.select_inverse", text="Inverse")
|
||||
layout.operator("pose.select_constraint_target", text="Constraint Target")
|
||||
layout.operator("pose.select_linked", text="Linked")
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("pose.select_hierarchy").direction = 'PARENT'
|
||||
layout.operator("pose.select_hierarchy").direction = 'CHILD'
|
||||
layout.operator("pose.select_hierarchy", text="Parent").direction = 'PARENT'
|
||||
layout.operator("pose.select_hierarchy", text="Child").direction = 'CHILD'
|
||||
|
||||
layout.separator()
|
||||
|
||||
@ -362,6 +410,8 @@ class VIEW3D_MT_select_pose(bpy.types.Menu):
|
||||
props.extend = True
|
||||
props.direction = 'CHILD'
|
||||
|
||||
layout.operator("object.select_pattern", text="Select Pattern...")
|
||||
|
||||
|
||||
class VIEW3D_MT_select_particle(bpy.types.Menu):
|
||||
bl_label = "Select"
|
||||
@ -373,7 +423,7 @@ class VIEW3D_MT_select_particle(bpy.types.Menu):
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("particle.select_all_toggle", text="Select/Deselect All")
|
||||
layout.operator("particle.select_all", text="Select/Deselect All")
|
||||
layout.operator("particle.select_linked")
|
||||
layout.operator("particle.select_inverse")
|
||||
|
||||
@ -399,7 +449,7 @@ class VIEW3D_MT_select_edit_mesh(bpy.types.Menu):
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("mesh.select_all_toggle", text="Select/Deselect All")
|
||||
layout.operator("mesh.select_all", text="Select/Deselect All")
|
||||
layout.operator("mesh.select_inverse", text="Inverse")
|
||||
|
||||
layout.separator()
|
||||
@ -448,7 +498,7 @@ class VIEW3D_MT_select_edit_curve(bpy.types.Menu):
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("curve.select_all_toggle", text="Select/Deselect All")
|
||||
layout.operator("curve.select_all", text="Select/Deselect All")
|
||||
layout.operator("curve.select_inverse")
|
||||
layout.operator("curve.select_random")
|
||||
layout.operator("curve.select_every_nth")
|
||||
@ -477,7 +527,7 @@ class VIEW3D_MT_select_edit_surface(bpy.types.Menu):
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("curve.select_all_toggle", text="Select/Deselect All")
|
||||
layout.operator("curve.select_all", text="Select/Deselect All")
|
||||
layout.operator("curve.select_inverse")
|
||||
layout.operator("curve.select_random")
|
||||
layout.operator("curve.select_every_nth")
|
||||
@ -520,7 +570,7 @@ class VIEW3D_MT_select_edit_lattice(bpy.types.Menu):
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("lattice.select_all_toggle", text="Select/Deselect All")
|
||||
layout.operator("lattice.select_all", text="Select/Deselect All")
|
||||
|
||||
|
||||
class VIEW3D_MT_select_edit_armature(bpy.types.Menu):
|
||||
@ -534,7 +584,7 @@ class VIEW3D_MT_select_edit_armature(bpy.types.Menu):
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("armature.select_all_toggle", text="Select/Deselect All")
|
||||
layout.operator("armature.select_all", text="Select/Deselect All")
|
||||
layout.operator("armature.select_inverse", text="Inverse")
|
||||
|
||||
layout.separator()
|
||||
@ -552,6 +602,8 @@ class VIEW3D_MT_select_edit_armature(bpy.types.Menu):
|
||||
props.extend = True
|
||||
props.direction = 'CHILD'
|
||||
|
||||
layout.operator("object.select_pattern", text="Select Pattern...")
|
||||
|
||||
|
||||
class VIEW3D_MT_select_face(bpy.types.Menu):# XXX no matching enum
|
||||
bl_label = "Select"
|
||||
@ -580,8 +632,8 @@ class VIEW3D_MT_object(bpy.types.Menu):
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("anim.insert_keyframe_menu", text="Insert Keyframe...")
|
||||
layout.operator("anim.delete_keyframe_v3d", text="Delete Keyframe...")
|
||||
layout.operator("anim.keyframe_insert_menu", text="Insert Keyframe...")
|
||||
layout.operator("anim.keyframe_delete_v3d", text="Delete Keyframe...")
|
||||
|
||||
layout.separator()
|
||||
|
||||
@ -592,7 +644,6 @@ class VIEW3D_MT_object(bpy.types.Menu):
|
||||
layout.menu("VIEW3D_MT_make_links", text="Make Links...")
|
||||
layout.operator_menu_enum("object.make_local", "type", text="Make Local...")
|
||||
layout.menu("VIEW3D_MT_make_single_user")
|
||||
layout.menu("VIEW3D_MT_make_links")
|
||||
|
||||
layout.separator()
|
||||
|
||||
@ -603,6 +654,7 @@ class VIEW3D_MT_object(bpy.types.Menu):
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("object.join_shapes")
|
||||
layout.operator("object.join")
|
||||
|
||||
layout.separator()
|
||||
@ -872,8 +924,8 @@ class VIEW3D_MT_pose(bpy.types.Menu):
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("anim.insert_keyframe_menu", text="Insert Keyframe...")
|
||||
layout.operator("anim.delete_keyframe_v3d", text="Delete Keyframe...")
|
||||
layout.operator("anim.keyframe_insert_menu", text="Insert Keyframe...")
|
||||
layout.operator("anim.keyframe_delete_v3d", text="Delete Keyframe...")
|
||||
|
||||
layout.separator()
|
||||
|
||||
@ -1516,18 +1568,16 @@ class VIEW3D_PT_3dview_properties(bpy.types.Panel):
|
||||
col.label(text="Camera:")
|
||||
col.prop(view, "camera", text="")
|
||||
col.prop(view, "lens")
|
||||
col.label(text="Lock to Object:")
|
||||
col.prop(view, "lock_object", text="")
|
||||
if view.lock_object and view.lock_object.type == 'ARMATURE':
|
||||
col.prop_object(view, "lock_bone", view.lock_object.data, "bones", text="")
|
||||
|
||||
col = layout.column(align=True)
|
||||
col.label(text="Clip:")
|
||||
col.prop(view, "clip_start", text="Start")
|
||||
col.prop(view, "clip_end", text="End")
|
||||
|
||||
col = layout.column(align=True)
|
||||
col.label(text="Grid:")
|
||||
col.prop(view, "grid_lines", text="Lines")
|
||||
col.prop(view, "grid_spacing", text="Spacing")
|
||||
col.prop(view, "grid_subdivisions", text="Subdivisions")
|
||||
|
||||
layout.column().prop(scene, "cursor_location", text="3D Cursor:")
|
||||
|
||||
class VIEW3D_PT_3dview_item(bpy.types.Panel):
|
||||
@ -1577,17 +1627,24 @@ class VIEW3D_PT_3dview_display(bpy.types.Panel):
|
||||
ob = context.object
|
||||
|
||||
col = layout.column()
|
||||
col.prop(view, "display_floor", text="Grid Floor")
|
||||
col.prop(view, "display_x_axis", text="X Axis")
|
||||
col.prop(view, "display_y_axis", text="Y Axis")
|
||||
col.prop(view, "display_z_axis", text="Z Axis")
|
||||
col.prop(view, "outline_selected")
|
||||
col.prop(view, "all_object_centers")
|
||||
col.prop(view, "all_object_origins")
|
||||
col.prop(view, "relationship_lines")
|
||||
if ob and ob.type == 'MESH':
|
||||
mesh = ob.data
|
||||
col.prop(mesh, "all_edges")
|
||||
|
||||
col = layout.column()
|
||||
col.prop(view, "display_floor", text="Grid Floor")
|
||||
sub = col.column(align=True)
|
||||
sub.active = view.display_floor
|
||||
sub.prop(view, "grid_lines", text="Lines")
|
||||
sub.prop(view, "grid_spacing", text="Spacing")
|
||||
sub.prop(view, "grid_subdivisions", text="Subdivisions")
|
||||
|
||||
col = layout.column()
|
||||
col.label(text="Shading:")
|
||||
col.prop(gs, "material_mode", text="")
|
||||
@ -1687,8 +1744,7 @@ class VIEW3D_PT_background_image(bpy.types.Panel):
|
||||
layout.active = view.display_background_image
|
||||
|
||||
col = layout.column()
|
||||
col.prop(bg, "image", text="")
|
||||
#col.prop(bg, "image_user")
|
||||
col.template_ID(bg, "image", open="image.open")
|
||||
col.prop(bg, "size")
|
||||
col.prop(bg, "transparency", slider=True)
|
||||
|
||||
@ -1805,46 +1861,6 @@ class VIEW3D_PT_context_properties(bpy.types.Panel):
|
||||
rna_prop_ui.draw(self.layout, context, member, False)
|
||||
|
||||
|
||||
# Operators
|
||||
from bpy.props import *
|
||||
|
||||
|
||||
class OBJECT_OT_select_pattern(bpy.types.Operator):
|
||||
'''Select object matching a naming pattern.'''
|
||||
bl_idname = "object.select_pattern"
|
||||
bl_label = "Select Pattern"
|
||||
bl_register = True
|
||||
bl_undo = True
|
||||
|
||||
pattern = StringProperty(name="Pattern", description="Name filter using '*' and '?' wildcard chars", maxlen=32, default="*")
|
||||
case_sensitive = BoolProperty(name="Case Sensitive", description="Do a case sensitive compare", default=False)
|
||||
extend = BoolProperty(name="Extend", description="Extend the existing selection", default=True)
|
||||
|
||||
def execute(self, context):
|
||||
|
||||
import fnmatch
|
||||
|
||||
if self.properties.case_sensitive:
|
||||
pattern_match = fnmatch.fnmatchcase
|
||||
else:
|
||||
pattern_match = lambda a, b: fnmatch.fnmatchcase(a.upper(), b.upper())
|
||||
|
||||
for ob in context.visible_objects:
|
||||
if pattern_match(ob.name, self.properties.pattern):
|
||||
ob.selected = True
|
||||
elif not self.properties.extend:
|
||||
ob.selected = False
|
||||
|
||||
return ('FINISHED',)
|
||||
|
||||
# TODO - python cant do popups yet
|
||||
'''
|
||||
def invoke(self, context, event):
|
||||
wm = context.manager
|
||||
wm.add_fileselect(self)
|
||||
return ('RUNNING_MODAL',)
|
||||
'''
|
||||
|
||||
bpy.types.register(VIEW3D_HT_header) # Header
|
||||
|
||||
bpy.types.register(VIEW3D_MT_view) #View Menus
|
||||
@ -1939,5 +1955,3 @@ bpy.types.register(VIEW3D_PT_transform_orientations)
|
||||
bpy.types.register(VIEW3D_PT_etch_a_ton)
|
||||
|
||||
bpy.types.register(VIEW3D_PT_context_properties)
|
||||
|
||||
bpy.ops.add(OBJECT_OT_select_pattern)
|
||||
|
@ -57,8 +57,8 @@ class VIEW3D_PT_tools_objectmode(View3DPanel):
|
||||
|
||||
col = layout.column(align=True)
|
||||
col.label(text="Keyframes:")
|
||||
col.operator("anim.insert_keyframe_menu", text="Insert")
|
||||
col.operator("anim.delete_keyframe_v3d", text="Remove")
|
||||
col.operator("anim.keyframe_insert_menu", text="Insert")
|
||||
col.operator("anim.keyframe_delete_v3d", text="Remove")
|
||||
|
||||
col = layout.column(align=True)
|
||||
col.label(text="Repeat:")
|
||||
@ -101,8 +101,8 @@ class VIEW3D_PT_tools_meshedit(View3DPanel):
|
||||
col.label(text="Add:")
|
||||
col.operator("mesh.extrude_move")
|
||||
col.operator("mesh.subdivide")
|
||||
col.operator("mesh.loopcut")
|
||||
col.operator("mesh.duplicate_move")
|
||||
col.operator("mesh.loopcut_slide")
|
||||
col.operator("mesh.duplicate_move", text="Duplicate")
|
||||
col.operator("mesh.spin")
|
||||
col.operator("mesh.screw")
|
||||
|
||||
@ -173,8 +173,8 @@ class VIEW3D_PT_tools_curveedit(View3DPanel):
|
||||
col.operator("tfm.resize", text="Scale")
|
||||
|
||||
col = layout.column(align=True)
|
||||
col.operator("tfm.transform").mode = 'TILT'
|
||||
col.operator("tfm.transform").mode = 'CURVE_SHRINKFATTEN'
|
||||
col.operator("tfm.transform", text="Tilt").mode = 'TILT'
|
||||
col.operator("tfm.transform", text="Shrink/Fatten").mode = 'CURVE_SHRINKFATTEN'
|
||||
|
||||
col = layout.column(align=True)
|
||||
col.label(text="Curve:")
|
||||
@ -188,9 +188,9 @@ class VIEW3D_PT_tools_curveedit(View3DPanel):
|
||||
col.label(text="Handles:")
|
||||
row = col.row()
|
||||
row.operator("curve.handle_type_set", text="Auto").type = 'AUTOMATIC'
|
||||
row.operator("curve.handle_type_set").type = 'VECTOR'
|
||||
row.operator("curve.handle_type_set", text="Vector").type = 'VECTOR'
|
||||
row = col.row()
|
||||
row.operator("curve.handle_type_set").type = 'ALIGN'
|
||||
row.operator("curve.handle_type_set", text="Align").type = 'ALIGN'
|
||||
row.operator("curve.handle_type_set", text="Free").type = 'FREE_ALIGN'
|
||||
|
||||
col = layout.column(align=True)
|
||||
@ -273,9 +273,9 @@ class VIEW3D_PT_tools_textedit(View3DPanel):
|
||||
|
||||
col = layout.column(align=True)
|
||||
col.label(text="Style:")
|
||||
col.operator("font.style_toggle").style = 'BOLD'
|
||||
col.operator("font.style_toggle").style = 'ITALIC'
|
||||
col.operator("font.style_toggle").style = 'UNDERLINE'
|
||||
col.operator("font.style_toggle", text="Bold").style = 'BOLD'
|
||||
col.operator("font.style_toggle", text="Italic").style = 'ITALIC'
|
||||
col.operator("font.style_toggle", text="Underline").style = 'UNDERLINE'
|
||||
|
||||
col = layout.column(align=True)
|
||||
col.label(text="Repeat:")
|
||||
@ -430,8 +430,8 @@ class VIEW3D_PT_tools_posemode(View3DPanel):
|
||||
col = layout.column(align=True)
|
||||
col.label(text="Keyframes:")
|
||||
|
||||
col.operator("anim.insert_keyframe_menu", text="Insert")
|
||||
col.operator("anim.delete_keyframe_v3d", text="Remove")
|
||||
col.operator("anim.keyframe_insert_menu", text="Insert")
|
||||
col.operator("anim.keyframe_delete_v3d", text="Remove")
|
||||
|
||||
col = layout.column(align=True)
|
||||
col.label(text="Repeat:")
|
||||
|
@ -43,7 +43,7 @@ struct bContext;
|
||||
struct ReportList;
|
||||
|
||||
#define BLENDER_VERSION 250
|
||||
#define BLENDER_SUBVERSION 7
|
||||
#define BLENDER_SUBVERSION 8
|
||||
|
||||
#define BLENDER_MINVERSION 250
|
||||
#define BLENDER_MINSUBVERSION 0
|
||||
|
@ -34,12 +34,6 @@ struct CurveMap;
|
||||
struct ImBuf;
|
||||
struct rctf;
|
||||
|
||||
void gamma_correct_rec709(float *c, float gamma);
|
||||
void gamma_correct(float *c, float gamma);
|
||||
float srgb_to_linearrgb(float c);
|
||||
float linearrgb_to_srgb(float c);
|
||||
void color_manage_linearize(float *col_to, float *col_from);
|
||||
|
||||
void floatbuf_to_srgb_byte(float *rectf, unsigned char *rectc, int x1, int x2, int y1, int y2, int w);
|
||||
void floatbuf_to_byte(float *rectf, unsigned char *rectc, int x1, int x2, int y1, int y2, int w);
|
||||
|
||||
|
@ -249,8 +249,8 @@ int CTX_data_visible_bones(const bContext *C, ListBase *list);
|
||||
int CTX_data_editable_bones(const bContext *C, ListBase *list);
|
||||
|
||||
struct bPoseChannel *CTX_data_active_pose_bone(const bContext *C);
|
||||
int CTX_data_selected_pchans(const bContext *C, ListBase *list);
|
||||
int CTX_data_visible_pchans(const bContext *C, ListBase *list);
|
||||
int CTX_data_selected_pose_bones(const bContext *C, ListBase *list);
|
||||
int CTX_data_visible_pose_bones(const bContext *C, ListBase *list);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -222,7 +222,7 @@ void copy_particle_key(struct ParticleKey *to, struct ParticleKey *from, int tim
|
||||
void psys_particle_on_emitter(struct ParticleSystemModifierData *psmd, int distr, int index, int index_dmcache, float *fuv, float foffset, float *vec, float *nor, float *utan, float *vtan, float *orco, float *ornor);
|
||||
struct ParticleSystemModifierData *psys_get_modifier(struct Object *ob, struct ParticleSystem *psys);
|
||||
|
||||
void object_add_particle_system(struct Scene *scene, struct Object *ob);
|
||||
struct ModifierData *object_add_particle_system(struct Scene *scene, struct Object *ob, char *name);
|
||||
void object_remove_particle_system(struct Scene *scene, struct Object *ob);
|
||||
struct ParticleSettings *psys_new_settings(char *name, struct Main *main);
|
||||
struct ParticleSettings *psys_copy_settings(struct ParticleSettings *part);
|
||||
|
@ -151,6 +151,7 @@ typedef struct PTCacheBaker {
|
||||
int (*break_test)(void *data);
|
||||
void *break_data;
|
||||
void (*progressbar)(void *data, int num);
|
||||
void (*progressend)(void *data);
|
||||
void *progresscontext;
|
||||
} PTCacheBaker;
|
||||
|
||||
|
@ -41,6 +41,7 @@ struct Header;
|
||||
struct Menu;
|
||||
struct ScrArea;
|
||||
struct SpaceType;
|
||||
struct Scene;
|
||||
struct wmNotifier;
|
||||
struct wmWindow;
|
||||
struct wmWindowManager;
|
||||
@ -233,7 +234,7 @@ void BKE_screen_area_free(struct ScrArea *sa);
|
||||
|
||||
/* screen */
|
||||
void free_screen(struct bScreen *sc);
|
||||
unsigned int BKE_screen_visible_layers(struct bScreen *screen);
|
||||
unsigned int BKE_screen_visible_layers(struct bScreen *screen, struct Scene *scene);
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -62,7 +62,7 @@ int do_colorband(struct ColorBand *coba, float in, float out[4]);
|
||||
void colorband_table_RGBA(struct ColorBand *coba, float **array, int *size);
|
||||
|
||||
void default_tex(struct Tex *tex);
|
||||
struct Tex *add_texture(char *name);
|
||||
struct Tex *add_texture(const char *name);
|
||||
void default_mtex(struct MTex *mtex);
|
||||
struct MTex *add_mtex(void);
|
||||
struct Tex *copy_texture(struct Tex *tex);
|
||||
|
@ -456,6 +456,8 @@ bPoseChannel *verify_pose_channel(bPose* pose, const char* name)
|
||||
chan->ikrotweight = chan->iklinweight = 0.0f;
|
||||
unit_m4(chan->constinv);
|
||||
|
||||
chan->protectflag = OB_LOCK_ROT4D; /* lock by components by default */
|
||||
|
||||
BLI_addtail(&pose->chanbase, chan);
|
||||
|
||||
return chan;
|
||||
@ -1083,7 +1085,10 @@ void copy_pose_result(bPose *to, bPose *from)
|
||||
|
||||
VECCOPY(pchanto->pose_head, pchanfrom->pose_head);
|
||||
VECCOPY(pchanto->pose_tail, pchanfrom->pose_tail);
|
||||
|
||||
pchanto->rotmode= pchanfrom->rotmode;
|
||||
pchanto->flag= pchanfrom->flag;
|
||||
pchanto->protectflag= pchanfrom->protectflag;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_blenlib.h"
|
||||
|
||||
#include "DNA_anim_types.h"
|
||||
#include "DNA_armature_types.h"
|
||||
#include "DNA_action_types.h"
|
||||
#include "DNA_curve_types.h"
|
||||
@ -49,6 +50,7 @@
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_view3d_types.h"
|
||||
|
||||
#include "BKE_animsys.h"
|
||||
#include "BKE_armature.h"
|
||||
#include "BKE_action.h"
|
||||
#include "BKE_anim.h"
|
||||
@ -127,6 +129,12 @@ void free_armature(bArmature *arm)
|
||||
freeSketch(arm->sketch);
|
||||
arm->sketch = NULL;
|
||||
}
|
||||
|
||||
/* free animation data */
|
||||
if (arm->adt) {
|
||||
BKE_free_animdata(&arm->id);
|
||||
arm->adt= NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -176,6 +184,9 @@ static void copy_bonechildren (Bone* newBone, Bone* oldBone, Bone* actBone, Bone
|
||||
if(oldBone == actBone)
|
||||
*newActBone= newBone;
|
||||
|
||||
if(oldBone->prop)
|
||||
newBone->prop= IDP_CopyProperty(oldBone->prop);
|
||||
|
||||
/* Copy this bone's list*/
|
||||
BLI_duplicatelist(&newBone->childbase, &oldBone->childbase);
|
||||
|
||||
@ -1501,6 +1512,10 @@ static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected
|
||||
pchanw.child= pchan->child;
|
||||
pchanw.path= NULL;
|
||||
|
||||
/* this is freed so copy a copy, else undo crashes */
|
||||
if(pchanw.prop)
|
||||
pchanw.prop= IDP_CopyProperty(pchanw.prop);
|
||||
|
||||
/* constraints - proxy constraints are flushed... local ones are added after
|
||||
* 1. extract constraints not from proxy (CONSTRAINT_PROXY_LOCAL) from pchan's constraints
|
||||
* 2. copy proxy-pchan's constraints on-to new
|
||||
@ -2220,35 +2235,44 @@ void where_is_pose_bone(Scene *scene, Object *ob, bPoseChannel *pchan, float cti
|
||||
|
||||
/* the rotation of the parent restposition */
|
||||
copy_m4_m4(tmat, parbone->arm_mat);
|
||||
|
||||
/* the location of actual parent transform */
|
||||
VECCOPY(tmat[3], offs_bone[3]);
|
||||
offs_bone[3][0]= offs_bone[3][1]= offs_bone[3][2]= 0.0f;
|
||||
mul_m4_v3(parchan->pose_mat, tmat[3]);
|
||||
|
||||
mul_serie_m4(pchan->pose_mat, tmat, offs_bone, pchan->chan_mat, NULL, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
else if(bone->flag & BONE_NO_SCALE) {
|
||||
float orthmat[4][4];
|
||||
|
||||
/* get the official transform, but we only use the vector from it (optimize...) */
|
||||
mul_serie_m4(pchan->pose_mat, parchan->pose_mat, offs_bone, pchan->chan_mat, NULL, NULL, NULL, NULL, NULL);
|
||||
VECCOPY(vec, pchan->pose_mat[3]);
|
||||
|
||||
/* do this again, but with an ortho-parent matrix */
|
||||
/* do transform, with an ortho-parent matrix */
|
||||
copy_m4_m4(orthmat, parchan->pose_mat);
|
||||
normalize_m4(orthmat);
|
||||
mul_serie_m4(pchan->pose_mat, orthmat, offs_bone, pchan->chan_mat, NULL, NULL, NULL, NULL, NULL);
|
||||
|
||||
/* copy correct transform */
|
||||
VECCOPY(pchan->pose_mat[3], vec);
|
||||
}
|
||||
else
|
||||
mul_serie_m4(pchan->pose_mat, parchan->pose_mat, offs_bone, pchan->chan_mat, NULL, NULL, NULL, NULL, NULL);
|
||||
|
||||
/* in these cases we need to compute location separately */
|
||||
if(bone->flag & (BONE_HINGE|BONE_NO_SCALE|BONE_NO_LOCAL_LOCATION)) {
|
||||
float bone_loc[3], chan_loc[3];
|
||||
|
||||
mul_v3_m4v3(bone_loc, parchan->pose_mat, offs_bone[3]);
|
||||
copy_v3_v3(chan_loc, pchan->chan_mat[3]);
|
||||
|
||||
/* no local location is not transformed by bone matrix */
|
||||
if(!(bone->flag & BONE_NO_LOCAL_LOCATION))
|
||||
mul_mat3_m4_v3(offs_bone, chan_loc);
|
||||
|
||||
/* for hinge we use armature instead of pose mat */
|
||||
if(bone->flag & BONE_HINGE) mul_mat3_m4_v3(parbone->arm_mat, chan_loc);
|
||||
else mul_mat3_m4_v3(parchan->pose_mat, chan_loc);
|
||||
|
||||
add_v3_v3v3(pchan->pose_mat[3], bone_loc, chan_loc);
|
||||
}
|
||||
}
|
||||
else {
|
||||
mul_m4_m4m4(pchan->pose_mat, pchan->chan_mat, bone->arm_mat);
|
||||
|
||||
/* optional location without arm_mat rotation */
|
||||
if(bone->flag & BONE_NO_LOCAL_LOCATION)
|
||||
add_v3_v3v3(pchan->pose_mat[3], bone->arm_mat[3], pchan->chan_mat[3]);
|
||||
|
||||
/* only rootbones get the cyclic offset (unless user doesn't want that) */
|
||||
if ((bone->flag & BONE_NO_CYCLICOFFSET) == 0)
|
||||
add_v3_v3v3(pchan->pose_mat[3], pchan->pose_mat[3], ob->pose->cyclic_offset);
|
||||
|
@ -58,52 +58,6 @@
|
||||
#include "IMB_imbuf.h"
|
||||
#include "IMB_imbuf_types.h"
|
||||
|
||||
/* ********************************* color transforms ********************************* */
|
||||
|
||||
/*Transform linear RGB values to nonlinear RGB values. Rec.
|
||||
709 is ITU-R Recommendation BT. 709 (1990) ``Basic
|
||||
Parameter Values for the HDTV Standard for the Studio and
|
||||
for International Programme Exchange'', formerly CCIR Rec.
|
||||
709.*/
|
||||
void gamma_correct_rec709(float *c, float gamma)
|
||||
{
|
||||
/* Rec. 709 gamma correction. */
|
||||
const float cc = 0.018f;
|
||||
|
||||
if (*c < cc)
|
||||
*c *= ((1.099f * (float)powf(cc, gamma)) - 0.099f) * (1.0f/cc);
|
||||
else
|
||||
*c = (1.099f * (float)powf(*c, gamma)) - 0.099f;
|
||||
}
|
||||
|
||||
void gamma_correct(float *c, float gamma)
|
||||
{
|
||||
*c = powf((*c), gamma);
|
||||
}
|
||||
|
||||
float srgb_to_linearrgb(float c)
|
||||
{
|
||||
if (c < 0.04045f)
|
||||
return (c < 0.0f)? 0.0f: c*(1.0f/12.92f);
|
||||
else
|
||||
return powf((c + 0.055f)*(1.0f/1.055f), 2.4f);
|
||||
}
|
||||
|
||||
float linearrgb_to_srgb(float c)
|
||||
{
|
||||
if (c < 0.0031308f)
|
||||
return (c < 0.0f)? 0.0f: c * 12.92f;
|
||||
else
|
||||
return 1.055f * powf(c, 1.0f/2.4f) - 0.055f;
|
||||
}
|
||||
|
||||
/* utility function convert an RGB triplet from sRGB to linear RGB color space */
|
||||
void color_manage_linearize(float *col_to, float *col_from)
|
||||
{
|
||||
col_to[0] = srgb_to_linearrgb(col_from[0]);
|
||||
col_to[1] = srgb_to_linearrgb(col_from[1]);
|
||||
col_to[2] = srgb_to_linearrgb(col_from[2]);
|
||||
}
|
||||
|
||||
void floatbuf_to_srgb_byte(float *rectf, unsigned char *rectc, int x1, int x2, int y1, int y2, int w)
|
||||
{
|
||||
|
@ -883,13 +883,13 @@ struct bPoseChannel *CTX_data_active_pose_bone(const bContext *C)
|
||||
return ctx_data_pointer_get(C, "active_pose_bone");
|
||||
}
|
||||
|
||||
int CTX_data_selected_pchans(const bContext *C, ListBase *list)
|
||||
int CTX_data_selected_pose_bones(const bContext *C, ListBase *list)
|
||||
{
|
||||
return ctx_data_collection_get(C, "selected_pchans", list);
|
||||
return ctx_data_collection_get(C, "selected_pose_bones", list);
|
||||
}
|
||||
|
||||
int CTX_data_visible_pchans(const bContext *C, ListBase *list)
|
||||
int CTX_data_visible_pose_bones(const bContext *C, ListBase *list)
|
||||
{
|
||||
return ctx_data_collection_get(C, "visible_pchans", list);
|
||||
return ctx_data_collection_get(C, "visible_pose_bones", list);
|
||||
}
|
||||
|
||||
|
@ -2155,7 +2155,7 @@ static void dag_current_scene_layers(Main *bmain, Scene **sce, unsigned int *lay
|
||||
for(win=wm->windows.first; win; win=win->next) {
|
||||
if(win->screen) {
|
||||
if(!*sce) *sce= win->screen->scene;
|
||||
*lay |= BKE_screen_visible_layers(win->screen);
|
||||
*lay |= BKE_screen_visible_layers(win->screen, win->screen->scene);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4050,7 +4050,7 @@ static void dxf_read(Scene *scene, char *filename)
|
||||
|
||||
ob->type= OB_MESH;
|
||||
|
||||
ob->dt= OB_SHADED;
|
||||
ob->dt= OB_TEXTURE;
|
||||
|
||||
ob->trackflag= OB_POSY;
|
||||
ob->upflag= OB_POSZ;
|
||||
|
@ -822,7 +822,7 @@ float driver_get_target_value (ChannelDriver *driver, DriverTarget *dtar)
|
||||
}
|
||||
|
||||
/* get property to read from, and get value as appropriate */
|
||||
if (RNA_path_resolve(&id_ptr, path, &ptr, &prop)) {
|
||||
if (RNA_path_resolve_full(&id_ptr, path, &ptr, &prop, &index)) {
|
||||
switch (RNA_property_type(prop)) {
|
||||
case PROP_BOOLEAN:
|
||||
if (RNA_property_array_length(&ptr, prop))
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user