Merge from trunk -r 24247:24313, -r 24313:24390.

This commit is contained in:
Arystanbek Dyussenov 2009-11-07 14:21:07 +00:00
parent 7c80440dda
commit 58e44463fb
211 changed files with 14436 additions and 13098 deletions

@ -518,9 +518,9 @@ IF(APPLE)
ENDIF (WITH_COCOA)
IF(WITH_OPENMP)
SET(LLIBS "${LLIBS} -lgomp ")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fopenmp ")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fopenmp ")
SET(LLIBS "${LLIBS} -lgomp")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fopenmp")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fopenmp")
ENDIF(WITH_OPENMP)
IF (WITH_OPENCOLLADA)
@ -555,6 +555,16 @@ IF(APPLE)
SET(TIFF_INC ${TIFF}/include)
SET(EXETYPE MACOSX_BUNDLE)
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")
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")
ENDIF(CMAKE_OSX_ARCHITECTURES MATCHES "i386")
ENDIF(APPLE)
IF(CMAKE_SYSTEM_NAME MATCHES "Linux")

@ -124,7 +124,10 @@ if toolset:
#if env:
# btools.SetupSpawn(env)
else:
env = BlenderEnvironment(ENV = os.environ)
if bitness==64 and platform=='win32':
env = BlenderEnvironment(ENV = os.environ, MSVS_ARCH='amd64')
else:
env = BlenderEnvironment(ENV = os.environ)
if not env:
print "Could not create a build environment"

@ -158,7 +158,7 @@ BF_COLLADA_LIB = 'bf_collada'
BF_OPENCOLLADA = LIBDIR + '/opencollada'
BF_OPENCOLLADA_INC = '${BF_OPENCOLLADA}/include'
BF_OPENCOLLADA_LIB = 'opencollada'
BF_OPENCOLLADA_LIB = 'OpenCOLLADAStreamWriter OpenCOLLADASaxFrameworkLoader OpenCOLLADAFramework OpenCOLLADABaseUtils GeneratedSaxParser UTF MathMLSolver xml2 pcre'
BF_OPENCOLLADA_LIBPATH = '${BF_OPENCOLLADA}/lib'
WITH_BF_STATICOPENGL = False

@ -202,7 +202,6 @@ void btConvexConvexAlgorithm ::processCollision (btCollisionObject* body0,btColl
input.m_maximumDistanceSquared*= input.m_maximumDistanceSquared;
}
input.m_stackAlloc = dispatchInfo.m_stackAllocator;
input.m_transformA = body0->getWorldTransform();
input.m_transformB = body1->getWorldTransform();

@ -33,7 +33,7 @@ public:
const btConvexShape* convexA,const btConvexShape* convexB,
const btTransform& transA,const btTransform& transB,
btVector3& v, btVector3& pa, btVector3& pb,
class btIDebugDraw* debugDraw,btStackAlloc* stackAlloc
class btIDebugDraw* debugDraw
) = 0;

@ -41,15 +41,13 @@ struct btDiscreteCollisionDetectorInterface
struct ClosestPointInput
{
ClosestPointInput()
:m_maximumDistanceSquared(btScalar(1e30)),
m_stackAlloc(0)
:m_maximumDistanceSquared(btScalar(1e30))
{
}
btTransform m_transformA;
btTransform m_transformB;
btScalar m_maximumDistanceSquared;
btStackAlloc* m_stackAlloc;
};
virtual ~btDiscreteCollisionDetectorInterface() {};

@ -25,7 +25,7 @@ bool btGjkEpaPenetrationDepthSolver::calcPenDepth( btSimplexSolverInterface& sim
const btConvexShape* pConvexA, const btConvexShape* pConvexB,
const btTransform& transformA, const btTransform& transformB,
btVector3& v, btVector3& wWitnessOnA, btVector3& wWitnessOnB,
class btIDebugDraw* debugDraw, btStackAlloc* stackAlloc )
class btIDebugDraw* debugDraw )
{
(void)debugDraw;

@ -29,7 +29,7 @@ class btGjkEpaPenetrationDepthSolver : public btConvexPenetrationDepthSolver
const btConvexShape* pConvexA, const btConvexShape* pConvexB,
const btTransform& transformA, const btTransform& transformB,
btVector3& v, btVector3& wWitnessOnA, btVector3& wWitnessOnB,
class btIDebugDraw* debugDraw,btStackAlloc* stackAlloc );
class btIDebugDraw* debugDraw );
private :

@ -293,7 +293,7 @@ void btGjkPairDetector::getClosestPoints(const ClosestPointInput& input,Result&
m_minkowskiA,m_minkowskiB,
localTransA,localTransB,
m_cachedSeparatingAxis, tmpPointOnA, tmpPointOnB,
debugDraw,input.m_stackAlloc
debugDraw
);
if (isValid2)

@ -71,11 +71,10 @@ bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& s
const btConvexShape* convexA,const btConvexShape* convexB,
const btTransform& transA,const btTransform& transB,
btVector3& v, btVector3& pa, btVector3& pb,
class btIDebugDraw* debugDraw,btStackAlloc* stackAlloc
class btIDebugDraw* debugDraw
)
{
(void)stackAlloc;
(void)v;

@ -28,7 +28,7 @@ public:
const btConvexShape* convexA,const btConvexShape* convexB,
const btTransform& transA,const btTransform& transB,
btVector3& v, btVector3& pa, btVector3& pb,
class btIDebugDraw* debugDraw,btStackAlloc* stackAlloc
class btIDebugDraw* debugDraw
);
};

@ -365,10 +365,6 @@ double plNearestPoints(float p1[3], float p2[3], float p3[3], float q1[3], float
btPointCollector gjkOutput;
btGjkPairDetector::ClosestPointInput input;
btStackAlloc gStackAlloc(1024*1024*2);
input.m_stackAlloc = &gStackAlloc;
btTransform tr;
tr.setIdentity();

@ -5,8 +5,5 @@ sources = env.Glob('intern/*.cpp')
incs = 'intern ../container ../moto/include ../memutil'
if (env['OURPLATFORM'] == 'win32-mingw'):
env.BlenderLib ('blender_BSP', sources, Split(incs), [], libtype='core', priority=26 )
else:
env.BlenderLib ('blender_BSP', sources, Split(incs), [], libtype='core', priority=20 )
env.BlenderLib ('blender_BSP', sources, Split(incs), [], libtype='core', priority=200 )

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

@ -786,7 +786,7 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent)
case NSFlagsChanged:
handleKeyEvent(event);
/* Support system-wide keyboard shortcuts, like Exposé, ...) =>included in always NSApp sendEvent */
/* Support system-wide keyboard shortcuts, like Exposé, ...) =>included in always NSApp sendEvent */
/* if (([event modifierFlags] & NSCommandKeyMask) || [event type] == NSFlagsChanged) {
[NSApp sendEvent:event];
}*/
@ -891,8 +891,8 @@ GHOST_TUns8 GHOST_SystemCocoa::handleQuitRequest()
//Check open windows if some changes are not saved
if (m_windowManager->getAnyModifiedState())
{
int shouldQuit = NSRunAlertPanel(@"Exit Blender", @"Some changes have not been saved. Do you really want to quit ?",
@"Cancel", @"Quit anyway", nil);
int shouldQuit = NSRunAlertPanel(@"Exit Blender", @"Some changes have not been saved.\nDo you really want to quit ?",
@"Cancel", @"Quit Anyway", nil);
if (shouldQuit == NSAlertAlternateReturn)
{
pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventQuit, NULL) );

