BPython:
- Stephane Soppera added long missed support for edge data in Blender.NMesh + related doc; - Michael Reimpell improved script registration (fixes bug report #2160) and the file and image selectors in Blender.Window (improved with suggestions from Yann Vernier). They now suppport methods as callbacks; - World.get/setMode were not registered, so could not be directly called (reported by Ken Hughes). Still needs some work to improve things, including docs. Scripts: - Jean-Michel Soler updated his texture baker based on input from Appolux; - Campbell and Jean-Michel improved the bvh importer: faster, better float units scaling (by Campbell); supports Poser 3.01 files (by jms). Thanks guys!
This commit is contained in:
@@ -2,30 +2,44 @@
|
||||
|
||||
"""
|
||||
Name: 'Motion Capture (.bvh)...'
|
||||
Blender: 232
|
||||
Blender: 236
|
||||
Group: 'Import'
|
||||
Tip: 'Import a (.bvh) motion capture file'
|
||||
"""
|
||||
|
||||
__author__ = "Campbell Barton"
|
||||
__url__ = ("blender", "elysiun")
|
||||
__version__ = "1.0 03/25/04"
|
||||
__url__ = ("blender", "elysiun", "http://jmsoler.free.fr/util/blenderfile/py/bvh_import.py")
|
||||
__version__ = "1.0.2 04/12/28"
|
||||
|
||||
__bpydoc__ = """\
|
||||
This script imports BVH motion capture data to Blender.
|
||||
|
||||
Supported:<br>
|
||||
Supported: Poser 3.01<br>
|
||||
|
||||
Missing:<br>
|
||||
|
||||
Known issues:<br>
|
||||
|
||||
Notes:<br>
|
||||
Jean-Michel Soler improved importer to support Poser 3.01 files.
|
||||
|
||||
"""
|
||||
|
||||
# $Id$
|
||||
#
|
||||
|
||||
#===============================================#
|
||||
# BVH Import script 1.03 patched by Campbell #
|
||||
# Small optimizations and scale input #
|
||||
# 01/01/2005, #
|
||||
#===============================================#
|
||||
|
||||
#===============================================#
|
||||
# BVH Import script 1.02 patched by Jm Soler #
|
||||
# to the Poser 3.01 bvh file #
|
||||
# 28/12/2004, #
|
||||
#===============================================#
|
||||
|
||||
#===============================================#
|
||||
# BVH Import script 1.0 by Campbell Barton #
|
||||
# 25/03/2004, euler rotation code taken from #
|
||||
@@ -67,7 +81,7 @@ Notes:<br>
|
||||
import string
|
||||
import math
|
||||
import Blender
|
||||
from Blender import Window, Object, Scene, Ipo
|
||||
from Blender import Window, Object, Scene, Ipo, Draw
|
||||
from Blender.Scene import Render
|
||||
|
||||
|
||||
@@ -80,14 +94,13 @@ from Blender.Scene import Render
|
||||
#
|
||||
# except:
|
||||
# print 'psyco is not present on this system'
|
||||
|
||||
|
||||
# Default scale
|
||||
scale = 0.01
|
||||
|
||||
# Update as we load?
|
||||
debug = 0
|
||||
|
||||
# Global scale facctor # sHOULD BE 1 BY DEFAULT
|
||||
scale = 1
|
||||
|
||||
# Get the current scene.
|
||||
scn = Scene.GetCurrent()
|
||||
context = scn.getRenderingContext()
|
||||
@@ -100,6 +113,9 @@ channelCurves = []
|
||||
# Chenging there rotation to EULER rotation
|
||||
objectList = []
|
||||
|
||||
def getScale():
|
||||
return Draw.PupFloatInput('BVH Scale: ', 0.01, 0.001, 10.0, 0.1, 3)
|
||||
|
||||
def MAT(m):
|
||||
if len(m) == 3:
|
||||
return Blender.Mathutils.Matrix(m[0], m[1], m[2])
|
||||
@@ -127,7 +143,6 @@ def eulerRotate(x,y,z):
|
||||
for k in range(3):
|
||||
for j in range(3):
|
||||
mat3[i][k]=mat3[i][k]+mat1[i][j]*mat2[j][k]
|
||||
mat1 = mat2 = i = k = j = None # Save memory
|
||||
return mat3
|
||||
|
||||
|
||||
@@ -162,7 +177,6 @@ def eulerRotate(x,y,z):
|
||||
mat3[2][1]=t*y*z-s*x
|
||||
mat3[2][2]=t*z*z+c
|
||||
|
||||
rot4 = s = c = t = x = y = z = None # Save some memory
|
||||
return mat3
|
||||
|
||||
eul = [x,y,z]
|
||||
@@ -202,8 +216,6 @@ def eulerRotate(x,y,z):
|
||||
y =- eul[1]/-10
|
||||
z =- eul[2]/-10
|
||||
|
||||
|
||||
eul = mat = zmat = xmat = ymat = jj = None
|
||||
return x, y, z # Returm euler roration values.
|
||||
|
||||
|
||||
@@ -213,6 +225,7 @@ def eulerRotate(x,y,z):
|
||||
# from the BVA file to create an empty #
|
||||
#===============================================#
|
||||
def makeJoint(name, parent, prefix, offset, channels):
|
||||
global scale
|
||||
# Make Empty, with the prefix in front of the name
|
||||
ob = Object.New('Empty', prefix + name) # New object, ob is shorter and nicer to use.
|
||||
scn.link(ob) # place the object in the current scene
|
||||
@@ -253,8 +266,6 @@ def makeJoint(name, parent, prefix, offset, channels):
|
||||
# Add to object list
|
||||
objectList.append(ob)
|
||||
|
||||
ob = newIpo = opParent = None
|
||||
|
||||
# Redraw if debugging
|
||||
if debug: Blender.Redraw()
|
||||
|
||||
@@ -280,13 +291,22 @@ def makeEnd(parent, prefix, offset):
|
||||
|
||||
|
||||
|
||||
|
||||
#===============================================#
|
||||
# MAIN FUNCTION - All things are done from here #
|
||||
#===============================================#
|
||||
def loadBVH(filename):
|
||||
global scale
|
||||
print ''
|
||||
print 'BVH Importer 1.0 by Campbell Barton (Ideasman) - ideasman@linuxmail.org'
|
||||
|
||||
alpha='abcdefghijklmnopqrstuvewxyz'
|
||||
ALPHA=alpha+alpha.upper()
|
||||
ALPHA+=' 0123456789+-{}. '
|
||||
time1 = Blender.sys.time()
|
||||
tmpScale = getScale()
|
||||
if tmpScale != None:
|
||||
scale = tmpScale
|
||||
|
||||
# File loading stuff
|
||||
# Open the file for importing
|
||||
file = open(filename, 'r')
|
||||
@@ -294,10 +314,19 @@ def loadBVH(filename):
|
||||
# Make a list of lines
|
||||
lines = []
|
||||
for fileLine in fileData:
|
||||
fileLine=fileLine.replace('..','.')
|
||||
newLine = string.split(fileLine)
|
||||
if newLine != []:
|
||||
lines.append(string.split(fileLine))
|
||||
fileData = None
|
||||
t=[]
|
||||
for n in newLine:
|
||||
for n0 in n:
|
||||
if n0 not in ALPHA:
|
||||
n=n.replace(n0,'')
|
||||
t.append(n)
|
||||
lines.append(t)
|
||||
|
||||
|
||||
del fileData
|
||||
# End file loading code
|
||||
|
||||
# Call object names with this prefix, mainly for scenes with multiple BVH's - Can imagine most partr names are the same
|
||||
@@ -320,18 +349,25 @@ def loadBVH(filename):
|
||||
#channelList [(<objectName>, [channelType1, channelType2...]), (<objectName>, [channelType1, channelType2...)]
|
||||
channelList = []
|
||||
channelIndex = -1
|
||||
|
||||
|
||||
|
||||
lineIdx = 1 # An index for the file.
|
||||
while lineIdx < len(lines) -1:
|
||||
#...
|
||||
if lines[lineIdx][0] == 'ROOT' or lines[lineIdx][0] == 'JOINT':
|
||||
if lines[lineIdx][0] == 'JOINT' and len(lines[lineIdx])>2:
|
||||
for j in range(2,len(lines[lineIdx])) :
|
||||
lines[lineIdx][1]+='_'+lines[lineIdx][j]
|
||||
|
||||
# MAY NEED TO SUPPORT MULTIPLE ROOT's HERE!!!, Still unsure weather multiple roots are possible.??
|
||||
|
||||
print len(parent) * ' ' + 'node:',lines[lineIdx][1],' parent:',parent[-1]
|
||||
|
||||
print lineIdx
|
||||
name = lines[lineIdx][1]
|
||||
print name,lines[lineIdx+1],lines[lineIdx+2]
|
||||
lineIdx += 2 # Incriment to the next line (Offset)
|
||||
offset = ( eval(lines[lineIdx][1]), eval(lines[lineIdx][2]), eval(lines[lineIdx][3]) )
|
||||
offset = ( float(lines[lineIdx][1]), float(lines[lineIdx][2]), float(lines[lineIdx][3]) )
|
||||
lineIdx += 1 # Incriment to the next line (Channels)
|
||||
|
||||
# newChannel[Xposition, Yposition, Zposition, Xrotation, Yrotation, Zrotation]
|
||||
@@ -367,7 +403,7 @@ def loadBVH(filename):
|
||||
# Account for an end node
|
||||
if lines[lineIdx][0] == 'End' and lines[lineIdx][1] == 'Site': # There is somtimes a name afetr 'End Site' but we will ignore it.
|
||||
lineIdx += 2 # Incriment to the next line (Offset)
|
||||
offset = ( eval(lines[lineIdx][1]), eval(lines[lineIdx][2]), eval(lines[lineIdx][3]) )
|
||||
offset = ( float(lines[lineIdx][1]), float(lines[lineIdx][2]), float(lines[lineIdx][3]) )
|
||||
makeEnd(parent, prefix, offset)
|
||||
|
||||
# Just so we can remove the Parents in a uniform way- End end never has kids
|
||||
@@ -431,21 +467,46 @@ def loadBVH(filename):
|
||||
if debug: Blender.Redraw()
|
||||
while obIdx < len(objectList) -1:
|
||||
if channelList[obIdx][0] != -1:
|
||||
objectList[obIdx].getIpo().getCurve('LocX').addBezier((currentFrame, scale * eval(lines[lineIdx][channelList[obIdx][0]])))
|
||||
VAL0=lines[lineIdx][channelList[obIdx][0]]
|
||||
if VAL0.find('.')==-1:
|
||||
VAL0=VAL0[:len(VAL0)-6]+'.'+VAL0[-6:]
|
||||
objectList[obIdx].getIpo().getCurve('LocX').addBezier((currentFrame, scale * float(VAL0)))
|
||||
|
||||
if channelList[obIdx][1] != -1:
|
||||
objectList[obIdx].getIpo().getCurve('LocY').addBezier((currentFrame, scale * eval(lines[lineIdx][channelList[obIdx][1]])))
|
||||
VAL1=lines[lineIdx][channelList[obIdx][0]]
|
||||
if VAL1.find('.')==-1:
|
||||
VAL1=VAL1[:len(VAL1)-6]+'.'+VAL1[-6:]
|
||||
objectList[obIdx].getIpo().getCurve('LocY').addBezier((currentFrame, scale * float(VAL1)))
|
||||
|
||||
if channelList[obIdx][2] != -1:
|
||||
objectList[obIdx].getIpo().getCurve('LocZ').addBezier((currentFrame, scale * eval(lines[lineIdx][channelList[obIdx][2]])))
|
||||
VAL2=lines[lineIdx][channelList[obIdx][0]]
|
||||
if VAL2.find('.')==-1:
|
||||
VAL2=VAL2[:len(VAL2)-6]+'.'+VAL2[-6:]
|
||||
objectList[obIdx].getIpo().getCurve('LocZ').addBezier((currentFrame, scale * float(VAL2)))
|
||||
|
||||
if channelList[obIdx][3] != '-1' or channelList[obIdx][4] != '-1' or channelList[obIdx][5] != '-1':
|
||||
x, y, z = eulerRotate(eval(lines[lineIdx][channelList[obIdx][3]]), eval(lines[lineIdx][channelList[obIdx][4]]), eval(lines[lineIdx][channelList[obIdx][5]]))
|
||||
VAL3=lines[lineIdx][channelList[obIdx][3]]
|
||||
if VAL3.find('.')==-1:
|
||||
VAL3=VAL3[:len(VAL3)-6]+'.'+VAL3[-6:]
|
||||
|
||||
VAL4=lines[lineIdx][channelList[obIdx][4]]
|
||||
if VAL4.find('.')==-1:
|
||||
VAL4=VAL4[:len(VAL4)-6]+'.'+VAL4[-6:]
|
||||
|
||||
VAL5=lines[lineIdx][channelList[obIdx][5]]
|
||||
if VAL5.find('.')==-1:
|
||||
VAL5=VAL5[:len(VAL5)-6]+'.'+VAL5[-6:]
|
||||
|
||||
x, y, z = eulerRotate(float(VAL3), float(VAL4), float(VAL5))
|
||||
|
||||
objectList[obIdx].getIpo().getCurve('RotX').addBezier((currentFrame, x))
|
||||
objectList[obIdx].getIpo().getCurve('RotY').addBezier((currentFrame, y))
|
||||
objectList[obIdx].getIpo().getCurve('RotZ').addBezier((currentFrame, z))
|
||||
|
||||
obIdx += 1
|
||||
# Done importing motion data #
|
||||
|
||||
lines[lineIdx] = None # Scrap old motion data, save some memory?
|
||||
# lines[lineIdx] = None # Scrap old motion data, save some memory?
|
||||
lineIdx += 1
|
||||
# We have finished now
|
||||
print currentFrame, 'done.'
|
||||
@@ -457,5 +518,6 @@ def loadBVH(filename):
|
||||
|
||||
# Main file loop
|
||||
lineIdx += 1
|
||||
print "bvh import time: ", Blender.sys.time() - time1
|
||||
|
||||
Blender.Window.FileSelector(loadBVH, "Import BVH")
|
||||
|
||||
@@ -11,7 +11,7 @@ __author__ = "Jean-Michel Soler (jms)"
|
||||
__url__ = ("blender", "elysiun",
|
||||
"Script online, http://jmsoler.free.fr/util/blenderfile/py/text2uvbaker.py",
|
||||
"Communicate problems and errors, http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender")
|
||||
__version__ = "0.2.2 2004/08/01"
|
||||
__version__ = "0.2.3 2004/12/30"
|
||||
|
||||
__bpydoc__ = """\
|
||||
This script "bakes" Blender procedural materials (including textures): it saves
|
||||
@@ -33,7 +33,7 @@ Notes:<br>
|
||||
"""
|
||||
|
||||
#---------------------------------------------
|
||||
# Last release : 0.2.2 , 2004/08/01 , 22h13
|
||||
# Last release : 0.2.3 , 2004/12/30 , 22h13
|
||||
#---------------------------------------------
|
||||
#---------------------------------------------
|
||||
# (c) jm soler 07/2004 : 'Procedural Texture Baker'
|
||||
@@ -43,12 +43,40 @@ Notes:<br>
|
||||
# original mesh.
|
||||
# released under Blender Artistic Licence
|
||||
#
|
||||
# 0.2.2 : if the uv mesh objet exists it used,
|
||||
# no creation of a new one. As the lamp and
|
||||
# the camera
|
||||
# 0.2.1 : This script automaticaly frame and shoot the
|
||||
# new uv mesh . The image file is saved ine the
|
||||
# /render folder.
|
||||
#
|
||||
# 0.2.3 :
|
||||
# Great thanks for Apollux who sees a lot of these
|
||||
# problems
|
||||
#
|
||||
# --Everytime you run the script a new set
|
||||
# of objects is created. File size and memory
|
||||
# consumption can go pretty high if you are
|
||||
# not aware of that .
|
||||
# Now it ONLY creates 3 objects: a flattened
|
||||
# mesh, a camera and a lamp.
|
||||
# --all the 3 objects was placed on layer 1, but if
|
||||
# that layer was not visible while you used the script
|
||||
# all you will get a is an empty render.
|
||||
# Now the layer is tst and activated befor the shoot
|
||||
# --The flattened mesh was really flattend only after
|
||||
# frame 100 (if you playbacked the animation, you can
|
||||
# actually see the mesh becoming flat on the first 100
|
||||
# frames). No more.
|
||||
# -- When the script is run, it changes temporary to
|
||||
# the new cammera, set the render output to a square
|
||||
# (i.e. 1024 x 1024 or else), does the render, and then
|
||||
# resets the render output and the active camera to the
|
||||
# original one. But if no original camera was found
|
||||
# this produce an error.
|
||||
#
|
||||
# 0.2.2 :
|
||||
# if the uv mesh objet exists it used,
|
||||
# no creation of a new one. As the lamp and
|
||||
# the camera
|
||||
# 0.2.1 :
|
||||
# This script automaticaly frame and shoot the
|
||||
# new uv mesh . The image file is saved ine the
|
||||
# /render folder.
|
||||
#
|
||||
#---------------------------------------------
|
||||
# On user-friendly side :
|
||||
@@ -83,9 +111,9 @@ Basic instructions:
|
||||
- Run this script and check the console.
|
||||
"""
|
||||
|
||||
def GET_newobject (TYPE):
|
||||
def GET_newobject (TYPE,NAME):
|
||||
SCENE = Blender.Scene.getCurrent()
|
||||
OBJECT = Blender.Object.New(TYPE)
|
||||
OBJECT = Blender.Object.New(TYPE,NAME)
|
||||
SCENE.link(OBJECT)
|
||||
return OBJECT, SCENE
|
||||
|
||||
@@ -138,7 +166,7 @@ def SHOOT (XYlimit, frame, obj, name, FRAME):
|
||||
except:
|
||||
Cam = Blender.Camera.New()
|
||||
Cam.name = 'UVCamera'
|
||||
CAM, SC = GET_newobject('Camera')
|
||||
CAM, SC = GET_newobject('Camera','UVCAMERA')
|
||||
CAM.link(Cam)
|
||||
CAM.setName('UVCAMERA')
|
||||
Cam.lens = 30
|
||||
@@ -151,22 +179,23 @@ def SHOOT (XYlimit, frame, obj, name, FRAME):
|
||||
CAM.setEuler (0.0, 0.0, 0.0)
|
||||
|
||||
try:
|
||||
LAMP = Blender.Object.Get('Eclairage')
|
||||
LAMP = Blender.Object.Get('ECLAIRAGE')
|
||||
lampe = LAMP.getData()
|
||||
SC = Blender.Scene.getCurrent()
|
||||
|
||||
except:
|
||||
lampe = Blender.Lamp.New()
|
||||
lampe.name = 'lumin'
|
||||
LAMP, SC = GET_newobject('Lamp')
|
||||
LAMP, SC = GET_newobject('Lamp','ECLAIRAGE')
|
||||
LAMP.link(lampe)
|
||||
LAMP.setName('Eclairage')
|
||||
LAMP.setName('ECLAIRAGE')
|
||||
|
||||
LAMP.setLocation(obj.getLocation())
|
||||
LAMP.LocX += XYlimit[0] / 2.0
|
||||
LAMP.LocY += XYlimit[1] / 2.0
|
||||
LAMP.LocZ += max (XYlimit[0], XYlimit[1])
|
||||
LAMP.setEuler (0.0, 0.0, 0.0)
|
||||
|
||||
context = SC.getRenderingContext()
|
||||
Camold = SC.getCurrentCamera()
|
||||
SC.setCurrentCamera(CAM)
|
||||
@@ -189,16 +218,27 @@ def SHOOT (XYlimit, frame, obj, name, FRAME):
|
||||
SAVE_image (context, name, FRAME)
|
||||
context.imageSizeY(OLDy)
|
||||
context.imageSizeX(OLDx)
|
||||
SC.setCurrentCamera(Camold)
|
||||
|
||||
if Camold :SC.setCurrentCamera(Camold)
|
||||
|
||||
Blender.Set ('curframe', frame)
|
||||
|
||||
def Mesh2UVCoord ():
|
||||
try:
|
||||
if 1:#try:
|
||||
MESH3D = Object.GetSelected()[0]
|
||||
|
||||
if MESH3D.getType() == 'Mesh':
|
||||
MESH = MESH3D.getData()
|
||||
MESH2 = Blender.NMesh.GetRaw()
|
||||
|
||||
try:
|
||||
NewOBJECT=Blender.Object.Get('UVOBJECT')
|
||||
CurSCENE=Blender.Scene.getCurrent()
|
||||
MESH2 = NewOBJECT.getData()
|
||||
MESH2.faces=[]
|
||||
|
||||
except:
|
||||
NewOBJECT, CurSCENE = GET_newobject('Mesh','UVOBJECT')
|
||||
MESH2 = Blender.NMesh.GetRaw()
|
||||
|
||||
for f in MESH.faces:
|
||||
f1 = Blender.NMesh.Face()
|
||||
@@ -218,25 +258,14 @@ def Mesh2UVCoord ():
|
||||
|
||||
MESH2.materials = MESH.materials[:]
|
||||
|
||||
try:
|
||||
NewOBJECT=Blender.Object.Get('UVOBJECT')
|
||||
CurSCENE=Blender.Scene.getCurrent()
|
||||
except:
|
||||
NewOBJECT, CurSCENE = GET_newobject('Mesh')
|
||||
|
||||
NewOBJECT.link(MESH2)
|
||||
|
||||
#NewOBJECT, CurSCENE = GET_newobject('Mesh')
|
||||
#NewOBJECT.link(MESH2)
|
||||
|
||||
|
||||
NewOBJECT.setLocation (OBJPOS, OBJPOS, 0.0)
|
||||
NewOBJECT.setEuler (0.0, 0.0, 0.0)
|
||||
|
||||
MESH2.removeAllKeys()
|
||||
|
||||
MESH2.update()
|
||||
MESH2.insertKey (1, 'absolute')
|
||||
MESH2.update()
|
||||
|
||||
for f in MESH2.faces:
|
||||
for v in f.v:
|
||||
@@ -248,6 +277,10 @@ def Mesh2UVCoord ():
|
||||
|
||||
print XYLIMIT
|
||||
|
||||
MESH2.update()
|
||||
MESH2.insertKey (1, 'absolute')
|
||||
MESH2.update()
|
||||
|
||||
MESH2.update()
|
||||
MESH2.insertKey (FRAME, 'absolute')
|
||||
MESH2.update()
|
||||
@@ -271,9 +304,9 @@ def Mesh2UVCoord ():
|
||||
result = Draw.PupMenu(name)
|
||||
print 'problem : no object selected or not mesh'
|
||||
|
||||
except:
|
||||
name = "Error%t|Active object is not a mesh or has no UV coordinates"
|
||||
result = Draw.PupMenu(name)
|
||||
#except:
|
||||
# name = "Error%t|Active object is not a mesh or has no UV coordinates"
|
||||
# result = Draw.PupMenu(name)
|
||||
print 'problem : no object selected or not mesh'
|
||||
|
||||
Mesh2UVCoord()
|
||||
|
||||
@@ -647,14 +647,13 @@ static int bpymenu_CreateFromDir( char *dirname, int whichdir )
|
||||
int scriptGroup;
|
||||
BPyMenu *scriptMenu = NULL;
|
||||
/* other */
|
||||
int scanDir = 1;
|
||||
int returnValue = 0;
|
||||
|
||||
/* open directory stream */
|
||||
dir = opendir(dirname);
|
||||
if (dir != NULL) {
|
||||
/* directory stream opened */
|
||||
while (((dirEntry = readdir(dir)) != NULL) && (scanDir == 1)) {
|
||||
while ((dirEntry = readdir(dir)) != NULL) {
|
||||
/* Check if filename does not start with a dot,
|
||||
* ends with '.py' and is a regular file. */
|
||||
BLI_make_file_string("/", fileName, dirname, dirEntry->d_name);
|
||||
@@ -722,10 +721,7 @@ static int bpymenu_CreateFromDir( char *dirname, int whichdir )
|
||||
if (DEBUG) {
|
||||
fprintf(stderr, "BPyMenus error: Couldn't create entry for: %s\n", fileName);
|
||||
}
|
||||
/* abort */
|
||||
parserState = 0;
|
||||
scanDir = 0;
|
||||
returnValue = -2;
|
||||
} else {
|
||||
parserState++;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -52,6 +52,7 @@ extern PyTypeObject NMesh_Type;
|
||||
extern PyTypeObject NMFace_Type;
|
||||
extern PyTypeObject NMVert_Type;
|
||||
extern PyTypeObject NMCol_Type;
|
||||
extern PyTypeObject NMEdge_Type;
|
||||
|
||||
|
||||
struct BPy_Object;
|
||||
@@ -71,6 +72,7 @@ void remove_vert_def_nr( Object * ob, int def_nr, int vertnum );
|
||||
#define BPy_NMFace_Check(v) ((v)->ob_type == &NMFace_Type)
|
||||
#define BPy_NMVert_Check(v) ((v)->ob_type == &NMVert_Type)
|
||||
#define BPy_NMCol_Check(v) ((v)->ob_type == &NMCol_Type)
|
||||
#define BPy_NMEdge_Check(v) ((v)->ob_type == &NMEdge_Type)
|
||||
|
||||
/* Typedefs for the new types */
|
||||
|
||||
@@ -103,6 +105,14 @@ typedef struct {
|
||||
|
||||
} BPy_NMFace; /* an NMesh face */
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD /* required python macro */
|
||||
PyObject *v1;
|
||||
PyObject *v2;
|
||||
char crease;
|
||||
short flag;
|
||||
} BPy_NMEdge; /* an NMesh edge */
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD /* required python macro */
|
||||
Mesh * mesh;
|
||||
@@ -111,6 +121,7 @@ typedef struct {
|
||||
PyObject *materials;
|
||||
PyObject *verts;
|
||||
PyObject *faces;
|
||||
PyObject *edges;
|
||||
int sel_face; /*@ XXX remove */
|
||||
short smoothresh; /* max AutoSmooth angle */
|
||||
short subdiv[2]; /* SubDiv Levels: display and rendering */
|
||||
@@ -134,7 +145,7 @@ int NMesh_CheckPyObject( PyObject * pyobj );
|
||||
|
||||
void mesh_update( Mesh * mesh );
|
||||
PyObject *new_NMesh( Mesh * oldmesh );
|
||||
Mesh *Mesh_fromNMesh( BPy_NMesh * nmesh );
|
||||
Mesh *Mesh_fromNMesh( BPy_NMesh * nmesh , int store_edges );
|
||||
PyObject *NMesh_assignMaterials_toObject( BPy_NMesh * nmesh, Object * ob );
|
||||
Material **nmesh_updateMaterials( BPy_NMesh * nmesh );
|
||||
Material **newMaterialList_fromPyList( PyObject * list );
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
*
|
||||
* This is a new part of Blender.
|
||||
*
|
||||
* Contributor(s): Willian P. Germano, Tom Musgrove
|
||||
* Contributor(s): Willian P. Germano, Tom Musgrove, Michael Reimpell, Yann Vernier
|
||||
*
|
||||
* ***** END GPL/BL DUAL LICENSE BLOCK *****
|
||||
*/
|
||||
@@ -68,7 +68,7 @@
|
||||
extern int EXPP_disable_force_draw;
|
||||
|
||||
/* Callback used by the file and image selector access functions */
|
||||
static PyObject *( *EXPP_FS_PyCallback ) ( PyObject * arg ) = NULL;
|
||||
static PyObject *EXPP_FS_PyCallback = NULL;
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Python API function prototypes for the Window module. */
|
||||
@@ -452,13 +452,24 @@ static PyObject *M_Window_QRedrawAll( PyObject * self, PyObject * args )
|
||||
|
||||
static void getSelectedFile( char *name )
|
||||
{
|
||||
if( !EXPP_FS_PyCallback )
|
||||
return;
|
||||
|
||||
PyObject_CallFunction( ( PyObject * ) EXPP_FS_PyCallback, "s", name );
|
||||
|
||||
EXPP_FS_PyCallback = NULL;
|
||||
|
||||
PyObject *callback;
|
||||
PyObject *result;
|
||||
|
||||
callback = EXPP_FS_PyCallback;
|
||||
result = PyObject_CallFunction( EXPP_FS_PyCallback, "s", name );
|
||||
if ((!result) && (G.f & G_DEBUG)) {
|
||||
fprintf(stderr, "BPy error: Callback call failed!\n");
|
||||
}
|
||||
Py_XDECREF(result);
|
||||
/* Catch changes of EXPP_FS_PyCallback during the callback call
|
||||
* due to calls to Blender.Window.FileSelector or
|
||||
* Blender.Window.ImageSelector inside the python callback. */
|
||||
if (callback == EXPP_FS_PyCallback) {
|
||||
Py_DECREF(EXPP_FS_PyCallback);
|
||||
EXPP_FS_PyCallback = NULL;
|
||||
} else {
|
||||
Py_DECREF(callback);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -470,12 +481,12 @@ static PyObject *M_Window_FileSelector( PyObject * self, PyObject * args )
|
||||
Script *script = G.main->script.last;
|
||||
int startspace = 0;
|
||||
|
||||
if( !PyArg_ParseTuple( args, "O!|ss",
|
||||
&PyFunction_Type, &EXPP_FS_PyCallback, &title,
|
||||
&filename ) )
|
||||
if( (!PyArg_ParseTuple( args, "O|ss", &EXPP_FS_PyCallback, &title, &filename ) )
|
||||
|| (!PyCallable_Check(EXPP_FS_PyCallback)))
|
||||
return EXPP_ReturnPyObjError( PyExc_AttributeError,
|
||||
"\nexpected a callback function (and optionally one or two strings) "
|
||||
"as argument(s)" );
|
||||
Py_XINCREF(EXPP_FS_PyCallback);
|
||||
|
||||
/* trick: we move to a spacescript because then the fileselector will properly
|
||||
* unset our SCRIPT_FILESEL flag when the user chooses a file or cancels the
|
||||
@@ -514,13 +525,13 @@ static PyObject *M_Window_ImageSelector( PyObject * self, PyObject * args )
|
||||
Script *script = G.main->script.last;
|
||||
int startspace = 0;
|
||||
|
||||
if( !PyArg_ParseTuple( args, "O!|ss",
|
||||
&PyFunction_Type, &EXPP_FS_PyCallback, &title,
|
||||
&filename ) )
|
||||
if( !PyArg_ParseTuple( args, "O|ss", &EXPP_FS_PyCallback, &title, &filename )
|
||||
|| (!PyCallable_Check(EXPP_FS_PyCallback)))
|
||||
return ( EXPP_ReturnPyObjError
|
||||
( PyExc_AttributeError,
|
||||
"\nexpected a callback function (and optionally one or two strings) "
|
||||
"as argument(s)" ) );
|
||||
Py_XINCREF(EXPP_FS_PyCallback);
|
||||
|
||||
/* trick: we move to a spacescript because then the fileselector will properly
|
||||
* unset our SCRIPT_FILESEL flag when the user chooses a file or cancels the
|
||||
|
||||
@@ -68,6 +68,8 @@ static PyObject *World_setIpo( BPy_World * self, PyObject * args );
|
||||
static PyObject *World_clearIpo( BPy_World * self );
|
||||
static PyObject *World_getName( BPy_World * self );
|
||||
static PyObject *World_setName( BPy_World * self, PyObject * args );
|
||||
static PyObject *World_getMode( BPy_World * self );
|
||||
static PyObject *World_setMode( BPy_World * self, PyObject * args );
|
||||
static PyObject *World_getSkytype( BPy_World * self );
|
||||
static PyObject *World_setSkytype( BPy_World * self, PyObject * args );
|
||||
static PyObject *World_getMistype( BPy_World * self );
|
||||
@@ -162,7 +164,11 @@ static PyMethodDef BPy_World_methods[] = {
|
||||
{"getName", ( PyCFunction ) World_getName, METH_NOARGS,
|
||||
"() - Return World Data name"},
|
||||
{"setName", ( PyCFunction ) World_setName, METH_VARARGS,
|
||||
"() - Return World Data name"},
|
||||
"() - Set World Data name"},
|
||||
{"getMode", ( PyCFunction ) World_getMode, METH_NOARGS,
|
||||
"() - Return World Data mode"},
|
||||
{"setMode", ( PyCFunction ) World_setMode, METH_VARARGS,
|
||||
"(i) - Set World Data mode"},
|
||||
{"getSkytype", ( PyCFunction ) World_getSkytype, METH_NOARGS,
|
||||
"() - Return World Data skytype"},
|
||||
{"setSkytype", ( PyCFunction ) World_setSkytype, METH_VARARGS,
|
||||
|
||||
@@ -66,6 +66,11 @@ Example::
|
||||
- ADD - add to background (halo).
|
||||
- ALPHA - draw with transparency.
|
||||
- SUB - subtract from background.
|
||||
@var EdgeFlags: The available edge flags.
|
||||
- SELECT - selected.
|
||||
- EDGEDRAW - edge is drawn out of edition mode.
|
||||
- SEAM - edge is a seam for LSCM UV unwrapping
|
||||
- FGON - edge is part of a F-Gon.
|
||||
"""
|
||||
|
||||
def Col(col = [255, 255, 255, 255]):
|
||||
@@ -139,16 +144,18 @@ def GetRawFromObject(name):
|
||||
be created.
|
||||
"""
|
||||
|
||||
def PutRaw(nmesh, name = None, recalculate_normals = 1):
|
||||
def PutRaw(nmesh, name = None, recalculate_normals = 1, store_edges = 0):
|
||||
"""
|
||||
Put an NMesh object back in Blender.
|
||||
@type nmesh: NMesh
|
||||
@type name: string
|
||||
@type recalculate_normals: int
|
||||
@type store_edges: int
|
||||
@param name: The name of the mesh data object in Blender which will receive
|
||||
this nmesh data. It can be an existing mesh data object or a new one.
|
||||
@param recalculate_normals: If non-zero, the vertex normals for the mesh will
|
||||
be recalculated.
|
||||
@param store_edges: if non-zero, the edges data are stored
|
||||
@rtype: None or Object
|
||||
@return: It depends on the 'name' parameter:
|
||||
- I{name} refers to an existing mesh data obj already linked to an
|
||||
@@ -193,6 +200,21 @@ class NMVert:
|
||||
each face can be independently mapped to any part of its texture.
|
||||
"""
|
||||
|
||||
class NMEdge:
|
||||
"""
|
||||
The NMEdge object
|
||||
=================
|
||||
This object holds mesh edge data.
|
||||
@type v1: NMVert
|
||||
@cvar v1: The first vertex of the edge.
|
||||
@type v2: NMVert
|
||||
@cvar v2: The second vertex of the edge.
|
||||
@type crease: int
|
||||
@cvar crease: The crease value of the edge. It is in the range [0,255].
|
||||
@type flag: int
|
||||
@cvar flag: The bitmask describing edge properties. See L{NMesh.EdgeFlags<EdgeFlags>}.
|
||||
"""
|
||||
|
||||
class NMFace:
|
||||
"""
|
||||
The NMFace object
|
||||
@@ -264,11 +286,71 @@ class NMesh:
|
||||
@cvar verts: The list of NMesh vertices (NMVerts).
|
||||
@cvar users: The number of Objects using (linked to) this mesh.
|
||||
@cvar faces: The list of NMesh faces (NMFaces).
|
||||
@cvar edges: None if mesh has no edge data, else a list of L{NMEdge} edges. Use L{addEdgesData} to create edge data if it do not exist.
|
||||
@cvar mode: The mode flags for this mesh. See L{setMode}.
|
||||
@cvar subDivLevels: The [display, rendering] subdivision levels in [1, 6].
|
||||
@cvar maxSmoothAngle: The max angle for auto smoothing. See L{setMode}.
|
||||
"""
|
||||
|
||||
def addEdge(v1, v2):
|
||||
"""
|
||||
Create an edge between two vertices.
|
||||
If an edge already exists between those vertices, it is returned. (in blender, only zero or one edge can link two vertices).
|
||||
Created edge is automatically added to edges list.
|
||||
You can only call this method if mesh has edge data.
|
||||
@type v1: NMVert
|
||||
@param v1: the first vertex of the edge.
|
||||
@type v2: NMVert
|
||||
@param v2: the second vertex of the edge.
|
||||
@rtype: NMEdge
|
||||
@return: The created or already existing edge.
|
||||
"""
|
||||
|
||||
def findEdge(v1, v2):
|
||||
"""
|
||||
Try to find an edge between two vertices.
|
||||
If no edge exists between v1 and v2, None is returned.
|
||||
You can only call this method if mesh has edge data.
|
||||
@type v1: NMVert
|
||||
@param v1: the first vertex of the edge.
|
||||
@type v2: NMVert
|
||||
@param v2: the second vertex of the edge.
|
||||
@rtype: NMEdge
|
||||
@return: The found edge. None if no edge was found.
|
||||
"""
|
||||
|
||||
def removeEdge():
|
||||
"""
|
||||
remove an edge between two vertices.
|
||||
All faces using this edge are removed from faces list.
|
||||
You can only call this method if mesh has edge data.
|
||||
@type v1: NMVert
|
||||
@param v1: the first vertex of the edge.
|
||||
@type v2: NMVert
|
||||
@param v2: the second vertex of the edge.
|
||||
"""
|
||||
|
||||
def addFace(face):
|
||||
"""
|
||||
Add a face to face list and add to edge list (if edge data exists) necessary edges.
|
||||
@type face: NMFace
|
||||
@param face: the face to add to the mesh.
|
||||
@rtype: list of NMEdge
|
||||
@return: If mesh has edge data, return the list of face edges.
|
||||
"""
|
||||
|
||||
def removeFace():
|
||||
"""
|
||||
Remove a face for face list and remove edges no more used by any other face (if edge data exists).
|
||||
@type face: NMFace
|
||||
@param face: the face to add to the mesh.
|
||||
"""
|
||||
|
||||
def addEdgesData():
|
||||
"""
|
||||
If edge data does not exist for the mesh (ie L{edges}==None), then create them.
|
||||
"""
|
||||
|
||||
def addMaterial(material):
|
||||
"""
|
||||
Add a new material to this NMesh's list of materials. This method is the
|
||||
@@ -412,7 +494,7 @@ class NMesh:
|
||||
add them.
|
||||
"""
|
||||
|
||||
def update(recalc_normals = 0):
|
||||
def update(recalc_normals = 0, store_edges = 0):
|
||||
"""
|
||||
Update the mesh in Blender. The changes made are put back to the mesh in
|
||||
Blender, if available, or put in a newly created mesh object if this NMesh
|
||||
@@ -420,6 +502,8 @@ class NMesh:
|
||||
@type recalc_normals: int
|
||||
@param recalc_normals: If given and equal to 1, the vertex normals are
|
||||
recalculated.
|
||||
@type store_edges: int
|
||||
@param store_edges: if not 0, then edge data are stored.
|
||||
@note: if your mesh disappears after it's updated, try
|
||||
L{Object.Object.makeDisplayList}. 'Subsurf' meshes (see L{getMode},
|
||||
L{setMode}) need their display lists updated, too.
|
||||
|
||||
Reference in New Issue
Block a user