Sculpt Branch:

svn merge https://svn.blender.org/svnroot/bf-blender/trunk/blender -r24889:25180
This commit is contained in:
Brecht Van Lommel 2009-12-07 19:22:48 +00:00
commit 82ddfbf99f
383 changed files with 31716 additions and 24473 deletions

@ -1,4 +1,4 @@
# $Id$
# $Id$
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
@ -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']

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

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

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

@ -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,10 +254,12 @@ 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;
}
@ -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
return i2,i1
def ord_ind(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,31 +240,48 @@ class MeshEdge(StructRNA):
class MeshFace(StructRNA):
__slots__ = ()
@property
def edge_keys(self):
verts = tuple(self.verts)
if len(verts)==3:
if len(verts) == 3:
return ord_ind(verts[0], verts[1]), ord_ind(verts[1], verts[2]), ord_ind(verts[2], verts[0])
return ord_ind(verts[0], verts[1]), ord_ind(verts[1], verts[2]), ord_ind(verts[2], verts[3]), ord_ind(verts[3], verts[0])
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

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

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

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

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

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

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

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

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

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

@ -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']
@ -57,7 +58,7 @@ def rna_idprop_ui_prop_clear(item, prop):
pass
def draw(layout, context, context_member, use_edit = True):
def draw(layout, context, context_member, use_edit=True):
def assign_props(prop, val, key):
prop.path = context_member
@ -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"
@ -252,7 +236,7 @@ class WM_OT_properties_add(bpy.types.Operator):
i = 1
while prop_new in names:
prop_new = prop + str(i)
i+=1
i += 1
return prop_new
@ -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,19 +25,21 @@ 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)
val, output = subprocess.getstatusoutput(text)
if not val:
style= 'OUTPUT'
style = 'OUTPUT'
else:
style= 'ERROR'
style = 'ERROR'
add_scrollback(output, style)
@ -60,7 +62,7 @@ def execute(context):
bpy.ops.console.history_append(text="", current_character=0,
remove_duplicates=True)
sc.prompt = os.getcwd()+PROMPT
sc.prompt = os.getcwd() + PROMPT
return ('FINISHED',)
@ -74,7 +76,6 @@ def banner(context):
sc = context.space_data
shell_run("bash --version")
sc.prompt = os.getcwd()+PROMPT
sc.prompt = os.getcwd() + PROMPT
return ('FINISHED',)

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

@ -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")
@ -179,7 +185,7 @@ class INFO_MT_add(bpy.types.Menu):
layout.operator_context = 'EXEC_SCREEN'
# layout.operator_menu_enum("object.mesh_add", "type", text="Mesh", icon='ICON_OUTLINER_OB_MESH')
#layout.operator_menu_enum("object.mesh_add", "type", text="Mesh", icon='ICON_OUTLINER_OB_MESH')
layout.menu("INFO_MT_mesh_add", icon='ICON_OUTLINER_OB_MESH')
layout.operator_menu_enum("object.curve_add", "type", text="Curve", icon='ICON_OUTLINER_OB_CURVE')
@ -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