@ -132,8 +132,8 @@
GHOST_SystemWin32::GHOST_SystemWin32()
: m_hasPerformanceCounter(false), m_freq(0), m_start(0),
m_seperateLeftRight(false),
m_seperateLeftRightInitialized(false)
m_separateLeftRight(false),
m_separateLeftRightInitialized(false)
{
m_displayManager = new GHOST_DisplayManagerWin32 ();
GHOST_ASSERT(m_displayManager, "GHOST_SystemWin32::GHOST_SystemWin32(): m_displayManager==0\n");
@ -274,7 +274,7 @@ GHOST_TSuccess GHOST_SystemWin32::getModifierKeys(GHOST_ModifierKeys& keys) cons
It didn't work all that well on some newer hardware, and worked less
well with the passage of time, so it was fully disabled in ME.
*/
if (m_seperateLeftRight && m_seperateLeftRightInitialized) {
if (m_separateLeftRight && m_separateLeftRightInitialized) {
bool down = HIBYTE(::GetKeyState(VK_LSHIFT)) != 0;
keys.set(GHOST_kModifierKeyLeftShift, down);
down = HIBYTE(::GetKeyState(VK_RSHIFT)) != 0;
@ -581,29 +581,29 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
case VK_SHIFT:
case VK_CONTROL:
case VK_MENU:
if (!system->m_seperateLeftRightInitialized) {
if (!system->m_separateLeftRightInitialized) {
// Check whether this system supports seperate left and right keys
switch (wParam) {
case VK_SHIFT:
system->m_seperateLeftRight =
system->m_separateLeftRight =
(HIBYTE(::GetKeyState(VK_LSHIFT)) != 0) ||
(HIBYTE(::GetKeyState(VK_RSHIFT)) != 0) ?
true : false;
break;
case VK_CONTROL:
system->m_seperateLeftRight =
system->m_separateLeftRight =
(HIBYTE(::GetKeyState(VK_LCONTROL)) != 0) ||
(HIBYTE(::GetKeyState(VK_RCONTROL)) != 0) ?
true : false;
break;
case VK_MENU:
system->m_seperateLeftRight =
system->m_separateLeftRight =
(HIBYTE(::GetKeyState(VK_LMENU)) != 0) ||
(HIBYTE(::GetKeyState(VK_RMENU)) != 0) ?
true : false;
break;
}
system->m_seperateLeftRightInitialized = true;
system->m_separateLeftRightInitialized = true;
}
system->processModifierKeys(window);
// Bypass call to DefWindowProc

@ -283,9 +283,9 @@ protected:
/** High frequency timer variable. */
__int64 m_start;
/** Stores the capability of this system to distinguish left and right modifier keys. */
bool m_seperateLeftRight;
bool m_separateLeftRight;
/** Stores the initialization state of the member m_leftRightDistinguishable. */
bool m_seperateLeftRightInitialized;
bool m_separateLeftRightInitialized;
};

@ -68,7 +68,7 @@ extern "C" {
- (void)windowWillClose:(NSNotification *)notification;
- (void)windowDidBecomeKey:(NSNotification *)notification;
- (void)windowDidResignKey:(NSNotification *)notification;
- (void)windowDidUpdate:(NSNotification *)notification;
- (void)windowDidExpose:(NSNotification *)notification;
- (void)windowDidResize:(NSNotification *)notification;
@end
@ -91,13 +91,10 @@ extern "C" {
- (void)windowDidResignKey:(NSNotification *)notification
{
//The window is no more key when its own view becomes fullscreen
//but ghost doesn't know the view/window difference, so hide this fact
if (associatedWindow->getState() != GHOST_kWindowStateFullScreen)
systemCocoa->handleWindowEvent(GHOST_kEventWindowDeactivate, associatedWindow);
systemCocoa->handleWindowEvent(GHOST_kEventWindowDeactivate, associatedWindow);
}
- (void)windowDidUpdate:(NSNotification *)notification
- (void)windowDidExpose:(NSNotification *)notification
{
systemCocoa->handleWindowEvent(GHOST_kEventWindowUpdate, associatedWindow);
}
@ -622,6 +619,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state)
//Make window normal and resize it
[m_window setStyleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask)];
[m_window setFrame:[[m_window screen] visibleFrame] display:YES];
//TODO for 10.6 only : window title is forgotten after the style change
[m_window makeFirstResponder:m_openGLView];
#else
//With 10.5, we need to create a new window to change its style to borderless

@ -76,7 +76,7 @@ abort();
#endif /* breakpoint */
#if defined(WIN32) && !defined(__GNUC__)
#if defined(_WIN32) && !defined(__GNUC__)
#define MT_assert(predicate) assert(predicate)
#else

@ -74,7 +74,7 @@
<Tool
Name="VCLinkerTool"
AdditionalOptions="/MACHINE:I386"
AdditionalDependencies="libsamplerate.lib SDL.lib freetype2ST.lib gnu_gettext.lib qtmlClient.lib OpenAL32.lib wrap_oal.lib ws2_32.lib dxguid.lib opengl32.lib libjpeg.lib glu32.lib vfw32.lib winmm.lib libpng_st.lib zlib.lib python31.lib pthreadVSE2.lib pthreadVC2.lib libtiff.lib Half.lib Iex.lib IlmImf.lib Imath.lib IlmThread.lib avcodec-52.lib avformat-52.lib avutil-50.lib swscale-0.lib avdevice-52.lib libsndfile-1.lib opencollada.lib"
AdditionalDependencies="libsamplerate.lib SDL.lib freetype2ST.lib gnu_gettext.lib qtmlClient.lib OpenAL32.lib wrap_oal.lib ws2_32.lib dxguid.lib opengl32.lib libjpeg.lib glu32.lib vfw32.lib winmm.lib libpng_st.lib zlib.lib python31.lib pthreadVSE2.lib pthreadVC2.lib libtiff.lib Half.lib Iex.lib IlmImf.lib Imath.lib IlmThread.lib avcodec-52.lib avformat-52.lib avutil-50.lib swscale-0.lib avdevice-52.lib libsndfile-1.lib OpenCOLLADABaseUtils.lib OpenCOLLADAFramework.lib OpenCOLLADAStreamWriter.lib OpenCOLLADASaxFrameworkLoader.lib pcre.lib UTF.lib GeneratedSaxParser.lib MathMLSolver.lib xml2.lib"
ShowProgress="0"
OutputFile="..\..\..\install\msvc_9\blender.exe"
LinkIncremental="1"
@ -169,7 +169,7 @@
<Tool
Name="VCLinkerTool"
AdditionalOptions="/MACHINE:I386&#x0D;&#x0A;"
AdditionalDependencies="libsamplerate.lib SDL.lib freetype2ST.lib gnu_gettext.lib qtmlClient.lib OpenAL32.lib wrap_oal.lib ws2_32.lib dxguid.lib opengl32.lib libjpeg.lib glu32.lib vfw32.lib winmm.lib libpng_st.lib zlib.lib python31_d.lib pthreadVSE2.lib pthreadVC2.lib libtiff.lib Half_d.lib Iex_d.lib Imath_d.lib IlmImf_d.lib IlmThread_d.lib avcodec-52.lib avformat-52.lib avdevice-52.lib avutil-50.lib swscale-0.lib libsndfile-1.lib opencollada.lib"
AdditionalDependencies="libsamplerate.lib SDL.lib freetype2ST.lib gnu_gettext.lib qtmlClient.lib OpenAL32.lib wrap_oal.lib ws2_32.lib dxguid.lib opengl32.lib libjpeg.lib glu32.lib vfw32.lib winmm.lib libpng_st.lib zlib.lib python31_d.lib pthreadVSE2.lib pthreadVC2.lib libtiff.lib Half_d.lib Iex_d.lib Imath_d.lib IlmImf_d.lib IlmThread_d.lib avcodec-52.lib avformat-52.lib avdevice-52.lib avutil-50.lib swscale-0.lib libsndfile-1.lib OpenCOLLADABaseUtils.lib OpenCOLLADAFramework.lib OpenCOLLADAStreamWriter.lib OpenCOLLADASaxFrameworkLoader.lib pcre.lib UTF.lib GeneratedSaxParser.lib MathMLSolver.lib xml2.lib"
ShowProgress="0"
OutputFile="..\..\..\install\msvc_9d\blender.exe"
LinkIncremental="2"

@ -1109,7 +1109,7 @@ def save_3ds(filename, context):
# Blender.Draw.PupMenu("Error%t|This script requires a full python installation")
# # save_3ds('/test_b.3ds')
from bpy.props import *
class EXPORT_OT_autodesk_3ds(bpy.types.Operator):
class Export3DS(bpy.types.Operator):
'''Export to 3DS file format (.3ds).'''
bl_idname = "export.autodesk_3ds"
bl_label = 'Export 3DS'
@ -1135,9 +1135,13 @@ class EXPORT_OT_autodesk_3ds(bpy.types.Operator):
print("Poll")
return context.active_object != None
bpy.ops.add(EXPORT_OT_autodesk_3ds)
bpy.ops.add(Export3DS)
# Add to a menu
import dynamic_menu
menu_func = lambda self, context: self.layout.itemO("export.autodesk_3ds", text="Autodesk 3DS...")
def menu_func(self, context):
default_path = bpy.data.filename.replace(".blend", ".3ds")
self.layout.item_stringO(Export3DS.bl_idname, "path", default_path, text="Autodesk 3DS...")
menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_export, menu_func)

@ -237,14 +237,14 @@ def sane_groupname(data): return sane_name(data, sane_name_mapping_group)
# FORCE_CWD - dont use the basepath, just add a ./ to the filename.
# use when we know the file will be in the basepath.
# '''
# fname = bpy.sys.expandpath(fname_orig)
# fname = bpy.utils.expandpath(fname_orig)
# # fname = Blender.sys.expandpath(fname_orig)
# fname_strip = os.path.basename(fname)
# # fname_strip = strip_path(fname)
# if FORCE_CWD:
# fname_rel = '.' + os.sep + fname_strip
# else:
# fname_rel = bpy.sys.relpath(fname, basepath)
# fname_rel = bpy.utils.relpath(fname, basepath)
# # fname_rel = Blender.sys.relpath(fname, basepath)
# if fname_rel.startswith('//'): fname_rel = '.' + os.sep + fname_rel[2:]
# return fname, fname_strip, fname_rel
@ -349,7 +349,7 @@ def write(filename, batch_objects = None, \
fbxpath = filename
# get the path component of filename
tmp_exists = bpy.sys.exists(fbxpath)
tmp_exists = bpy.utils.exists(fbxpath)
# tmp_exists = Blender.sys.exists(fbxpath)
if tmp_exists != 2: # a file, we want a path
@ -363,7 +363,7 @@ def write(filename, batch_objects = None, \
# Draw.PupMenu('Error%t|Directory does not exist!')
return
tmp_exists = bpy.sys.exists(fbxpath)
tmp_exists = bpy.utils.exists(fbxpath)
# tmp_exists = Blender.sys.exists(fbxpath)
if tmp_exists != 2:
@ -398,7 +398,7 @@ def write(filename, batch_objects = None, \
# path may alredy exist
# TODO - might exist but be a file. unlikely but should probably account for it.
if bpy.sys.exists(new_fbxpath) == 0:
if bpy.utils.exists(new_fbxpath) == 0:
# if Blender.sys.exists(new_fbxpath) == 0:
os.mkdir(new_fbxpath)
@ -3351,7 +3351,7 @@ def write_ui():
# GLOBALS.clear()
from bpy.props import *
class EXPORT_OT_fbx(bpy.types.Operator):
class ExportFBX(bpy.types.Operator):
'''Selection to an ASCII Autodesk FBX'''
bl_idname = "export.fbx"
bl_label = "Export FBX"
@ -3433,7 +3433,7 @@ class EXPORT_OT_fbx(bpy.types.Operator):
return ('RUNNING_MODAL',)
bpy.ops.add(EXPORT_OT_fbx)
bpy.ops.add(ExportFBX)
# if __name__ == "__main__":
# bpy.ops.EXPORT_OT_ply(filename="/tmp/test.ply")
@ -3456,7 +3456,7 @@ bpy.ops.add(EXPORT_OT_fbx)
# - bpy.data.remove_scene: line 366
# - bpy.sys.time move to bpy.sys.util?
# - new scene creation, activation: lines 327-342, 368
# - uses bpy.sys.expandpath, *.relpath - replace at least relpath
# - uses bpy.utils.expandpath, *.relpath - replace at least relpath
# SMALL or COSMETICAL
# - find a way to get blender version, and put it in bpy.util?, old was Blender.Get('version')
@ -3464,6 +3464,10 @@ bpy.ops.add(EXPORT_OT_fbx)
# Add to a menu
import dynamic_menu
menu_func = lambda self, context: self.layout.itemO("export.fbx", text="Autodesk FBX...")
def menu_func(self, context):
default_path = bpy.data.filename.replace(".blend", ".fbx")
self.layout.item_stringO(ExportFBX.bl_idname, "path", default_path, text="Autodesk FBX...")
menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_export, menu_func)

@ -54,148 +54,148 @@ import os
#from Blender import *
#import BPyMessages
try:
from struct import pack
from struct import pack
except:
pack = None
pack = None
def zero_file(filepath):
'''
If a file fails, this replaces it with 1 char, better not remove it?
'''
file = open(filepath, 'w')
file.write('\n') # apparently macosx needs some data in a blank file?
file.close()
'''
If a file fails, this replaces it with 1 char, better not remove it?
'''
file = open(filepath, 'w')
file.write('\n') # apparently macosx needs some data in a blank file?
file.close()
def check_vertcount(mesh,vertcount):
'''
check and make sure the vertcount is consistent throughout the frame range
'''
if len(mesh.verts) != vertcount:
raise Exception('Error, number of verts has changed during animation, cannot export')
f.close()
zero_file(filepath)
return
'''
check and make sure the vertcount is consistent throughout the frame range
'''
if len(mesh.verts) != vertcount:
raise Exception('Error, number of verts has changed during animation, cannot export')
f.close()
zero_file(filepath)
return
def write(filename, sce, ob, PREF_STARTFRAME, PREF_ENDFRAME, PREF_FPS):
if not pack:
raise Exception('Error, this script requires the "pack" module')
if ob.type != 'MESH':
raise Exception('Error, active object is not a mesh')
"""
Window.EditMode(0)
Blender.Window.WaitCursor(1)
"""
Blender.Window.WaitCursor(1)
mesh_orig = Mesh.New()
mesh_orig.getFromObject(ob.name)
"""
orig_frame = sce.current_frame
sce.set_frame(PREF_STARTFRAME)
me = ob.create_mesh(True, 'PREVIEW')
mesh_orig = Mesh.New()
mesh_orig.getFromObject(ob.name)
"""
#Flip y and z
mat_flip= Mathutils.Matrix(\
[1.0, 0.0, 0.0, 0.0],\
[0.0, 0.0, 1.0, 0.0],\
[0.0, 1.0, 0.0, 0.0],\
[0.0, 0.0, 0.0, 1.0],\
)
bpy.ops.object.mode_set(mode='OBJECT')
numverts = len(me.verts)
orig_frame = sce.current_frame
sce.set_frame(PREF_STARTFRAME)
me = ob.create_mesh(True, 'PREVIEW')
numframes = PREF_ENDFRAME-PREF_STARTFRAME+1
PREF_FPS= float(PREF_FPS)
f = open(filename, 'wb') #no Errors yet:Safe to create file
# Write the header
f.write(pack(">2i", numframes, numverts))
# Write the frame times (should we use the time IPO??)
f.write( pack(">%df" % (numframes), *[frame/PREF_FPS for frame in range(numframes)]) ) # seconds
#rest frame needed to keep frames in sync
"""
Blender.Set('curframe', PREF_STARTFRAME)
me_tmp.getFromObject(ob.name)
"""
#Flip y and z
mat_flip= Mathutils.Matrix(\
[1.0, 0.0, 0.0, 0.0],\
[0.0, 0.0, 1.0, 0.0],\
[0.0, 1.0, 0.0, 0.0],\
[0.0, 0.0, 0.0, 1.0],\
)
check_vertcount(me,numverts)
me.transform(mat_flip * ob.matrix)
f.write(pack(">%df" % (numverts*3), *[axis for v in me.verts for axis in v.co]))
for frame in range(PREF_STARTFRAME,PREF_ENDFRAME+1):#in order to start at desired frame
"""
Blender.Set('curframe', frame)
me_tmp.getFromObject(ob.name)
"""
numverts = len(me.verts)
sce.set_frame(frame)
me = ob.create_mesh(True, 'PREVIEW')
check_vertcount(me,numverts)
me.transform(mat_flip * ob.matrix)
# Write the vertex data
f.write(pack(">%df" % (numverts*3), *[axis for v in me.verts for axis in v.co]))
"""
me_tmp.verts= None
"""
f.close()
print ('MDD Exported: %s frames:%d\n'% (filename, numframes-1))
"""
Blender.Window.WaitCursor(0)
Blender.Set('curframe', orig_frame)
"""
sce.set_frame(orig_frame)
numframes = PREF_ENDFRAME-PREF_STARTFRAME+1
PREF_FPS= float(PREF_FPS)
f = open(filename, 'wb') #no Errors yet:Safe to create file
# Write the header
f.write(pack(">2i", numframes, numverts))
# Write the frame times (should we use the time IPO??)
f.write( pack(">%df" % (numframes), *[frame/PREF_FPS for frame in range(numframes)]) ) # seconds
#rest frame needed to keep frames in sync
"""
Blender.Set('curframe', PREF_STARTFRAME)
me_tmp.getFromObject(ob.name)
"""
check_vertcount(me,numverts)
me.transform(mat_flip * ob.matrix)
f.write(pack(">%df" % (numverts*3), *[axis for v in me.verts for axis in v.co]))
for frame in range(PREF_STARTFRAME,PREF_ENDFRAME+1):#in order to start at desired frame
"""
Blender.Set('curframe', frame)
me_tmp.getFromObject(ob.name)
"""
sce.set_frame(frame)
me = ob.create_mesh(True, 'PREVIEW')
check_vertcount(me,numverts)
me.transform(mat_flip * ob.matrix)
# Write the vertex data
f.write(pack(">%df" % (numverts*3), *[axis for v in me.verts for axis in v.co]))
"""
me_tmp.verts= None
"""
f.close()
print ('MDD Exported: %s frames:%d\n'% (filename, numframes-1))
"""
Blender.Window.WaitCursor(0)
Blender.Set('curframe', orig_frame)
"""
sce.set_frame(orig_frame)
from bpy.props import *
class EXPORT_OT_mdd(bpy.types.Operator):
'''Animated mesh to MDD vertex keyframe file.'''
bl_idname = "export.mdd"
bl_label = "Export MDD"
class ExportMDD(bpy.types.Operator):
'''Animated mesh to MDD vertex keyframe file.'''
bl_idname = "export.mdd"
bl_label = "Export MDD"
# get first scene to get min and max properties for frames, fps
# get first scene to get min and max properties for frames, fps
sce = bpy.data.scenes[bpy.data.scenes.keys()[0]]
minframe = sce.rna_type.properties["current_frame"].soft_min
maxframe = sce.rna_type.properties["current_frame"].soft_max
minfps = sce.render_data.rna_type.properties["fps"].soft_min
maxfps = sce.render_data.rna_type.properties["fps"].soft_max
sce = bpy.data.scenes[bpy.data.scenes.keys()[0]]
minframe = sce.rna_type.properties["current_frame"].soft_min
maxframe = sce.rna_type.properties["current_frame"].soft_max
minfps = sce.render_data.rna_type.properties["fps"].soft_min
maxfps = sce.render_data.rna_type.properties["fps"].soft_max
# List of operator properties, the attributes will be assigned
# to the class instance from the operator settings before calling.
path = StringProperty(name="File Path", description="File path used for exporting the MDD file", maxlen= 1024, default= "tmp.mdd")
fps = IntProperty(name="Frames Per Second", description="Number of frames/second", min=minfps, max=maxfps, default= 25)
start_frame = IntProperty(name="Start Frame", description="Start frame for baking", min=minframe,max=maxframe,default=1)
end_frame = IntProperty(name="End Frame", description="End frame for baking", min=minframe, max=maxframe, default= 250)
# List of operator properties, the attributes will be assigned
# to the class instance from the operator settings before calling.
path = StringProperty(name="File Path", description="File path used for exporting the MDD file", maxlen= 1024, default= "tmp.mdd")
fps = IntProperty(name="Frames Per Second", description="Number of frames/second", min=minfps, max=maxfps, default= 25)
start_frame = IntProperty(name="Start Frame", description="Start frame for baking", min=minframe,max=maxframe,default=1)
end_frame = IntProperty(name="End Frame", description="End frame for baking", min=minframe, max=maxframe, default= 250)
def poll(self, context):
return context.active_object != None
def poll(self, context):
ob = context.active_object
return (ob and ob.type=='MESH')
def execute(self, context):
if not self.path:
raise Exception("filename not set")
write(self.path, context.scene, context.active_object,
self.start_frame, self.end_frame, self.fps )
return ('FINISHED',)
def invoke(self, context, event):
wm = context.manager
wm.add_fileselect(self)
return ('RUNNING_MODAL',)
def execute(self, context):
if not self.path:
raise Exception("filename not set")
write(self.path, context.scene, context.active_object,
self.start_frame, self.end_frame, self.fps )
return ('FINISHED',)
def invoke(self, context, event):
wm = context.manager
wm.add_fileselect(self)
return ('RUNNING_MODAL',)
bpy.ops.add(EXPORT_OT_mdd)
bpy.ops.add(ExportMDD)
# Add to a menu
import dynamic_menu
menu_func = lambda self, context: self.layout.itemO("export.mdd", text="Vertex Keyframe Animation (.mdd)...")
def menu_func(self, context):
default_path = bpy.data.filename.replace(".blend", ".mdd")
self.layout.item_stringO(ExportMDD.bl_idname, "path", default_path, text="Vertex Keyframe Animation (.mdd)...")
menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_export, menu_func)
if __name__=='__main__':
#if not pack:
# Draw.PupMenu('Error%t|This script requires a full python install')
#Blender.Window.FileSelector(mdd_export_ui, 'EXPORT MDD', sys.makename(ext='.mdd'))
bpy.ops.EXPORT_OT_mdd(path="/tmp/test.mdd")
#Blender.Window.FileSelector(mdd_export_ui, 'EXPORT MDD', sys.makename(ext='.mdd'))
bpy.ops.EXPORT_OT_mdd(path="/tmp/test.mdd")

@ -223,11 +223,11 @@ def copy_images(dest_dir):
copyCount = 0
# for bImage in uniqueImages.values():
# image_path = bpy.sys.expandpath(bImage.filename)
# image_path = bpy.utils.expandpath(bImage.filename)
# if bpy.sys.exists(image_path):
# # Make a name for the target path.
# dest_image_path = dest_dir + image_path.split('\\')[-1].split('/')[-1]
# if not bpy.sys.exists(dest_image_path): # Image isnt alredy there
# if not bpy.utils.exists(dest_image_path): # Image isnt alredy there
# print('\tCopying "%s" > "%s"' % (image_path, dest_image_path))
# copy_file(image_path, dest_image_path)
# copyCount+=1
@ -932,7 +932,7 @@ Currently the exporter lacks these features:
from bpy.props import *
class EXPORT_OT_obj(bpy.types.Operator):
class ExportOBJ(bpy.types.Operator):
'''Save a Wavefront OBJ File'''
bl_idname = "export.obj"
@ -1002,10 +1002,14 @@ class EXPORT_OT_obj(bpy.types.Operator):
print("Poll")
return context.active_object != None
bpy.ops.add(EXPORT_OT_obj)
bpy.ops.add(ExportOBJ)
import dynamic_menu
menu_func = lambda self, context: self.layout.itemO("export.obj", text="Wavefront (.obj)...")
def menu_func(self, context):
default_path = bpy.data.filename.replace(".blend", ".obj")
self.layout.item_stringO(ExportOBJ.bl_idname, "path", default_path, text="Wavefront (.obj)...")
menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_export, menu_func)
if __name__ == "__main__":

@ -252,7 +252,7 @@ def write(filename, scene, ob, \
from bpy.props import *
class EXPORT_OT_ply(bpy.types.Operator):
class ExportPLY(bpy.types.Operator):
'''Export a single object as a stanford PLY with normals, colours and texture coordinates.'''
bl_idname = "export.ply"
bl_label = "Export PLY"
@ -292,10 +292,14 @@ class EXPORT_OT_ply(bpy.types.Operator):
return ('RUNNING_MODAL',)
bpy.ops.add(EXPORT_OT_ply)
bpy.ops.add(ExportPLY)
import dynamic_menu
menu_func = lambda self, context: self.layout.itemO("export.ply", text="Stanford (.ply)...")
def menu_func(self, context):
default_path = bpy.data.filename.replace(".blend", ".ply")
self.layout.item_stringO(ExportPLY.bl_idname, "path", default_path, text="Stanford (.ply)...")
menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_export, menu_func)
if __name__ == "__main__":

@ -1215,7 +1215,7 @@ def x3d_export_ui(filename):
from bpy.props import *
class EXPORT_OT_x3d(bpy.types.Operator):
class ExportX3D(bpy.types.Operator):
'''Export selection to Extensible 3D file (.x3d)'''
bl_idname = "export.x3d"
bl_label = 'Export X3D'
@ -1238,10 +1238,14 @@ class EXPORT_OT_x3d(bpy.types.Operator):
wm.add_fileselect(self)
return ('RUNNING_MODAL',)
bpy.ops.add(EXPORT_OT_x3d)
bpy.ops.add(ExportX3D)
import dynamic_menu
menu_func = lambda self, context: self.layout.itemO("export.x3d", text="X3D Extensible 3D (.x3d)...")
def menu_func(self, context):
default_path = bpy.data.filename.replace(".blend", ".x3d")
self.layout.item_stringO(ExportX3D.bl_idname, "path", default_path, text="X3D Extensible 3D (.x3d)...")
menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_export, menu_func)
# NOTES

@ -0,0 +1,881 @@
import math
# import Blender
import bpy
# import BPyMessages
import Mathutils
Vector= Mathutils.Vector
Euler= Mathutils.Euler
Matrix= Mathutils.Matrix
RotationMatrix= Mathutils.RotationMatrix
TranslationMatrix= Mathutils.TranslationMatrix
# NASTY GLOBAL
ROT_STYLE = 'QUAT'
DEG2RAD = 0.017453292519943295
class bvh_node_class(object):
__slots__=(\
'name',# bvh joint name
'parent',# bvh_node_class type or None for no parent
'children',# a list of children of this type.
'rest_head_world',# worldspace rest location for the head of this node
'rest_head_local',# localspace rest location for the head of this node
'rest_tail_world',# # worldspace rest location for the tail of this node
'rest_tail_local',# # worldspace rest location for the tail of this node
'channels',# list of 6 ints, -1 for an unused channel, otherwise an index for the BVH motion data lines, lock triple then rot triple
'rot_order',# a triple of indicies as to the order rotation is applied. [0,1,2] is x/y/z - [None, None, None] if no rotation.
'anim_data',# a list one tuple's one for each frame. (locx, locy, locz, rotx, roty, rotz)
'has_loc',# Conveinience function, bool, same as (channels[0]!=-1 or channels[1]!=-1 channels[2]!=-1)
'has_rot',# Conveinience function, bool, same as (channels[3]!=-1 or channels[4]!=-1 channels[5]!=-1)
'temp')# use this for whatever you want
def __init__(self, name, rest_head_world, rest_head_local, parent, channels, rot_order):
self.name= name
self.rest_head_world= rest_head_world
self.rest_head_local= rest_head_local
self.rest_tail_world= None
self.rest_tail_local= None
self.parent= parent
self.channels= channels
self.rot_order= rot_order
# convenience functions
self.has_loc= channels[0] != -1 or channels[1] != -1 or channels[2] != -1
self.has_rot= channels[3] != -1 or channels[4] != -1 or channels[5] != -1
self.children= []
# list of 6 length tuples: (lx,ly,lz, rx,ry,rz)
# even if the channels arnt used they will just be zero
#
self.anim_data= [(0,0,0,0,0,0)]
def __repr__(self):
return 'BVH name:"%s", rest_loc:(%.3f,%.3f,%.3f), rest_tail:(%.3f,%.3f,%.3f)' %\
(self.name,\
self.rest_head_world.x, self.rest_head_world.y, self.rest_head_world.z,\
self.rest_head_world.x, self.rest_head_world.y, self.rest_head_world.z)
# Change the order rotation is applied.
MATRIX_IDENTITY_3x3 = Matrix([1,0,0],[0,1,0],[0,0,1])
MATRIX_IDENTITY_4x4 = Matrix([1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1])
def eulerRotate(x,y,z, rot_order):
# Clamp all values between 0 and 360, values outside this raise an error.
mats=[RotationMatrix(math.radians(x%360),3,'x'), RotationMatrix(math.radians(y%360),3,'y'), RotationMatrix(math.radians(z%360),3,'z')]
# print rot_order
# Standard BVH multiplication order, apply the rotation in the order Z,X,Y
#XXX, order changes???
#eul = (mats[rot_order[2]]*(mats[rot_order[1]]* (mats[rot_order[0]]* MATRIX_IDENTITY_3x3))).toEuler()
eul = (MATRIX_IDENTITY_3x3*mats[rot_order[0]]*(mats[rot_order[1]]* (mats[rot_order[2]]))).toEuler()
eul = math.degrees(eul.x), math.degrees(eul.y), math.degrees(eul.z)
return eul
def read_bvh(context, file_path, GLOBAL_SCALE=1.0):
# File loading stuff
# Open the file for importing
file = open(file_path, 'rU')
# Seperate into a list of lists, each line a list of words.
file_lines = file.readlines()
# Non standard carrage returns?
if len(file_lines) == 1:
file_lines = file_lines[0].split('\r')
# Split by whitespace.
file_lines =[ll for ll in [ l.split() for l in file_lines] if ll]
# Create Hirachy as empties
if file_lines[0][0].lower() == 'hierarchy':
#print 'Importing the BVH Hierarchy for:', file_path
pass
else:
raise 'ERROR: This is not a BVH file'
bvh_nodes= {None:None}
bvh_nodes_serial = [None]
channelIndex = -1
lineIdx = 0 # An index for the file.
while lineIdx < len(file_lines) -1:
#...
if file_lines[lineIdx][0].lower() == 'root' or file_lines[lineIdx][0].lower() == 'joint':
# Join spaces into 1 word with underscores joining it.
if len(file_lines[lineIdx]) > 2:
file_lines[lineIdx][1] = '_'.join(file_lines[lineIdx][1:])
file_lines[lineIdx] = file_lines[lineIdx][:2]
# MAY NEED TO SUPPORT MULTIPLE ROOT's HERE!!!, Still unsure weather multiple roots are possible.??
# Make sure the names are unique- Object names will match joint names exactly and both will be unique.
name = file_lines[lineIdx][1]
#print '%snode: %s, parent: %s' % (len(bvh_nodes_serial) * ' ', name, bvh_nodes_serial[-1])
lineIdx += 2 # Incriment to the next line (Offset)
rest_head_local = Vector( GLOBAL_SCALE*float(file_lines[lineIdx][1]), GLOBAL_SCALE*float(file_lines[lineIdx][2]), GLOBAL_SCALE*float(file_lines[lineIdx][3]) )
lineIdx += 1 # Incriment to the next line (Channels)
# newChannel[Xposition, Yposition, Zposition, Xrotation, Yrotation, Zrotation]
# newChannel references indecies to the motiondata,
# if not assigned then -1 refers to the last value that will be added on loading at a value of zero, this is appended
# We'll add a zero value onto the end of the MotionDATA so this is always refers to a value.
my_channel = [-1, -1, -1, -1, -1, -1]
my_rot_order= [None, None, None]
rot_count= 0
for channel in file_lines[lineIdx][2:]:
channel= channel.lower()
channelIndex += 1 # So the index points to the right channel
if channel == 'xposition': my_channel[0] = channelIndex
elif channel == 'yposition': my_channel[1] = channelIndex
elif channel == 'zposition': my_channel[2] = channelIndex
elif channel == 'xrotation':
my_channel[3] = channelIndex
my_rot_order[rot_count]= 0
rot_count+=1
elif channel == 'yrotation':
my_channel[4] = channelIndex
my_rot_order[rot_count]= 1
rot_count+=1
elif channel == 'zrotation':
my_channel[5] = channelIndex
my_rot_order[rot_count]= 2
rot_count+=1
channels = file_lines[lineIdx][2:]
my_parent= bvh_nodes_serial[-1] # account for none
# Apply the parents offset accumletivly
if my_parent==None:
rest_head_world= Vector(rest_head_local)
else:
rest_head_world= my_parent.rest_head_world + rest_head_local
bvh_node= bvh_nodes[name]= bvh_node_class(name, rest_head_world, rest_head_local, my_parent, my_channel, my_rot_order)
# If we have another child then we can call ourselves a parent, else
bvh_nodes_serial.append(bvh_node)
# Account for an end node
if file_lines[lineIdx][0].lower() == 'end' and file_lines[lineIdx][1].lower() == 'site': # There is somtimes a name after 'End Site' but we will ignore it.
lineIdx += 2 # Incriment to the next line (Offset)
rest_tail = Vector( GLOBAL_SCALE*float(file_lines[lineIdx][1]), GLOBAL_SCALE*float(file_lines[lineIdx][2]), GLOBAL_SCALE*float(file_lines[lineIdx][3]) )
bvh_nodes_serial[-1].rest_tail_world= bvh_nodes_serial[-1].rest_head_world + rest_tail
bvh_nodes_serial[-1].rest_tail_local= rest_tail
# Just so we can remove the Parents in a uniform way- End end never has kids
# so this is a placeholder
bvh_nodes_serial.append(None)
if len(file_lines[lineIdx]) == 1 and file_lines[lineIdx][0] == '}': # == ['}']
bvh_nodes_serial.pop() # Remove the last item
if len(file_lines[lineIdx]) == 1 and file_lines[lineIdx][0].lower() == 'motion':
#print '\nImporting motion data'
lineIdx += 3 # Set the cursor to the first frame
break
lineIdx += 1
# Remove the None value used for easy parent reference
del bvh_nodes[None]
# Dont use anymore
del bvh_nodes_serial
bvh_nodes_list= bvh_nodes.values()
while lineIdx < len(file_lines):
line= file_lines[lineIdx]
for bvh_node in bvh_nodes_list:
#for bvh_node in bvh_nodes_serial:
lx= ly= lz= rx= ry= rz= 0.0
channels= bvh_node.channels
anim_data= bvh_node.anim_data
if channels[0] != -1:
lx= GLOBAL_SCALE * float( line[channels[0]] )
if channels[1] != -1:
ly= GLOBAL_SCALE * float( line[channels[1]] )
if channels[2] != -1:
lz= GLOBAL_SCALE * float( line[channels[2]] )
if channels[3] != -1 or channels[4] != -1 or channels[5] != -1:
rx, ry, rz = float( line[channels[3]] ), float( line[channels[4]] ), float( line[channels[5]] )
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.
while anim_data[-1][3] - rx > 180: rx+=360
while anim_data[-1][3] - rx < -180: rx-=360
while anim_data[-1][4] - ry > 180: ry+=360
while anim_data[-1][4] - ry < -180: ry-=360
while anim_data[-1][5] - rz > 180: rz+=360
while anim_data[-1][5] - rz < -180: rz-=360
# Done importing motion data #
anim_data.append( (lx, ly, lz, rx, ry, rz) )
lineIdx += 1
# Assign children
for bvh_node in bvh_nodes.values():
bvh_node_parent= bvh_node.parent
if bvh_node_parent:
bvh_node_parent.children.append(bvh_node)
# Now set the tip of each bvh_node
for bvh_node in bvh_nodes.values():
if not bvh_node.rest_tail_world:
if len(bvh_node.children)==0:
# could just fail here, but rare BVH files have childless nodes
bvh_node.rest_tail_world = Vector(bvh_node.rest_head_world)
bvh_node.rest_tail_local = Vector(bvh_node.rest_head_local)
elif len(bvh_node.children)==1:
bvh_node.rest_tail_world= Vector(bvh_node.children[0].rest_head_world)
bvh_node.rest_tail_local= Vector(bvh_node.children[0].rest_head_local)
else:
# allow this, see above
#if not bvh_node.children:
# raise 'error, bvh node has no end and no children. bad file'
# Removed temp for now
rest_tail_world= Vector(0,0,0)
rest_tail_local= Vector(0,0,0)
for bvh_node_child in bvh_node.children:
rest_tail_world += bvh_node_child.rest_head_world
rest_tail_local += bvh_node_child.rest_head_local
bvh_node.rest_tail_world= rest_tail_world * (1.0/len(bvh_node.children))
bvh_node.rest_tail_local= rest_tail_local * (1.0/len(bvh_node.children))
# Make sure tail isnt the same location as the head.
if (bvh_node.rest_tail_local-bvh_node.rest_head_local).length <= 0.001*GLOBAL_SCALE:
bvh_node.rest_tail_local.y= bvh_node.rest_tail_local.y + GLOBAL_SCALE/10
bvh_node.rest_tail_world.y= bvh_node.rest_tail_world.y + GLOBAL_SCALE/10
return bvh_nodes
def bvh_node_dict2objects(context, bvh_nodes, IMPORT_START_FRAME= 1, IMPORT_LOOP= False):
if IMPORT_START_FRAME<1:
IMPORT_START_FRAME= 1
scn= context.scene
scn.objects.selected = []
objects= []
def add_ob(name):
ob = scn.objects.new('Empty')
objects.append(ob)
return ob
# Add objects
for name, bvh_node in bvh_nodes.items():
bvh_node.temp= add_ob(name)
# Parent the objects
for bvh_node in bvh_nodes.values():
bvh_node.temp.makeParent([ bvh_node_child.temp for bvh_node_child in bvh_node.children ], 1, 0) # ojbs, noninverse, 1 = not fast.
# Offset
for bvh_node in bvh_nodes.values():
# Make relative to parents offset
bvh_node.temp.loc= bvh_node.rest_head_local
# Add tail objects
for name, bvh_node in bvh_nodes.items():
if not bvh_node.children:
ob_end= add_ob(name + '_end')
bvh_node.temp.makeParent([ob_end], 1, 0) # ojbs, noninverse, 1 = not fast.
ob_end.loc= bvh_node.rest_tail_local
# 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)):
Blender.Set('curframe', current_frame+IMPORT_START_FRAME)
for bvh_node in bvh_nodes.values():
lx,ly,lz,rx,ry,rz= bvh_node.anim_data[current_frame]
rest_head_local= bvh_node.rest_head_local
bvh_node.temp.loc= rest_head_local.x+lx, rest_head_local.y+ly, rest_head_local.z+lz
bvh_node.temp.rot= rx*DEG2RAD,ry*DEG2RAD,rz*DEG2RAD
bvh_node.temp.insertIpoKey(Blender.Object.IpoKeyTypes.LOCROT)
scn.update(1)
return objects
def bvh_node_dict2armature(context, bvh_nodes, IMPORT_START_FRAME= 1, IMPORT_LOOP= False):
if IMPORT_START_FRAME<1:
IMPORT_START_FRAME= 1
# Add the new armature,
scn = context.scene
#XXX scn.objects.selected = []
for ob in scn.objects:
ob.selected = False
#XXX arm_data= bpy.data.armatures.new()
#XXX arm_ob = scn.objects.new(arm_data)
bpy.ops.object.armature_add()
arm_ob= scn.objects[-1]
arm_data= arm_ob.data
#XXX scn.objects.context = [arm_ob]
#XXX scn.objects.active = arm_ob
arm_ob.selected= True
scn.objects.active= arm_ob
print(scn.objects.active)
# Put us into editmode
#XXX arm_data.makeEditable()
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
bpy.ops.object.mode_set(mode='EDIT', toggle=False)
# Get the average bone length for zero length bones, we may not use this.
average_bone_length= 0.0
nonzero_count= 0
for bvh_node in bvh_nodes.values():
l= (bvh_node.rest_head_local-bvh_node.rest_tail_local).length
if l:
average_bone_length+= l
nonzero_count+=1
# Very rare cases all bones couldbe zero length???
if not average_bone_length:
average_bone_length = 0.1
else:
# Normal operation
average_bone_length = average_bone_length/nonzero_count
#XXX - sloppy operator code
bpy.ops.armature.delete()
bpy.ops.armature.select_all_toggle()
bpy.ops.armature.delete()
ZERO_AREA_BONES= []
for name, bvh_node in bvh_nodes.items():
# New editbone
bpy.ops.armature.bone_primitive_add(name="Bone")
#XXX bone= bvh_node.temp= Blender.Armature.Editbone()
bone= bvh_node.temp= arm_data.edit_bones[-1]
bone.name= name
# arm_data.bones[name]= bone
bone.head= bvh_node.rest_head_world
bone.tail= bvh_node.rest_tail_world
# ZERO AREA BONES.
if (bone.head-bone.tail).length < 0.001:
if bvh_node.parent:
ofs= bvh_node.parent.rest_head_local- bvh_node.parent.rest_tail_local
if ofs.length: # is our parent zero length also?? unlikely
bone.tail= bone.tail+ofs
else:
bone.tail.y= bone.tail.y+average_bone_length
else:
bone.tail.y= bone.tail.y+average_bone_length
ZERO_AREA_BONES.append(bone.name)
for bvh_node in bvh_nodes.values():
if bvh_node.parent:
# bvh_node.temp is the Editbone
# Set the bone parent
bvh_node.temp.parent= bvh_node.parent.temp
# Set the connection state
if not bvh_node.has_loc and\
bvh_node.parent and\
bvh_node.parent.temp.name not in ZERO_AREA_BONES and\
bvh_node.parent.rest_tail_local == bvh_node.rest_head_local:
bvh_node.temp.connected= True
# Replace the editbone with the editbone name,
# to avoid memory errors accessing the editbone outside editmode
for bvh_node in bvh_nodes.values():
bvh_node.temp= bvh_node.temp.name
#XXX arm_data.update()
# Now Apply the animation to the armature
# Get armature animation data
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
bpy.ops.object.mode_set(mode='POSE', toggle=False)
pose= arm_ob.pose
pose_bones= pose.pose_channels
if ROT_STYLE=='NATIVE':
eul_order_lookup = {\
(0,1,2):'XYZ',
(0,2,1):'XZY',
(1,0,2):'YXZ',
(1,2,0):'YZX',
(2,0,1):'ZXY',
(2,1,0):'ZYZ'
}
for bvh_node in bvh_nodes.values():
bone_name= bvh_node.temp # may not be the same name as the bvh_node, could have been shortened.
pose_bone= pose_bones[bone_name]
pose_bone.rotation_mode = eul_order_lookup[tuple(bvh_node.rot_order)]
elif ROT_STYLE=='XYZ':
for pose_bone in pose_bones:
pose_bone.rotation_mode = 'XYZ'
else:
# Quats default
pass
bpy.ops.pose.select_all_toggle() # set
bpy.ops.anim.insert_keyframe_menu(type=-4) # XXX - -4 ???
#for p in pose_bones:
# print(p)
#XXX action = Blender.Armature.NLA.NewAction("Action")
#XXX action.setActive(arm_ob)
#bpy.ops.act.new()
#action = bpy.data.actions[-1]
# arm_ob.animation_data.action = action
action = arm_ob.animation_data.action
#xformConstants= [ Blender.Object.Pose.LOC, Blender.Object.Pose.ROT ]
# Replace the bvh_node.temp (currently an editbone)
# With a tuple (pose_bone, armature_bone, bone_rest_matrix, bone_rest_matrix_inv)
for bvh_node in bvh_nodes.values():
bone_name= bvh_node.temp # may not be the same name as the bvh_node, could have been shortened.
pose_bone= pose_bones[bone_name]
rest_bone= arm_data.bones[bone_name]
#XXX bone_rest_matrix = rest_bone.matrix['ARMATURESPACE'].rotationPart()
bone_rest_matrix = rest_bone.matrix.rotationPart()
bone_rest_matrix_inv= Matrix(bone_rest_matrix)
bone_rest_matrix_inv.invert()
bone_rest_matrix_inv.resize4x4()
bone_rest_matrix.resize4x4()
bvh_node.temp= (pose_bone, bone, bone_rest_matrix, bone_rest_matrix_inv)
# Make a dict for fast access without rebuilding a list all the time.
'''
xformConstants_dict={
(True,True): [Blender.Object.Pose.LOC, Blender.Object.Pose.ROT],\
(False,True): [Blender.Object.Pose.ROT],\
(True,False): [Blender.Object.Pose.LOC],\
(False,False): [],\
}
'''
# KEYFRAME METHOD, SLOW, USE IPOS DIRECT
# 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)
# print current_frame
#if current_frame==150: # debugging
# break
# Dont neet to set the current frame
for bvh_node in bvh_nodes.values():
pose_bone, bone, bone_rest_matrix, bone_rest_matrix_inv= bvh_node.temp
lx,ly,lz,rx,ry,rz= bvh_node.anim_data[current_frame+1]
if bvh_node.has_rot:
if ROT_STYLE=='QUAT':
# Set the rotation, not so simple
bone_rotation_matrix= Euler(math.radians(rx), math.radians(ry), math.radians(rz)).toMatrix()
bone_rotation_matrix.resize4x4()
#XXX ORDER CHANGE???
#pose_bone.rotation_quaternion= (bone_rest_matrix * bone_rotation_matrix * bone_rest_matrix_inv).toQuat() # ORIGINAL
# pose_bone.rotation_quaternion= (bone_rest_matrix_inv * bone_rotation_matrix * bone_rest_matrix).toQuat()
# pose_bone.rotation_quaternion= (bone_rotation_matrix * bone_rest_matrix).toQuat() # BAD
# pose_bone.rotation_quaternion= bone_rotation_matrix.toQuat() # NOT GOOD
# pose_bone.rotation_quaternion= bone_rotation_matrix.toQuat() # NOT GOOD
#pose_bone.rotation_quaternion= (bone_rotation_matrix * bone_rest_matrix_inv * bone_rest_matrix).toQuat()
#pose_bone.rotation_quaternion= (bone_rest_matrix_inv * bone_rest_matrix * bone_rotation_matrix).toQuat()
#pose_bone.rotation_quaternion= (bone_rest_matrix * bone_rotation_matrix * bone_rest_matrix_inv).toQuat()
#pose_bone.rotation_quaternion= ( bone_rest_matrix* bone_rest_matrix_inv * bone_rotation_matrix).toQuat()
#pose_bone.rotation_quaternion= (bone_rotation_matrix * bone_rest_matrix * bone_rest_matrix_inv).toQuat()
#pose_bone.rotation_quaternion= (bone_rest_matrix_inv * bone_rotation_matrix * bone_rest_matrix ).toQuat()
pose_bone.rotation_quaternion= (bone_rest_matrix_inv * bone_rotation_matrix * bone_rest_matrix).toQuat()
else:
bone_rotation_matrix= Euler(math.radians(rx), math.radians(ry), math.radians(rz)).toMatrix()
bone_rotation_matrix.resize4x4()
eul= (bone_rest_matrix * bone_rotation_matrix * bone_rest_matrix_inv).toEuler()
#pose_bone.rotation_euler = math.radians(rx), math.radians(ry), math.radians(rz)
pose_bone.rotation_euler = eul
print("ROTATION" + str(Euler(math.radians(rx), math.radians(ry), math.radians(rz))))
if bvh_node.has_loc:
# Set the Location, simple too
#XXX ORDER CHANGE
# pose_bone.location= (TranslationMatrix(Vector(lx, ly, lz) - bvh_node.rest_head_local ) * bone_rest_matrix_inv).translationPart() # WHY * 10? - just how pose works
# pose_bone.location= (bone_rest_matrix_inv * TranslationMatrix(Vector(lx, ly, lz) - bvh_node.rest_head_local )).translationPart()
# pose_bone.location= lx, ly, lz
pose_bone.location= Vector(lx, ly, lz) - bvh_node.rest_head_local
#XXX # TODO- add in 2.5
if 0:
# Get the transform
xformConstants= xformConstants_dict[bvh_node.has_loc, bvh_node.has_rot]
if xformConstants:
# Insert the keyframe from the loc/quat
pose_bone.insertKey(arm_ob, current_frame+IMPORT_START_FRAME, xformConstants, True )
else:
if bvh_node.has_loc:
pose_bone.keyframe_insert("location")
if bvh_node.has_rot:
if ROT_STYLE=='QUAT':
pose_bone.keyframe_insert("rotation_quaternion")
else:
pose_bone.keyframe_insert("rotation_euler")
# bpy.ops.anim.insert_keyframe_menu(type=-4) # XXX - -4 ???
bpy.ops.screen.frame_offset(delta=1)
# First time, set the IPO's to linear
#XXX #TODO
if 0:
if current_frame==0:
for ipo in action.getAllChannelIpos().values():
if ipo:
for cur in ipo:
cur.interpolation = Blender.IpoCurve.InterpTypes.LINEAR
if IMPORT_LOOP:
cur.extend = Blender.IpoCurve.ExtendTypes.CYCLIC
else:
for cu in action.fcurves:
for bez in cu.keyframe_points:
bez.interpolation = 'CONSTANT'
# END KEYFRAME METHOD
"""
# IPO KEYFRAME SETTING
# Add in the IPOs by adding keyframes, AFAIK theres no way to add IPOs to an action so I do this :/
for bvh_node in bvh_nodes.values():
pose_bone, bone, bone_rest_matrix, bone_rest_matrix_inv= bvh_node.temp
# Get the transform
xformConstants= xformConstants_dict[bvh_node.has_loc, bvh_node.has_rot]
if xformConstants:
pose_bone.loc[:]= 0,0,0
pose_bone.quat[:]= 0,0,1,0
# Insert the keyframe from the loc/quat
pose_bone.insertKey(arm_ob, IMPORT_START_FRAME, xformConstants)
action_ipos= action.getAllChannelIpos()
for bvh_node in bvh_nodes.values():
has_loc= bvh_node.has_loc
has_rot= bvh_node.has_rot
if not has_rot and not has_loc:
# No animation data
continue
ipo= action_ipos[bvh_node.temp[0].name] # posebones name as key
if has_loc:
curve_xloc= ipo[Blender.Ipo.PO_LOCX]
curve_yloc= ipo[Blender.Ipo.PO_LOCY]
curve_zloc= ipo[Blender.Ipo.PO_LOCZ]
curve_xloc.interpolation= \
curve_yloc.interpolation= \
curve_zloc.interpolation= \
Blender.IpoCurve.InterpTypes.LINEAR
if has_rot:
curve_wquat= ipo[Blender.Ipo.PO_QUATW]
curve_xquat= ipo[Blender.Ipo.PO_QUATX]
curve_yquat= ipo[Blender.Ipo.PO_QUATY]
curve_zquat= ipo[Blender.Ipo.PO_QUATZ]
curve_wquat.interpolation= \
curve_xquat.interpolation= \
curve_yquat.interpolation= \
curve_zquat.interpolation= \
Blender.IpoCurve.InterpTypes.LINEAR
# Get the bone
pose_bone, bone, bone_rest_matrix, bone_rest_matrix_inv= bvh_node.temp
def pose_rot(anim_data):
bone_rotation_matrix= Euler(anim_data[3], anim_data[4], anim_data[5]).toMatrix()
bone_rotation_matrix.resize4x4()
return tuple((bone_rest_matrix * bone_rotation_matrix * bone_rest_matrix_inv).toQuat()) # qw,qx,qy,qz
def pose_loc(anim_data):
return tuple((TranslationMatrix(Vector(anim_data[0], anim_data[1], anim_data[2])) * bone_rest_matrix_inv).translationPart())
last_frame= len(bvh_node.anim_data)+IMPORT_START_FRAME-1
if has_loc:
pose_locations= [pose_loc(anim_key) for anim_key in bvh_node.anim_data]
# Add the start at the end, we know the start is just 0,0,0 anyway
curve_xloc.append((last_frame, pose_locations[-1][0]))
curve_yloc.append((last_frame, pose_locations[-1][1]))
curve_zloc.append((last_frame, pose_locations[-1][2]))
if len(pose_locations) > 1:
ox,oy,oz= pose_locations[0]
x,y,z= pose_locations[1]
for i in range(1, len(pose_locations)-1): # from second frame to second last frame
nx,ny,nz= pose_locations[i+1]
xset= yset= zset= True # we set all these by default
if abs((ox+nx)/2 - x) < 0.00001: xset= False
if abs((oy+ny)/2 - y) < 0.00001: yset= False
if abs((oz+nz)/2 - z) < 0.00001: zset= False
if xset: curve_xloc.append((i+IMPORT_START_FRAME, x))
if yset: curve_yloc.append((i+IMPORT_START_FRAME, y))
if zset: curve_zloc.append((i+IMPORT_START_FRAME, z))
# Set the old and use the new
ox,oy,oz= x,y,z
x,y,z= nx,ny,nz
if has_rot:
pose_rotations= [pose_rot(anim_key) for anim_key in bvh_node.anim_data]
# Add the start at the end, we know the start is just 0,0,0 anyway
curve_wquat.append((last_frame, pose_rotations[-1][0]))
curve_xquat.append((last_frame, pose_rotations[-1][1]))
curve_yquat.append((last_frame, pose_rotations[-1][2]))
curve_zquat.append((last_frame, pose_rotations[-1][3]))
if len(pose_rotations) > 1:
ow,ox,oy,oz= pose_rotations[0]
w,x,y,z= pose_rotations[1]
for i in range(1, len(pose_rotations)-1): # from second frame to second last frame
nw, nx,ny,nz= pose_rotations[i+1]
wset= xset= yset= zset= True # we set all these by default
if abs((ow+nw)/2 - w) < 0.00001: wset= False
if abs((ox+nx)/2 - x) < 0.00001: xset= False
if abs((oy+ny)/2 - y) < 0.00001: yset= False
if abs((oz+nz)/2 - z) < 0.00001: zset= False
if wset: curve_wquat.append((i+IMPORT_START_FRAME, w))
if xset: curve_xquat.append((i+IMPORT_START_FRAME, x))
if yset: curve_yquat.append((i+IMPORT_START_FRAME, y))
if zset: curve_zquat.append((i+IMPORT_START_FRAME, z))
# Set the old and use the new
ow,ox,oy,oz= w,x,y,z
w,x,y,z= nw,nx,ny,nz
# IPO KEYFRAME SETTING
"""
# XXX NOT NEEDED NOW?
# pose.update()
return arm_ob
#=============#
# TESTING #
#=============#
#('/metavr/mocap/bvh/boxer.bvh')
#('/d/staggered_walk.bvh')
#('/metavr/mocap/bvh/dg-306-g.bvh') # Incompleate EOF
#('/metavr/mocap/bvh/wa8lk.bvh') # duplicate joint names, \r line endings.
#('/metavr/mocap/bvh/walk4.bvh') # 0 channels
'''
import os
DIR = '/metavr/mocap/bvh/'
for f in ('/d/staggered_walk.bvh',):
#for f in os.listdir(DIR)[5:6]:
#for f in os.listdir(DIR):
if f.endswith('.bvh'):
s = Blender.Scene.New(f)
s.makeCurrent()
#file= DIR + f
file= f
print f
bvh_nodes= read_bvh(file, 1.0)
bvh_node_dict2armature(bvh_nodes, 1)
'''
def load_bvh_ui(context, file, PREF_UI= False):
#XXX if BPyMessages.Error_NoFile(file):
#XXX return
#XXX Draw= Blender.Draw
IMPORT_SCALE = 0.1
IMPORT_START_FRAME = 1
IMPORT_AS_ARMATURE = 1
IMPORT_AS_EMPTIES = 0
IMPORT_LOOP = 0
# Get USER Options
if PREF_UI:
pup_block = [\
('As Armature', IMPORT_AS_ARMATURE, 'Imports the BVH as an armature'),\
('As Empties', IMPORT_AS_EMPTIES, 'Imports the BVH as empties'),\
('Scale: ', IMPORT_SCALE, 0.001, 100.0, 'Scale the BVH, Use 0.01 when 1.0 is 1 metre'),\
('Start Frame: ', IMPORT_START_FRAME, 1, 30000, 'Frame to start BVH motion'),\
('Loop Animation', IMPORT_LOOP, 'Enable cyclic IPOs'),\
]
#XXX if not Draw.PupBlock('BVH Import...', pup_block):
#XXX return
# print('Attempting import BVH', file)
if not IMPORT_AS_ARMATURE and not IMPORT_AS_EMPTIES:
raise('No import option selected')
#XXX Blender.Window.WaitCursor(1)
# Get the BVH data and act on it.
import time
t1= time.time()
print('\tparsing bvh...', end= "")
bvh_nodes= read_bvh(context, file, IMPORT_SCALE)
print('%.4f' % (time.time()-t1))
t1= time.time()
print('\timporting to blender...', end="")
if IMPORT_AS_ARMATURE: bvh_node_dict2armature(context, bvh_nodes, IMPORT_START_FRAME, IMPORT_LOOP)
if IMPORT_AS_EMPTIES: bvh_node_dict2objects(context, bvh_nodes, IMPORT_START_FRAME, IMPORT_LOOP)
print('Done in %.4f\n' % (time.time()-t1))
#XXX Blender.Window.WaitCursor(0)
def main():
Blender.Window.FileSelector(load_bvh_ui, 'Import BVH', '*.bvh')
from bpy.props import *
class BvhImporter(bpy.types.Operator):
'''Load a Wavefront OBJ File.'''
bl_idname = "import_anim.bvh"
bl_label = "Import BVH"
path = StringProperty(name="File Path", description="File path used for importing the OBJ file", maxlen= 1024, default= "")
def execute(self, context):
# print("Selected: " + context.active_object.name)
read_bvh(context, self.path)
return ('FINISHED',)
def invoke(self, context, event):
wm = context.manager
wm.add_fileselect(self)
return ('RUNNING_MODAL',)
bpy.ops.add(BvhImporter)
import dynamic_menu
menu_func = lambda self, context: self.layout.itemO(BvhImporter.bl_idname, text="Motion Capture (.bvh)...")
menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_import, menu_func)

@ -0,0 +1,881 @@
import math
# import Blender
import bpy
# import BPyMessages
import Mathutils
Vector= Mathutils.Vector
Euler= Mathutils.Euler
Matrix= Mathutils.Matrix
RotationMatrix= Mathutils.RotationMatrix
TranslationMatrix= Mathutils.TranslationMatrix
# NASTY GLOBAL
ROT_STYLE = 'QUAT'
DEG2RAD = 0.017453292519943295
class bvh_node_class(object):
__slots__=(\
'name',# bvh joint name
'parent',# bvh_node_class type or None for no parent
'children',# a list of children of this type.
'rest_head_world',# worldspace rest location for the head of this node
'rest_head_local',# localspace rest location for the head of this node
'rest_tail_world',# # worldspace rest location for the tail of this node
'rest_tail_local',# # worldspace rest location for the tail of this node
'channels',# list of 6 ints, -1 for an unused channel, otherwise an index for the BVH motion data lines, lock triple then rot triple
'rot_order',# a triple of indicies as to the order rotation is applied. [0,1,2] is x/y/z - [None, None, None] if no rotation.
'anim_data',# a list one tuple's one for each frame. (locx, locy, locz, rotx, roty, rotz)
'has_loc',# Conveinience function, bool, same as (channels[0]!=-1 or channels[1]!=-1 channels[2]!=-1)
'has_rot',# Conveinience function, bool, same as (channels[3]!=-1 or channels[4]!=-1 channels[5]!=-1)
'temp')# use this for whatever you want
def __init__(self, name, rest_head_world, rest_head_local, parent, channels, rot_order):
self.name= name
self.rest_head_world= rest_head_world
self.rest_head_local= rest_head_local
self.rest_tail_world= None
self.rest_tail_local= None
self.parent= parent
self.channels= channels
self.rot_order= rot_order
# convenience functions
self.has_loc= channels[0] != -1 or channels[1] != -1 or channels[2] != -1
self.has_rot= channels[3] != -1 or channels[4] != -1 or channels[5] != -1
self.children= []
# list of 6 length tuples: (lx,ly,lz, rx,ry,rz)
# even if the channels arnt used they will just be zero
#
self.anim_data= [(0,0,0,0,0,0)]
def __repr__(self):
return 'BVH name:"%s", rest_loc:(%.3f,%.3f,%.3f), rest_tail:(%.3f,%.3f,%.3f)' %\
(self.name,\
self.rest_head_world.x, self.rest_head_world.y, self.rest_head_world.z,\
self.rest_head_world.x, self.rest_head_world.y, self.rest_head_world.z)
# Change the order rotation is applied.
MATRIX_IDENTITY_3x3 = Matrix([1,0,0],[0,1,0],[0,0,1])
MATRIX_IDENTITY_4x4 = Matrix([1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1])
def eulerRotate(x,y,z, rot_order):
# Clamp all values between 0 and 360, values outside this raise an error.
mats=[RotationMatrix(math.radians(x%360),3,'x'), RotationMatrix(math.radians(y%360),3,'y'), RotationMatrix(math.radians(z%360),3,'z')]
# print rot_order
# Standard BVH multiplication order, apply the rotation in the order Z,X,Y
#XXX, order changes???
#eul = (mats[rot_order[2]]*(mats[rot_order[1]]* (mats[rot_order[0]]* MATRIX_IDENTITY_3x3))).toEuler()
eul = (MATRIX_IDENTITY_3x3*mats[rot_order[0]]*(mats[rot_order[1]]* (mats[rot_order[2]]))).toEuler()
eul = math.degrees(eul.x), math.degrees(eul.y), math.degrees(eul.z)
return eul
def read_bvh(context, file_path, GLOBAL_SCALE=1.0):
# File loading stuff
# Open the file for importing
file = open(file_path, 'rU')
# Seperate into a list of lists, each line a list of words.
file_lines = file.readlines()
# Non standard carrage returns?
if len(file_lines) == 1:
file_lines = file_lines[0].split('\r')
# Split by whitespace.
file_lines =[ll for ll in [ l.split() for l in file_lines] if ll]
# Create Hirachy as empties
if file_lines[0][0].lower() == 'hierarchy':
#print 'Importing the BVH Hierarchy for:', file_path
pass
else:
raise 'ERROR: This is not a BVH file'
bvh_nodes= {None:None}
bvh_nodes_serial = [None]
channelIndex = -1
lineIdx = 0 # An index for the file.
while lineIdx < len(file_lines) -1:
#...
if file_lines[lineIdx][0].lower() == 'root' or file_lines[lineIdx][0].lower() == 'joint':
# Join spaces into 1 word with underscores joining it.
if len(file_lines[lineIdx]) > 2:
file_lines[lineIdx][1] = '_'.join(file_lines[lineIdx][1:])
file_lines[lineIdx] = file_lines[lineIdx][:2]
# MAY NEED TO SUPPORT MULTIPLE ROOT's HERE!!!, Still unsure weather multiple roots are possible.??
# Make sure the names are unique- Object names will match joint names exactly and both will be unique.
name = file_lines[lineIdx][1]
#print '%snode: %s, parent: %s' % (len(bvh_nodes_serial) * ' ', name, bvh_nodes_serial[-1])
lineIdx += 2 # Incriment to the next line (Offset)
rest_head_local = Vector( GLOBAL_SCALE*float(file_lines[lineIdx][1]), GLOBAL_SCALE*float(file_lines[lineIdx][2]), GLOBAL_SCALE*float(file_lines[lineIdx][3]) )
lineIdx += 1 # Incriment to the next line (Channels)
# newChannel[Xposition, Yposition, Zposition, Xrotation, Yrotation, Zrotation]
# newChannel references indecies to the motiondata,
# if not assigned then -1 refers to the last value that will be added on loading at a value of zero, this is appended
# We'll add a zero value onto the end of the MotionDATA so this is always refers to a value.
my_channel = [-1, -1, -1, -1, -1, -1]
my_rot_order= [None, None, None]
rot_count= 0
for channel in file_lines[lineIdx][2:]:
channel= channel.lower()
channelIndex += 1 # So the index points to the right channel
if channel == 'xposition': my_channel[0] = channelIndex
elif channel == 'yposition': my_channel[1] = channelIndex
elif channel == 'zposition': my_channel[2] = channelIndex
elif channel == 'xrotation':
my_channel[3] = channelIndex
my_rot_order[rot_count]= 0
rot_count+=1
elif channel == 'yrotation':
my_channel[4] = channelIndex
my_rot_order[rot_count]= 1
rot_count+=1
elif channel == 'zrotation':
my_channel[5] = channelIndex
my_rot_order[rot_count]= 2
rot_count+=1
channels = file_lines[lineIdx][2:]
my_parent= bvh_nodes_serial[-1] # account for none
# Apply the parents offset accumletivly
if my_parent==None:
rest_head_world= Vector(rest_head_local)
else:
rest_head_world= my_parent.rest_head_world + rest_head_local
bvh_node= bvh_nodes[name]= bvh_node_class(name, rest_head_world, rest_head_local, my_parent, my_channel, my_rot_order)
# If we have another child then we can call ourselves a parent, else
bvh_nodes_serial.append(bvh_node)
# Account for an end node
if file_lines[lineIdx][0].lower() == 'end' and file_lines[lineIdx][1].lower() == 'site': # There is somtimes a name after 'End Site' but we will ignore it.
lineIdx += 2 # Incriment to the next line (Offset)
rest_tail = Vector( GLOBAL_SCALE*float(file_lines[lineIdx][1]), GLOBAL_SCALE*float(file_lines[lineIdx][2]), GLOBAL_SCALE*float(file_lines[lineIdx][3]) )
bvh_nodes_serial[-1].rest_tail_world= bvh_nodes_serial[-1].rest_head_world + rest_tail
bvh_nodes_serial[-1].rest_tail_local= rest_tail
# Just so we can remove the Parents in a uniform way- End end never has kids
# so this is a placeholder
bvh_nodes_serial.append(None)
if len(file_lines[lineIdx]) == 1 and file_lines[lineIdx][0] == '}': # == ['}']
bvh_nodes_serial.pop() # Remove the last item
if len(file_lines[lineIdx]) == 1 and file_lines[lineIdx][0].lower() == 'motion':
#print '\nImporting motion data'
lineIdx += 3 # Set the cursor to the first frame
break
lineIdx += 1
# Remove the None value used for easy parent reference
del bvh_nodes[None]
# Dont use anymore
del bvh_nodes_serial
bvh_nodes_list= bvh_nodes.values()
while lineIdx < len(file_lines):
line= file_lines[lineIdx]
for bvh_node in bvh_nodes_list:
#for bvh_node in bvh_nodes_serial:
lx= ly= lz= rx= ry= rz= 0.0
channels= bvh_node.channels
anim_data= bvh_node.anim_data
if channels[0] != -1:
lx= GLOBAL_SCALE * float( line[channels[0]] )
if channels[1] != -1:
ly= GLOBAL_SCALE * float( line[channels[1]] )
if channels[2] != -1:
lz= GLOBAL_SCALE * float( line[channels[2]] )
if channels[3] != -1 or channels[4] != -1 or channels[5] != -1:
rx, ry, rz = float( line[channels[3]] ), float( line[channels[4]] ), float( line[channels[5]] )
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.
while anim_data[-1][3] - rx > 180: rx+=360
while anim_data[-1][3] - rx < -180: rx-=360
while anim_data[-1][4] - ry > 180: ry+=360
while anim_data[-1][4] - ry < -180: ry-=360
while anim_data[-1][5] - rz > 180: rz+=360
while anim_data[-1][5] - rz < -180: rz-=360
# Done importing motion data #
anim_data.append( (lx, ly, lz, rx, ry, rz) )
lineIdx += 1
# Assign children
for bvh_node in bvh_nodes.values():
bvh_node_parent= bvh_node.parent
if bvh_node_parent:
bvh_node_parent.children.append(bvh_node)
# Now set the tip of each bvh_node
for bvh_node in bvh_nodes.values():
if not bvh_node.rest_tail_world:
if len(bvh_node.children)==0:
# could just fail here, but rare BVH files have childless nodes
bvh_node.rest_tail_world = Vector(bvh_node.rest_head_world)
bvh_node.rest_tail_local = Vector(bvh_node.rest_head_local)
elif len(bvh_node.children)==1:
bvh_node.rest_tail_world= Vector(bvh_node.children[0].rest_head_world)
bvh_node.rest_tail_local= Vector(bvh_node.children[0].rest_head_local)
else:
# allow this, see above
#if not bvh_node.children:
# raise 'error, bvh node has no end and no children. bad file'
# Removed temp for now
rest_tail_world= Vector(0,0,0)
rest_tail_local= Vector(0,0,0)
for bvh_node_child in bvh_node.children:
rest_tail_world += bvh_node_child.rest_head_world
rest_tail_local += bvh_node_child.rest_head_local
bvh_node.rest_tail_world= rest_tail_world * (1.0/len(bvh_node.children))
bvh_node.rest_tail_local= rest_tail_local * (1.0/len(bvh_node.children))
# Make sure tail isnt the same location as the head.
if (bvh_node.rest_tail_local-bvh_node.rest_head_local).length <= 0.001*GLOBAL_SCALE:
bvh_node.rest_tail_local.y= bvh_node.rest_tail_local.y + GLOBAL_SCALE/10
bvh_node.rest_tail_world.y= bvh_node.rest_tail_world.y + GLOBAL_SCALE/10
return bvh_nodes
def bvh_node_dict2objects(context, bvh_nodes, IMPORT_START_FRAME= 1, IMPORT_LOOP= False):
if IMPORT_START_FRAME<1:
IMPORT_START_FRAME= 1
scn= context.scene
scn.objects.selected = []
objects= []
def add_ob(name):
ob = scn.objects.new('Empty')
objects.append(ob)
return ob
# Add objects
for name, bvh_node in bvh_nodes.items():
bvh_node.temp= add_ob(name)
# Parent the objects
for bvh_node in bvh_nodes.values():
bvh_node.temp.makeParent([ bvh_node_child.temp for bvh_node_child in bvh_node.children ], 1, 0) # ojbs, noninverse, 1 = not fast.
# Offset
for bvh_node in bvh_nodes.values():
# Make relative to parents offset
bvh_node.temp.loc= bvh_node.rest_head_local
# Add tail objects
for name, bvh_node in bvh_nodes.items():
if not bvh_node.children:
ob_end= add_ob(name + '_end')
bvh_node.temp.makeParent([ob_end], 1, 0) # ojbs, noninverse, 1 = not fast.
ob_end.loc= bvh_node.rest_tail_local
# 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)):
Blender.Set('curframe', current_frame+IMPORT_START_FRAME)
for bvh_node in bvh_nodes.values():
lx,ly,lz,rx,ry,rz= bvh_node.anim_data[current_frame]
rest_head_local= bvh_node.rest_head_local
bvh_node.temp.loc= rest_head_local.x+lx, rest_head_local.y+ly, rest_head_local.z+lz
bvh_node.temp.rot= rx*DEG2RAD,ry*DEG2RAD,rz*DEG2RAD
bvh_node.temp.insertIpoKey(Blender.Object.IpoKeyTypes.LOCROT)
scn.update(1)
return objects
def bvh_node_dict2armature(context, bvh_nodes, IMPORT_START_FRAME= 1, IMPORT_LOOP= False):
if IMPORT_START_FRAME<1:
IMPORT_START_FRAME= 1
# Add the new armature,
scn = context.scene
#XXX scn.objects.selected = []
for ob in scn.objects:
ob.selected = False
#XXX arm_data= bpy.data.armatures.new()
#XXX arm_ob = scn.objects.new(arm_data)
bpy.ops.object.armature_add()
arm_ob= scn.objects[-1]
arm_data= arm_ob.data
#XXX scn.objects.context = [arm_ob]
#XXX scn.objects.active = arm_ob
arm_ob.selected= True
scn.objects.active= arm_ob
print(scn.objects.active)
# Put us into editmode
#XXX arm_data.makeEditable()
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
bpy.ops.object.mode_set(mode='EDIT', toggle=False)
# Get the average bone length for zero length bones, we may not use this.
average_bone_length= 0.0
nonzero_count= 0
for bvh_node in bvh_nodes.values():
l= (bvh_node.rest_head_local-bvh_node.rest_tail_local).length
if l:
average_bone_length+= l
nonzero_count+=1
# Very rare cases all bones couldbe zero length???
if not average_bone_length:
average_bone_length = 0.1
else:
# Normal operation
average_bone_length = average_bone_length/nonzero_count
#XXX - sloppy operator code
bpy.ops.armature.delete()
bpy.ops.armature.select_all_toggle()
bpy.ops.armature.delete()
ZERO_AREA_BONES= []
for name, bvh_node in bvh_nodes.items():
# New editbone
bpy.ops.armature.bone_primitive_add(name="Bone")
#XXX bone= bvh_node.temp= Blender.Armature.Editbone()
bone= bvh_node.temp= arm_data.edit_bones[-1]
bone.name= name
# arm_data.bones[name]= bone
bone.head= bvh_node.rest_head_world
bone.tail= bvh_node.rest_tail_world
# ZERO AREA BONES.
if (bone.head-bone.tail).length < 0.001:
if bvh_node.parent:
ofs= bvh_node.parent.rest_head_local- bvh_node.parent.rest_tail_local
if ofs.length: # is our parent zero length also?? unlikely
bone.tail= bone.tail+ofs
else:
bone.tail.y= bone.tail.y+average_bone_length
else:
bone.tail.y= bone.tail.y+average_bone_length
ZERO_AREA_BONES.append(bone.name)
for bvh_node in bvh_nodes.values():
if bvh_node.parent:
# bvh_node.temp is the Editbone
# Set the bone parent
bvh_node.temp.parent= bvh_node.parent.temp
# Set the connection state
if not bvh_node.has_loc and\
bvh_node.parent and\
bvh_node.parent.temp.name not in ZERO_AREA_BONES and\
bvh_node.parent.rest_tail_local == bvh_node.rest_head_local:
bvh_node.temp.connected= True
# Replace the editbone with the editbone name,
# to avoid memory errors accessing the editbone outside editmode
for bvh_node in bvh_nodes.values():
bvh_node.temp= bvh_node.temp.name
#XXX arm_data.update()
# Now Apply the animation to the armature
# Get armature animation data
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
bpy.ops.object.mode_set(mode='POSE', toggle=False)
pose= arm_ob.pose
pose_bones= pose.pose_channels
if ROT_STYLE=='NATIVE':
eul_order_lookup = {\
(0,1,2):'XYZ',
(0,2,1):'XZY',
(1,0,2):'YXZ',
(1,2,0):'YZX',
(2,0,1):'ZXY',
(2,1,0):'ZYZ'
}
for bvh_node in bvh_nodes.values():
bone_name= bvh_node.temp # may not be the same name as the bvh_node, could have been shortened.
pose_bone= pose_bones[bone_name]
pose_bone.rotation_mode = eul_order_lookup[tuple(bvh_node.rot_order)]
elif ROT_STYLE=='XYZ':
for pose_bone in pose_bones:
pose_bone.rotation_mode = 'XYZ'
else:
# Quats default
pass
bpy.ops.pose.select_all_toggle() # set
bpy.ops.anim.insert_keyframe_menu(type=-4) # XXX - -4 ???
#for p in pose_bones:
# print(p)
#XXX action = Blender.Armature.NLA.NewAction("Action")
#XXX action.setActive(arm_ob)
#bpy.ops.act.new()
#action = bpy.data.actions[-1]
# arm_ob.animation_data.action = action
action = arm_ob.animation_data.action
#xformConstants= [ Blender.Object.Pose.LOC, Blender.Object.Pose.ROT ]
# Replace the bvh_node.temp (currently an editbone)
# With a tuple (pose_bone, armature_bone, bone_rest_matrix, bone_rest_matrix_inv)
for bvh_node in bvh_nodes.values():
bone_name= bvh_node.temp # may not be the same name as the bvh_node, could have been shortened.
pose_bone= pose_bones[bone_name]
rest_bone= arm_data.bones[bone_name]
#XXX bone_rest_matrix = rest_bone.matrix['ARMATURESPACE'].rotationPart()
bone_rest_matrix = rest_bone.matrix.rotationPart()
bone_rest_matrix_inv= Matrix(bone_rest_matrix)
bone_rest_matrix_inv.invert()
bone_rest_matrix_inv.resize4x4()
bone_rest_matrix.resize4x4()
bvh_node.temp= (pose_bone, bone, bone_rest_matrix, bone_rest_matrix_inv)
# Make a dict for fast access without rebuilding a list all the time.
'''
xformConstants_dict={
(True,True): [Blender.Object.Pose.LOC, Blender.Object.Pose.ROT],\
(False,True): [Blender.Object.Pose.ROT],\
(True,False): [Blender.Object.Pose.LOC],\
(False,False): [],\
}
'''
# KEYFRAME METHOD, SLOW, USE IPOS DIRECT
# 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)
# print current_frame
#if current_frame==150: # debugging
# break
# Dont neet to set the current frame
for bvh_node in bvh_nodes.values():
pose_bone, bone, bone_rest_matrix, bone_rest_matrix_inv= bvh_node.temp
lx,ly,lz,rx,ry,rz= bvh_node.anim_data[current_frame+1]
if bvh_node.has_rot:
if ROT_STYLE=='QUAT':
# Set the rotation, not so simple
bone_rotation_matrix= Euler(math.radians(rx), math.radians(ry), math.radians(rz)).toMatrix()
bone_rotation_matrix.resize4x4()
#XXX ORDER CHANGE???
#pose_bone.rotation_quaternion= (bone_rest_matrix * bone_rotation_matrix * bone_rest_matrix_inv).toQuat() # ORIGINAL
# pose_bone.rotation_quaternion= (bone_rest_matrix_inv * bone_rotation_matrix * bone_rest_matrix).toQuat()
# pose_bone.rotation_quaternion= (bone_rotation_matrix * bone_rest_matrix).toQuat() # BAD
# pose_bone.rotation_quaternion= bone_rotation_matrix.toQuat() # NOT GOOD
# pose_bone.rotation_quaternion= bone_rotation_matrix.toQuat() # NOT GOOD
#pose_bone.rotation_quaternion= (bone_rotation_matrix * bone_rest_matrix_inv * bone_rest_matrix).toQuat()
#pose_bone.rotation_quaternion= (bone_rest_matrix_inv * bone_rest_matrix * bone_rotation_matrix).toQuat()
#pose_bone.rotation_quaternion= (bone_rest_matrix * bone_rotation_matrix * bone_rest_matrix_inv).toQuat()
#pose_bone.rotation_quaternion= ( bone_rest_matrix* bone_rest_matrix_inv * bone_rotation_matrix).toQuat()
#pose_bone.rotation_quaternion= (bone_rotation_matrix * bone_rest_matrix * bone_rest_matrix_inv).toQuat()
#pose_bone.rotation_quaternion= (bone_rest_matrix_inv * bone_rotation_matrix * bone_rest_matrix ).toQuat()
pose_bone.rotation_quaternion= (bone_rest_matrix_inv * bone_rotation_matrix * bone_rest_matrix).toQuat()
else:
bone_rotation_matrix= Euler(math.radians(rx), math.radians(ry), math.radians(rz)).toMatrix()
bone_rotation_matrix.resize4x4()
eul= (bone_rest_matrix * bone_rotation_matrix * bone_rest_matrix_inv).toEuler()
#pose_bone.rotation_euler = math.radians(rx), math.radians(ry), math.radians(rz)
pose_bone.rotation_euler = eul
print("ROTATION" + str(Euler(math.radians(rx), math.radians(ry), math.radians(rz))))
if bvh_node.has_loc:
# Set the Location, simple too
#XXX ORDER CHANGE
# pose_bone.location= (TranslationMatrix(Vector(lx, ly, lz) - bvh_node.rest_head_local ) * bone_rest_matrix_inv).translationPart() # WHY * 10? - just how pose works
# pose_bone.location= (bone_rest_matrix_inv * TranslationMatrix(Vector(lx, ly, lz) - bvh_node.rest_head_local )).translationPart()
# pose_bone.location= lx, ly, lz
pose_bone.location= Vector(lx, ly, lz) - bvh_node.rest_head_local
#XXX # TODO- add in 2.5
if 0:
# Get the transform
xformConstants= xformConstants_dict[bvh_node.has_loc, bvh_node.has_rot]
if xformConstants:
# Insert the keyframe from the loc/quat
pose_bone.insertKey(arm_ob, current_frame+IMPORT_START_FRAME, xformConstants, True )
else:
if bvh_node.has_loc:
pose_bone.keyframe_insert("location")
if bvh_node.has_rot:
if ROT_STYLE=='QUAT':
pose_bone.keyframe_insert("rotation_quaternion")
else:
pose_bone.keyframe_insert("rotation_euler")
# bpy.ops.anim.insert_keyframe_menu(type=-4) # XXX - -4 ???
bpy.ops.screen.frame_offset(delta=1)
# First time, set the IPO's to linear
#XXX #TODO
if 0:
if current_frame==0:
for ipo in action.getAllChannelIpos().values():
if ipo:
for cur in ipo:
cur.interpolation = Blender.IpoCurve.InterpTypes.LINEAR
if IMPORT_LOOP:
cur.extend = Blender.IpoCurve.ExtendTypes.CYCLIC
else:
for cu in action.fcurves:
for bez in cu.keyframe_points:
bez.interpolation = 'CONSTANT'
# END KEYFRAME METHOD
"""
# IPO KEYFRAME SETTING
# Add in the IPOs by adding keyframes, AFAIK theres no way to add IPOs to an action so I do this :/
for bvh_node in bvh_nodes.values():
pose_bone, bone, bone_rest_matrix, bone_rest_matrix_inv= bvh_node.temp
# Get the transform
xformConstants= xformConstants_dict[bvh_node.has_loc, bvh_node.has_rot]
if xformConstants:
pose_bone.loc[:]= 0,0,0
pose_bone.quat[:]= 0,0,1,0
# Insert the keyframe from the loc/quat
pose_bone.insertKey(arm_ob, IMPORT_START_FRAME, xformConstants)
action_ipos= action.getAllChannelIpos()
for bvh_node in bvh_nodes.values():
has_loc= bvh_node.has_loc
has_rot= bvh_node.has_rot
if not has_rot and not has_loc:
# No animation data
continue
ipo= action_ipos[bvh_node.temp[0].name] # posebones name as key
if has_loc:
curve_xloc= ipo[Blender.Ipo.PO_LOCX]
curve_yloc= ipo[Blender.Ipo.PO_LOCY]
curve_zloc= ipo[Blender.Ipo.PO_LOCZ]
curve_xloc.interpolation= \
curve_yloc.interpolation= \
curve_zloc.interpolation= \
Blender.IpoCurve.InterpTypes.LINEAR
if has_rot:
curve_wquat= ipo[Blender.Ipo.PO_QUATW]
curve_xquat= ipo[Blender.Ipo.PO_QUATX]
curve_yquat= ipo[Blender.Ipo.PO_QUATY]
curve_zquat= ipo[Blender.Ipo.PO_QUATZ]
curve_wquat.interpolation= \
curve_xquat.interpolation= \
curve_yquat.interpolation= \
curve_zquat.interpolation= \
Blender.IpoCurve.InterpTypes.LINEAR
# Get the bone
pose_bone, bone, bone_rest_matrix, bone_rest_matrix_inv= bvh_node.temp
def pose_rot(anim_data):
bone_rotation_matrix= Euler(anim_data[3], anim_data[4], anim_data[5]).toMatrix()
bone_rotation_matrix.resize4x4()
return tuple((bone_rest_matrix * bone_rotation_matrix * bone_rest_matrix_inv).toQuat()) # qw,qx,qy,qz
def pose_loc(anim_data):
return tuple((TranslationMatrix(Vector(anim_data[0], anim_data[1], anim_data[2])) * bone_rest_matrix_inv).translationPart())
last_frame= len(bvh_node.anim_data)+IMPORT_START_FRAME-1
if has_loc:
pose_locations= [pose_loc(anim_key) for anim_key in bvh_node.anim_data]
# Add the start at the end, we know the start is just 0,0,0 anyway
curve_xloc.append((last_frame, pose_locations[-1][0]))
curve_yloc.append((last_frame, pose_locations[-1][1]))
curve_zloc.append((last_frame, pose_locations[-1][2]))
if len(pose_locations) > 1:
ox,oy,oz= pose_locations[0]
x,y,z= pose_locations[1]
for i in range(1, len(pose_locations)-1): # from second frame to second last frame
nx,ny,nz= pose_locations[i+1]
xset= yset= zset= True # we set all these by default
if abs((ox+nx)/2 - x) < 0.00001: xset= False
if abs((oy+ny)/2 - y) < 0.00001: yset= False
if abs((oz+nz)/2 - z) < 0.00001: zset= False
if xset: curve_xloc.append((i+IMPORT_START_FRAME, x))
if yset: curve_yloc.append((i+IMPORT_START_FRAME, y))
if zset: curve_zloc.append((i+IMPORT_START_FRAME, z))
# Set the old and use the new
ox,oy,oz= x,y,z
x,y,z= nx,ny,nz
if has_rot:
pose_rotations= [pose_rot(anim_key) for anim_key in bvh_node.anim_data]
# Add the start at the end, we know the start is just 0,0,0 anyway
curve_wquat.append((last_frame, pose_rotations[-1][0]))
curve_xquat.append((last_frame, pose_rotations[-1][1]))
curve_yquat.append((last_frame, pose_rotations[-1][2]))
curve_zquat.append((last_frame, pose_rotations[-1][3]))
if len(pose_rotations) > 1:
ow,ox,oy,oz= pose_rotations[0]
w,x,y,z= pose_rotations[1]
for i in range(1, len(pose_rotations)-1): # from second frame to second last frame
nw, nx,ny,nz= pose_rotations[i+1]
wset= xset= yset= zset= True # we set all these by default
if abs((ow+nw)/2 - w) < 0.00001: wset= False
if abs((ox+nx)/2 - x) < 0.00001: xset= False
if abs((oy+ny)/2 - y) < 0.00001: yset= False
if abs((oz+nz)/2 - z) < 0.00001: zset= False
if wset: curve_wquat.append((i+IMPORT_START_FRAME, w))
if xset: curve_xquat.append((i+IMPORT_START_FRAME, x))
if yset: curve_yquat.append((i+IMPORT_START_FRAME, y))
if zset: curve_zquat.append((i+IMPORT_START_FRAME, z))
# Set the old and use the new
ow,ox,oy,oz= w,x,y,z
w,x,y,z= nw,nx,ny,nz
# IPO KEYFRAME SETTING
"""
# XXX NOT NEEDED NOW?
# pose.update()
return arm_ob
#=============#
# TESTING #
#=============#
#('/metavr/mocap/bvh/boxer.bvh')
#('/d/staggered_walk.bvh')
#('/metavr/mocap/bvh/dg-306-g.bvh') # Incompleate EOF
#('/metavr/mocap/bvh/wa8lk.bvh') # duplicate joint names, \r line endings.
#('/metavr/mocap/bvh/walk4.bvh') # 0 channels
'''
import os
DIR = '/metavr/mocap/bvh/'
for f in ('/d/staggered_walk.bvh',):
#for f in os.listdir(DIR)[5:6]:
#for f in os.listdir(DIR):
if f.endswith('.bvh'):
s = Blender.Scene.New(f)
s.makeCurrent()
#file= DIR + f
file= f
print f
bvh_nodes= read_bvh(file, 1.0)
bvh_node_dict2armature(bvh_nodes, 1)
'''
def load_bvh_ui(context, file, PREF_UI= False):
#XXX if BPyMessages.Error_NoFile(file):
#XXX return
#XXX Draw= Blender.Draw
IMPORT_SCALE = 0.1
IMPORT_START_FRAME = 1
IMPORT_AS_ARMATURE = 1
IMPORT_AS_EMPTIES = 0
IMPORT_LOOP = 0
# Get USER Options
if PREF_UI:
pup_block = [\
('As Armature', IMPORT_AS_ARMATURE, 'Imports the BVH as an armature'),\
('As Empties', IMPORT_AS_EMPTIES, 'Imports the BVH as empties'),\
('Scale: ', IMPORT_SCALE, 0.001, 100.0, 'Scale the BVH, Use 0.01 when 1.0 is 1 metre'),\
('Start Frame: ', IMPORT_START_FRAME, 1, 30000, 'Frame to start BVH motion'),\
('Loop Animation', IMPORT_LOOP, 'Enable cyclic IPOs'),\
]
#XXX if not Draw.PupBlock('BVH Import...', pup_block):
#XXX return
# print('Attempting import BVH', file)
if not IMPORT_AS_ARMATURE and not IMPORT_AS_EMPTIES:
raise('No import option selected')
#XXX Blender.Window.WaitCursor(1)
# Get the BVH data and act on it.
import time
t1= time.time()
print('\tparsing bvh...', end= "")
bvh_nodes= read_bvh(context, file, IMPORT_SCALE)
print('%.4f' % (time.time()-t1))
t1= time.time()
print('\timporting to blender...', end="")
if IMPORT_AS_ARMATURE: bvh_node_dict2armature(context, bvh_nodes, IMPORT_START_FRAME, IMPORT_LOOP)
if IMPORT_AS_EMPTIES: bvh_node_dict2objects(context, bvh_nodes, IMPORT_START_FRAME, IMPORT_LOOP)
print('Done in %.4f\n' % (time.time()-t1))
#XXX Blender.Window.WaitCursor(0)
def main():
Blender.Window.FileSelector(load_bvh_ui, 'Import BVH', '*.bvh')
from bpy.props import *
class BvhImporter(bpy.types.Operator):
'''Load a Wavefront OBJ File.'''
bl_idname = "import.bvh"
bl_label = "Import BVH"
path = StringProperty(name="File Path", description="File path used for importing the OBJ file", maxlen= 1024, default= "")
def execute(self, context):
# print("Selected: " + context.active_object.name)
read_bvh(context, self.path)
return ('FINISHED',)
def invoke(self, context, event):
wm = context.manager
wm.add_fileselect(self)
return ('RUNNING_MODAL',)
bpy.ops.add(BvhImporter)
import dynamic_menu
menu_func = lambda self, context: self.layout.itemO("import.bvh", text="Motion Capture (.bvh)...")
menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_import, menu_func)

@ -139,7 +139,7 @@ import os
import time
import struct
from import_obj import unpack_face_list, load_image
from import_scene_obj import unpack_face_list, load_image
import bpy
import Mathutils
@ -1143,7 +1143,7 @@ from bpy.props import *
class IMPORT_OT_autodesk_3ds(bpy.types.Operator):
'''Import from 3DS file format (.3ds)'''
bl_idname = "import.autodesk_3ds"
bl_idname = "import_scene.autodesk_3ds"
bl_label = 'Import 3DS'
# List of operator properties, the attributes will be assigned
@ -1167,7 +1167,7 @@ class IMPORT_OT_autodesk_3ds(bpy.types.Operator):
bpy.ops.add(IMPORT_OT_autodesk_3ds)
import dynamic_menu
menu_func = lambda self, context: self.layout.itemO("import.autodesk_3ds", text="3D Studio (.3ds)...")
menu_func = lambda self, context: self.layout.itemO(IMPORT_OT_autodesk_3ds.bl_idname, text="3D Studio (.3ds)...")
menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_import, menu_func)
# NOTES:

@ -1574,7 +1574,7 @@ from bpy.props import *
class IMPORT_OT_obj(bpy.types.Operator):
'''Load a Wavefront OBJ File.'''
bl_idname = "import.obj"
bl_idname = "import_scene.obj"
bl_label = "Import OBJ"
# List of operator properties, the attributes will be assigned
@ -1626,7 +1626,7 @@ bpy.ops.add(IMPORT_OT_obj)
import dynamic_menu
menu_func = lambda self, context: self.layout.itemO("import.obj", text="Wavefront (.obj)...")
menu_func = lambda self, context: self.layout.itemO(IMPORT_OT_obj.bl_idname, text="Wavefront (.obj)...")
menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_import, menu_func)

@ -46,7 +46,7 @@ def addPointCache(job, ob, point_cache, default_path):
if name == "":
name = "".join(["%02X" % ord(c) for c in ob.name])
cache_path = bpy.sys.expandpath(point_cache.filepath) if point_cache.external else default_path
cache_path = bpy.utils.expandpath(point_cache.filepath) if point_cache.external else default_path
index = "%02i" % point_cache.index
@ -111,14 +111,14 @@ def clientSendJob(conn, scene, anim = False):
# LIBRARIES
###########################
for lib in bpy.data.libraries:
job.addFile(bpy.sys.expandpath(lib_path))
job.addFile(bpy.utils.expandpath(lib_path))
###########################
# IMAGES
###########################
for image in bpy.data.images:
if image.source == "FILE" and not image.packed_file:
job.addFile(bpy.sys.expandpath(image.filename))
job.addFile(bpy.utils.expandpath(image.filename))
###########################
# FLUID + POINT CACHE
@ -129,7 +129,7 @@ def clientSendJob(conn, scene, anim = False):
for object in bpy.data.objects:
for modifier in object.modifiers:
if modifier.type == 'FLUID_SIMULATION' and modifier.settings.type == "DOMAIN":
addFluidFiles(job, bpy.sys.expandpath(modifier.settings.path))
addFluidFiles(job, bpy.utils.expandpath(modifier.settings.path))
elif modifier.type == "CLOTH":
addPointCache(job, object, modifier.point_cache, default_path)
elif modifier.type == "SOFT_BODY":
@ -253,3 +253,15 @@ class NetworkRenderEngine(bpy.types.RenderEngine):
conn.close()
def compatible(module):
exec("import " + module)
module = eval(module)
for member in dir(module):
subclass = getattr(module, member)
try: subclass.COMPAT_ENGINES.add('NET_RENDER')
except: pass
del module
compatible("properties_render")
compatible("properties_world")
compatible("properties_material")

@ -0,0 +1,72 @@
# ##### 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 #####
def ord_ind(i1,i2):
if i1<i2: return i1,i2
return i2,i1
def edge_key(ed):
v1, v2 = tuple(ed.verts)
return ord_ind(v1, v2)
def face_edge_keys(face):
verts = tuple(face.verts)
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])
def mesh_edge_keys(mesh):
return [edge_key for face in mesh.faces for edge_key in face.edge_keys()]
def mesh_edge_face_count_dict(mesh, face_edge_keys=None):
# Optional speedup
if face_edge_keys==None:
face_edge_keys = [face.edge_keys() for face in face_list]
face_edge_count = {}
for face_keys in face_edge_keys:
for key in face_keys:
try:
face_edge_count[key] += 1
except:
face_edge_count[key] = 1
return face_edge_count
def mesh_edge_face_count(mesh, face_edge_keys=None):
edge_face_count_dict = mesh.edge_face_count_dict(face_edge_keys)
return [edge_face_count_dict.get(ed.key(), 0) for ed in mesh.edges]
import bpy
# * Edge *
class_obj = bpy.types.MeshEdge
class_obj.key = edge_key
# * Face *
class_obj = bpy.types.MeshFace
class_obj.edge_keys = face_edge_keys
# * Mesh *
class_obj = bpy.types.Mesh
class_obj.edge_keys = mesh_edge_keys
class_obj.edge_face_count = mesh_edge_face_count
class_obj.edge_face_count_dict = mesh_edge_face_count_dict

@ -19,4 +19,4 @@
import bpy
class_obj = bpy.types.Object
class_obj.getChildren = lambda ob: [child for child in bpy.data.objects if child.parent == ob]
class_obj.getChildren = lambda self: [child for child in bpy.data.objects if child.parent == self]

@ -17,3 +17,4 @@
# ##### END GPL LICENSE BLOCK #####
import bpy_ext.Object
import bpy_ext.Mesh

@ -127,6 +127,12 @@ class bpy_ops_submodule_op(object):
'''
__keys__ = ('module', 'func')
def _get_doc(self):
return op_as_string(self.idname())
__doc__ = property(_get_doc)
def __init__(self, module, func):
self.module = module
@ -186,365 +192,3 @@ class bpy_ops_submodule_op(object):
import bpy
bpy.ops = bpy_ops()
# TODO, C macro's cant define settings :|
from bpy.props import *
class MESH_OT_delete_edgeloop(bpy.types.Operator):
'''Export a single object as a stanford PLY with normals,
colours and texture coordinates.'''
bl_idname = "mesh.delete_edgeloop"
bl_label = "Delete Edge Loop"
def execute(self, context):
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",
description="rna context string", maxlen=1024, default="")
rna_reverse_prop = BoolProperty(name="Reverse",
description="Cycle backwards", default=False)
class NullPathMember:
pass
def context_path_validate(context, path):
import sys
try:
value = eval("context.%s" % path)
except AttributeError:
if "'NoneType'" in str(sys.exc_info()[1]):
# One of the items in the rna path is None, just ignore this
value = NullPathMember
else:
# We have a real error in the rna path, dont ignore that
raise
return value
def execute_context_assign(self, context):
if context_path_validate(context, self.path) == NullPathMember:
return ('PASS_THROUGH',)
exec("context.%s=self.value" % self.path)
return ('FINISHED',)
class WM_OT_context_set_boolean(bpy.types.Operator):
'''Set a context value.'''
bl_idname = "wm.context_set_boolean"
bl_label = "Context Set"
path = rna_path_prop
value = BoolProperty(name="Value",
description="Assignment value", default=True)
execute = execute_context_assign
class WM_OT_context_set_int(bpy.types.Operator): # same as enum
'''Set a context value.'''
bl_idname = "wm.context_set_int"
bl_label = "Context Set"
path = rna_path_prop
value = IntProperty(name="Value", description="Assign value", default=0)
execute = execute_context_assign
class WM_OT_context_set_float(bpy.types.Operator): # same as enum
'''Set a context value.'''
bl_idname = "wm.context_set_int"
bl_label = "Context Set"
path = rna_path_prop
value = FloatProperty(name="Value",
description="Assignment value", default=0.0)
execute = execute_context_assign
class WM_OT_context_set_string(bpy.types.Operator): # same as enum
'''Set a context value.'''
bl_idname = "wm.context_set_string"
bl_label = "Context Set"
path = rna_path_prop
value = StringProperty(name="Value",
description="Assign value", maxlen=1024, default="")
execute = execute_context_assign
class WM_OT_context_set_enum(bpy.types.Operator):
'''Set a context value.'''
bl_idname = "wm.context_set_enum"
bl_label = "Context Set"
path = rna_path_prop
value = StringProperty(name="Value",
description="Assignment value (as a string)",
maxlen=1024, default="")
execute = execute_context_assign
class WM_OT_context_toggle(bpy.types.Operator):
'''Toggle a context value.'''
bl_idname = "wm.context_toggle"
bl_label = "Context Toggle"
path = rna_path_prop
def execute(self, context):
if context_path_validate(context, self.path) == NullPathMember:
return ('PASS_THROUGH',)
exec("context.%s=not (context.%s)" % (self.path, self.path))
return ('FINISHED',)
class WM_OT_context_toggle_enum(bpy.types.Operator):
'''Toggle a context value.'''
bl_idname = "wm.context_toggle_enum"
bl_label = "Context Toggle Values"
path = rna_path_prop
value_1 = StringProperty(name="Value", \
description="Toggle enum", maxlen=1024, default="")
value_2 = StringProperty(name="Value", \
description="Toggle enum", maxlen=1024, default="")
def execute(self, context):
if context_path_validate(context, self.path) == NullPathMember:
return ('PASS_THROUGH',)
exec("context.%s = ['%s', '%s'][context.%s!='%s']" % \
(self.path, self.value_1, self.value_2, self.path, self.value_2))
return ('FINISHED',)
class WM_OT_context_cycle_int(bpy.types.Operator):
'''Set a context value. Useful for cycling active material,
vertex keys, groups' etc.'''
bl_idname = "wm.context_cycle_int"
bl_label = "Context Int Cycle"
path = rna_path_prop
reverse = rna_reverse_prop
def execute(self, context):
value = context_path_validate(context, self.path)
if value == NullPathMember:
return ('PASS_THROUGH',)
self.value = value
if self.reverse:
self.value -= 1
else:
self.value += 1
execute_context_assign(self, context)
if self.value != eval("context.%s" % self.path):
# relies on rna clamping int's out of the range
if self.reverse:
self.value = (1 << 32)
else:
self.value = - (1 << 32)
execute_context_assign(self, context)
return ('FINISHED',)
class WM_OT_context_cycle_enum(bpy.types.Operator):
'''Toggle a context value.'''
bl_idname = "wm.context_cycle_enum"
bl_label = "Context Enum Cycle"
path = rna_path_prop
reverse = rna_reverse_prop
def execute(self, context):
value = context_path_validate(context, self.path)
if value == NullPathMember:
return ('PASS_THROUGH',)
orig_value = value
# Have to get rna enum values
rna_struct_str, rna_prop_str = self.path.rsplit('.', 1)
i = rna_prop_str.find('[')
# just incse we get "context.foo.bar[0]"
if i != -1:
rna_prop_str = rna_prop_str[0:i]
rna_struct = eval("context.%s.rna_type" % rna_struct_str)
rna_prop = rna_struct.properties[rna_prop_str]
if type(rna_prop) != bpy.types.EnumProperty:
raise Exception("expected an enum property")
enums = rna_struct.properties[rna_prop_str].items.keys()
orig_index = enums.index(orig_value)
# Have the info we need, advance to the next item
if self.reverse:
if orig_index == 0:
advance_enum = enums[-1]
else:
advance_enum = enums[orig_index-1]
else:
if orig_index == len(enums) - 1:
advance_enum = enums[0]
else:
advance_enum = enums[orig_index + 1]
# set the new value
exec("context.%s=advance_enum" % self.path)
return ('FINISHED',)
doc_id = StringProperty(name="Doc ID",
description="ID for the documentation", maxlen=1024, default="")
doc_new = StringProperty(name="Doc New",
description="", maxlen=1024, default="")
class WM_OT_doc_view(bpy.types.Operator):
'''Load online reference docs'''
bl_idname = "wm.doc_view"
bl_label = "View Documentation"
doc_id = doc_id
_prefix = 'http://www.blender.org/documentation/250PythonDoc'
def _nested_class_string(self, class_string):
ls = []
class_obj = getattr(bpy.types, class_string, None).bl_rna
while class_obj:
ls.insert(0, class_obj)
class_obj = class_obj.nested
return '.'.join([class_obj.identifier for class_obj in ls])
def execute(self, context):
id_split = self.doc_id.split('.')
if len(id_split) == 1: # rna, class
url = '%s/bpy.types.%s-class.html' % (self._prefix, id_split[0])
elif len(id_split) == 2: # rna, class.prop
class_name, class_prop = id_split
# It so happens that epydoc nests these
class_name_full = self._nested_class_string(class_name)
if hasattr(bpy.types, class_name.upper() + '_OT_' + class_prop):
url = '%s/bpy.ops.%s-module.html#%s' % \
(self._prefix, class_name_full, class_prop)
else:
url = '%s/bpy.types.%s-class.html#%s' % \
(self._prefix, class_name_full, class_prop)
else:
return ('PASS_THROUGH',)
import webbrowser
webbrowser.open(url)
return ('FINISHED',)
class WM_OT_doc_edit(bpy.types.Operator):
'''Load online reference docs'''
bl_idname = "wm.doc_edit"
bl_label = "Edit Documentation"
doc_id = doc_id
doc_new = doc_new
_url = "http://www.mindrones.com/blender/svn/xmlrpc.php"
def _send_xmlrpc(self, data_dict):
print("sending data:", data_dict)
import xmlrpc.client
user = 'blenderuser'
pwd = 'blender>user'
docblog = xmlrpc.client.ServerProxy(self._url)
docblog.metaWeblog.newPost(1, user, pwd, data_dict, 1)
def execute(self, context):
class_name, class_prop = self.doc_id.split('.')
if not self.doc_new:
return 'OPERATOR_CANCELLED'
# check if this is an operator
op_name = class_name.upper() + '_OT_' + class_prop
op_class = getattr(bpy.types, op_name, None)
# Upload this to the web server
upload = {}
if op_class:
rna = op_class.bl_rna
doc_orig = rna.description
if doc_orig == self.doc_new:
return 'OPERATOR_CANCELLED'
print("op - old:'%s' -> new:'%s'" % (doc_orig, self.doc_new))
upload["title"] = 'OPERATOR %s:%s' % (self.doc_id, doc_orig)
upload["description"] = self.doc_new
self._send_xmlrpc(upload)
else:
rna = getattr(bpy.types, class_name).bl_rna
doc_orig = rna.properties[class_prop].description
if doc_orig == self.doc_new:
return 'OPERATOR_CANCELLED'
print("rna - old:'%s' -> new:'%s'" % (doc_orig, self.doc_new))
upload["title"] = 'RNA %s:%s' % s(self.doc_id, doc_orig)
upload["description"] = self.doc_new
self._send_xmlrpc(upload)
return ('FINISHED',)
def invoke(self, context, event):
wm = context.manager
wm.invoke_props_popup(self, event)
return ('RUNNING_MODAL',)
bpy.ops.add(MESH_OT_delete_edgeloop)
bpy.ops.add(WM_OT_context_set_boolean)
bpy.ops.add(WM_OT_context_set_int)
bpy.ops.add(WM_OT_context_set_float)
bpy.ops.add(WM_OT_context_set_string)
bpy.ops.add(WM_OT_context_set_enum)
bpy.ops.add(WM_OT_context_toggle)
bpy.ops.add(WM_OT_context_toggle_enum)
bpy.ops.add(WM_OT_context_cycle_enum)
bpy.ops.add(WM_OT_context_cycle_int)
bpy.ops.add(WM_OT_doc_view)
bpy.ops.add(WM_OT_doc_edit)

@ -26,5 +26,5 @@ def expandpath(path):
return path
import types
bpy.sys = types.ModuleType("bpy.sys")
bpy.sys.expandpath = expandpath
bpy.utils = types.ModuleType("bpy.utils")
bpy.utils.expandpath = expandpath

@ -16,10 +16,11 @@
"""This module provides intellisense features such as:
* autocompletion
* calltips (not yet implemented)
* calltips
It unifies all completion plugins and only loads them on demand.
"""
# TODO: file complete if startswith quotes
import os
import re
@ -63,6 +64,9 @@ def complete(line, cursor, namespace, private=True):
:type private: bool
:returns: list of completions, word
:rtype: list, str
>>> complete('re.sr', 5, {'re': re})
(['re.sre_compile', 're.sre_parse'], 're.sr')
"""
re_unquoted_word = RE_UNQUOTED_WORD.search(line[:cursor])
if re_unquoted_word:
@ -99,14 +103,28 @@ def expand(line, cursor, namespace, private=True):
current expanded line, updated cursor position and scrollback
:rtype: str, int, str
>>> expand('os.path.isdir(', 14, {'os': os})[-1]
'isdir(s)\\nReturn true if the pathname refers to an existing directory.'
>>> expand('abs(', 4, {})[-1]
'abs(number) -> number\\nReturn the absolute value of the argument.'
"""
matches, word = complete(line, cursor, namespace, private)
if line[:cursor].strip().endswith('('):
import complete_calltip
matches, word, scrollback = complete_calltip.complete(line,
cursor, namespace)
no_calltip = False
else:
matches, word = complete(line, cursor, namespace, private)
if len(matches) == 1:
scrollback = ''
else:
scrollback = ' '.join([m.split('.')[-1] for m in matches])
no_calltip = True
prefix = os.path.commonprefix(matches)[len(word):]
if prefix:
line = line[:cursor] + prefix + line[cursor:]
cursor += len(prefix)
if len(matches) == 1:
scrollback = ''
else:
scrollback = ' '.join([m.split('.')[-1] for m in matches])
if no_calltip and prefix.endswith('('):
return expand(line, cursor, namespace, private)
return line, cursor, scrollback

@ -74,7 +74,7 @@ def add_torus(major_rad, minor_rad, major_seg, minor_seg):
from bpy.props import *
class AddTorusPrimitive(bpy.types.Operator):
class AddTorus(bpy.types.Operator):
'''Add a torus mesh.'''
bl_idname = "mesh.primitive_torus_add"
bl_label = "Add Torus"
@ -117,7 +117,7 @@ class AddTorusPrimitive(bpy.types.Operator):
ob_new = bpy.data.add_object('MESH', "Torus")
ob_new.data = mesh
scene.add_object(ob_new)
scene.active_object = ob_new
scene.objects.active = ob_new
ob_new.selected = True
ob_new.location = tuple(context.scene.cursor_location)
@ -125,12 +125,12 @@ class AddTorusPrimitive(bpy.types.Operator):
return ('FINISHED',)
# Register the operator
bpy.ops.add(AddTorusPrimitive)
bpy.ops.add(AddTorus)
# Add to a menu
import dynamic_menu
menu_func = (lambda self, context: self.layout.itemO("mesh.primitive_torus_add",
menu_func = (lambda self, context: self.layout.itemO(AddTorus.bl_idname,
text="Torus", icon='ICON_MESH_DONUT'))
menu_item = dynamic_menu.add(bpy.types.INFO_MT_mesh_add, menu_func)

@ -0,0 +1,225 @@
# ##### 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 sys
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
currently each text datablock gets its own
console - bpython_code.InteractiveConsole()
...which is stored in this function.
console_id can be any hashable type
'''
from code import InteractiveConsole
try:
consoles = get_console.consoles
except:
consoles = get_console.consoles = {}
# clear all dead consoles, use text names as IDs
# TODO, find a way to clear IDs
'''
for console_id in list(consoles.keys()):
if console_id not in bpy.data.texts:
del consoles[id]
'''
try:
console, stdout, stderr = consoles[console_id]
except:
namespace = {'__builtins__': __builtins__, 'bpy': bpy}
console = InteractiveConsole(namespace)
import io
stdout = io.StringIO()
stderr = io.StringIO()
consoles[console_id] = console, stdout, stderr
return console, stdout, stderr
class PyConsoleExec(bpy.types.Operator):
'''Execute the current console line as a python expression.'''
bl_idname = "console.execute_" + language_id
bl_label = "Console Execute"
bl_register = False
# Both prompts must be the same length
PROMPT = '>>> '
PROMPT_MULTI = '... '
# is this working???
'''
def poll(self, context):
return (context.space_data.type == 'PYTHON')
'''
# its not :|
def execute(self, context):
sc = context.space_data
try:
line = sc.history[-1].line
except:
return ('CANCELLED',)
if sc.console_type != 'PYTHON':
return ('CANCELLED',)
console, stdout, stderr = get_console(hash(context.region))
# Hack, useful but must add some other way to access
#if "C" not in console.locals:
console.locals["C"] = context
# redirect output
sys.stdout = stdout
sys.stderr = stderr
# run the console
if not line.strip():
line_exec = '\n' # executes a multiline statement
else:
line_exec = line
is_multiline = console.push(line_exec)
stdout.seek(0)
stderr.seek(0)
output = stdout.read()
output_err = stderr.read()
# cleanup
sys.stdout = sys.__stdout__
sys.stderr = sys.__stderr__
sys.last_traceback = None
# So we can reuse, clear all data
stdout.truncate(0)
stderr.truncate(0)
bpy.ops.console.scrollback_append(text=sc.prompt + line, type='INPUT')
if is_multiline:
sc.prompt = self.PROMPT_MULTI
else:
sc.prompt = self.PROMPT
# insert a new blank line
bpy.ops.console.history_append(text="", current_character=0,
remove_duplicates=True)
# Insert the output into the editor
# not quite correct because the order might have changed,
# but ok 99% of the time.
if output:
add_scrollback(output, 'OUTPUT')
if output_err:
add_scrollback(output_err, 'ERROR')
return ('FINISHED',)
class PyConsoleAutocomplete(bpy.types.Operator):
'''Evaluate the namespace up until the cursor and give a list of
options or complete the name if there is only one.'''
bl_idname = "console.autocomplete_" + language_id
bl_label = "Python Console Autocomplete"
bl_register = False
def poll(self, context):
return context.space_data.console_type == 'PYTHON'
def execute(self, context):
from console import intellisense
sc = context.space_data
console = get_console(hash(context.region))[0]
current_line = sc.history[-1]
line = current_line.line
if not console:
return ('CANCELLED',)
if sc.console_type != 'PYTHON':
return ('CANCELLED',)
# This function isnt aware of the text editor or being an operator
# just does the autocomp then copy its results back
current_line.line, current_line.current_character, scrollback = \
intellisense.expand(
line=current_line.line,
cursor=current_line.current_character,
namespace=console.locals,
private='-d' in sys.argv)
# Now we need to copy back the line from blender back into the
# text editor. This will change when we dont use the text editor
# anymore
if scrollback:
add_scrollback(scrollback, 'INFO')
context.area.tag_redraw()
return ('FINISHED',)
class PyConsoleBanner(bpy.types.Operator):
bl_idname = "console.banner_" + language_id
def execute(self, context):
sc = context.space_data
version_string = sys.version.strip().replace('\n', ' ')
add_scrollback(" * Python Interactive Console %s *" % version_string, 'OUTPUT')
add_scrollback("Command History: Up/Down Arrow", 'OUTPUT')
add_scrollback("Cursor: Left/Right Home/End", 'OUTPUT')
add_scrollback("Remove: Backspace/Delete", 'OUTPUT')
add_scrollback("Execute: Enter", 'OUTPUT')
add_scrollback("Autocomplete: Ctrl+Space", 'OUTPUT')
add_scrollback("Ctrl +/- Wheel: Zoom", 'OUTPUT')
add_scrollback("Builtin Modules: bpy, bpy.data, bpy.ops, bpy.props, bpy.types, bpy.context, Mathutils, Geometry, BGL", 'OUTPUT')
add_scrollback("", 'OUTPUT')
add_scrollback("", 'OUTPUT')
sc.prompt = PyConsoleExec.PROMPT
# Add context into the namespace for quick access
console = get_console(hash(context.region))[0]
console.locals["C"] = bpy.context
return ('FINISHED',)
bpy.ops.add(PyConsoleExec)
bpy.ops.add(PyConsoleAutocomplete)
bpy.ops.add(PyConsoleBanner)

@ -0,0 +1,102 @@
# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
import sys
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 os
add_scrollback(os.popen(text).read(), 'OUTPUT')
class ShellConsoleExec(bpy.types.Operator):
'''Execute the current console line as a python expression.'''
bl_idname = "console.execute_" + language_id
bl_label = "Console Execute"
bl_register = False
# Both prompts must be the same length
PROMPT = '$ '
# is this working???
'''
def poll(self, context):
return (context.space_data.type == 'PYTHON')
'''
# its not :|
def execute(self, context):
sc = context.space_data
try:
line = sc.history[-1].line
except:
return ('CANCELLED',)
bpy.ops.console.scrollback_append(text=sc.prompt + line, type='INPUT')
shell_run(line)
# insert a new blank line
bpy.ops.console.history_append(text="", current_character=0,
remove_duplicates=True)
return ('FINISHED',)
class ShellConsoleAutocomplete(bpy.types.Operator):
'''Evaluate the namespace up until the cursor and give a list of
options or complete the name if there is only one.'''
bl_idname = "console.autocomplete_" + language_id
bl_label = "Python Console Autocomplete"
bl_register = False
def poll(self, context):
return context.space_data.console_type == 'PYTHON'
def execute(self, context):
from console import intellisense
sc = context.space_data
# TODO
return ('CANCELLED',)
class ShellConsoleBanner(bpy.types.Operator):
bl_idname = "console.banner_" + language_id
def execute(self, context):
sc = context.space_data
shell_run("bash --version")
sc.prompt = ShellConsoleExec.PROMPT
return ('FINISHED',)
bpy.ops.add(ShellConsoleExec)
bpy.ops.add(ShellConsoleAutocomplete)
bpy.ops.add(ShellConsoleBanner)

@ -0,0 +1,71 @@
# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ##### END GPL LICENSE BLOCK #####
import bpy
def main(context):
ob = context.active_object
bpy.ops.mesh.selection_type(type='FACE')
is_editmode = (ob.mode=='EDIT')
if is_editmode:
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
mesh = ob.data
face_list = [face for face in mesh.faces]
face_edge_keys = [face.edge_keys() for face in face_list]
edge_face_count = mesh.edge_face_count_dict(face_edge_keys)
def test_interior(index):
for key in face_edge_keys[index]:
if edge_face_count[key] < 3:
return False
return True
for index, face in enumerate(face_list):
if(test_interior(index)):
face.selected = True
else:
face.selected = False
if is_editmode:
bpy.ops.object.mode_set(mode='EDIT', toggle=False)
class MeshSelectInteriorFaces(bpy.types.Operator):
'''Select faces where all edges have more then 2 face users.'''
bl_idname = "mesh.faces_select_interior"
bl_label = "Select Interior Faces"
bl_register = True
bl_undo = True
def poll(self, context):
ob = context.active_object
return (ob and ob.type == 'MESH')
def execute(self, context):
main(context)
return ('FINISHED',)
# Register the operator
bpy.ops.add(MeshSelectInteriorFaces)
if __name__ == "__main__":
bpy.ops.mesh.faces_select_interior()

@ -222,22 +222,6 @@ class edgeLoop(object):
# Returns face edges.
# face must have edge data.
# Utility funcs for 2.5, make into a module??
def ord_ind(i1,i2):
if i1<i2: return i1,i2
return i2,i1
def edge_key(ed):
v1,v2 = tuple(ed.verts)
return ord_ind(v1, v2)
def face_edge_keys(f):
verts = tuple(f.verts)
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])
def mesh_faces_extend(me, faces, mat_idx = 0):
orig_facetot = len(me.faces)
@ -272,15 +256,15 @@ def getSelectedEdges(context, me, ob):
if MESH_MODE == 'FACE':
context.scene.tool_settings.mesh_selection_mode = 'EDGE'
# value is [edge, face_sel_user_in]
edge_dict= dict((edge_key(ed), [ed, 0]) for ed in me.edges)
edge_dict= dict((ed.key(), [ed, 0]) for ed in me.edges)
for f in me.faces:
if f.sel:
for edkey in face_edge_keys(f):
if f.selected:
for edkey in f.edge_keys():
edge_dict[edkey][1] += 1
context.scene.tool_settings.mesh_selection_mode = MESH_MODE
return [ ed_data[0] for ed_data in edge_dict.itervalues() if ed_data[1] == 1 ]
return [ ed_data[0] for ed_data in edge_dict.values() if ed_data[1] == 1 ]
@ -296,7 +280,7 @@ def getVertLoops(selEdges, me):
vert_used = [False] * tot
for ed in selEdges:
i1, i2 = edge_key(ed)
i1, i2 = ed.key()
vert_siblings[i1].append(i2)
vert_siblings[i2].append(i1)

File diff suppressed because it is too large Load Diff

@ -1,7 +1,3 @@
# bl_author = ["Campbell Barton aka ideasman42", "Keith Boshoff aka Wahooney"]
# bl_url = ["www.blender.org", "blenderartists.org", "www.python.org"]
# bl_version = "0.2"
# ***** BEGIN GPL LICENSE BLOCK *****
#
# Script copyright (C) Campbell J Barton
@ -25,6 +21,8 @@
# History
#
# Originally written by Campbell Barton aka ideasman42
#
# 2009-11-01: * 2.5 port by Keith "Wahooney" Boshoff
# * Replaced old method with my own, speed is similar (about 0.001 sec on Suzanne)
# but results are far more accurate
@ -38,19 +36,20 @@ import time
from Mathutils import Vector
from bpy.props import *
def applyVertexDirt(me, blur_iterations, blur_strength, clamp_dirt, clamp_clean, dirt_only, sel_only):
def applyVertexDirt(me, blur_iterations, blur_strength, clamp_dirt, clamp_clean, dirt_only):
## Window.WaitCursor(1)
#BPyMesh.meshCalcNormals(me)
vert_tone= [0.0] * len(me.verts)
vert_tone_count= [0] * len(me.verts)
vert_tone = [0.0] * len(me.verts)
min_tone =180.0
max_tone =0.0
# create lookup table for each vertex's connected vertices (via edges)
con = [[] for i in range(len(me.verts))]
con = []
min_tone=180.0
max_tone=0.0
con = [[] for i in range(len(me.verts))]
# add connected verts
for e in me.edges:
@ -73,64 +72,56 @@ def applyVertexDirt(me, blur_iterations, blur_strength, clamp_dirt, clamp_clean,
ang = math.acos(no.dot(vec))
# enforce min/max
ang = max(clamp_dirt, ang)
vert_tone[v.index] = max(clamp_clean, min(clamp_dirt, ang))
if not dirt_only:
ang = min(clamp_clean, ang)
# average vert_tone_list into vert_tonef
# for i, tones in enumerate(vert_tone):
# if vert_tone_count[i]:
# vert_tone[i] = vert_tone[i] / vert_tone_count[i]
# Below we use edges to blur along so the edges need counting, not the faces
vert_tone_count= [0] * len(me.verts)
for ed in me.edges:
vert_tone_count[ed.verts[0]] += 1
vert_tone_count[ed.verts[1]] += 1
# Blur tone
blur = blur_strength
blur_inv = 1.0 - blur_strength
vert_tone[v.index] = ang
# blur tones
for i in range(blur_iterations):
# backup the original tones
orig_vert_tone= list(vert_tone)
orig_vert_tone = list(vert_tone)
for ed in me.edges:
# use connected verts look up for blurring
for j, c in enumerate(con):
for v in c:
vert_tone[j] += blur_strength * orig_vert_tone[v]
i1 = ed.verts[0]
i2 = ed.verts[1]
vert_tone[j] /= len(c) * blur_strength + 1
val1 = (orig_vert_tone[i2]*blur) + (orig_vert_tone[i1]*blur_inv)
val2 = (orig_vert_tone[i1]*blur) + (orig_vert_tone[i2]*blur_inv)
min_tone = min(vert_tone)
max_tone = max(vert_tone)
# Apply the ton divided by the number of faces connected
vert_tone[i1] += val1 / max(vert_tone_count[i1], 1)
vert_tone[i2] += val2 / max(vert_tone_count[i2], 1)
# debug information
# print(min_tone * 2 * math.pi)
# print(max_tone * 2 * math.pi)
# print(clamp_clean)
# print(clamp_dirt)
tone_range = max_tone-min_tone
min_tone= min(vert_tone)
max_tone= max(vert_tone)
print(min_tone)
print(max_tone)
print(clamp_clean)
print(clamp_dirt)
tone_range= max_tone-min_tone
if max_tone==min_tone:
if not tone_range:
return
for lay in me.vertex_colors:
if lay.active:
active_col_layer = lay.data
active_col_layer = None
if len(me.vertex_colors):
for lay in me.vertex_colors:
if lay.active:
active_col_layer = lay.data
else:
bpy.ops.mesh.vertex_color_add()
me.vertex_colors[0].active = True
active_col_layer = me.vertex_colors[0].data
if not active_col_layer:
return('CANCELLED', )
return("CANCELLED", )
for i, f in enumerate(me.faces):
if not sel_only or f.sel:
if not me.use_paint_mask or f.selected:
f_col = active_col_layer[i]
f_col = [f_col.color1, f_col.color2, f_col.color3, f_col.color4]
@ -140,49 +131,47 @@ def applyVertexDirt(me, blur_iterations, blur_strength, clamp_dirt, clamp_clean,
tone = vert_tone[me.verts[v].index]
tone = (tone-min_tone)/tone_range
if dirt_only:
tone = min(tone, 0.5)
tone *= 2
col[0] = tone*col[0]
col[1] = tone*col[1]
col[2] = tone*col[2]
## Window.WaitCursor(0)
class VertexPaintDirt(bpy.types.Operator):
'''This script uses the concavity of vertices to shade the mesh, and optionaly blur the shading to remove artifacts from spesific edges.'''
bl_idname = "mesh.vertex_paint_dirt"
bl_label = "Dirty Vertex Colors"
bl_register = True
bl_undo = True
blur_strength = FloatProperty(name="Blur Strength", description="Blur strength per iteration", default=1.0, min=0.01, max=1.0)
blur_iterations = IntProperty(name="Blur Iterations", description="Number times to blur the colors. (higher blurs more)", default=1, min=0, max=40)
clean_angle = FloatProperty(name="Highlight Angle", description="Less then 90 limits the angle used in the tonal range", default=0.0, min=0.0, max=180.0)
dirt_angle = FloatProperty(name="Dirt Angle", description="Less then 90 limits the angle used in the tonal range", default=180.0, min=0.0, max=180.0)
dirt_only = BoolProperty(name="Dirt Only", description="Dont calculate cleans for convex areas", default=False)
sel_faces_only = BoolProperty(name="Selected Faces Only", description="Only apply to UV/Face selected faces (mix vpain/uvface select)", default=False)
blur_strength = FloatProperty(name = "Blur Strength", description = "Blur strength per iteration", default = 1.0, min = 0.01, max = 1.0)
blur_iterations = IntProperty(name = "Blur Iterations", description = "Number times to blur the colors. (higher blurs more)", default = 1, min = 0, max = 40)
clean_angle = FloatProperty(name = "Highlight Angle", description = "Less then 90 limits the angle used in the tonal range", default = 180.0, min = 0.0, max = 180.0)
dirt_angle = FloatProperty(name = "Dirt Angle", description = "Less then 90 limits the angle used in the tonal range", default = 0.0, min = 0.0, max = 180.0)
dirt_only = BoolProperty(name= "Dirt Only", description = "Dont calculate cleans for convex areas", default = False)
def execute(self, context):
sce= context.scene
ob= context.object
sce = context.scene
ob = context.object
if not ob or ob.type != 'MESH':
print('Error, no active mesh object, aborting.')
print(ob)
print(ob.type)
return('CANCELLED',)
me = ob.data
t = time.time()
applyVertexDirt(me, self.blur_iterations, self.blur_strength, math.radians(self.dirt_angle), math.radians(self.clean_angle), self.dirt_only, self.sel_faces_only)
applyVertexDirt(me, self.blur_iterations, self.blur_strength, math.radians(self.dirt_angle), math.radians(self.clean_angle), self.dirt_only)
print('done in %.6f' % (time.time()-t))
print('Dirt calculated in %.6f' % (time.time()-t))
return('FINISHED',)
bpy.ops.add(VertexPaintDirt)
if __name__ == "__main__":

378
release/scripts/op/wm.py Normal file

@ -0,0 +1,378 @@
# ##### 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-80 compliant>
import bpy
from bpy.props import *
class MESH_OT_delete_edgeloop(bpy.types.Operator):
'''Export a single object as a stanford PLY with normals,
colours and texture coordinates.'''
bl_idname = "mesh.delete_edgeloop"
bl_label = "Delete Edge Loop"
def execute(self, context):
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",
description="rna context string", maxlen=1024, default="")
rna_reverse_prop = BoolProperty(name="Reverse",
description="Cycle backwards", default=False)
class NullPathMember:
pass
def context_path_validate(context, path):
import sys
try:
value = eval("context.%s" % path)
except AttributeError:
if "'NoneType'" in str(sys.exc_info()[1]):
# One of the items in the rna path is None, just ignore this
value = NullPathMember
else:
# We have a real error in the rna path, dont ignore that
raise
return value
def execute_context_assign(self, context):
if context_path_validate(context, self.path) == NullPathMember:
return ('PASS_THROUGH',)
exec("context.%s=self.value" % self.path)
return ('FINISHED',)
class WM_OT_context_set_boolean(bpy.types.Operator):
'''Set a context value.'''
bl_idname = "wm.context_set_boolean"
bl_label = "Context Set"
path = rna_path_prop
value = BoolProperty(name="Value",
description="Assignment value", default=True)
execute = execute_context_assign
class WM_OT_context_set_int(bpy.types.Operator): # same as enum
'''Set a context value.'''
bl_idname = "wm.context_set_int"
bl_label = "Context Set"
path = rna_path_prop
value = IntProperty(name="Value", description="Assign value", default=0)
execute = execute_context_assign
class WM_OT_context_set_float(bpy.types.Operator): # same as enum
'''Set a context value.'''
bl_idname = "wm.context_set_int"
bl_label = "Context Set"
path = rna_path_prop
value = FloatProperty(name="Value",
description="Assignment value", default=0.0)
execute = execute_context_assign
class WM_OT_context_set_string(bpy.types.Operator): # same as enum
'''Set a context value.'''
bl_idname = "wm.context_set_string"
bl_label = "Context Set"
path = rna_path_prop
value = StringProperty(name="Value",
description="Assign value", maxlen=1024, default="")
execute = execute_context_assign
class WM_OT_context_set_enum(bpy.types.Operator):
'''Set a context value.'''
bl_idname = "wm.context_set_enum"
bl_label = "Context Set"
path = rna_path_prop
value = StringProperty(name="Value",
description="Assignment value (as a string)",
maxlen=1024, default="")
execute = execute_context_assign
class WM_OT_context_toggle(bpy.types.Operator):
'''Toggle a context value.'''
bl_idname = "wm.context_toggle"
bl_label = "Context Toggle"
path = rna_path_prop
def execute(self, context):
if context_path_validate(context, self.path) == NullPathMember:
return ('PASS_THROUGH',)
exec("context.%s=not (context.%s)" % (self.path, self.path))
return ('FINISHED',)
class WM_OT_context_toggle_enum(bpy.types.Operator):
'''Toggle a context value.'''
bl_idname = "wm.context_toggle_enum"
bl_label = "Context Toggle Values"
path = rna_path_prop
value_1 = StringProperty(name="Value", \
description="Toggle enum", maxlen=1024, default="")
value_2 = StringProperty(name="Value", \
description="Toggle enum", maxlen=1024, default="")
def execute(self, context):
if context_path_validate(context, self.path) == NullPathMember:
return ('PASS_THROUGH',)
exec("context.%s = ['%s', '%s'][context.%s!='%s']" % \
(self.path, self.value_1, self.value_2, self.path, self.value_2))
return ('FINISHED',)
class WM_OT_context_cycle_int(bpy.types.Operator):
'''Set a context value. Useful for cycling active material,
vertex keys, groups' etc.'''
bl_idname = "wm.context_cycle_int"
bl_label = "Context Int Cycle"
path = rna_path_prop
reverse = rna_reverse_prop
def execute(self, context):
value = context_path_validate(context, self.path)
if value == NullPathMember:
return ('PASS_THROUGH',)
self.value = value
if self.reverse:
self.value -= 1
else:
self.value += 1
execute_context_assign(self, context)
if self.value != eval("context.%s" % self.path):
# relies on rna clamping int's out of the range
if self.reverse:
self.value = (1 << 32)
else:
self.value = - (1 << 32)
execute_context_assign(self, context)
return ('FINISHED',)
class WM_OT_context_cycle_enum(bpy.types.Operator):
'''Toggle a context value.'''
bl_idname = "wm.context_cycle_enum"
bl_label = "Context Enum Cycle"
path = rna_path_prop
reverse = rna_reverse_prop
def execute(self, context):
value = context_path_validate(context, self.path)
if value == NullPathMember:
return ('PASS_THROUGH',)
orig_value = value
# Have to get rna enum values
rna_struct_str, rna_prop_str = self.path.rsplit('.', 1)
i = rna_prop_str.find('[')
# just incse we get "context.foo.bar[0]"
if i != -1:
rna_prop_str = rna_prop_str[0:i]
rna_struct = eval("context.%s.rna_type" % rna_struct_str)
rna_prop = rna_struct.properties[rna_prop_str]
if type(rna_prop) != bpy.types.EnumProperty:
raise Exception("expected an enum property")
enums = rna_struct.properties[rna_prop_str].items.keys()
orig_index = enums.index(orig_value)
# Have the info we need, advance to the next item
if self.reverse:
if orig_index == 0:
advance_enum = enums[-1]
else:
advance_enum = enums[orig_index-1]
else:
if orig_index == len(enums) - 1:
advance_enum = enums[0]
else:
advance_enum = enums[orig_index + 1]
# set the new value
exec("context.%s=advance_enum" % self.path)
return ('FINISHED',)
doc_id = StringProperty(name="Doc ID",
description="ID for the documentation", maxlen=1024, default="")
doc_new = StringProperty(name="Doc New",
description="", maxlen=1024, default="")
class WM_OT_doc_view(bpy.types.Operator):
'''Load online reference docs'''
bl_idname = "wm.doc_view"
bl_label = "View Documentation"
doc_id = doc_id
_prefix = 'http://www.blender.org/documentation/250PythonDoc'
def _nested_class_string(self, class_string):
ls = []
class_obj = getattr(bpy.types, class_string, None).bl_rna
while class_obj:
ls.insert(0, class_obj)
class_obj = class_obj.nested
return '.'.join([class_obj.identifier for class_obj in ls])
def execute(self, context):
id_split = self.doc_id.split('.')
if len(id_split) == 1: # rna, class
url = '%s/bpy.types.%s-class.html' % (self._prefix, id_split[0])
elif len(id_split) == 2: # rna, class.prop
class_name, class_prop = id_split
if hasattr(bpy.types, class_name.upper() + '_OT_' + class_prop):
url = '%s/bpy.ops.%s-module.html#%s' % \
(self._prefix, class_name, class_prop)
else:
# It so happens that epydoc nests these
class_name_full = self._nested_class_string(class_name)
url = '%s/bpy.types.%s-class.html#%s' % \
(self._prefix, class_name_full, class_prop)
else:
return ('PASS_THROUGH',)
import webbrowser
webbrowser.open(url)
return ('FINISHED',)
class WM_OT_doc_edit(bpy.types.Operator):
'''Load online reference docs'''
bl_idname = "wm.doc_edit"
bl_label = "Edit Documentation"
doc_id = doc_id
doc_new = doc_new
_url = "http://www.mindrones.com/blender/svn/xmlrpc.php"
def _send_xmlrpc(self, data_dict):
print("sending data:", data_dict)
import xmlrpc.client
user = 'blenderuser'
pwd = 'blender>user'
docblog = xmlrpc.client.ServerProxy(self._url)
docblog.metaWeblog.newPost(1, user, pwd, data_dict, 1)
def execute(self, context):
class_name, class_prop = self.doc_id.split('.')
if not self.doc_new:
return ('RUNNING_MODAL',)
# check if this is an operator
op_name = class_name.upper() + '_OT_' + class_prop
op_class = getattr(bpy.types, op_name, None)
# Upload this to the web server
upload = {}
if op_class:
rna = op_class.bl_rna
doc_orig = rna.description
if doc_orig == self.doc_new:
return ('RUNNING_MODAL',)
print("op - old:'%s' -> new:'%s'" % (doc_orig, self.doc_new))
upload["title"] = 'OPERATOR %s:%s' % (self.doc_id, doc_orig)
upload["description"] = self.doc_new
self._send_xmlrpc(upload)
else:
rna = getattr(bpy.types, class_name).bl_rna
doc_orig = rna.properties[class_prop].description
if doc_orig == self.doc_new:
return ('RUNNING_MODAL',)
print("rna - old:'%s' -> new:'%s'" % (doc_orig, self.doc_new))
upload["title"] = 'RNA %s:%s' % (self.doc_id, doc_orig)
upload["description"] = self.doc_new
self._send_xmlrpc(upload)
return ('FINISHED',)
def invoke(self, context, event):
wm = context.manager
wm.invoke_props_popup(self, event)
return ('RUNNING_MODAL',)
bpy.ops.add(MESH_OT_delete_edgeloop)
bpy.ops.add(WM_OT_context_set_boolean)
bpy.ops.add(WM_OT_context_set_int)
bpy.ops.add(WM_OT_context_set_float)
bpy.ops.add(WM_OT_context_set_string)
bpy.ops.add(WM_OT_context_set_enum)
bpy.ops.add(WM_OT_context_toggle)
bpy.ops.add(WM_OT_context_toggle_enum)
bpy.ops.add(WM_OT_context_cycle_enum)
bpy.ops.add(WM_OT_context_cycle_int)
bpy.ops.add(WM_OT_doc_view)
bpy.ops.add(WM_OT_doc_edit)

@ -19,6 +19,7 @@
import bpy
def write_some_data(context, path, use_some_setting):
print("running write_some_data...")
pass
from bpy.props import *
@ -33,16 +34,18 @@ class ExportSomeData(bpy.types.Operator):
# TODO, add better example props
path = StringProperty(name="File Path", description="File path used for exporting the PLY file", maxlen= 1024, default= "")
use_some_setting = BoolProperty(name="Apply Modifiers", description="Apply Modifiers to the exported mesh", default= True)
use_setting = BoolProperty(name="Example Boolean", description="Example Tooltip", default= True)
def poll(self, context):
return context.active_object != None
def execute(self, context):
if not self.is_property_set("path"):
raise Exception("filename not set")
write(self.path, context, use_setting, SOME_SETTING = self.use_some_setting)
# # Bug, currently isnt working
#if not self.is_property_set("path"):
# raise Exception("filename not set")
write_some_data(self.path, context, self.use_setting)
return ('FINISHED',)
@ -53,11 +56,11 @@ class ExportSomeData(bpy.types.Operator):
# File selector
wm.add_fileselect(self) # will run self.execute()
return ('RUNNING_MODAL',)
else if 0:
elif 0:
# Redo popup
wm.invoke_props_popup(self, event) #
return ('RUNNING_MODAL',)
else if 0:
elif 0:
return self.execute(context)

@ -4,12 +4,12 @@
# 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.

@ -4,12 +4,12 @@
# 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.

@ -4,12 +4,12 @@
# 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.

@ -4,12 +4,12 @@
# 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.

@ -4,12 +4,12 @@
# 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.

@ -4,12 +4,12 @@
# 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.

@ -4,12 +4,12 @@
# 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.

@ -4,12 +4,12 @@
# 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.
@ -179,20 +179,22 @@ class DATA_PT_shape_keys(DataButtonsPanel):
sub.alignment = 'RIGHT'
subrow = sub.row(align=True)
subrow.active = enable_edit_value
subrow1 = subrow.row(align=True)
subrow1.active = enable_edit_value
if ob.shape_key_lock:
subrow.itemR(ob, "shape_key_lock", icon='ICON_PINNED', text="")
subrow1.itemR(ob, "shape_key_lock", icon='ICON_PINNED', text="")
else:
subrow.itemR(ob, "shape_key_lock", icon='ICON_UNPINNED', text="")
subrow1.itemR(ob, "shape_key_lock", icon='ICON_UNPINNED', text="")
if kb.mute:
subrow.itemR(kb, "mute", icon='ICON_MUTE_IPO_ON', text="")
subrow1.itemR(kb, "mute", icon='ICON_MUTE_IPO_ON', text="")
else:
subrow.itemR(kb, "mute", icon='ICON_MUTE_IPO_OFF', text="")
subrow1.itemR(kb, "mute", icon='ICON_MUTE_IPO_OFF', text="")
subrow.itemR(ob, "shape_key_edit_mode", text="")
subrow = sub.row(align=True)
subrow.itemO("object.shape_key_mirror", icon='ICON_ARROW_LEFTRIGHT', text="")
subrow.itemO("object.shape_key_clear", icon='ICON_X', text="")
sub.itemO("object.shape_key_mirror", icon='ICON_MOD_MIRROR', text="")
sub.itemR(ob, "shape_key_edit_mode", text="")
row = layout.row()
row.itemR(kb, "name")

@ -4,12 +4,12 @@
# 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.

@ -4,12 +4,12 @@
# 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.

@ -4,12 +4,12 @@
# 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.

@ -4,12 +4,12 @@
# 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.

@ -4,12 +4,12 @@
# 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.

@ -4,12 +4,12 @@
# 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.

@ -4,12 +4,12 @@
# 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.
@ -88,7 +88,7 @@ class ConstraintButtonsPanel(bpy.types.Panel):
col = split.column()
col.itemR(con, "chain_length")
col.itemR(con, "targetless")
def CHILD_OF(self, context, layout, con):
self.target_template(layout, con)
@ -129,7 +129,7 @@ class ConstraintButtonsPanel(bpy.types.Panel):
row.itemR(con, "target_z")
self.space_template(layout, con)
def IK(self, context, layout, con):
if context.object.pose.ik_solver == "ITASC":
layout.itemR(con, "ik_type")
@ -168,7 +168,7 @@ class ConstraintButtonsPanel(bpy.types.Panel):
sub = col.column()
sub.active = con.rotation
sub.itemR(con, "orient_weight", text="Rotation", slider=True)
def IK_COPY_POSE(self, context, layout, con):
self.target_template(layout, con)
self.ik_template(layout, con)
@ -212,7 +212,7 @@ class ConstraintButtonsPanel(bpy.types.Panel):
row = layout.row()
row.itemR(con, "weight", text="Weight", slider=True)
row.itemR(con, "distance", text="Distance", slider=True)
def FOLLOW_PATH(self, context, layout, con):
self.target_template(layout, con)
@ -310,7 +310,7 @@ class ConstraintButtonsPanel(bpy.types.Panel):
row = layout.row()
row.itemL(text="Convert:")
row.itemR(con, "owner_space", text="")
def LIMIT_SCALE(self, context, layout, con):
split = layout.split()
@ -351,7 +351,7 @@ class ConstraintButtonsPanel(bpy.types.Panel):
row = layout.row()
row.itemL(text="Convert:")
row.itemR(con, "owner_space", text="")
def COPY_ROTATION(self, context, layout, con):
self.target_template(layout, con)
@ -378,7 +378,7 @@ class ConstraintButtonsPanel(bpy.types.Panel):
layout.itemR(con, "offset")
self.space_template(layout, con)
def COPY_LOCATION(self, context, layout, con):
self.target_template(layout, con)
@ -438,7 +438,7 @@ class ConstraintButtonsPanel(bpy.types.Panel):
row = layout.row()
row.itemL(text="Convert:")
row.itemR(con, "owner_space", text="")
row.itemR(con, "target_space", text="")
def LOCKED_TRACK(self, context, layout, con):
self.target_template(layout, con)
@ -597,17 +597,17 @@ class ConstraintButtonsPanel(bpy.types.Panel):
def SPLINE_IK(self, context, layout, con):
self.target_template(layout, con)
col = layout.column()
col.itemL(text="Spline Fitting:")
col.itemR(con, "chain_length")
col.itemR(con, "even_divisions")
#col.itemR(con, "affect_root") # XXX: this is not that useful yet
col = layout.column()
col.itemL(text="Chain Scaling:")
col.itemR(con, "keep_max_length")
col.itemR(con, "radius_to_thickness")
col.itemR(con, "xz_scaling_mode")
class OBJECT_PT_constraints(ConstraintButtonsPanel):

@ -4,12 +4,12 @@
# 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.
@ -930,63 +930,64 @@ class PARTICLE_PT_vertexgroups(ParticleButtonsPanel):
def draw(self, context):
layout = self.layout
ob = context.object
psys = context.particle_system
part = psys.settings
layout.itemL(text="Nothing here yet.")
# layout.itemL(text="Nothing here yet.")
#row = layout.row()
#row.itemL(text="Vertex Group")
#row.itemL(text="Negate")
row = layout.row()
row.itemL(text="Vertex Group")
row.itemL(text="Negate")
#row = layout.row()
#row.itemR(psys, "vertex_group_density")
#row.itemR(psys, "vertex_group_density_negate", text="")
row = layout.row()
row.item_pointerR(psys, "vertex_group_density", ob, "vertex_groups", text="Density")
row.itemR(psys, "vertex_group_density_negate", text="")
#row = layout.row()
#row.itemR(psys, "vertex_group_velocity")
#row.itemR(psys, "vertex_group_velocity_negate", text="")
row = layout.row()
row.item_pointerR(psys, "vertex_group_velocity", ob, "vertex_groups", text="Velocity")
row.itemR(psys, "vertex_group_velocity_negate", text="")
#row = layout.row()
#row.itemR(psys, "vertex_group_length")
#row.itemR(psys, "vertex_group_length_negate", text="")
row = layout.row()
row.item_pointerR(psys, "vertex_group_length", ob, "vertex_groups", text="Length")
row.itemR(psys, "vertex_group_length_negate", text="")
#row = layout.row()
#row.itemR(psys, "vertex_group_clump")
#row.itemR(psys, "vertex_group_clump_negate", text="")
row = layout.row()
row.item_pointerR(psys, "vertex_group_clump", ob, "vertex_groups", text="Clump")
row.itemR(psys, "vertex_group_clump_negate", text="")
#row = layout.row()
#row.itemR(psys, "vertex_group_kink")
#row.itemR(psys, "vertex_group_kink_negate", text="")
row = layout.row()
row.item_pointerR(psys, "vertex_group_kink", ob, "vertex_groups", text="Kink")
row.itemR(psys, "vertex_group_kink_negate", text="")
#row = layout.row()
#row.itemR(psys, "vertex_group_roughness1")
#row.itemR(psys, "vertex_group_roughness1_negate", text="")
row = layout.row()
row.item_pointerR(psys, "vertex_group_roughness1", ob, "vertex_groups", text="Roughness 1")
row.itemR(psys, "vertex_group_roughness1_negate", text="")
#row = layout.row()
#row.itemR(psys, "vertex_group_roughness2")
#row.itemR(psys, "vertex_group_roughness2_negate", text="")
row = layout.row()
row.item_pointerR(psys, "vertex_group_roughness2", ob, "vertex_groups", text="Roughness 2")
row.itemR(psys, "vertex_group_roughness2_negate", text="")
#row = layout.row()
#row.itemR(psys, "vertex_group_roughness_end")
#row.itemR(psys, "vertex_group_roughness_end_negate", text="")
row = layout.row()
row.item_pointerR(psys, "vertex_group_roughness_end", ob, "vertex_groups", text="Roughness End")
row.itemR(psys, "vertex_group_roughness_end_negate", text="")
#row = layout.row()
#row.itemR(psys, "vertex_group_size")
#row.itemR(psys, "vertex_group_size_negate", text="")
row = layout.row()
row.item_pointerR(psys, "vertex_group_size", ob, "vertex_groups", text="Size")
row.itemR(psys, "vertex_group_size_negate", text="")
#row = layout.row()
#row.itemR(psys, "vertex_group_tangent")
#row.itemR(psys, "vertex_group_tangent_negate", text="")
row = layout.row()
row.item_pointerR(psys, "vertex_group_tangent", ob, "vertex_groups", text="Tangent")
row.itemR(psys, "vertex_group_tangent_negate", text="")
#row = layout.row()
#row.itemR(psys, "vertex_group_rotation")
#row.itemR(psys, "vertex_group_rotation_negate", text="")
row = layout.row()
row.item_pointerR(psys, "vertex_group_rotation", ob, "vertex_groups", text="Rotation")
row.itemR(psys, "vertex_group_rotation_negate", text="")
#row = layout.row()
#row.itemR(psys, "vertex_group_field")
#row.itemR(psys, "vertex_group_field_negate", text="")
row = layout.row()
row.item_pointerR(psys, "vertex_group_field", ob, "vertex_groups", text="Field")
row.itemR(psys, "vertex_group_field_negate", text="")
bpy.types.register(PARTICLE_PT_particles)
bpy.types.register(PARTICLE_PT_hair_dynamics)

@ -4,12 +4,12 @@
# 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.

@ -4,12 +4,12 @@
# 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.

@ -4,12 +4,12 @@
# 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.

@ -4,12 +4,12 @@
# 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.

@ -4,12 +4,12 @@
# 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.

@ -4,12 +4,12 @@
# 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.
@ -73,8 +73,9 @@ class PHYSICS_PT_softbody(PhysicButtonsPanel):
col = split.column()
col.itemL(text="Object:")
col.itemR(softbody, "mass")
col.itemR(softbody, "friction")
col.itemR(softbody, "mass")
col.item_pointerR(softbody, "mass_vertex_group", ob, "vertex_groups", text="Mass:")
col = split.column()
col.itemL(text="Simulation:")
@ -167,6 +168,7 @@ class PHYSICS_PT_softbody_edge(PhysicButtonsPanel):
col.itemR(softbody, "plastic")
col.itemR(softbody, "bending")
col.itemR(softbody, "spring_length", text="Length")
col.item_pointerR(softbody, "spring_vertex_group", ob, "vertex_groups", text="Springs:")
col = split.column()
col.itemR(softbody, "stiff_quads")

@ -4,12 +4,12 @@
# 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.

@ -4,12 +4,12 @@
# 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.

@ -4,12 +4,12 @@
# 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.

@ -4,12 +4,12 @@
# 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.

@ -4,12 +4,12 @@
# 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.

@ -4,12 +4,12 @@
# 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.
@ -19,6 +19,7 @@
# <pep8 compliant>
import sys
import bpy
from bpy.props import *
class CONSOLE_HT_header(bpy.types.Header):
@ -68,6 +69,7 @@ class CONSOLE_MT_console(bpy.types.Menu):
layout.itemO("console.clear")
layout.itemO("console.copy")
layout.itemO("console.paste")
layout.itemM("CONSOLE_MT_language")
class CONSOLE_MT_report(bpy.types.Menu):
@ -81,6 +83,24 @@ class CONSOLE_MT_report(bpy.types.Menu):
layout.itemO("console.report_delete")
layout.itemO("console.report_copy")
class CONSOLE_MT_language(bpy.types.Menu):
bl_label = "Languages..."
def draw(self, context):
layout = self.layout
layout.column()
mod = bpy.ops.console
languages = []
for opname in dir(mod):
# execute_python, execute_shell etc.
if opname.startswith("execute_"):
languages.append(opname.split('_', 1)[-1])
languages.sort()
for language in languages:
layout.item_stringO("console.language", "language", language, text=language[0].upper() + language[1:])
def add_scrollback(text, text_type):
for l in text.split('\n'):
@ -88,125 +108,26 @@ def add_scrollback(text, text_type):
type=text_type)
def get_console(console_id):
'''
helper function for console operators
currently each text datablock gets its own
console - bpython_code.InteractiveConsole()
...which is stored in this function.
console_id can be any hashable type
'''
from code import InteractiveConsole
try:
consoles = get_console.consoles
except:
consoles = get_console.consoles = {}
# clear all dead consoles, use text names as IDs
# TODO, find a way to clear IDs
'''
for console_id in list(consoles.keys()):
if console_id not in bpy.data.texts:
del consoles[id]
'''
try:
console, stdout, stderr = consoles[console_id]
except:
namespace = {'__builtins__': __builtins__, 'bpy': bpy}
console = InteractiveConsole(namespace)
import io
stdout = io.StringIO()
stderr = io.StringIO()
consoles[console_id] = console, stdout, stderr
return console, stdout, stderr
class CONSOLE_OT_exec(bpy.types.Operator):
class ConsoleExec(bpy.types.Operator):
'''Execute the current console line as a python expression.'''
bl_idname = "console.execute"
bl_label = "Console Execute"
bl_register = False
# Both prompts must be the same length
PROMPT = '>>> '
PROMPT_MULTI = '... '
# is this working???
'''
def poll(self, context):
return (context.space_data.type == 'PYTHON')
'''
# its not :|
def execute(self, context):
sc = context.space_data
try:
line = sc.history[-1].line
except:
return ('CANCELLED',)
execute = getattr(bpy.ops.console, "execute_" + sc.language, None)
if sc.console_type != 'PYTHON':
return ('CANCELLED',)
console, stdout, stderr = get_console(hash(context.region))
# redirect output
sys.stdout = stdout
sys.stderr = stderr
# run the console
if not line.strip():
line_exec = '\n' # executes a multiline statement
if execute:
execute()
else:
line_exec = line
is_multiline = console.push(line_exec)
stdout.seek(0)
stderr.seek(0)
output = stdout.read()
output_err = stderr.read()
# cleanup
sys.stdout = sys.__stdout__
sys.stderr = sys.__stderr__
sys.last_traceback = None
# So we can reuse, clear all data
stdout.truncate(0)
stderr.truncate(0)
bpy.ops.console.scrollback_append(text=sc.prompt + line, type='INPUT')
if is_multiline:
sc.prompt = self.PROMPT_MULTI
else:
sc.prompt = self.PROMPT
# insert a new blank line
bpy.ops.console.history_append(text="", current_character=0,
remove_duplicates=True)
# Insert the output into the editor
# not quite correct because the order might have changed,
# but ok 99% of the time.
if output:
add_scrollback(output, 'OUTPUT')
if output_err:
add_scrollback(output_err, 'ERROR')
print("Error: bpy.ops.console.execute_" + sc.language + " - not found")
return ('FINISHED',)
class CONSOLE_OT_autocomplete(bpy.types.Operator):
class ConsoleAutocomplete(bpy.types.Operator):
'''Evaluate the namespace up until the cursor and give a list of
options or complete the name if there is only one.'''
bl_idname = "console.autocomplete"
@ -214,40 +135,58 @@ class CONSOLE_OT_autocomplete(bpy.types.Operator):
bl_register = False
def poll(self, context):
return context.space_data.console_type == 'PYTHON'
return context.space_data.console_type != 'REPORT'
def execute(self, context):
from console import intellisense
sc = context.space_data
console = get_console(hash(context.region))[0]
autocomplete = getattr(bpy.ops.console, "autocomplete_" + sc.language, None)
current_line = sc.history[-1]
line = current_line.line
if autocomplete:
autocomplete()
else:
print("Error: bpy.ops.console.autocomplete_" + sc.language + " - not found")
if not console:
return ('CANCELLED',)
return ('FINISHED',)
if sc.console_type != 'PYTHON':
return ('CANCELLED',)
# This function isnt aware of the text editor or being an operator
# just does the autocomp then copy its results back
current_line.line, current_line.current_character, scrollback = \
intellisense.expand(
line=current_line.line,
cursor=current_line.current_character,
namespace=console.locals,
private='-d' in sys.argv)
class ConsoleBanner(bpy.types.Operator):
bl_idname = "console.banner"
# Now we need to copy back the line from blender back into the
# text editor. This will change when we dont use the text editor
# anymore
if scrollback:
add_scrollback(scrollback, 'INFO')
def execute(self, context):
sc = context.space_data
# default to python
if not sc.language:
sc.language = 'python'
context.area.tag_redraw()
banner = getattr(bpy.ops.console, "banner_" + sc.language, None)
if banner:
banner()
else:
print("Error: bpy.ops.console.banner_" + sc.language + " - not found")
return ('FINISHED',)
class ConsoleLanguage(bpy.types.Operator):
'''Set the current language for this console'''
bl_idname = "console.language"
language = StringProperty(name="Language", maxlen= 32, default= "")
def execute(self, context):
sc = context.space_data
# defailt to python
sc.language = self.language
bpy.ops.console.banner()
# insert a new blank line
bpy.ops.console.history_append(text="", current_character=0,
remove_duplicates=True)
return ('FINISHED',)
@ -255,6 +194,12 @@ class CONSOLE_OT_autocomplete(bpy.types.Operator):
bpy.types.register(CONSOLE_HT_header)
bpy.types.register(CONSOLE_MT_console)
bpy.types.register(CONSOLE_MT_report)
bpy.types.register(CONSOLE_MT_language)
bpy.ops.add(CONSOLE_OT_exec)
bpy.ops.add(CONSOLE_OT_autocomplete)
# Stubs that call the language operators
bpy.ops.add(ConsoleExec)
bpy.ops.add(ConsoleAutocomplete)
bpy.ops.add(ConsoleBanner)
# Set the language and call the banner
bpy.ops.add(ConsoleLanguage)

@ -4,12 +4,12 @@
# 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.

@ -4,12 +4,12 @@
# 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.
@ -208,7 +208,7 @@ class IMAGE_MT_uvs(bpy.types.Menu):
layout.itemS()
layout.itemR(settings, "proportional_editing")
layout.item_menu_enumR(settings, "proportional_editing")
layout.item_menu_enumR(settings, "proportional_editing_falloff")
layout.itemS()

@ -4,12 +4,12 @@
# 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.
@ -187,7 +187,9 @@ class INFO_MT_add(bpy.types.Menu):
layout.itemO("object.text_add", text="Text", icon='ICON_OUTLINER_OB_FONT')
layout.itemS()
layout.operator_context = "INVOKE_SCREEN"
layout.itemO("object.armature_add", text="Armature", icon='ICON_OUTLINER_OB_ARMATURE')
layout.item_enumO("object.add", "type", 'LATTICE', icon='ICON_OUTLINER_OB_LATTICE')
layout.item_enumO("object.add", "type", 'EMPTY', icon='ICON_OUTLINER_OB_EMPTY')
@ -195,6 +197,9 @@ class INFO_MT_add(bpy.types.Menu):
layout.itemS()
layout.item_enumO("object.add", "type", 'CAMERA', icon='ICON_OUTLINER_OB_CAMERA')
layout.operator_context = "EXEC_SCREEN"
layout.item_menu_enumO("object.lamp_add", "type", 'LAMP', text="Lamp", icon='ICON_OUTLINER_OB_LAMP')
layout.itemS()

@ -4,12 +4,12 @@
# 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.

@ -4,12 +4,12 @@
# 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.

@ -4,12 +4,12 @@
# 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.

@ -4,12 +4,12 @@
# 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.
@ -118,7 +118,7 @@ class SEQUENCER_MT_view(bpy.types.Menu):
if st.display_mode == 'IMAGE':
layout.itemR(st, "draw_safe_margin")
if st.display_mode == 'WAVEFORM':
layout.itemR(st, "seperate_color_preview")
layout.itemR(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, "");

@ -4,12 +4,12 @@
# 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.

@ -4,12 +4,12 @@
# 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.

@ -4,12 +4,12 @@
# 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.
@ -342,6 +342,722 @@ class USERPREF_PT_system(bpy.types.Panel):
sub1.itemR(system, "memory_cache_limit")
class USERPREF_PT_theme(bpy.types.Panel):
bl_space_type = 'USER_PREFERENCES'
bl_label = "Themes"
bl_region_type = 'WINDOW'
bl_show_header = False
def poll(self, context):
userpref = context.user_preferences
return (userpref.active_section == 'THEMES')
def draw(self, context):
layout = self.layout
theme = context.user_preferences.themes[0]
split = layout.split(percentage=0.33)
split.itemR(theme, "active_theme", text="")
layout.itemS()
split = layout.split()
if theme.active_theme == 'VIEW_3D':
v3d = theme.view_3d
col = split.column()
col.itemR(v3d, "back")
col.itemR(v3d, "title")
col.itemR(v3d, "text")
col.itemR(v3d, "text_hi")
col.itemR(v3d, "header")
col.itemR(v3d, "header_text")
col = split.column()
col.itemR(v3d, "header_text_hi")
col.itemR(v3d, "grid")
col.itemR(v3d, "panel", slider=True)
col.itemR(v3d, "wire")
col.itemR(v3d, "lamp", slider=True)
col = split.column()
col.itemR(v3d, "current_frame")
col.itemR(v3d, "editmesh_active", slider=True)
col.itemR(v3d, "object_selected")
col.itemR(v3d, "object_active")
col.itemR(v3d, "object_grouped")
col.itemR(v3d, "object_grouped_active")
col = split.column()
col.itemR(v3d, "transform")
col.itemR(v3d, "vertex")
col.itemR(v3d, "face", slider=True)
col.itemR(v3d, "normal")
col.itemR(v3d, "bone_solid")
col.itemR(v3d, "bone_pose")
# col.itemR(v3d, "edge") Doesn't seem to work
elif theme.active_theme == 'USER_INTERFACE':
ui = theme.user_interface.wcol_regular
layout.itemL(text="Regular:")
sub = layout.row()
sub1 = sub.column()
sub1.itemR(ui, "outline")
sub1.itemR(ui, "item", slider=True)
sub1 = sub.column()
sub1.itemR(ui, "inner", slider=True)
sub1.itemR(ui, "inner_sel", slider=True)
sub1 = sub.column()
sub1.itemR(ui, "text")
sub1.itemR(ui, "text_sel")
sub1 = sub.column()
sub1.itemR(ui, "shaded")
sub2 = sub1.column(align=True)
sub2.active = ui.shaded
sub2.itemR(ui, "shadetop")
sub2.itemR(ui, "shadedown")
layout.itemS()
ui = theme.user_interface.wcol_tool
layout.itemL(text="Tool:")
sub = layout.row()
sub1 = sub.column()
sub1.itemR(ui, "outline")
sub1.itemR(ui, "item", slider=True)
sub1 = sub.column()
sub1.itemR(ui, "inner", slider=True)
sub1.itemR(ui, "inner_sel", slider=True)
sub1 = sub.column()
sub1.itemR(ui, "text")
sub1.itemR(ui, "text_sel")
sub1 = sub.column()
sub1.itemR(ui, "shaded")
sub2 = sub1.column(align=True)
sub2.active = ui.shaded
sub2.itemR(ui, "shadetop")
sub2.itemR(ui, "shadedown")
ui = theme.user_interface.wcol_radio
layout.itemL(text="Radio Buttons:")
sub = layout.row()
sub1 = sub.column()
sub1.itemR(ui, "outline")
sub1.itemR(ui, "item", slider=True)
sub1 = sub.column()
sub1.itemR(ui, "inner", slider=True)
sub1.itemR(ui, "inner_sel", slider=True)
sub1 = sub.column()
sub1.itemR(ui, "text")
sub1.itemR(ui, "text_sel")
sub1 = sub.column()
sub1.itemR(ui, "shaded")
sub2 = sub1.column(align=True)
sub2.active = ui.shaded
sub2.itemR(ui, "shadetop")
sub2.itemR(ui, "shadedown")
ui = theme.user_interface.wcol_text
layout.itemL(text="Text:")
sub = layout.row()
sub1 = sub.column()
sub1.itemR(ui, "outline")
sub1.itemR(ui, "item", slider=True)
sub1 = sub.column()
sub1.itemR(ui, "inner", slider=True)
sub1.itemR(ui, "inner_sel", slider=True)
sub1 = sub.column()
sub1.itemR(ui, "text")
sub1.itemR(ui, "text_sel")
sub1 = sub.column()
sub1.itemR(ui, "shaded")
sub2 = sub1.column(align=True)
sub2.active = ui.shaded
sub2.itemR(ui, "shadetop")
sub2.itemR(ui, "shadedown")
ui = theme.user_interface.wcol_option
layout.itemL(text="Option:")
sub = layout.row()
sub1 = sub.column()
sub1.itemR(ui, "outline")
sub1.itemR(ui, "item", slider=True)
sub1 = sub.column()
sub1.itemR(ui, "inner", slider=True)
sub1.itemR(ui, "inner_sel", slider=True)
sub1 = sub.column()
sub1.itemR(ui, "text")
sub1.itemR(ui, "text_sel")
sub1 = sub.column()
sub1.itemR(ui, "shaded")
sub2 = sub1.column(align=True)
sub2.active = ui.shaded
sub2.itemR(ui, "shadetop")
sub2.itemR(ui, "shadedown")
ui = theme.user_interface.wcol_toggle
layout.itemL(text="Toggle:")
sub = layout.row()
sub1 = sub.column()
sub1.itemR(ui, "outline")
sub1.itemR(ui, "item", slider=True)
sub1 = sub.column()
sub1.itemR(ui, "inner", slider=True)
sub1.itemR(ui, "inner_sel", slider=True)
sub1 = sub.column()
sub1.itemR(ui, "text")
sub1.itemR(ui, "text_sel")
sub1 = sub.column()
sub1.itemR(ui, "shaded")
sub2 = sub1.column(align=True)
sub2.active = ui.shaded
sub2.itemR(ui, "shadetop")
sub2.itemR(ui, "shadedown")
ui = theme.user_interface.wcol_num
layout.itemL(text="Number Field:")
sub = layout.row()
sub1 = sub.column()
sub1.itemR(ui, "outline")
sub1.itemR(ui, "item", slider=True)
sub1 = sub.column()
sub1.itemR(ui, "inner", slider=True)
sub1.itemR(ui, "inner_sel", slider=True)
sub1 = sub.column()
sub1.itemR(ui, "text")
sub1.itemR(ui, "text_sel")
sub1 = sub.column()
sub1.itemR(ui, "shaded")
sub2 = sub1.column(align=True)
sub2.active = ui.shaded
sub2.itemR(ui, "shadetop")
sub2.itemR(ui, "shadedown")
ui = theme.user_interface.wcol_numslider
layout.itemL(text="Value Slider:")
sub = layout.row()
sub1 = sub.column()
sub1.itemR(ui, "outline")
sub1.itemR(ui, "item", slider=True)
sub1 = sub.column()
sub1.itemR(ui, "inner", slider=True)
sub1.itemR(ui, "inner_sel", slider=True)
sub1 = sub.column()
sub1.itemR(ui, "text")
sub1.itemR(ui, "text_sel")
sub1 = sub.column()
sub1.itemR(ui, "shaded")
sub2 = sub1.column(align=True)
sub2.active = ui.shaded
sub2.itemR(ui, "shadetop")
sub2.itemR(ui, "shadedown")
ui = theme.user_interface.wcol_box
layout.itemL(text="Box:")
sub = layout.row()
sub1 = sub.column()
sub1.itemR(ui, "outline")
sub1.itemR(ui, "item", slider=True)
sub1 = sub.column()
sub1.itemR(ui, "inner", slider=True)
sub1.itemR(ui, "inner_sel", slider=True)
sub1 = sub.column()
sub1.itemR(ui, "text")
sub1.itemR(ui, "text_sel")
sub1 = sub.column()
sub1.itemR(ui, "shaded")
sub2 = sub1.column(align=True)
sub2.active = ui.shaded
sub2.itemR(ui, "shadetop")
sub2.itemR(ui, "shadedown")
ui = theme.user_interface.wcol_menu
layout.itemL(text="Menu:")
sub = layout.row()
sub1 = sub.column()
sub1.itemR(ui, "outline")
sub1.itemR(ui, "item", slider=True)
sub1 = sub.column()
sub1.itemR(ui, "inner", slider=True)
sub1.itemR(ui, "inner_sel", slider=True)
sub1 = sub.column()
sub1.itemR(ui, "text")
sub1.itemR(ui, "text_sel")
sub1 = sub.column()
sub1.itemR(ui, "shaded")
sub2 = sub1.column(align=True)
sub2.active = ui.shaded
sub2.itemR(ui, "shadetop")
sub2.itemR(ui, "shadedown")
ui = theme.user_interface.wcol_pulldown
layout.itemL(text="Pulldown:")
sub = layout.row()
sub1 = sub.column()
sub1.itemR(ui, "outline")
sub1.itemR(ui, "item", slider=True)
sub1 = sub.column()
sub1.itemR(ui, "inner", slider=True)
sub1.itemR(ui, "inner_sel", slider=True)
sub1 = sub.column()
sub1.itemR(ui, "text")
sub1.itemR(ui, "text_sel")
sub1 = sub.column()
sub1.itemR(ui, "shaded")
sub2 = sub1.column(align=True)
sub2.active = ui.shaded
sub2.itemR(ui, "shadetop")
sub2.itemR(ui, "shadedown")
ui = theme.user_interface.wcol_menu_back
layout.itemL(text="Menu Back:")
sub = layout.row()
sub1 = sub.column()
sub1.itemR(ui, "outline")
sub1.itemR(ui, "item", slider=True)
sub1 = sub.column()
sub1.itemR(ui, "inner", slider=True)
sub1.itemR(ui, "inner_sel", slider=True)
sub1 = sub.column()
sub1.itemR(ui, "text")
sub1.itemR(ui, "text_sel")
sub1 = sub.column()
sub1.itemR(ui, "shaded")
sub2 = sub1.column(align=True)
sub2.active = ui.shaded
sub2.itemR(ui, "shadetop")
sub2.itemR(ui, "shadedown")
ui = theme.user_interface.wcol_menu_item
layout.itemL(text="Menu Item:")
sub = layout.row()
sub1 = sub.column()
sub1.itemR(ui, "outline")
sub1.itemR(ui, "item", slider=True)
sub1 = sub.column()
sub1.itemR(ui, "inner", slider=True)
sub1.itemR(ui, "inner_sel", slider=True)
sub1 = sub.column()
sub1.itemR(ui, "text")
sub1.itemR(ui, "text_sel")
sub1 = sub.column()
sub1.itemR(ui, "shaded")
sub2 = sub1.column(align=True)
sub2.active = ui.shaded
sub2.itemR(ui, "shadetop")
sub2.itemR(ui, "shadedown")
ui = theme.user_interface.wcol_scroll
layout.itemL(text="Scroll Bar:")
sub = layout.row()
sub1 = sub.column()
sub1.itemR(ui, "outline")
sub1.itemR(ui, "item", slider=True)
sub1 = sub.column()
sub1.itemR(ui, "inner", slider=True)
sub1.itemR(ui, "inner_sel", slider=True)
sub1 = sub.column()
sub1.itemR(ui, "text")
sub1.itemR(ui, "text_sel")
sub1 = sub.column()
sub1.itemR(ui, "shaded")
sub2 = sub1.column(align=True)
sub2.active = ui.shaded
sub2.itemR(ui, "shadetop")
sub2.itemR(ui, "shadedown")
ui = theme.user_interface.wcol_list_item
layout.itemL(text="List Item:")
sub = layout.row()
sub1 = sub.column()
sub1.itemR(ui, "outline")
sub1.itemR(ui, "item", slider=True)
sub1 = sub.column()
sub1.itemR(ui, "inner", slider=True)
sub1.itemR(ui, "inner_sel", slider=True)
sub1 = sub.column()
sub1.itemR(ui, "text")
sub1.itemR(ui, "text_sel")
sub1 = sub.column()
sub1.itemR(ui, "shaded")
sub2 = sub1.column(align=True)
sub2.active = ui.shaded
sub2.itemR(ui, "shadetop")
sub2.itemR(ui, "shadedown")
ui = theme.user_interface.wcol_state
layout.itemL(text="State:")
sub = layout.row()
sub1 = sub.column()
sub1.itemR(ui, "inner_anim")
sub1.itemR(ui, "inner_anim_sel")
sub1 = sub.column()
sub1.itemR(ui, "inner_driven")
sub1.itemR(ui, "inner_driven_sel")
sub1 = sub.column()
sub1.itemR(ui, "inner_key")
sub1.itemR(ui, "inner_key_sel")
sub1 = sub.column()
sub1.itemR(ui, "blend")
ui = theme.user_interface
layout.itemS()
sub = layout.row()
sub.itemR(ui, "icon_file")
layout.itemS()
layout.itemS()
elif theme.active_theme == 'GRAPH_EDITOR':
graph = theme.graph_editor
col = split.column()
col.itemR(graph, "back")
col.itemR(graph, "title")
col.itemR(graph, "text")
col.itemR(graph, "text_hi")
col.itemR(graph, "header")
col = split.column()
col.itemR(graph, "header_text")
col.itemR(graph, "header_text_hi")
col.itemR(graph, "grid")
col.itemR(graph, "panel")
col.itemR(graph, "window_sliders")
col = split.column()
col.itemR(graph, "channels_region")
col.itemR(graph, "vertex")
col.itemR(graph, "current_frame")
col.itemR(graph, "handle_vertex")
col.itemR(graph, "handle_vertex_select")
col = split.column()
col.itemR(graph, "handle_vertex_size")
col.itemR(graph, "channel_group")
col.itemR(graph, "active_channels_group")
col.itemR(graph, "dopesheet_channel")
col.itemR(graph, "dopesheet_subchannel")
elif theme.active_theme == 'FILE_BROWSER':
file = theme.file_browser
col = split.column()
col.itemR(file, "back")
col.itemR(file, "title")
col.itemR(file, "text")
col.itemR(file, "text_hi")
col = split.column()
col.itemR(file, "header")
col.itemR(file, "header_text")
col.itemR(file, "header_text_hi")
col = split.column()
col.itemR(file, "selected_file")
col.itemR(file, "tiles")
col.itemR(file, "scrollbar")
col = split.column()
col.itemR(file, "scroll_handle")
col.itemR(file, "active_file")
col.itemR(file, "active_file_text")
elif theme.active_theme == 'NLA_EDITOR':
nla = theme.nla_editor
col = split.column()
col.itemR(nla, "back")
col.itemR(nla, "title")
col.itemR(nla, "text")
col.itemR(nla, "text_hi")
col = split.column()
col.itemR(nla, "header")
col.itemR(nla, "header_text")
col.itemR(nla, "header_text_hi")
col.itemR(nla, "grid")
col = split.column()
col.itemR(nla, "view_sliders")
col.itemR(nla, "bars")
col.itemR(nla, "bars_selected")
col = split.column()
col.itemR(nla, "strips")
col.itemR(nla, "strips_selected")
col.itemR(nla, "current_frame")
elif theme.active_theme == 'DOPESHEET_EDITOR':
dope = theme.dopesheet_editor
col = split.column()
col.itemR(dope, "back")
col.itemR(dope, "title")
col.itemR(dope, "text")
col.itemR(dope, "text_hi")
col.itemR(dope, "header")
col = split.column()
col.itemR(dope, "header_text")
col.itemR(dope, "header_text_hi")
col.itemR(dope, "grid")
col.itemR(dope, "value_sliders")
col.itemR(dope, "view_sliders")
col = split.column()
col.itemR(dope, "channels")
col.itemR(dope, "channels_selected")
col.itemR(dope, "channel_group")
col.itemR(dope, "active_channels_group")
col.itemR(dope, "long_key")
col = split.column()
col.itemR(dope, "long_key_selected")
col.itemR(dope, "current_frame")
col.itemR(dope, "dopesheet_channel")
col.itemR(dope, "dopesheet_subchannel")
elif theme.active_theme == 'IMAGE_EDITOR':
image = theme.image_editor
col = split.column()
col.itemR(image, "back")
col.itemR(image, "title")
col = split.column()
col.itemR(image, "text")
col.itemR(image, "text_hi")
col = split.column()
col.itemR(image, "header")
col.itemR(image, "header_text")
col = split.column()
col.itemR(image, "header_text_hi")
col.itemR(image, "editmesh_active", slider=True)
elif theme.active_theme == 'SEQUENCE_EDITOR':
seq = theme.sequence_editor
col = split.column()
col.itemR(seq, "back")
col.itemR(seq, "title")
col.itemR(seq, "text")
col.itemR(seq, "text_hi")
col.itemR(seq, "header")
col = split.column()
col.itemR(seq, "header_text")
col.itemR(seq, "header_text_hi")
col.itemR(seq, "grid")
col.itemR(seq, "window_sliders")
col.itemR(seq, "movie_strip")
col = split.column()
col.itemR(seq, "image_strip")
col.itemR(seq, "scene_strip")
col.itemR(seq, "audio_strip")
col.itemR(seq, "effect_strip")
col.itemR(seq, "plugin_strip")
col = split.column()
col.itemR(seq, "transition_strip")
col.itemR(seq, "meta_strip")
col.itemR(seq, "current_frame")
col.itemR(seq, "keyframe")
col.itemR(seq, "draw_action")
elif theme.active_theme == 'PROPERTIES':
prop = theme.properties
col = split.column()
col.itemR(prop, "back")
col.itemR(prop, "title")
col = split.column()
col.itemR(prop, "text")
col.itemR(prop, "text_hi")
col = split.column()
col.itemR(prop, "header")
col.itemR(prop, "header_text")
col = split.column()
col.itemR(prop, "header_text_hi")
col.itemR(prop, "panel")
elif theme.active_theme == 'TEXT_EDITOR':
text = theme.text_editor
col = split.column()
col.itemR(text, "back")
col.itemR(text, "title")
col.itemR(text, "text")
col.itemR(text, "text_hi")
col = split.column()
col.itemR(text, "header")
col.itemR(text, "header_text")
col.itemR(text, "header_text_hi")
col.itemR(text, "line_numbers_background")
col = split.column()
col.itemR(text, "scroll_bar")
col.itemR(text, "selected_text")
col.itemR(text, "cursor")
col.itemR(text, "syntax_builtin")
col = split.column()
col.itemR(text, "syntax_special")
col.itemR(text, "syntax_comment")
col.itemR(text, "syntax_string")
col.itemR(text, "syntax_numbers")
elif theme.active_theme == 'TIMELINE':
time = theme.timeline
col = split.column()
col.itemR(time, "back")
col.itemR(time, "title")
col.itemR(time, "text")
col = split.column()
col.itemR(time, "text_hi")
col.itemR(time, "header")
col = split.column()
col.itemR(time, "header_text")
col.itemR(time, "header_text_hi")
col = split.column()
col.itemR(time, "grid")
col.itemR(time, "current_frame")
elif theme.active_theme == 'NODE_EDITOR':
node = theme.node_editor
col = split.column()
col.itemR(node, "back")
col.itemR(node, "title")
col.itemR(node, "text")
col.itemR(node, "text_hi")
col = split.column()
col.itemR(node, "header")
col.itemR(node, "header_text")
col.itemR(node, "header_text_hi")
col.itemR(node, "wires")
col = split.column()
col.itemR(node, "wire_select")
col.itemR(node, "selected_text")
col.itemR(node, "node_backdrop")
col.itemR(node, "in_out_node")
col = split.column()
col.itemR(node, "converter_node")
col.itemR(node, "operator_node")
col.itemR(node, "group_node")
elif theme.active_theme == 'LOGIC_EDITOR':
logic = theme.logic_editor
col = split.column()
col.itemR(logic, "back")
col.itemR(logic, "title")
col = split.column()
col.itemR(logic, "text")
col.itemR(logic, "text_hi")
col = split.column()
col.itemR(logic, "header")
col.itemR(logic, "header_text")
col = split.column()
col.itemR(logic, "header_text_hi")
col.itemR(logic, "panel")
elif theme.active_theme == 'OUTLINER':
out = theme.outliner
col = split.column()
col.itemR(out, "back")
col.itemR(out, "title")
col = split.column()
col.itemR(out, "text")
col.itemR(out, "text_hi")
col = split.column()
col.itemR(out, "header")
col.itemR(out, "header_text")
col = split.column()
col.itemR(out, "header_text_hi")
elif theme.active_theme == 'INFO':
info = theme.info
col = split.column()
col.itemR(info, "back")
col.itemR(info, "title")
col = split.column()
col.itemR(info, "text")
col.itemR(info, "text_hi")
col = split.column()
col.itemR(info, "header")
col.itemR(info, "header_text")
col = split.column()
col.itemR(info, "header_text_hi")
elif theme.active_theme == 'USER_PREFERENCES':
prefs = theme.user_preferences
col = split.column()
col.itemR(prefs, "back")
col.itemR(prefs, "title")
col = split.column()
col.itemR(prefs, "text")
col.itemR(prefs, "text_hi")
col = split.column()
col.itemR(prefs, "header")
col.itemR(prefs, "header_text")
col = split.column()
col.itemR(prefs, "header_text_hi")
class USERPREF_PT_file(bpy.types.Panel):
bl_space_type = 'USER_PREFERENCES'
bl_label = "Files"
@ -515,9 +1231,9 @@ class USERPREF_PT_input(bpy.types.Panel):
itemrow = row.row()
itemrow.enabled = km.user_defined
if kmi.active:
itemrow.itemR(kmi, "active", text="", icon="ICON_CHECKBOX_HLT")
itemrow.itemR(kmi, "active", text="", icon="ICON_CHECKBOX_HLT")
else:
itemrow.itemR(kmi, "active", text="", icon="ICON_CHECKBOX_DEHLT")
itemrow.itemR(kmi, "active", text="", icon="ICON_CHECKBOX_DEHLT")
itemcol = itemrow.column()
itemcol.active = kmi.active
@ -585,6 +1301,7 @@ bpy.types.register(USERPREF_HT_header)
bpy.types.register(USERPREF_MT_view)
bpy.types.register(USERPREF_PT_tabs)
bpy.types.register(USERPREF_PT_interface)
bpy.types.register(USERPREF_PT_theme)
bpy.types.register(USERPREF_PT_edit)
bpy.types.register(USERPREF_PT_system)
bpy.types.register(USERPREF_PT_file)

@ -4,12 +4,12 @@
# 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.
@ -90,6 +90,22 @@ class VIEW3D_MT_snap(bpy.types.Menu):
layout.itemO("view3d.snap_cursor_to_grid", text="Cursor to Grid")
layout.itemO("view3d.snap_cursor_to_active", text="Cursor to Active")
class VIEW3D_MT_uv_map(dynamic_menu.DynMenu):
bl_label = "UV Mapping"
def draw(self, context):
layout = self.layout
layout.itemO("uv.unwrap")
layout.itemO("uv.cube_project")
layout.itemO("uv.cylinder_project")
layout.itemO("uv.sphere_project")
layout.itemO("uv.project_from_view")
layout.itemS()
layout.itemO("uv.reset")
# ********** View menus **********
@ -175,11 +191,41 @@ class VIEW3D_MT_view_align(bpy.types.Menu):
def draw(self, context):
layout = self.layout
layout.itemM("VIEW3D_MT_view_align_selected")
layout.itemS()
layout.item_booleanO("view3d.view_all", "center", True, text="Center Cursor and View All")
layout.itemO("view3d.camera_to_view", text="Align Active Camera to View")
layout.itemO("view3d.view_center")
class VIEW3D_MT_view_align_selected(bpy.types.Menu):
bl_label = "Align View to Selected"
def draw(self, context):
layout = self.layout
props = layout.itemO("view3d.viewnumpad", properties=True, text="Top")
props.align_active = True
props.type = 'TOP'
props = layout.itemO("view3d.viewnumpad", properties=True, text="Bottom")
props.align_active = True
props.type = 'BOTTOM'
props = layout.itemO("view3d.viewnumpad", properties=True, text="Front")
props.align_active = True
props.type = 'FRONT'
props = layout.itemO("view3d.viewnumpad", properties=True, text="Back")
props.align_active = True
props.type = 'BACK'
props = layout.itemO("view3d.viewnumpad", properties=True, text="Right")
props.align_active = True
props.type = 'RIGHT'
props = layout.itemO("view3d.viewnumpad", properties=True, text="Left")
props.align_active = True
props.type = 'LEFT'
class VIEW3D_MT_view_cameras(bpy.types.Menu):
bl_label = "Cameras"
@ -209,9 +255,9 @@ class VIEW3D_MT_select_object(bpy.types.Menu):
layout.itemO("object.select_mirror", text="Mirror")
layout.itemO("object.select_by_layer", text="Select All by Layer")
layout.item_menu_enumO("object.select_by_type", "type", "", text="Select All by Type...")
layout.itemS()
layout.item_menu_enumO("object.select_grouped", "type", text="Grouped")
layout.item_menu_enumO("object.select_linked", "type", text="Linked")
layout.itemO("object.select_pattern", text="Select Pattern...")
@ -286,6 +332,8 @@ class VIEW3D_MT_select_edit_mesh(bpy.types.Menu):
layout.itemO("mesh.select_random", text="Random...")
layout.itemO("mesh.edges_select_sharp", text="Sharp Edges")
layout.itemO("mesh.faces_select_linked_flat", text="Linked Flat Faces")
layout.itemO("mesh.faces_select_interior", text="Interior Faces")
layout.itemO("mesh.select_axis", text="Side of Active")
layout.itemS()
@ -407,7 +455,7 @@ class VIEW3D_MT_select_edit_armature(bpy.types.Menu):
layout = self.layout
layout.itemO("view3d.select_border")
layout.itemS()
@ -463,8 +511,10 @@ class VIEW3D_MT_object(bpy.types.Menu):
layout.item_booleanO("object.duplicate", "linked", True, text="Duplicate Linked")
layout.itemO("object.delete", text="Delete...")
layout.itemO("object.proxy_make", text="Make Proxy...")
layout.itemM("VIEW3D_MT_make_links", text="Make Links...")
layout.item_menu_enumO("object.make_local", "type", text="Make Local...")
layout.itemM("VIEW3D_MT_make_single_user")
layout.itemM("VIEW3D_MT_make_links")
layout.itemS()
@ -588,6 +638,18 @@ class VIEW3D_MT_make_single_user(bpy.types.Menu):
props = layout.itemO("object.make_single_user", properties=True, text="Animation")
props.animation = True
class VIEW3D_MT_make_links(bpy.types.Menu):
bl_label = "Make Links"
def draw(self, context):
layout = self.layout
layout.item_menu_enumO("object.make_links_scene", "type", text="Objects to Scene...")
layout.items_enumO("object.make_links_data", property="type") # inline
# ********** Vertex paint menu **********
@ -831,7 +893,7 @@ class VIEW3D_MT_edit_mesh(bpy.types.Menu):
layout.itemS()
layout.itemO("uv.mapping_menu", text="UV Unwrap...")
layout.itemM("VIEW3D_MT_uv_map", text="UV Unwrap...")
layout.itemS()
@ -1307,6 +1369,33 @@ class VIEW3D_PT_3dview_properties(bpy.types.Panel):
layout.column().itemR(scene, "cursor_location", text="3D Cursor:")
class VIEW3D_PT_3dview_item(bpy.types.Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
bl_label = "Item"
def poll(self, context):
return (context.active_object or context.bone or context.edit_bone)
def draw(self, context):
layout = self.layout
ob = context.object
row = layout.row()
row.itemL(text="", icon='ICON_OBJECT_DATA')
row.itemR(ob, "name", text="")
if ((context.active_bone or context.active_pchan) and ob.type == 'ARMATURE' and (ob.mode == 'EDIT' or ob.mode == 'POSE')):
bone = context.active_bone
if not bone:
pchan = context.active_pchan
if pchan:
bone = pchan.bone
row = layout.row()
row.itemL(text="", icon='ICON_BONE_DATA')
row.itemR(bone, "name", text="")
class VIEW3D_PT_3dview_display(bpy.types.Panel):
bl_space_type = 'VIEW_3D'
@ -1358,8 +1447,8 @@ class VIEW3D_PT_3dview_meshdisplay(bpy.types.Panel):
bl_label = "Mesh Display"
def poll(self, context):
editmesh = context.mode == 'EDIT_MESH'
return (editmesh)
# The active object check is needed because of localmode
return (context.active_object and (context.mode == 'EDIT_MESH'))
def draw(self, context):
layout = self.layout
@ -1562,6 +1651,7 @@ bpy.types.register(VIEW3D_HT_header) # Header
bpy.types.register(VIEW3D_MT_view) #View Menus
bpy.types.register(VIEW3D_MT_view_navigation)
bpy.types.register(VIEW3D_MT_view_align)
bpy.types.register(VIEW3D_MT_view_align_selected)
bpy.types.register(VIEW3D_MT_view_cameras)
bpy.types.register(VIEW3D_MT_select_object) # Select Menus
@ -1584,6 +1674,7 @@ bpy.types.register(VIEW3D_MT_object_group)
bpy.types.register(VIEW3D_MT_object_constraints)
bpy.types.register(VIEW3D_MT_object_showhide)
bpy.types.register(VIEW3D_MT_make_single_user)
bpy.types.register(VIEW3D_MT_make_links)
bpy.types.register(VIEW3D_MT_sculpt) # Sculpt Menu
@ -1603,6 +1694,7 @@ bpy.types.register(VIEW3D_MT_pose_constraints)
bpy.types.register(VIEW3D_MT_pose_showhide)
bpy.types.register(VIEW3D_MT_snap) # Edit Menus
bpy.types.register(VIEW3D_MT_uv_map) # Edit Menus
bpy.types.register(VIEW3D_MT_edit_mesh)
bpy.types.register(VIEW3D_MT_edit_mesh_specials) # Only as a menu for keybindings
@ -1631,7 +1723,8 @@ bpy.types.register(VIEW3D_MT_edit_armature)
bpy.types.register(VIEW3D_MT_edit_armature_parent)
bpy.types.register(VIEW3D_MT_edit_armature_roll)
bpy.types.register(VIEW3D_PT_3dview_properties) # Panels
bpy.types.register(VIEW3D_PT_3dview_item) # Panels
bpy.types.register(VIEW3D_PT_3dview_properties)
bpy.types.register(VIEW3D_PT_3dview_display)
bpy.types.register(VIEW3D_PT_3dview_meshdisplay)
bpy.types.register(VIEW3D_PT_3dview_curvedisplay)

@ -4,12 +4,12 @@
# 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.
@ -101,6 +101,7 @@ class VIEW3D_PT_tools_meshedit(View3DPanel):
col.itemO("mesh.screw")
col.itemO("mesh.merge")
col.itemO("mesh.rip_move")
col.itemO("mesh.flip_normals")
col = layout.column(align=True)
col.itemL(text="Shading:")
@ -109,7 +110,8 @@ class VIEW3D_PT_tools_meshedit(View3DPanel):
col = layout.column(align=True)
col.itemL(text="UV Mapping:")
col.itemO("uv.mapping_menu", text="Unwrap")
col.item_stringO("wm.call_menu", "name", "VIEW3D_MT_uv_map", text="Unwrap")
col.itemO("mesh.uvs_rotate")
col.itemO("mesh.uvs_mirror")
@ -133,10 +135,12 @@ class VIEW3D_PT_tools_meshedit_options(View3DPanel):
def draw(self, context):
layout = self.layout
mesh = context.active_object.data
ob = context.active_object
col = layout.column(align=True)
col.itemR(mesh, "use_mirror_x")
if ob:
mesh = context.active_object.data
col = layout.column(align=True)
col.itemR(mesh, "use_mirror_x")
# ********** default tools for editmode_curve ****************
@ -521,7 +525,7 @@ class VIEW3D_PT_tools_brush(PaintPanel):
col.row().itemR(brush, "direction", expand=True)
if brush.sculpt_tool == 'LAYER':
col.itemR(brush, "persistent")
col.itemR(brush, "use_persistent")
col.itemO("sculpt.set_persistent_base")
# Texture Paint Mode #
@ -826,6 +830,8 @@ class VIEW3D_PT_tools_particlemode(View3DPanel):
layout.itemR(pe, "type", text="")
ptcache = None
if pe.type == 'PARTICLES':
if ob.particle_systems:
if len(ob.particle_systems) > 1:

@ -78,8 +78,6 @@ endif
GRPLIB = $(OCGDIR)/creator/$(DEBUG_DIR)libcreator.a
GRPLIB += $(OCGDIR)/blender/windowmanager/$(DEBUG_DIR)libwindowmanager.a
GRPLIB += $(NAN_BSP)/lib/$(DEBUG_DIR)libbsp.a
GRPLIB += $(NAN_BOOLOP)/lib/$(DEBUG_DIR)libboolop.a
GRPLIB += $(NAN_GHOST)/lib/$(DEBUG_DIR)libghost.a
GRPLIB += $(NAN_STRING)/lib/$(DEBUG_DIR)libstring.a
GRPLIB += $(OCGDIR)/blender/render/$(DEBUG_DIR)librender.a
@ -118,6 +116,9 @@ COMLIB += $(NAN_AUDASPACE)/lib/$(DEBUG_DIR)libaud_sdl.a
COMLIB += $(NAN_SAMPLERATE)/lib/$(DEBUG_DIR)libsamplerate.a
COMLIB += $(NAN_LZO)/lib/$(DEBUG_DIR)libminilzo.a
COMLIB += $(NAN_LZMA)/lib/$(DEBUG_DIR)liblzma.a
COMLIB += $(NAN_BSP)/lib/$(DEBUG_DIR)libbsp.a
COMLIB += $(NAN_BOOLOP)/lib/$(DEBUG_DIR)libboolop.a
COMLIB += $(NAN_DECIMATION)/lib/$(DEBUG_DIR)libdecimation.a
ifeq ($(WITH_FFMPEG),true)
COMLIB += $(NAN_AUDASPACE)/lib/$(DEBUG_DIR)libaud_ffmpeg.a
@ -233,7 +234,6 @@ endif
# note: space_api.a in begin of editors, screen.a in end
PULIB = $(NAN_MOTO)/lib/libmoto.a
PULIB += $(NAN_DECIMATION)/lib/$(DEBUG_DIR)libdecimation.a
PULIB += $(OCGDIR)/blender/readblenfile/$(DEBUG_DIR)libreadblenfile.a
PULIB += $(OCGDIR)/blender/ed_space/$(DEBUG_DIR)libed_space.a
PULIB += $(OCGDIR)/blender/ed_sound/$(DEBUG_DIR)libed_sound.a

@ -44,7 +44,7 @@ void copy_defgroups (struct ListBase *lb1, struct ListBase *lb2);
struct bDeformGroup *copy_defgroup (struct bDeformGroup *ingroup);
struct bDeformGroup *get_named_vertexgroup (Object *ob, char *name);
int get_defgroup_num (struct Object *ob, struct bDeformGroup *dg);
int get_named_vertexgroup_num (Object *ob, char *name);
int get_named_vertexgroup_num (Object *ob, const char *name);
void unique_vertexgroup_name (struct bDeformGroup *dg, struct Object *ob);
float deformvert_get_weight(const struct MDeformVert *dvert, int group_num);

@ -1689,7 +1689,9 @@ static void splineik_init_tree_from_pchan(Object *ob, bPoseChannel *pchan_tip)
/* setup new empty array for the points list */
if (ikData->points)
MEM_freeN(ikData->points);
ikData->numpoints= (ikData->flag & CONSTRAINT_SPLINEIK_NO_ROOT)? ikData->chainlen : ikData->chainlen+1;
// NOTE: just do chainlen+1 always for now, since we may get crashes otherwise
//ikData->numpoints= (ikData->flag & CONSTRAINT_SPLINEIK_NO_ROOT)? ikData->chainlen : ikData->chainlen+1;
ikData->numpoints= ikData->chainlen+1;
ikData->points= MEM_callocN(sizeof(float)*ikData->numpoints, "Spline IK Binding");
/* perform binding of the joints to parametric positions along the curve based
@ -1804,106 +1806,128 @@ static void splineik_init_tree(Scene *scene, Object *ob, float ctime)
static void splineik_evaluate_bone(tSplineIK_Tree *tree, Scene *scene, Object *ob, bPoseChannel *pchan, int index, float ctime)
{
bSplineIKConstraint *ikData= tree->ikData;
float dirX[3]={1,0,0}, dirZ[3]={0,0,1};
float axis1[3], axis2[3], tmpVec[3];
float poseHead[3], poseTail[3], poseMat[4][4];
float splineVec[3], scaleFac;
float rad, radius=1.0f;
float vec[4], dir[3];
/* step 1: get xyz positions for the endpoints of the bone
* assume that they can be calculated on the path so that these calls will never fail
*/
/* tail */
/* firstly, calculate the bone matrix the standard way, since this is needed for roll control */
where_is_pose_bone(scene, ob, pchan, ctime);
VECCOPY(poseHead, pchan->pose_head);
VECCOPY(poseTail, pchan->pose_tail);
/* step 1a: get xyz positions for the tail endpoint of the bone */
if ( where_on_path(ikData->tar, tree->points[index], vec, dir, NULL, &rad) ) {
/* convert the position to pose-space, then store it */
Mat4MulVecfl(ob->imat, vec);
VECCOPY(pchan->pose_tail, vec);
VECCOPY(poseTail, vec);
/* set the new radius */
radius= rad;
}
/* head
* - check that this isn't the last bone that is subject to restrictions
* i.e. if no-root option is enabled, the root should be calculated in the standard way
*/
if ((ikData->flag & CONSTRAINT_SPLINEIK_NO_ROOT)==0 || (index+1 < ikData->chainlen))
{
/* the head location of this bone is driven by the spline */
if ( where_on_path(ikData->tar, tree->points[index+1], vec, dir, NULL, &rad) ) {
/* store the position, and convert it to pose space */
Mat4MulVecfl(ob->imat, vec);
VECCOPY(pchan->pose_head, vec);
/* set the new radius (it should be the average value) */
radius = (radius+rad) / 2;
}
}
else {
// FIXME: this option isn't really useful yet...
// maybe we are more interested in the head deltas that arise from this instead?
/* use the standard calculations for this */
where_is_pose_bone(scene, ob, pchan, ctime);
/* step 1b: get xyz positions for the head endpoint of the bone */
/* firstly, calculate the position that the path suggests */
if ( where_on_path(ikData->tar, tree->points[index+1], vec, dir, NULL, &rad) ) {
/* store the position, and convert it to pose space */
Mat4MulVecfl(ob->imat, vec);
VECCOPY(poseHead, vec);
/* hack: assume for now that the pose_tail vector is still valid from the previous step,
* and set that again now so that the chain doesn't get broken
*/
VECCOPY(pchan->pose_tail, vec);
/* set the new radius (it should be the average value) */
radius = (radius+rad) / 2;
}
if ((ikData->flag & CONSTRAINT_SPLINEIK_NO_ROOT) && (pchan == tree->root))
{
// this is the root bone, and it can be controlled however we like...
// TODO: how do we calculate the offset of the root, if we don't even know the binding?
VECCOPY(poseHead, pchan->pose_head);
}
/* step 2a: determine the implied transform from these endpoints
/* step 2: determine the implied transform from these endpoints
* - splineVec: the vector direction that the spline applies on the bone
* - scaleFac: the factor that the bone length is scaled by to get the desired amount
*/
VecSubf(splineVec, pchan->pose_tail, pchan->pose_head);
scaleFac= VecLength(splineVec) / pchan->bone->length; // TODO: this will need to be modified by blending factor
VecSubf(splineVec, poseTail, poseHead);
scaleFac= VecLength(splineVec) / pchan->bone->length;
/* step 2b: the spline vector now becomes the y-axis of the bone
* - we need to normalise the splineVec first, so that it's just a unit direction vector
/* step 3: compute the shortest rotation needed to map from the bone rotation to the current axis
* - this uses the same method as is used for the Damped Track Constraint (see the code there for details)
*/
Mat4One(pchan->pose_mat);
Normalize(splineVec);
VECCOPY(pchan->pose_mat[1], splineVec);
/* step 3a: determine two vectors which will both be at right angles to the bone vector
* based on the "Gram Schmidt process" for finding a set of Orthonormal Vectors, described at
* http://ltcconline.net/greenl/courses/203/Vectors/orthonormalBases.htm
* and normalise them to make sure they will behave nicely (as unit vectors)
*/
/* x-axis = dirX - projection(dirX onto splineVec) */
Projf(axis1, dirX, splineVec); /* project dirX onto splineVec */
VecSubf(pchan->pose_mat[0], dirX, axis1);
Normalize(pchan->pose_mat[0]);
/* z-axis = dirZ - projection(dirZ onto splineVec) - projection(dirZ onto dirX) */
Projf(axis1, dirZ, splineVec); /* project dirZ onto Y-Axis */
Projf(axis2, dirZ, pchan->pose_mat[0]); /* project dirZ onto X-Axis */
VecSubf(tmpVec, dirZ, axis1); /* dirZ - proj(dirZ->YAxis) */
VecSubf(pchan->pose_mat[2], tmpVec, axis2); /* (dirZ - proj(dirZ->YAxis)) - proj(dirZ->XAxis) */
Normalize(pchan->pose_mat[2]);
/* step 3b: rotate these axes for roll control and also to minimise flipping rotations */
// NOTE: for controlling flipping rotations, we could look to the curve for guidance...
// TODO: code me!
{
float dmat[3][3], rmat[3][3], tmat[3][3];
float raxis[3], rangle;
/* compute the raw rotation matrix from the bone's current matrix by extracting only the
* orientation-relevant axes, and normalising them
*/
VECCOPY(rmat[0], pchan->pose_mat[0]);
VECCOPY(rmat[1], pchan->pose_mat[1]);
VECCOPY(rmat[2], pchan->pose_mat[2]);
Mat3Ortho(rmat);
/* also, normalise the orientation imposed by the bone, now that we've extracted the scale factor */
Normalize(splineVec);
/* calculate smallest axis-angle rotation necessary for getting from the
* current orientation of the bone, to the spline-imposed direction
*/
Crossf(raxis, rmat[1], splineVec);
rangle= Inpf(rmat[1], splineVec);
rangle= acos( MAX2(-1.0f, MIN2(1.0f, rangle)) );
/* construct rotation matrix from the axis-angle rotation found above
* - this call takes care to make sure that the axis provided is a unit vector first
*/
AxisAngleToMat3(raxis, rangle, dmat);
/* combine these rotations so that the y-axis of the bone is now aligned as the spline dictates,
* while still maintaining roll control from the existing bone animation
*/
Mat3MulMat3(tmat, dmat, rmat); // m1, m3, m2
Mat3Ortho(tmat); /* attempt to reduce shearing, though I doubt this'll really help too much now... */
Mat4CpyMat3(poseMat, tmat);
}
/* step 4: set the scaling factors for the axes */
// TODO: include a no-scale option?
{
/* only multiply the y-axis by the scaling factor to get nice volume-preservation */
VecMulf(pchan->pose_mat[1], scaleFac);
VecMulf(poseMat[1], scaleFac);
/* set the scaling factors of the x and z axes from the average radius of the curve? */
if (ikData->flag & CONSTRAINT_SPLINEIK_RAD2FAT) {
VecMulf(pchan->pose_mat[0], radius);
VecMulf(pchan->pose_mat[2], radius);
/* set the scaling factors of the x and z axes from... */
switch (ikData->xzScaleMode) {
case CONSTRAINT_SPLINEIK_XZS_RADIUS:
{
/* radius of curve */
VecMulf(poseMat[0], radius);
VecMulf(poseMat[2], radius);
}
break;
case CONSTRAINT_SPLINEIK_XZS_ORIGINAL:
{
/* original scales get used */
float scale;
/* x-axis scale */
scale= VecLength(pchan->pose_mat[0]);
VecMulf(poseMat[0], scale);
/* z-axis scale */
scale= VecLength(pchan->pose_mat[2]);
VecMulf(poseMat[2], scale);
}
break;
}
}
/* step 5: set the location of the bone in the matrix */
VECCOPY(pchan->pose_mat[3], pchan->pose_head);
VECCOPY(poseMat[3], pchan->pose_head);
/* finally, store the new transform */
Mat4CpyMat4(pchan->pose_mat, poseMat);
VECCOPY(pchan->pose_head, poseHead);
VECCOPY(pchan->pose_tail, poseTail);
/* done! */
pchan->flag |= POSE_DONE;

@ -537,7 +537,7 @@ static int read_undosave(bContext *C, UndoElem *uel)
int success=0, fileflags;
/* This is needed so undoing/redoing doesnt crash with threaded previews going */
WM_jobs_stop(CTX_wm_manager(C), CTX_wm_screen(C));
WM_jobs_stop_all(CTX_wm_manager(C));
strcpy(scestr, G.sce); /* temporal store */
fileflags= G.fileflags;

@ -526,8 +526,8 @@ DerivedMesh *NewBooleanDerivedMesh_intern(
CSG_FreeVertexDescriptor(&vd_o);
CSG_FreeFaceDescriptor(&fd_o);
}
// else
// XXX error("Unknown internal error in boolean");
else
printf("Unknown internal error in boolean");
CSG_FreeBooleanOperation(bool_op);

@ -145,6 +145,7 @@ Curve *add_curve(char *name, int type)
cu->fsize= 1.0;
cu->ulheight = 0.05;
cu->texflag= CU_AUTOSPACE;
cu->twist_mode= CU_TWIST_MINIMUM; // XXX: this one seems to be the best one in most cases, at least for curve deform...
cu->bb= unit_boundbox();
@ -2906,7 +2907,7 @@ void curve_applyVertexCos(Curve *cu, ListBase *lb, float (*vertexCos)[3])
float (*curve_getKeyVertexCos(Curve *cu, ListBase *lb, float *key))[3]
{
int i, numVerts;
int i, numVerts = count_curveverts(lb);
float *co, (*cos)[3] = MEM_mallocN(sizeof(*cos)*numVerts, "cu_vcos");
Nurb *nu;

@ -110,7 +110,7 @@ bDeformGroup *get_named_vertexgroup (Object *ob, char *name)
return NULL;
}
int get_named_vertexgroup_num (Object *ob, char *name)
int get_named_vertexgroup_num (Object *ob, const char *name)
{
/* Return the location of the named deform group within the list of
* deform groups. This function is a combination of get_defgroup_num and

@ -82,7 +82,7 @@
#include "BKE_anim.h"
#include "BKE_action.h"
#include "BKE_bmesh.h"
// XXX #include "BKE_booleanops.h"
#include "BKE_booleanops.h"
#include "BKE_cloth.h"
#include "BKE_collision.h"
#include "BKE_cdderivedmesh.h"
@ -113,18 +113,12 @@
#include "BKE_shrinkwrap.h"
#include "BKE_simple_deform.h"
//XXX #include "LOD_DependKludge.h"
#include "LOD_decimation.h"
// XXX
static struct DerivedMesh *NewBooleanDerivedMesh() {return NULL;}
#include "CCGSubSurf.h"
#include "RE_shader_ext.h"
//XXX #include "BIF_meshlaplacian.h"
/* Utility */
static int is_last_displist(Object *ob)
@ -3577,10 +3571,11 @@ static void get_texture_coords(DisplaceModifierData *dmd, Object *ob,
{
int i;
int texmapping = dmd->texmapping;
float mapob_imat[4][4];
if(texmapping == MOD_DISP_MAP_OBJECT) {
if(dmd->map_object)
Mat4Invert(dmd->map_object->imat, dmd->map_object->obmat);
Mat4Invert(mapob_imat, dmd->map_object->obmat);
else /* if there is no map object, default to local */
texmapping = MOD_DISP_MAP_LOCAL;
}
@ -3651,7 +3646,7 @@ static void get_texture_coords(DisplaceModifierData *dmd, Object *ob,
case MOD_DISP_MAP_OBJECT:
VECCOPY(*texco, *co);
Mat4MulVecfl(ob->obmat, *texco);
Mat4MulVecfl(dmd->map_object->imat, *texco);
Mat4MulVecfl(mapob_imat, *texco);
break;
}
}
@ -4137,11 +4132,11 @@ static DerivedMesh *decimateModifier_applyModifier(
ModifierData *md, Object *ob, DerivedMesh *derivedData,
int useRenderParams, int isFinalCalc)
{
// DecimateModifierData *dmd = (DecimateModifierData*) md;
DecimateModifierData *dmd = (DecimateModifierData*) md;
DerivedMesh *dm = derivedData, *result = NULL;
MVert *mvert;
MFace *mface;
// LOD_Decimation_Info lod;
LOD_Decimation_Info lod;
int totvert, totface;
int a, numTris;
@ -4163,8 +4158,6 @@ static DerivedMesh *decimateModifier_applyModifier(
goto exit;
}
// XXX
#if 0
lod.vertex_buffer= MEM_mallocN(3*sizeof(float)*totvert, "vertices");
lod.vertex_normal_buffer= MEM_mallocN(3*sizeof(float)*totvert, "normals");
lod.triangle_index_buffer= MEM_mallocN(3*sizeof(int)*numTris, "trias");
@ -4249,10 +4242,6 @@ static DerivedMesh *decimateModifier_applyModifier(
MEM_freeN(lod.vertex_buffer);
MEM_freeN(lod.vertex_normal_buffer);
MEM_freeN(lod.triangle_index_buffer);
#else
modifier_setError(md, "Modifier not working yet in 2.5.");
goto exit;
#endif
exit:
return result;
@ -6389,12 +6378,6 @@ static CustomDataMask booleanModifier_requiredDataMask(Object *ob, ModifierData
dataMask |= (1 << CD_MDEFORMVERT);
/* particles only need this if they are after a non deform modifier, and
* the modifier stack will only create them in that case. */
// dataMask |= CD_MASK_ORIGSPACE;
// dataMask |= CD_MASK_ORCO;
return dataMask;
}
@ -7865,17 +7848,17 @@ static void meshdeformModifier_do(
float (*vertexCos)[3], int numVerts)
{
MeshDeformModifierData *mmd = (MeshDeformModifierData*) md;
Mesh *me= ob->data;
Mesh *me= (mmd->object)? mmd->object->data: NULL;
EditMesh *em = (me)? BKE_mesh_get_editmesh(me): NULL;
DerivedMesh *tmpdm, *cagedm;
MDeformVert *dvert = NULL;
MDeformWeight *dw;
EditMesh *em = BKE_mesh_get_editmesh(me);
MVert *cagemvert;
float imat[4][4], cagemat[4][4], iobmat[4][4], icagemat[3][3], cmat[4][4];
float weight, totweight, fac, co[3], *weights, (*dco)[3], (*bindcos)[3];
int a, b, totvert, totcagevert, defgrp_index;
if(!mmd->object || (!mmd->bindcos && !mmd->needbind))
if(!mmd->object || (!mmd->bindcos && !mmd->bindfunc))
return;
/* get cage derivedmesh */
@ -7913,7 +7896,7 @@ static void meshdeformModifier_do(
/* progress bar redraw can make this recursive .. */
if(!recursive) {
recursive = 1;
//XXX harmonic_coordinates_bind(mmd, vertexCos, numVerts, cagemat);
mmd->bindfunc(md->scene, mmd, (float*)vertexCos, numVerts, cagemat);
recursive = 0;
}
}

@ -2276,7 +2276,7 @@ static int psys_threads_init_path(ParticleThread *threads, Scene *scene, float c
/* Object *ob= ctx->sim.ob; */
ParticleSystem *psys= ctx->sim.psys;
ParticleSettings *part = psys->part;
ParticleEditSettings *pset = &scene->toolsettings->particle;
/* ParticleEditSettings *pset = &scene->toolsettings->particle; */
int totparent=0, between=0;
int steps = (int)pow(2.0, (double)part->draw_step);
int totchild = psys->totchild;
@ -3334,6 +3334,8 @@ void object_remove_particle_system(Scene *scene, Object *ob)
if(ob->particlesystem.first)
((ParticleSystem *) ob->particlesystem.first)->flag |= PSYS_CURRENT;
else
ob->mode &= ~OB_MODE_PARTICLE_EDIT;
DAG_scene_sort(scene);
DAG_id_flush_update(&ob->id, OB_RECALC_DATA);

@ -1156,7 +1156,7 @@ static int seq_proxy_get_fname(Scene *scene, Sequence * seq, int cfra, char * na
return TRUE;
}
/* generate a seperate proxy directory for each preview size */
/* generate a separate proxy directory for each preview size */
if (seq->type == SEQ_IMAGE) {
StripElem * se = give_stripelem(seq, cfra);
@ -1285,7 +1285,7 @@ static void seq_proxy_build_frame(Scene *scene, Sequence * seq, int cfra, int re
IMB_scalefastImBuf(ibuf, (short)rectx, (short)recty);
}
/* quality is fixed, otherwise one has to generate seperate
/* quality is fixed, otherwise one has to generate separate
directories for every quality...
depth = 32 is intentionally left in, otherwise ALPHA channels

@ -92,12 +92,13 @@ static int (*SB_localInterruptCallBack)(void) = NULL;
/* ********** soft body engine ******* */
typedef enum {SB_EDGE=1,SB_BEND=2,SB_STIFFQUAD=3} type_spring;
typedef struct BodySpring {
int v1, v2;
float len, strength, cf,load;
float len,cf,load;
float ext_force[3]; /* edges colliding and sailing */
short order;
type_spring springtype;
short flag;
} BodySpring;
@ -613,13 +614,11 @@ static void add_mesh_quad_diag_springs(Object *ob)
if(mface->v4) {
bs->v1= mface->v1;
bs->v2= mface->v3;
bs->strength= s_shear;
bs->order =2;
bs->springtype =SB_STIFFQUAD;
bs++;
bs->v1= mface->v2;
bs->v2= mface->v4;
bs->strength= s_shear;
bs->order =2;
bs->springtype =SB_STIFFQUAD;
bs++;
}
@ -670,8 +669,7 @@ static void add_2nd_order_roller(Object *ob,float stiffness,int *counter, int ad
if (addsprings){
bs3->v1= v0;
bs3->v2= bs2->v1;
bs3->strength= stiffness;
bs3->order=2;
bs3->springtype =SB_BEND;
bs3++;
}
}
@ -680,8 +678,7 @@ static void add_2nd_order_roller(Object *ob,float stiffness,int *counter, int ad
if (addsprings){
bs3->v1= v0;
bs3->v2= bs2->v2;
bs3->strength= stiffness;
bs3->order=2;
bs3->springtype =SB_BEND;
bs3++;
}
@ -785,7 +782,7 @@ static void calculate_collision_balls(Object *ob)
/* first estimation based on attached */
for(b=bp->nofsprings;b>0;b--){
bs = sb->bspring + bp->springs[b-1];
if (bs->order == 1){
if (bs->springtype == SB_EDGE){
akku += bs->len;
akku_count++,
min = MIN2(bs->len,min);
@ -1529,7 +1526,7 @@ static void _scan_for_ext_spring_forces(Scene *scene, Object *ob, float timenow,
feedback[0]=feedback[1]=feedback[2]=0.0f;
bs->flag &= ~BSF_INTERSECT;
if (bs->order ==1){
if (bs->springtype == SB_EDGE){
/* +++ springs colliding */
if (ob->softflag & OB_SB_EDGECOLL){
if ( sb_detect_edge_collisionCached (sb->bpoint[bs->v1].pos , sb->bpoint[bs->v2].pos,
@ -2074,10 +2071,24 @@ static void sb_spring_force(Object *ob,int bpi,BodySpring *bs,float iks,float fo
forcefactor = iks/bs->len;
else
forcefactor = iks;
kw = (bp1->springweight+bp2->springweight)/2.0f;
kw = kw * kw;
kw = kw * kw;
forcefactor *= bs->strength * kw;
kw = (bp1->springweight+bp2->springweight)/2.0f;
kw = kw * kw;
kw = kw * kw;
switch (bs->springtype){
case SB_EDGE:
forcefactor *= kw;
break;
case SB_BEND:
forcefactor *=sb->secondspring*kw;
break;
case SB_STIFFQUAD:
forcefactor *=sb->shearstiff*sb->shearstiff* kw;
break;
default:
break;
}
Vec3PlusStVec(bp1->force,(bs->len - distance)*forcefactor,dir);
/* do bp1 <--> bp2 viscous */
@ -3275,8 +3286,7 @@ static void mesh_to_softbody(Scene *scene, Object *ob)
for(a=me->totedge; a>0; a--, medge++, bs++) {
bs->v1= medge->v1;
bs->v2= medge->v2;
bs->strength= 1.0;
bs->order=1;
bs->springtype=SB_EDGE;
}
@ -3354,44 +3364,39 @@ static void makelatticesprings(Lattice *lt, BodySpring *bs, int dostiff,Object *
if(w) {
bs->v1 = bpc;
bs->v2 = bpc-dw;
bs->strength= 1.0;
bs->order=1;
bs->springtype=SB_EDGE;
bs->len= globallen((bp-dw)->vec, bp->vec,ob);
bs++;
}
if(v) {
bs->v1 = bpc;
bs->v2 = bpc-dv;
bs->strength= 1.0;
bs->order=1;
bs->springtype=SB_EDGE;
bs->len= globallen((bp-dv)->vec, bp->vec,ob);
bs++;
}
if(u) {
bs->v1 = bpuc;
bs->v2 = bpc;
bs->strength= 1.0;
bs->order=1;
bs->springtype=SB_EDGE;
bs->len= globallen((bpu)->vec, bp->vec,ob);
bs++;
}
if (dostiff) {
if(w){
if(w){
if( v && u ) {
bs->v1 = bpc;
bs->v2 = bpc-dw-dv-1;
bs->strength= 1.0;
bs->order=2;
bs->springtype=SB_BEND;
bs->len= globallen((bp-dw-dv-1)->vec, bp->vec,ob);
bs++;
}
if( (v < lt->pntsv-1) && (u) ) {
bs->v1 = bpc;
bs->v2 = bpc-dw+dv-1;
bs->strength= 1.0;
bs->order=2;
bs->springtype=SB_BEND;
bs->len= globallen((bp-dw+dv-1)->vec, bp->vec,ob);
bs++;
}
@ -3401,16 +3406,14 @@ static void makelatticesprings(Lattice *lt, BodySpring *bs, int dostiff,Object *
if( v && u ) {
bs->v1 = bpc;
bs->v2 = bpc+dw-dv-1;
bs->strength= 1.0;
bs->order=2;
bs->springtype=SB_BEND;
bs->len= globallen((bp+dw-dv-1)->vec, bp->vec,ob);
bs++;
}
if( (v < lt->pntsv-1) && (u) ) {
bs->v1 = bpc;
bs->v2 = bpc+dw+dv-1;
bs->strength= 1.0;
bs->order=2;
bs->springtype=SB_BEND;
bs->len= globallen((bp+dw+dv-1)->vec, bp->vec,ob);
bs++;
}
@ -3520,22 +3523,19 @@ static void curve_surf_to_softbody(Scene *scene, Object *ob)
if(a>0) {
bs->v1= curindex-1;
bs->v2= curindex;
bs->strength= 1.0;
bs->order=1;
bs->springtype=SB_EDGE;
bs->len= globallen( (bezt-1)->vec[2], bezt->vec[0], ob );
bs++;
}
bs->v1= curindex;
bs->v2= curindex+1;
bs->strength= 1.0;
bs->order=1;
bs->springtype=SB_EDGE;
bs->len= globallen( bezt->vec[0], bezt->vec[1], ob );
bs++;
bs->v1= curindex+1;
bs->v2= curindex+2;
bs->strength= 1.0;
bs->order=1;
bs->springtype=SB_EDGE;
bs->len= globallen( bezt->vec[1], bezt->vec[2], ob );
bs++;
}
@ -3551,8 +3551,7 @@ static void curve_surf_to_softbody(Scene *scene, Object *ob)
if(totspring && a>0) {
bs->v1= curindex-1;
bs->v2= curindex;
bs->strength= 1.0;
bs->order=1;
bs->springtype=SB_EDGE;
bs->len= globallen( (bpnt-1)->vec, bpnt->vec , ob );
bs++;
}
@ -3769,7 +3768,15 @@ static void softbody_step(Scene *scene, Object *ob, SoftBody *sb, float dtime)
{
/* the simulator */
float forcetime;
double sct,sst=PIL_check_seconds_timer();
double sct,sst;
sst=PIL_check_seconds_timer();
/* Integration back in time is possible in theory, but pretty useless here.
So we refuse to do so. Since we do not know anything about 'outside' canges
especially colliders we refuse to go more than 10 frames.
*/
if(dtime < 0 || dtime > 10.5f) return;
ccd_update_deflector_hash(scene, ob, sb->scratch->colliderhash);
@ -3784,8 +3791,8 @@ static void softbody_step(Scene *scene, Object *ob, SoftBody *sb, float dtime)
/* special case of 2nd order Runge-Kutta type AKA Heun */
int mid_flags=0;
float err = 0;
float forcetimemax = 1.0f;
float forcetimemin = 0.001f;
float forcetimemax = 1.0f; /* set defaults guess we shall do one frame */
float forcetimemin = 0.01f; /* set defaults guess 1/100 is tight enough */
float timedone =0.0; /* how far did we get without violating error condition */
/* loops = counter for emergency brake
* we don't want to lock up the system if physics fail
@ -3793,13 +3800,12 @@ static void softbody_step(Scene *scene, Object *ob, SoftBody *sb, float dtime)
int loops =0 ;
SoftHeunTol = sb->rklimit; /* humm .. this should be calculated from sb parameters and sizes */
if (sb->minloops > 0) forcetimemax = 1.0f / sb->minloops;
if (sb->maxloops > 0) forcetimemin = 1.0f / sb->maxloops;
/* adjust loop limits */
if (sb->minloops > 0) forcetimemax = dtime / sb->minloops;
if (sb->maxloops > 0) forcetimemin = dtime / sb->maxloops;
if(sb->solver_ID>0) mid_flags |= MID_PRESERVE;
//forcetime = dtime; /* hope for integrating in one step */
forcetime =forcetimemax; /* hope for integrating in one step */
while ( (ABS(timedone) < ABS(dtime)) && (loops < 2000) )
{
@ -3853,7 +3859,7 @@ static void softbody_step(Scene *scene, Object *ob, SoftBody *sb, float dtime)
loops++;
if(sb->solverflags & SBSO_MONITOR ){
sct=PIL_check_seconds_timer();
if (sct-sst > 0.5f) printf("%3.0f%% \r",100.0f*timedone);
if (sct-sst > 0.5f) printf("%3.0f%% \r",100.0f*timedone/dtime);
}
/* ask for user break */
if (SB_localInterruptCallBack && SB_localInterruptCallBack()) break;
@ -4022,11 +4028,11 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i
/* checking time: */
dtime = framedelta*timescale;
/* do simulation */
softbody_step(scene, ob, sb, dtime);
softbody_to_object(ob, vertexCos, numVerts, 0);
/* do simulation */
cache->simframe= framenr;
cache->flag |= PTCACHE_SIMULATION_VALID;

@ -1125,7 +1125,7 @@ PointDensity *BKE_add_pointdensity(void)
pd->totpoints = 0;
pd->coba = add_colorband(1);
pd->object = NULL;
pd->psys = NULL;
pd->psys = 0;
return pd;
}

@ -2882,10 +2882,8 @@ static void lib_link_texture(FileData *fd, Main *main)
tex->ima= newlibadr_us(fd, tex->id.lib, tex->ima);
tex->ipo= newlibadr_us(fd, tex->id.lib, tex->ipo);
if(tex->env) tex->env->object= newlibadr(fd, tex->id.lib, tex->env->object);
if(tex->pd) {
if(tex->pd)
tex->pd->object= newlibadr(fd, tex->id.lib, tex->pd->object);
tex->pd->psys= newlibadr(fd, tex->id.lib, tex->pd->psys);
}
if(tex->vd) tex->vd->object= newlibadr(fd, tex->id.lib, tex->vd->object);
if(tex->nodetree)

@ -1293,7 +1293,7 @@ static int animchannels_borderselect_exec(bContext *C, wmOperator *op)
bAnimContext ac;
rcti rect;
short selectmode=0;
int event;
int gesture_mode;
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
@ -1305,8 +1305,8 @@ static int animchannels_borderselect_exec(bContext *C, wmOperator *op)
rect.xmax= RNA_int_get(op->ptr, "xmax");
rect.ymax= RNA_int_get(op->ptr, "ymax");
event= RNA_int_get(op->ptr, "event_type");
if (event == LEFTMOUSE) // FIXME... hardcoded
gesture_mode= RNA_int_get(op->ptr, "gesture_mode");
if (gesture_mode == GESTURE_MODAL_SELECT)
selectmode = ACHANNEL_SETFLAG_ADD;
else
selectmode = ACHANNEL_SETFLAG_CLEAR;
@ -1338,11 +1338,7 @@ void ANIM_OT_channels_select_border(wmOperatorType *ot)
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
/* rna */
RNA_def_int(ot->srna, "event_type", 0, INT_MIN, INT_MAX, "Event Type", "", INT_MIN, INT_MAX);
RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN, INT_MAX);
RNA_def_int(ot->srna, "xmax", 0, INT_MIN, INT_MAX, "X Max", "", INT_MIN, INT_MAX);
RNA_def_int(ot->srna, "ymin", 0, INT_MIN, INT_MAX, "Y Min", "", INT_MIN, INT_MAX);
RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN, INT_MAX);
WM_operator_properties_gesture_border(ot, FALSE);
}
/* ******************** Mouse-Click Operator *********************** */

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