Manual merge of soc-2009-kazanbas branch:
* copied I/O scripts * copied, modified rna_*_api.c and rna_*.c I/O scripts not working yet due to slight BPY differences and RNA changes. Will fix them later. Not merged changes: * C unit testing integration, because it is clumsy * scons cross-compiling, can be merged easily later
This commit is contained in:
@@ -281,7 +281,7 @@ def write_pov(filename, scene=None, info_callback = None):
|
||||
me = ob.data
|
||||
me_materials= me.materials
|
||||
|
||||
me = ob.create_render_mesh(scene)
|
||||
me = ob.create_mesh(True, 'RENDER')
|
||||
|
||||
if not me:
|
||||
continue
|
||||
|
1128
release/io/export_3ds.py
Normal file
1128
release/io/export_3ds.py
Normal file
File diff suppressed because it is too large
Load Diff
3457
release/io/export_fbx.py
Normal file
3457
release/io/export_fbx.py
Normal file
File diff suppressed because it is too large
Load Diff
988
release/io/export_obj.py
Normal file
988
release/io/export_obj.py
Normal file
@@ -0,0 +1,988 @@
|
||||
#!BPY
|
||||
|
||||
"""
|
||||
Name: 'Wavefront (.obj)...'
|
||||
Blender: 248
|
||||
Group: 'Export'
|
||||
Tooltip: 'Save a Wavefront OBJ File'
|
||||
"""
|
||||
|
||||
__author__ = "Campbell Barton, Jiri Hnidek, Paolo Ciccone"
|
||||
__url__ = ['http://wiki.blender.org/index.php/Scripts/Manual/Export/wavefront_obj', 'www.blender.org', 'blenderartists.org']
|
||||
__version__ = "1.21"
|
||||
|
||||
__bpydoc__ = """\
|
||||
This script is an exporter to OBJ file format.
|
||||
|
||||
Usage:
|
||||
|
||||
Select the objects you wish to export and run this script from "File->Export" menu.
|
||||
Selecting the default options from the popup box will be good in most cases.
|
||||
All objects that can be represented as a mesh (mesh, curve, metaball, surface, text3d)
|
||||
will be exported as mesh data.
|
||||
"""
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# OBJ Export v1.1 by Campbell Barton (AKA Ideasman)
|
||||
# --------------------------------------------------------------------------
|
||||
# ***** 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 LICENCE BLOCK *****
|
||||
# --------------------------------------------------------------------------
|
||||
|
||||
# import math and other in functions that use them for the sake of fast Blender startup
|
||||
# import math
|
||||
import os
|
||||
|
||||
import bpy
|
||||
import Mathutils
|
||||
|
||||
|
||||
# Returns a tuple - path,extension.
|
||||
# 'hello.obj' > ('hello', '.obj')
|
||||
def splitExt(path):
|
||||
dotidx = path.rfind('.')
|
||||
if dotidx == -1:
|
||||
return path, ''
|
||||
else:
|
||||
return path[:dotidx], path[dotidx:]
|
||||
|
||||
def fixName(name):
|
||||
if name == None:
|
||||
return 'None'
|
||||
else:
|
||||
return name.replace(' ', '_')
|
||||
|
||||
|
||||
# this used to be in BPySys module
|
||||
# frankly, I don't understand how it works
|
||||
def BPySys_cleanName(name):
|
||||
|
||||
v = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,46,47,58,59,60,61,62,63,64,91,92,93,94,96,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254]
|
||||
|
||||
invalid = ''.join([chr(i) for i in v])
|
||||
|
||||
for ch in invalid:
|
||||
name = name.replace(ch, '_')
|
||||
return name
|
||||
|
||||
# A Dict of Materials
|
||||
# (material.name, image.name):matname_imagename # matname_imagename has gaps removed.
|
||||
MTL_DICT = {}
|
||||
|
||||
def write_mtl(scene, filename, copy_images):
|
||||
|
||||
world = scene.world
|
||||
worldAmb = world.ambient_color
|
||||
|
||||
dest_dir = os.path.dirname(filename)
|
||||
|
||||
def copy_image(image):
|
||||
rel = image.get_export_path(dest_dir, True)
|
||||
|
||||
if copy_images:
|
||||
abspath = image.get_export_path(dest_dir, False)
|
||||
if not os.path.exists(abs_path):
|
||||
shutil.copy(bpy.sys.expandpath(image.filename), abs_path)
|
||||
|
||||
return rel
|
||||
|
||||
|
||||
file = open(filename, "w")
|
||||
# XXX
|
||||
# file.write('# Blender3D MTL File: %s\n' % Blender.Get('filename').split('\\')[-1].split('/')[-1])
|
||||
file.write('# Material Count: %i\n' % len(MTL_DICT))
|
||||
# Write material/image combinations we have used.
|
||||
for key, (mtl_mat_name, mat, img) in MTL_DICT.items():
|
||||
|
||||
# Get the Blender data for the material and the image.
|
||||
# Having an image named None will make a bug, dont do it :)
|
||||
|
||||
file.write('newmtl %s\n' % mtl_mat_name) # Define a new material: matname_imgname
|
||||
|
||||
if mat:
|
||||
file.write('Ns %.6f\n' % ((mat.specular_hardness-1) * 1.9607843137254901) ) # Hardness, convert blenders 1-511 to MTL's
|
||||
file.write('Ka %.6f %.6f %.6f\n' % tuple([c*mat.ambient for c in worldAmb]) ) # Ambient, uses mirror colour,
|
||||
file.write('Kd %.6f %.6f %.6f\n' % tuple([c*mat.diffuse_intensity for c in mat.diffuse_color]) ) # Diffuse
|
||||
file.write('Ks %.6f %.6f %.6f\n' % tuple([c*mat.specular_intensity for c in mat.specular_color]) ) # Specular
|
||||
if hasattr(mat, "ior"):
|
||||
file.write('Ni %.6f\n' % mat.ior) # Refraction index
|
||||
else:
|
||||
file.write('Ni %.6f\n' % 1.0)
|
||||
file.write('d %.6f\n' % mat.alpha) # Alpha (obj uses 'd' for dissolve)
|
||||
|
||||
# 0 to disable lighting, 1 for ambient & diffuse only (specular color set to black), 2 for full lighting.
|
||||
if mat.shadeless:
|
||||
file.write('illum 0\n') # ignore lighting
|
||||
elif mat.specular_intensity == 0:
|
||||
file.write('illum 1\n') # no specular.
|
||||
else:
|
||||
file.write('illum 2\n') # light normaly
|
||||
|
||||
else:
|
||||
#write a dummy material here?
|
||||
file.write('Ns 0\n')
|
||||
file.write('Ka %.6f %.6f %.6f\n' % tuple([c for c in worldAmb]) ) # Ambient, uses mirror colour,
|
||||
file.write('Kd 0.8 0.8 0.8\n')
|
||||
file.write('Ks 0.8 0.8 0.8\n')
|
||||
file.write('d 1\n') # No alpha
|
||||
file.write('illum 2\n') # light normaly
|
||||
|
||||
# Write images!
|
||||
if img: # We have an image on the face!
|
||||
# write relative image path
|
||||
rel = copy_image(img)
|
||||
file.write('map_Kd %s\n' % rel) # Diffuse mapping image
|
||||
# file.write('map_Kd %s\n' % img.filename.split('\\')[-1].split('/')[-1]) # Diffuse mapping image
|
||||
|
||||
elif mat: # No face image. if we havea material search for MTex image.
|
||||
for mtex in mat.textures:
|
||||
if mtex and mtex.texure.type == 'IMAGE':
|
||||
try:
|
||||
filename = copy_image(mtex.texture.image)
|
||||
# filename = mtex.texture.image.filename.split('\\')[-1].split('/')[-1]
|
||||
file.write('map_Kd %s\n' % filename) # Diffuse mapping image
|
||||
break
|
||||
except:
|
||||
# Texture has no image though its an image type, best ignore.
|
||||
pass
|
||||
|
||||
file.write('\n\n')
|
||||
|
||||
file.close()
|
||||
|
||||
# XXX not used
|
||||
def copy_file(source, dest):
|
||||
file = open(source, 'rb')
|
||||
data = file.read()
|
||||
file.close()
|
||||
|
||||
file = open(dest, 'wb')
|
||||
file.write(data)
|
||||
file.close()
|
||||
|
||||
|
||||
# XXX not used
|
||||
def copy_images(dest_dir):
|
||||
if dest_dir[-1] != os.sep:
|
||||
dest_dir += os.sep
|
||||
# if dest_dir[-1] != sys.sep:
|
||||
# dest_dir += sys.sep
|
||||
|
||||
# Get unique image names
|
||||
uniqueImages = {}
|
||||
for matname, mat, image in MTL_DICT.values(): # Only use image name
|
||||
# Get Texface images
|
||||
if image:
|
||||
uniqueImages[image] = image # Should use sets here. wait until Python 2.4 is default.
|
||||
|
||||
# Get MTex images
|
||||
if mat:
|
||||
for mtex in mat.textures:
|
||||
if mtex and mtex.texture.type == 'IMAGE':
|
||||
image_tex = mtex.texture.image
|
||||
if image_tex:
|
||||
try:
|
||||
uniqueImages[image_tex] = image_tex
|
||||
except:
|
||||
pass
|
||||
|
||||
# Now copy images
|
||||
copyCount = 0
|
||||
|
||||
# for bImage in uniqueImages.values():
|
||||
# image_path = bpy.sys.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
|
||||
# print('\tCopying "%s" > "%s"' % (image_path, dest_image_path))
|
||||
# copy_file(image_path, dest_image_path)
|
||||
# copyCount+=1
|
||||
|
||||
# paths= bpy.util.copy_images(uniqueImages.values(), dest_dir)
|
||||
|
||||
print('\tCopied %d images' % copyCount)
|
||||
# print('\tCopied %d images' % copyCount)
|
||||
|
||||
# XXX not converted
|
||||
def test_nurbs_compat(ob):
|
||||
if ob.type != 'Curve':
|
||||
return False
|
||||
|
||||
for nu in ob.data:
|
||||
if (not nu.knotsV) and nu.type != 1: # not a surface and not bezier
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
# XXX not converted
|
||||
def write_nurb(file, ob, ob_mat):
|
||||
tot_verts = 0
|
||||
cu = ob.data
|
||||
|
||||
# use negative indices
|
||||
Vector = Blender.Mathutils.Vector
|
||||
for nu in cu:
|
||||
|
||||
if nu.type==0: DEG_ORDER_U = 1
|
||||
else: DEG_ORDER_U = nu.orderU-1 # Tested to be correct
|
||||
|
||||
if nu.type==1:
|
||||
print("\tWarning, bezier curve:", ob.name, "only poly and nurbs curves supported")
|
||||
continue
|
||||
|
||||
if nu.knotsV:
|
||||
print("\tWarning, surface:", ob.name, "only poly and nurbs curves supported")
|
||||
continue
|
||||
|
||||
if len(nu) <= DEG_ORDER_U:
|
||||
print("\tWarning, orderU is lower then vert count, skipping:", ob.name)
|
||||
continue
|
||||
|
||||
pt_num = 0
|
||||
do_closed = (nu.flagU & 1)
|
||||
do_endpoints = (do_closed==0) and (nu.flagU & 2)
|
||||
|
||||
for pt in nu:
|
||||
pt = Vector(pt[0], pt[1], pt[2]) * ob_mat
|
||||
file.write('v %.6f %.6f %.6f\n' % (pt[0], pt[1], pt[2]))
|
||||
pt_num += 1
|
||||
tot_verts += pt_num
|
||||
|
||||
file.write('g %s\n' % (fixName(ob.name))) # fixName(ob.getData(1)) could use the data name too
|
||||
file.write('cstype bspline\n') # not ideal, hard coded
|
||||
file.write('deg %d\n' % DEG_ORDER_U) # not used for curves but most files have it still
|
||||
|
||||
curve_ls = [-(i+1) for i in range(pt_num)]
|
||||
|
||||
# 'curv' keyword
|
||||
if do_closed:
|
||||
if DEG_ORDER_U == 1:
|
||||
pt_num += 1
|
||||
curve_ls.append(-1)
|
||||
else:
|
||||
pt_num += DEG_ORDER_U
|
||||
curve_ls = curve_ls + curve_ls[0:DEG_ORDER_U]
|
||||
|
||||
file.write('curv 0.0 1.0 %s\n' % (' '.join( [str(i) for i in curve_ls] ))) # Blender has no U and V values for the curve
|
||||
|
||||
# 'parm' keyword
|
||||
tot_parm = (DEG_ORDER_U + 1) + pt_num
|
||||
tot_parm_div = float(tot_parm-1)
|
||||
parm_ls = [(i/tot_parm_div) for i in range(tot_parm)]
|
||||
|
||||
if do_endpoints: # end points, force param
|
||||
for i in range(DEG_ORDER_U+1):
|
||||
parm_ls[i] = 0.0
|
||||
parm_ls[-(1+i)] = 1.0
|
||||
|
||||
file.write('parm u %s\n' % ' '.join( [str(i) for i in parm_ls] ))
|
||||
|
||||
file.write('end\n')
|
||||
|
||||
return tot_verts
|
||||
|
||||
def write(filename, objects, scene,
|
||||
EXPORT_TRI=False,
|
||||
EXPORT_EDGES=False,
|
||||
EXPORT_NORMALS=False,
|
||||
EXPORT_NORMALS_HQ=False,
|
||||
EXPORT_UV=True,
|
||||
EXPORT_MTL=True,
|
||||
EXPORT_COPY_IMAGES=False,
|
||||
EXPORT_APPLY_MODIFIERS=True,
|
||||
EXPORT_ROTX90=True,
|
||||
EXPORT_BLEN_OBS=True,
|
||||
EXPORT_GROUP_BY_OB=False,
|
||||
EXPORT_GROUP_BY_MAT=False,
|
||||
EXPORT_KEEP_VERT_ORDER=False,
|
||||
EXPORT_POLYGROUPS=False,
|
||||
EXPORT_CURVE_AS_NURBS=True):
|
||||
'''
|
||||
Basic write function. The context and options must be alredy set
|
||||
This can be accessed externaly
|
||||
eg.
|
||||
write( 'c:\\test\\foobar.obj', Blender.Object.GetSelected() ) # Using default options.
|
||||
'''
|
||||
|
||||
# XXX
|
||||
import math
|
||||
|
||||
def veckey3d(v):
|
||||
return round(v.x, 6), round(v.y, 6), round(v.z, 6)
|
||||
|
||||
def veckey2d(v):
|
||||
return round(v.x, 6), round(v.y, 6)
|
||||
|
||||
def findVertexGroupName(face, vWeightMap):
|
||||
"""
|
||||
Searches the vertexDict to see what groups is assigned to a given face.
|
||||
We use a frequency system in order to sort out the name because a given vetex can
|
||||
belong to two or more groups at the same time. To find the right name for the face
|
||||
we list all the possible vertex group names with their frequency and then sort by
|
||||
frequency in descend order. The top element is the one shared by the highest number
|
||||
of vertices is the face's group
|
||||
"""
|
||||
weightDict = {}
|
||||
for vert_index in face.verts:
|
||||
# for vert in face:
|
||||
vWeights = vWeightMap[vert_index]
|
||||
# vWeights = vWeightMap[vert]
|
||||
for vGroupName, weight in vWeights:
|
||||
weightDict[vGroupName] = weightDict.get(vGroupName, 0) + weight
|
||||
|
||||
if weightDict:
|
||||
alist = [(weight,vGroupName) for vGroupName, weight in weightDict.items()] # sort least to greatest amount of weight
|
||||
alist.sort()
|
||||
return(alist[-1][1]) # highest value last
|
||||
else:
|
||||
return '(null)'
|
||||
|
||||
# TODO: implement this in C? dunno how it should be called...
|
||||
def getVertsFromGroup(me, group_index):
|
||||
ret = []
|
||||
|
||||
for i, v in enumerate(me.verts):
|
||||
for g in v.groups:
|
||||
if g.group == group_index:
|
||||
ret.append((i, g.weight))
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
print('OBJ Export path: "%s"' % filename)
|
||||
temp_mesh_name = '~tmp-mesh'
|
||||
|
||||
time1 = bpy.sys.time()
|
||||
# time1 = sys.time()
|
||||
# scn = Scene.GetCurrent()
|
||||
|
||||
file = open(filename, "w")
|
||||
|
||||
# Write Header
|
||||
version = "2.5"
|
||||
file.write('# Blender3D v%s OBJ File: %s\n' % (version, bpy.data.filename.split('/')[-1].split('\\')[-1] ))
|
||||
file.write('# www.blender3d.org\n')
|
||||
|
||||
# Tell the obj file what material file to use.
|
||||
if EXPORT_MTL:
|
||||
mtlfilename = '%s.mtl' % '.'.join(filename.split('.')[:-1])
|
||||
file.write('mtllib %s\n' % ( mtlfilename.split('\\')[-1].split('/')[-1] ))
|
||||
|
||||
if EXPORT_ROTX90:
|
||||
mat_xrot90= Mathutils.RotationMatrix(-math.pi/2, 4, 'x')
|
||||
|
||||
# Initialize totals, these are updated each object
|
||||
totverts = totuvco = totno = 1
|
||||
|
||||
face_vert_index = 1
|
||||
|
||||
globalNormals = {}
|
||||
|
||||
# Get all meshes
|
||||
for ob_main in objects:
|
||||
|
||||
# ignore dupli children
|
||||
if ob_main.parent and ob_main.parent.dupli_type != 'NONE':
|
||||
# XXX
|
||||
print(ob_main.name, 'is a dupli child - ignoring')
|
||||
continue
|
||||
|
||||
obs = []
|
||||
if ob_main.dupli_type != 'NONE':
|
||||
# XXX
|
||||
print('creating dupli_list on', ob_main.name)
|
||||
ob_main.create_dupli_list()
|
||||
|
||||
obs = [(dob.object, dob.matrix) for dob in ob_main.dupli_list]
|
||||
|
||||
# XXX debug print
|
||||
print(ob_main.name, 'has', len(obs), 'dupli children')
|
||||
else:
|
||||
obs = [(ob_main, ob_main.matrix)]
|
||||
|
||||
for ob, ob_mat in obs:
|
||||
|
||||
# XXX postponed
|
||||
# # Nurbs curve support
|
||||
# if EXPORT_CURVE_AS_NURBS and test_nurbs_compat(ob):
|
||||
# if EXPORT_ROTX90:
|
||||
# ob_mat = ob_mat * mat_xrot90
|
||||
|
||||
# totverts += write_nurb(file, ob, ob_mat)
|
||||
|
||||
# continue
|
||||
# end nurbs
|
||||
|
||||
if ob.type != 'MESH':
|
||||
continue
|
||||
|
||||
me = ob.create_mesh(EXPORT_APPLY_MODIFIERS, 'PREVIEW')
|
||||
|
||||
if EXPORT_ROTX90:
|
||||
me.transform(ob_mat * mat_xrot90)
|
||||
else:
|
||||
me.transform(ob_mat)
|
||||
|
||||
# # Will work for non meshes now! :)
|
||||
# me= BPyMesh.getMeshFromObject(ob, containerMesh, EXPORT_APPLY_MODIFIERS, EXPORT_POLYGROUPS, scn)
|
||||
# if not me:
|
||||
# continue
|
||||
|
||||
if EXPORT_UV:
|
||||
faceuv = len(me.uv_textures) > 0
|
||||
else:
|
||||
faceuv = False
|
||||
|
||||
# We have a valid mesh
|
||||
if EXPORT_TRI and me.faces:
|
||||
# Add a dummy object to it.
|
||||
has_quads = False
|
||||
for f in me.faces:
|
||||
if f.verts[3] != 0:
|
||||
has_quads = True
|
||||
break
|
||||
|
||||
if has_quads:
|
||||
newob = bpy.data.add_object('MESH', 'temp_object')
|
||||
newob.data = me
|
||||
# if we forget to set Object.data - crash
|
||||
scene.add_object(newob)
|
||||
newob.convert_to_triface(scene)
|
||||
# mesh will still be there
|
||||
scene.remove_object(newob)
|
||||
|
||||
# Make our own list so it can be sorted to reduce context switching
|
||||
face_index_pairs = [ (face, index) for index, face in enumerate(me.faces)]
|
||||
# faces = [ f for f in me.faces ]
|
||||
|
||||
if EXPORT_EDGES:
|
||||
edges = me.edges
|
||||
else:
|
||||
edges = []
|
||||
|
||||
if not (len(face_index_pairs)+len(edges)+len(me.verts)): # Make sure there is somthing to write
|
||||
|
||||
# clean up
|
||||
bpy.data.remove_mesh(me)
|
||||
|
||||
continue # dont bother with this mesh.
|
||||
|
||||
# XXX
|
||||
# High Quality Normals
|
||||
if EXPORT_NORMALS and face_index_pairs:
|
||||
me.calc_normals()
|
||||
# if EXPORT_NORMALS_HQ:
|
||||
# BPyMesh.meshCalcNormals(me)
|
||||
# else:
|
||||
# # transforming normals is incorrect
|
||||
# # when the matrix is scaled,
|
||||
# # better to recalculate them
|
||||
# me.calcNormals()
|
||||
|
||||
materials = me.materials
|
||||
|
||||
materialNames = []
|
||||
materialItems = [m for m in materials]
|
||||
if materials:
|
||||
for mat in materials:
|
||||
if mat: # !=None
|
||||
materialNames.append(mat.name)
|
||||
else:
|
||||
materialNames.append(None)
|
||||
# Cant use LC because some materials are None.
|
||||
# materialNames = map(lambda mat: mat.name, materials) # Bug Blender, dosent account for null materials, still broken.
|
||||
|
||||
# Possible there null materials, will mess up indicies
|
||||
# but at least it will export, wait until Blender gets fixed.
|
||||
materialNames.extend((16-len(materialNames)) * [None])
|
||||
materialItems.extend((16-len(materialItems)) * [None])
|
||||
|
||||
# Sort by Material, then images
|
||||
# so we dont over context switch in the obj file.
|
||||
if EXPORT_KEEP_VERT_ORDER:
|
||||
pass
|
||||
elif faceuv:
|
||||
# XXX update
|
||||
tface = me.active_uv_texture.data
|
||||
|
||||
# exception only raised if Python 2.3 or lower...
|
||||
try:
|
||||
face_index_pairs.sort(key = lambda a: (a[0].material_index, tface[a[1]].image, a[0].smooth))
|
||||
except:
|
||||
face_index_pairs.sort(lambda a,b: cmp((a[0].material_index, tface[a[1]].image, a[0].smooth),
|
||||
(b[0].material_index, tface[b[1]].image, b[0].smooth)))
|
||||
elif len(materials) > 1:
|
||||
try:
|
||||
face_index_pairs.sort(key = lambda a: (a[0].material_index, a[0].smooth))
|
||||
except:
|
||||
face_index_pairs.sort(lambda a,b: cmp((a[0].material_index, a[0].smooth),
|
||||
(b[0].material_index, b[0].smooth)))
|
||||
else:
|
||||
# no materials
|
||||
try:
|
||||
face_index_pairs.sort(key = lambda a: a[0].smooth)
|
||||
except:
|
||||
face_index_pairs.sort(lambda a,b: cmp(a[0].smooth, b[0].smooth))
|
||||
# if EXPORT_KEEP_VERT_ORDER:
|
||||
# pass
|
||||
# elif faceuv:
|
||||
# try: faces.sort(key = lambda a: (a.mat, a.image, a.smooth))
|
||||
# except: faces.sort(lambda a,b: cmp((a.mat, a.image, a.smooth), (b.mat, b.image, b.smooth)))
|
||||
# elif len(materials) > 1:
|
||||
# try: faces.sort(key = lambda a: (a.mat, a.smooth))
|
||||
# except: faces.sort(lambda a,b: cmp((a.mat, a.smooth), (b.mat, b.smooth)))
|
||||
# else:
|
||||
# # no materials
|
||||
# try: faces.sort(key = lambda a: a.smooth)
|
||||
# except: faces.sort(lambda a,b: cmp(a.smooth, b.smooth))
|
||||
|
||||
faces = [pair[0] for pair in face_index_pairs]
|
||||
|
||||
# Set the default mat to no material and no image.
|
||||
contextMat = (0, 0) # Can never be this, so we will label a new material teh first chance we get.
|
||||
contextSmooth = None # Will either be true or false, set bad to force initialization switch.
|
||||
|
||||
if EXPORT_BLEN_OBS or EXPORT_GROUP_BY_OB:
|
||||
name1 = ob.name
|
||||
name2 = ob.data.name
|
||||
if name1 == name2:
|
||||
obnamestring = fixName(name1)
|
||||
else:
|
||||
obnamestring = '%s_%s' % (fixName(name1), fixName(name2))
|
||||
|
||||
if EXPORT_BLEN_OBS:
|
||||
file.write('o %s\n' % obnamestring) # Write Object name
|
||||
else: # if EXPORT_GROUP_BY_OB:
|
||||
file.write('g %s\n' % obnamestring)
|
||||
|
||||
|
||||
# Vert
|
||||
for v in me.verts:
|
||||
file.write('v %.6f %.6f %.6f\n' % tuple(v.co))
|
||||
|
||||
# UV
|
||||
if faceuv:
|
||||
uv_face_mapping = [[0,0,0,0] for f in faces] # a bit of a waste for tri's :/
|
||||
|
||||
uv_dict = {} # could use a set() here
|
||||
uv_layer = me.active_uv_texture
|
||||
for f, f_index in face_index_pairs:
|
||||
|
||||
tface = uv_layer.data[f_index]
|
||||
|
||||
uvs = [tface.uv1, tface.uv2, tface.uv3]
|
||||
|
||||
# add another UV if it's a quad
|
||||
if f.verts[3] != 0:
|
||||
uvs.append(tface.uv4)
|
||||
|
||||
for uv_index, uv in enumerate(uvs):
|
||||
uvkey = veckey2d(uv)
|
||||
try:
|
||||
uv_face_mapping[f_index][uv_index] = uv_dict[uvkey]
|
||||
except:
|
||||
uv_face_mapping[f_index][uv_index] = uv_dict[uvkey] = len(uv_dict)
|
||||
file.write('vt %.6f %.6f\n' % tuple(uv))
|
||||
|
||||
# uv_dict = {} # could use a set() here
|
||||
# for f_index, f in enumerate(faces):
|
||||
|
||||
# for uv_index, uv in enumerate(f.uv):
|
||||
# uvkey = veckey2d(uv)
|
||||
# try:
|
||||
# uv_face_mapping[f_index][uv_index] = uv_dict[uvkey]
|
||||
# except:
|
||||
# uv_face_mapping[f_index][uv_index] = uv_dict[uvkey] = len(uv_dict)
|
||||
# file.write('vt %.6f %.6f\n' % tuple(uv))
|
||||
|
||||
uv_unique_count = len(uv_dict)
|
||||
# del uv, uvkey, uv_dict, f_index, uv_index
|
||||
# Only need uv_unique_count and uv_face_mapping
|
||||
|
||||
# NORMAL, Smooth/Non smoothed.
|
||||
if EXPORT_NORMALS:
|
||||
for f in faces:
|
||||
if f.smooth:
|
||||
for v in f:
|
||||
noKey = veckey3d(v.normal)
|
||||
if noKey not in globalNormals:
|
||||
globalNormals[noKey] = totno
|
||||
totno +=1
|
||||
file.write('vn %.6f %.6f %.6f\n' % noKey)
|
||||
else:
|
||||
# Hard, 1 normal from the face.
|
||||
noKey = veckey3d(f.normal)
|
||||
if noKey not in globalNormals:
|
||||
globalNormals[noKey] = totno
|
||||
totno +=1
|
||||
file.write('vn %.6f %.6f %.6f\n' % noKey)
|
||||
|
||||
if not faceuv:
|
||||
f_image = None
|
||||
|
||||
# XXX
|
||||
if EXPORT_POLYGROUPS:
|
||||
# Retrieve the list of vertex groups
|
||||
# vertGroupNames = me.getVertGroupNames()
|
||||
|
||||
currentVGroup = ''
|
||||
# Create a dictionary keyed by face id and listing, for each vertex, the vertex groups it belongs to
|
||||
vgroupsMap = [[] for _i in range(len(me.verts))]
|
||||
# vgroupsMap = [[] for _i in xrange(len(me.verts))]
|
||||
for g in ob.vertex_groups:
|
||||
# for vertexGroupName in vertGroupNames:
|
||||
for vIdx, vWeight in getVertsFromGroup(me, g.index):
|
||||
# for vIdx, vWeight in me.getVertsFromGroup(vertexGroupName, 1):
|
||||
vgroupsMap[vIdx].append((g.name, vWeight))
|
||||
|
||||
for f_index, f in enumerate(faces):
|
||||
f_v = [{"index": index, "vertex": me.verts[index]} for index in f.verts]
|
||||
|
||||
if f.verts[3] == 0:
|
||||
f_v.pop()
|
||||
|
||||
# f_v= f.v
|
||||
f_smooth= f.smooth
|
||||
f_mat = min(f.material_index, len(materialNames)-1)
|
||||
# f_mat = min(f.mat, len(materialNames)-1)
|
||||
if faceuv:
|
||||
|
||||
tface = me.active_uv_texture.data[face_index_pairs[f_index][1]]
|
||||
|
||||
f_image = tface.image
|
||||
f_uv= [tface.uv1, tface.uv2, tface.uv3]
|
||||
if f.verts[3] != 0:
|
||||
f_uv.append(tface.uv4)
|
||||
# f_image = f.image
|
||||
# f_uv= f.uv
|
||||
|
||||
# MAKE KEY
|
||||
if faceuv and f_image: # Object is always true.
|
||||
key = materialNames[f_mat], f_image.name
|
||||
else:
|
||||
key = materialNames[f_mat], None # No image, use None instead.
|
||||
|
||||
# Write the vertex group
|
||||
if EXPORT_POLYGROUPS:
|
||||
if len(ob.vertex_groups):
|
||||
# find what vertext group the face belongs to
|
||||
theVGroup = findVertexGroupName(f,vgroupsMap)
|
||||
if theVGroup != currentVGroup:
|
||||
currentVGroup = theVGroup
|
||||
file.write('g %s\n' % theVGroup)
|
||||
# # Write the vertex group
|
||||
# if EXPORT_POLYGROUPS:
|
||||
# if vertGroupNames:
|
||||
# # find what vertext group the face belongs to
|
||||
# theVGroup = findVertexGroupName(f,vgroupsMap)
|
||||
# if theVGroup != currentVGroup:
|
||||
# currentVGroup = theVGroup
|
||||
# file.write('g %s\n' % theVGroup)
|
||||
|
||||
# CHECK FOR CONTEXT SWITCH
|
||||
if key == contextMat:
|
||||
pass # Context alredy switched, dont do anything
|
||||
else:
|
||||
if key[0] == None and key[1] == None:
|
||||
# Write a null material, since we know the context has changed.
|
||||
if EXPORT_GROUP_BY_MAT:
|
||||
# can be mat_image or (null)
|
||||
file.write('g %s_%s\n' % (fixName(ob.name), fixName(ob.data.name)) ) # can be mat_image or (null)
|
||||
file.write('usemtl (null)\n') # mat, image
|
||||
|
||||
else:
|
||||
mat_data= MTL_DICT.get(key)
|
||||
if not mat_data:
|
||||
# First add to global dict so we can export to mtl
|
||||
# Then write mtl
|
||||
|
||||
# Make a new names from the mat and image name,
|
||||
# converting any spaces to underscores with fixName.
|
||||
|
||||
# If none image dont bother adding it to the name
|
||||
if key[1] == None:
|
||||
mat_data = MTL_DICT[key] = ('%s'%fixName(key[0])), materialItems[f_mat], f_image
|
||||
else:
|
||||
mat_data = MTL_DICT[key] = ('%s_%s' % (fixName(key[0]), fixName(key[1]))), materialItems[f_mat], f_image
|
||||
|
||||
if EXPORT_GROUP_BY_MAT:
|
||||
file.write('g %s_%s_%s\n' % (fixName(ob.name), fixName(ob.data.name), mat_data[0]) ) # can be mat_image or (null)
|
||||
|
||||
file.write('usemtl %s\n' % mat_data[0]) # can be mat_image or (null)
|
||||
|
||||
contextMat = key
|
||||
if f_smooth != contextSmooth:
|
||||
if f_smooth: # on now off
|
||||
file.write('s 1\n')
|
||||
contextSmooth = f_smooth
|
||||
else: # was off now on
|
||||
file.write('s off\n')
|
||||
contextSmooth = f_smooth
|
||||
|
||||
file.write('f')
|
||||
if faceuv:
|
||||
if EXPORT_NORMALS:
|
||||
if f_smooth: # Smoothed, use vertex normals
|
||||
for vi, v in enumerate(f_v):
|
||||
file.write( ' %d/%d/%d' % \
|
||||
(v["index"] + totverts,
|
||||
totuvco + uv_face_mapping[f_index][vi],
|
||||
globalNormals[ veckey3d(v["vertex"].normal) ]) ) # vert, uv, normal
|
||||
|
||||
else: # No smoothing, face normals
|
||||
no = globalNormals[ veckey3d(f.normal) ]
|
||||
for vi, v in enumerate(f_v):
|
||||
file.write( ' %d/%d/%d' % \
|
||||
(v["index"] + totverts,
|
||||
totuvco + uv_face_mapping[f_index][vi],
|
||||
no) ) # vert, uv, normal
|
||||
else: # No Normals
|
||||
for vi, v in enumerate(f_v):
|
||||
file.write( ' %d/%d' % (\
|
||||
v["index"] + totverts,\
|
||||
totuvco + uv_face_mapping[f_index][vi])) # vert, uv
|
||||
|
||||
face_vert_index += len(f_v)
|
||||
|
||||
else: # No UV's
|
||||
if EXPORT_NORMALS:
|
||||
if f_smooth: # Smoothed, use vertex normals
|
||||
for v in f_v:
|
||||
file.write( ' %d//%d' %
|
||||
(v["index"] + totverts, globalNormals[ veckey3d(v["vertex"].normal) ]) )
|
||||
else: # No smoothing, face normals
|
||||
no = globalNormals[ veckey3d(f.normal) ]
|
||||
for v in f_v:
|
||||
file.write( ' %d//%d' % (v["index"] + totverts, no) )
|
||||
else: # No Normals
|
||||
for v in f_v:
|
||||
file.write( ' %d' % (v["index"] + totverts) )
|
||||
|
||||
file.write('\n')
|
||||
|
||||
# Write edges.
|
||||
if EXPORT_EDGES:
|
||||
for ed in edges:
|
||||
if ed.loose:
|
||||
file.write('f %d %d\n' % (ed.verts[0] + totverts, ed.verts[1] + totverts))
|
||||
|
||||
# Make the indicies global rather then per mesh
|
||||
totverts += len(me.verts)
|
||||
if faceuv:
|
||||
totuvco += uv_unique_count
|
||||
|
||||
# clean up
|
||||
bpy.data.remove_mesh(me)
|
||||
|
||||
if ob_main.dupli_type != 'NONE':
|
||||
ob_main.free_dupli_list()
|
||||
|
||||
file.close()
|
||||
|
||||
|
||||
# Now we have all our materials, save them
|
||||
if EXPORT_MTL:
|
||||
write_mtl(scene, mtlfilename, EXPORT_COPY_IMAGES)
|
||||
# if EXPORT_COPY_IMAGES:
|
||||
# dest_dir = os.path.basename(filename)
|
||||
# # dest_dir = filename
|
||||
# # # Remove chars until we are just the path.
|
||||
# # while dest_dir and dest_dir[-1] not in '\\/':
|
||||
# # dest_dir = dest_dir[:-1]
|
||||
# if dest_dir:
|
||||
# copy_images(dest_dir)
|
||||
# else:
|
||||
# print('\tError: "%s" could not be used as a base for an image path.' % filename)
|
||||
|
||||
print("OBJ Export time: %.2f" % (bpy.sys.time() - time1))
|
||||
# print "OBJ Export time: %.2f" % (sys.time() - time1)
|
||||
|
||||
def do_export(filename, context,
|
||||
EXPORT_APPLY_MODIFIERS = True, # not used
|
||||
EXPORT_ROTX90 = True, # wrong
|
||||
EXPORT_TRI = False, # ok
|
||||
EXPORT_EDGES = False,
|
||||
EXPORT_NORMALS = False, # not yet
|
||||
EXPORT_NORMALS_HQ = False, # not yet
|
||||
EXPORT_UV = True, # ok
|
||||
EXPORT_MTL = True,
|
||||
EXPORT_SEL_ONLY = True, # ok
|
||||
EXPORT_ALL_SCENES = False, # XXX not working atm
|
||||
EXPORT_ANIMATION = False,
|
||||
EXPORT_COPY_IMAGES = False,
|
||||
EXPORT_BLEN_OBS = True,
|
||||
EXPORT_GROUP_BY_OB = False,
|
||||
EXPORT_GROUP_BY_MAT = False,
|
||||
EXPORT_KEEP_VERT_ORDER = False,
|
||||
EXPORT_POLYGROUPS = False,
|
||||
EXPORT_CURVE_AS_NURBS = True):
|
||||
# Window.EditMode(0)
|
||||
# Window.WaitCursor(1)
|
||||
|
||||
base_name, ext = splitExt(filename)
|
||||
context_name = [base_name, '', '', ext] # Base name, scene name, frame number, extension
|
||||
|
||||
orig_scene = context.scene
|
||||
|
||||
# if EXPORT_ALL_SCENES:
|
||||
# export_scenes = bpy.data.scenes
|
||||
# else:
|
||||
# export_scenes = [orig_scene]
|
||||
|
||||
# XXX only exporting one scene atm since changing
|
||||
# current scene is not possible.
|
||||
# Brecht says that ideally in 2.5 we won't need such a function,
|
||||
# allowing multiple scenes open at once.
|
||||
export_scenes = [orig_scene]
|
||||
|
||||
# Export all scenes.
|
||||
for scn in export_scenes:
|
||||
# scn.makeCurrent() # If already current, this is not slow.
|
||||
# context = scn.getRenderingContext()
|
||||
orig_frame = scn.current_frame
|
||||
|
||||
if EXPORT_ALL_SCENES: # Add scene name into the context_name
|
||||
context_name[1] = '_%s' % BPySys_cleanName(scn.name) # WARNING, its possible that this could cause a collision. we could fix if were feeling parranoied.
|
||||
|
||||
# Export an animation?
|
||||
if EXPORT_ANIMATION:
|
||||
scene_frames = range(scn.start_frame, context.end_frame+1) # Up to and including the end frame.
|
||||
else:
|
||||
scene_frames = [orig_frame] # Dont export an animation.
|
||||
|
||||
# Loop through all frames in the scene and export.
|
||||
for frame in scene_frames:
|
||||
if EXPORT_ANIMATION: # Add frame to the filename.
|
||||
context_name[2] = '_%.6d' % frame
|
||||
|
||||
scn.current_frame = frame
|
||||
if EXPORT_SEL_ONLY:
|
||||
export_objects = context.selected_objects
|
||||
else:
|
||||
export_objects = scn.objects
|
||||
|
||||
full_path= ''.join(context_name)
|
||||
|
||||
# erm... bit of a problem here, this can overwrite files when exporting frames. not too bad.
|
||||
# EXPORT THE FILE.
|
||||
write(full_path, export_objects, scn,
|
||||
EXPORT_TRI, EXPORT_EDGES, EXPORT_NORMALS,
|
||||
EXPORT_NORMALS_HQ, EXPORT_UV, EXPORT_MTL,
|
||||
EXPORT_COPY_IMAGES, EXPORT_APPLY_MODIFIERS,
|
||||
EXPORT_ROTX90, EXPORT_BLEN_OBS,
|
||||
EXPORT_GROUP_BY_OB, EXPORT_GROUP_BY_MAT, EXPORT_KEEP_VERT_ORDER,
|
||||
EXPORT_POLYGROUPS, EXPORT_CURVE_AS_NURBS)
|
||||
|
||||
|
||||
scn.current_frame = orig_frame
|
||||
|
||||
# Restore old active scene.
|
||||
# orig_scene.makeCurrent()
|
||||
# Window.WaitCursor(0)
|
||||
|
||||
|
||||
class EXPORT_OT_obj(bpy.types.Operator):
|
||||
'''
|
||||
Currently the exporter lacks these features:
|
||||
* nurbs
|
||||
* multiple scene export (only active scene is written)
|
||||
* particles
|
||||
'''
|
||||
__idname__ = "export.obj"
|
||||
__label__ = 'Export OBJ'
|
||||
|
||||
# List of operator properties, the attributes will be assigned
|
||||
# to the class instance from the operator settings before calling.
|
||||
|
||||
__props__ = [
|
||||
bpy.props.StringProperty(attr="filename", name="File Name", description="File name used for exporting the OBJ file", maxlen= 1024, default= ""),
|
||||
|
||||
# context group
|
||||
bpy.props.BoolProperty(attr="use_selection", name="Selection Only", description="", default= False),
|
||||
bpy.props.BoolProperty(attr="use_all_scenes", name="All Scenes", description="", default= False),
|
||||
bpy.props.BoolProperty(attr="use_animation", name="All Animation", description="", default= False),
|
||||
|
||||
# object group
|
||||
bpy.props.BoolProperty(attr="use_modifiers", name="Apply Modifiers", description="", default= True),
|
||||
bpy.props.BoolProperty(attr="use_rotate90", name="Rotate X90", description="", default= True),
|
||||
|
||||
# extra data group
|
||||
bpy.props.BoolProperty(attr="use_edges", name="Edges", description="", default= True),
|
||||
bpy.props.BoolProperty(attr="use_normals", name="Normals", description="", default= False),
|
||||
bpy.props.BoolProperty(attr="use_hq_normals", name="High Quality Normals", description="", default= True),
|
||||
bpy.props.BoolProperty(attr="use_uvs", name="UVs", description="", default= True),
|
||||
bpy.props.BoolProperty(attr="use_materials", name="Materials", description="", default= True),
|
||||
bpy.props.BoolProperty(attr="copy_images", name="Copy Images", description="", default= False),
|
||||
bpy.props.BoolProperty(attr="use_triangles", name="Triangulate", description="", default= False),
|
||||
bpy.props.BoolProperty(attr="use_vertex_groups", name="Polygroups", description="", default= False),
|
||||
bpy.props.BoolProperty(attr="use_nurbs", name="Nurbs", description="", default= False),
|
||||
|
||||
# grouping group
|
||||
bpy.props.BoolProperty(attr="use_blen_objects", name="Objects as OBJ Objects", description="", default= True),
|
||||
bpy.props.BoolProperty(attr="group_by_object", name="Objects as OBJ Groups ", description="", default= False),
|
||||
bpy.props.BoolProperty(attr="group_by_material", name="Material Groups", description="", default= False),
|
||||
bpy.props.BoolProperty(attr="keep_vertex_order", name="Keep Vertex Order", description="", default= False)
|
||||
]
|
||||
|
||||
def execute(self, context):
|
||||
|
||||
do_export(self.filename, context,
|
||||
EXPORT_TRI=self.use_triangles,
|
||||
EXPORT_EDGES=self.use_edges,
|
||||
EXPORT_NORMALS=self.use_normals,
|
||||
EXPORT_NORMALS_HQ=self.use_hq_normals,
|
||||
EXPORT_UV=self.use_uvs,
|
||||
EXPORT_MTL=self.use_materials,
|
||||
EXPORT_COPY_IMAGES=self.copy_images,
|
||||
EXPORT_APPLY_MODIFIERS=self.use_modifiers,
|
||||
EXPORT_ROTX90=self.use_rotate90,
|
||||
EXPORT_BLEN_OBS=self.use_blen_objects,
|
||||
EXPORT_GROUP_BY_OB=self.group_by_object,
|
||||
EXPORT_GROUP_BY_MAT=self.group_by_material,
|
||||
EXPORT_KEEP_VERT_ORDER=self.keep_vertex_order,
|
||||
EXPORT_POLYGROUPS=self.use_vertex_groups,
|
||||
EXPORT_CURVE_AS_NURBS=self.use_nurbs,
|
||||
EXPORT_SEL_ONLY=self.use_selection,
|
||||
EXPORT_ALL_SCENES=self.use_all_scenes)
|
||||
|
||||
return ('FINISHED',)
|
||||
|
||||
def invoke(self, context, event):
|
||||
wm = context.manager
|
||||
wm.add_fileselect(self.__operator__)
|
||||
return ('RUNNING_MODAL',)
|
||||
|
||||
def poll(self, context): # Poll isnt working yet
|
||||
print("Poll")
|
||||
return context.active_object != None
|
||||
|
||||
bpy.ops.add(EXPORT_OT_obj)
|
||||
|
||||
if __name__ == "__main__":
|
||||
bpy.ops.EXPORT_OT_obj(filename="/tmp/test.obj")
|
||||
|
||||
# CONVERSION ISSUES
|
||||
# - matrix problem
|
||||
# - duplis - only tested dupliverts
|
||||
# - NURBS - needs API additions
|
||||
# - all scenes export
|
||||
# + normals calculation
|
||||
# - get rid of cleanName somehow
|
@@ -78,7 +78,7 @@ def write(filename, scene, ob, \
|
||||
|
||||
#mesh = BPyMesh.getMeshFromObject(ob, None, EXPORT_APPLY_MODIFIERS, False, scn) # XXX
|
||||
if EXPORT_APPLY_MODIFIERS:
|
||||
mesh = ob.create_render_mesh(scene)
|
||||
mesh = ob.create_mesh(True, 'PREVIEW')
|
||||
else:
|
||||
mesh = ob.data
|
||||
|
||||
|
1239
release/io/export_x3d.py
Normal file
1239
release/io/export_x3d.py
Normal file
File diff suppressed because it is too large
Load Diff
1166
release/io/import_3ds.py
Normal file
1166
release/io/import_3ds.py
Normal file
File diff suppressed because it is too large
Load Diff
1633
release/io/import_obj.py
Normal file
1633
release/io/import_obj.py
Normal file
File diff suppressed because it is too large
Load Diff
@@ -84,7 +84,9 @@ class INFO_MT_file_import(bpy.types.Menu):
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
layout.itemL(text="Nothing yet")
|
||||
layout.itemO("import.3ds", text="3DS")
|
||||
layout.itemO("import.obj", text="OBJ")
|
||||
|
||||
|
||||
class INFO_MT_file_export(bpy.types.Menu):
|
||||
__space_type__ = 'INFO'
|
||||
@@ -93,7 +95,12 @@ class INFO_MT_file_export(bpy.types.Menu):
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
layout.itemO("export.3ds", text="3DS")
|
||||
layout.itemO("export.fbx", text="FBX")
|
||||
layout.itemO("export.obj", text="OBJ")
|
||||
layout.itemO("export.ply", text="PLY")
|
||||
layout.itemO("export.x3d", text="X3D")
|
||||
|
||||
|
||||
class INFO_MT_file_external_data(bpy.types.Menu):
|
||||
__space_type__ = 'INFO'
|
||||
|
@@ -39,14 +39,7 @@ struct PartEff;
|
||||
struct Scene;
|
||||
struct ListBase;
|
||||
|
||||
typedef struct DupliObject {
|
||||
struct DupliObject *next, *prev;
|
||||
struct Object *ob;
|
||||
unsigned int origlay;
|
||||
int index, no_draw, type, animated;
|
||||
float mat[4][4], omat[4][4];
|
||||
float orco[3], uv[2];
|
||||
} DupliObject;
|
||||
#include "DNA_object_types.h"
|
||||
|
||||
void free_path(struct Path *path);
|
||||
void calc_curvepath(struct Object *ob);
|
||||
|
@@ -2175,3 +2175,103 @@ void BKE_image_user_calc_imanr(ImageUser *iuser, int cfra, int fieldnr)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Produce image export path.
|
||||
|
||||
Fails returning 0 if image filename is empty or if destination path
|
||||
matches image path (i.e. both are the same file).
|
||||
|
||||
Trailing slash in dest_dir is optional.
|
||||
|
||||
Logic:
|
||||
|
||||
- if an image is "below" current .blend file directory, rebuild the
|
||||
same dir structure in dest_dir
|
||||
|
||||
For example //textures/foo/bar.png becomes
|
||||
[dest_dir]/textures/foo/bar.png.
|
||||
|
||||
- if an image is not "below" current .blend file directory,
|
||||
disregard it's path and copy it in the same directory where 3D file
|
||||
goes.
|
||||
|
||||
For example //../foo/bar.png becomes [dest_dir]/bar.png.
|
||||
|
||||
This logic will help ensure that all image paths are relative and
|
||||
that a user gets his images in one place. It'll also provide
|
||||
consistent behaviour across exporters.
|
||||
*/
|
||||
int BKE_get_image_export_path(struct Image *im, const char *dest_dir, char *abs, int abs_size, char *rel, int rel_size)
|
||||
{
|
||||
char path[FILE_MAX];
|
||||
char dir[FILE_MAX];
|
||||
char base[FILE_MAX];
|
||||
char blend_dir[FILE_MAX]; /* directory, where current .blend file resides */
|
||||
char dest_path[FILE_MAX];
|
||||
char rel_dir[FILE_MAX];
|
||||
int len;
|
||||
|
||||
if (abs)
|
||||
abs[0]= 0;
|
||||
|
||||
if (rel)
|
||||
rel[0]= 0;
|
||||
|
||||
BLI_split_dirfile_basic(G.sce, blend_dir, NULL);
|
||||
|
||||
if (!strlen(im->name)) {
|
||||
if (G.f & G_DEBUG) printf("Invalid image type.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
BLI_strncpy(path, im->name, sizeof(path));
|
||||
|
||||
/* expand "//" in filename and get absolute path */
|
||||
BLI_convertstringcode(path, G.sce);
|
||||
|
||||
/* get the directory part */
|
||||
BLI_split_dirfile_basic(path, dir, base);
|
||||
|
||||
len= strlen(blend_dir);
|
||||
|
||||
rel_dir[0] = 0;
|
||||
|
||||
/* if image is "below" current .blend file directory */
|
||||
if (!strncmp(path, blend_dir, len)) {
|
||||
|
||||
/* if image is _in_ current .blend file directory */
|
||||
if (!strcmp(dir, blend_dir)) {
|
||||
BLI_join_dirfile(dest_path, dest_dir, base);
|
||||
}
|
||||
/* "below" */
|
||||
else {
|
||||
/* rel = image_path_dir - blend_dir */
|
||||
BLI_strncpy(rel_dir, dir + len, sizeof(rel_dir));
|
||||
|
||||
BLI_join_dirfile(dest_path, dest_dir, rel_dir);
|
||||
BLI_join_dirfile(dest_path, dest_path, base);
|
||||
}
|
||||
|
||||
}
|
||||
/* image is out of current directory */
|
||||
else {
|
||||
BLI_join_dirfile(dest_path, dest_dir, base);
|
||||
}
|
||||
|
||||
if (abs)
|
||||
BLI_strncpy(abs, dest_path, abs_size);
|
||||
|
||||
if (rel) {
|
||||
strncat(rel, rel_dir, rel_size);
|
||||
strncat(rel, base, rel_size);
|
||||
}
|
||||
|
||||
/* return 2 if src=dest */
|
||||
if (!strcmp(path, dest_path)) {
|
||||
if (G.f & G_DEBUG) printf("%s and %s are the same file\n", path, dest_path);
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@@ -542,6 +542,7 @@ void set_mesh(Object *ob, Mesh *me)
|
||||
|
||||
if(ob->type==OB_MESH) {
|
||||
old= ob->data;
|
||||
if (old)
|
||||
old->id.us--;
|
||||
ob->data= me;
|
||||
id_us_plus((ID *)me);
|
||||
|
@@ -118,6 +118,7 @@ void EM_select_face(struct EditFace *efa, int sel);
|
||||
void EM_select_face_fgon(struct EditMesh *em, struct EditFace *efa, int val);
|
||||
void EM_select_swap(struct EditMesh *em);
|
||||
void EM_toggle_select_all(struct EditMesh *em);
|
||||
void EM_select_all(struct EditMesh *em);
|
||||
void EM_selectmode_flush(struct EditMesh *em);
|
||||
void EM_deselect_flush(struct EditMesh *em);
|
||||
void EM_selectmode_set(struct EditMesh *em);
|
||||
|
@@ -3293,6 +3293,11 @@ void EM_toggle_select_all(EditMesh *em) /* exported for UV */
|
||||
EM_set_flag_all(em, SELECT);
|
||||
}
|
||||
|
||||
void EM_select_all(EditMesh *em)
|
||||
{
|
||||
EM_set_flag_all(em, SELECT);
|
||||
}
|
||||
|
||||
static int toggle_select_all_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Object *obedit= CTX_data_edit_object(C);
|
||||
|
@@ -243,6 +243,7 @@ typedef struct Object {
|
||||
|
||||
ListBase gpulamp; /* runtime, for lamps only */
|
||||
ListBase pc_ids;
|
||||
ListBase *duplilist; /* for temporary dupli list storage, only for use by RNA API */
|
||||
} Object;
|
||||
|
||||
/* Warning, this is not used anymore because hooks are now modifiers */
|
||||
@@ -263,6 +264,14 @@ typedef struct ObHook {
|
||||
float force;
|
||||
} ObHook;
|
||||
|
||||
typedef struct DupliObject {
|
||||
struct DupliObject *next, *prev;
|
||||
struct Object *ob;
|
||||
unsigned int origlay;
|
||||
int index, no_draw, type, animated;
|
||||
float mat[4][4], omat[4][4];
|
||||
float orco[3], uv[2];
|
||||
} DupliObject;
|
||||
|
||||
/* this work object is defined in object.c */
|
||||
extern Object workob;
|
||||
|
@@ -1969,7 +1969,7 @@ RNAProcessItem PROCESS_ITEMS[]= {
|
||||
{"rna_rna.c", NULL, RNA_def_rna},
|
||||
{"rna_ID.c", NULL, RNA_def_ID},
|
||||
{"rna_texture.c", NULL, RNA_def_texture},
|
||||
{"rna_action.c", NULL, RNA_def_action},
|
||||
{"rna_action.c", "rna_action_api.c", RNA_def_action},
|
||||
{"rna_animation.c", "rna_animation_api.c", RNA_def_animation},
|
||||
{"rna_actuator.c", NULL, RNA_def_actuator},
|
||||
{"rna_armature.c", NULL, RNA_def_armature},
|
||||
@@ -1986,12 +1986,12 @@ RNAProcessItem PROCESS_ITEMS[]= {
|
||||
{"rna_fluidsim.c", NULL, RNA_def_fluidsim},
|
||||
{"rna_gpencil.c", NULL, RNA_def_gpencil},
|
||||
{"rna_group.c", NULL, RNA_def_group},
|
||||
{"rna_image.c", NULL, RNA_def_image},
|
||||
{"rna_image.c", "rna_image_api.c", RNA_def_image},
|
||||
{"rna_key.c", NULL, RNA_def_key},
|
||||
{"rna_lamp.c", NULL, RNA_def_lamp},
|
||||
{"rna_lattice.c", NULL, RNA_def_lattice},
|
||||
{"rna_main.c", "rna_main_api.c", RNA_def_main},
|
||||
{"rna_material.c", NULL, RNA_def_material},
|
||||
{"rna_material.c", "rna_material_api.c", RNA_def_material},
|
||||
{"rna_mesh.c", "rna_mesh_api.c", RNA_def_mesh},
|
||||
{"rna_meta.c", NULL, RNA_def_meta},
|
||||
{"rna_modifier.c", NULL, RNA_def_modifier},
|
||||
@@ -2001,7 +2001,7 @@ RNAProcessItem PROCESS_ITEMS[]= {
|
||||
{"rna_object_force.c", NULL, RNA_def_object_force},
|
||||
{"rna_packedfile.c", NULL, RNA_def_packedfile},
|
||||
{"rna_particle.c", NULL, RNA_def_particle},
|
||||
{"rna_pose.c", NULL, RNA_def_pose},
|
||||
{"rna_pose.c", "rna_pose_api.c", RNA_def_pose},
|
||||
{"rna_property.c", NULL, RNA_def_gameproperty},
|
||||
{"rna_render.c", NULL, RNA_def_render},
|
||||
{"rna_scene.c", "rna_scene_api.c", RNA_def_scene},
|
||||
|
@@ -100,6 +100,8 @@ static void rna_def_action(BlenderRNA *brna)
|
||||
RNA_def_property_collection_sdna(prop, NULL, "markers", NULL);
|
||||
RNA_def_property_struct_type(prop, "TimelineMarker");
|
||||
RNA_def_property_ui_text(prop, "Pose Markers", "Markers specific to this Action, for labeling poses.");
|
||||
|
||||
RNA_api_action(srna);
|
||||
}
|
||||
|
||||
/* --------- */
|
||||
|
80
source/blender/makesrna/intern/rna_action_api.c
Normal file
80
source/blender/makesrna/intern/rna_action_api.c
Normal file
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2009 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
*
|
||||
* Contributor(s): Arystanbek Dyussenov
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "RNA_define.h"
|
||||
#include "RNA_types.h"
|
||||
|
||||
#include "DNA_action_types.h"
|
||||
|
||||
#ifdef RNA_RUNTIME
|
||||
|
||||
#include "BKE_action.h"
|
||||
|
||||
#include "DNA_anim_types.h"
|
||||
#include "DNA_curve_types.h"
|
||||
|
||||
/* XXX disabled until RNA allows returning arrays */
|
||||
#if 0
|
||||
/* return frame range of all curves (min, max) or (0, 1) if there are no keys */
|
||||
int *rna_Action_get_frame_range(bAction *act, int *ret_length)
|
||||
{
|
||||
int *ret;
|
||||
float start, end;
|
||||
|
||||
calc_action_range(act, &start, &end, 1);
|
||||
|
||||
*ret_length= 2;
|
||||
ret= MEM_callocN(*ret_length * sizeof(int), "rna_Action_get_frame_range");
|
||||
|
||||
ret[0]= (int)start;
|
||||
ret[1]= (int)end;
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
void RNA_api_action(StructRNA *srna)
|
||||
{
|
||||
#if 0
|
||||
FunctionRNA *func;
|
||||
PropertyRNA *parm;
|
||||
|
||||
func= RNA_def_function(srna, "get_frame_range", "rna_Action_get_frame_range");
|
||||
RNA_def_function_ui_description(func, "Get action frame range as a (min, max) tuple.");
|
||||
parm= RNA_def_int_array(func, "frame_range", 1, NULL, 0, 0, "", "Action frame range.", 0, 0);
|
||||
RNA_def_property_flag(parm, PROP_DYNAMIC_ARRAY);
|
||||
RNA_def_function_return(func, parm);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
@@ -464,6 +464,37 @@ static void rna_def_bone(BlenderRNA *brna)
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", BONE_SELECTED);
|
||||
RNA_def_property_ui_text(prop, "Selected", "");
|
||||
RNA_def_property_update(prop, 0, "rna_Armature_redraw_data");
|
||||
|
||||
/* XXX better matrix descriptions possible (Arystan) */
|
||||
prop= RNA_def_property(srna, "matrix", PROP_FLOAT, PROP_MATRIX);
|
||||
RNA_def_property_float_sdna(prop, NULL, "bone_mat");
|
||||
RNA_def_property_array(prop, 9);
|
||||
RNA_def_property_ui_text(prop, "Bone Matrix", "3x3 bone matrix.");
|
||||
|
||||
prop= RNA_def_property(srna, "armature_matrix", PROP_FLOAT, PROP_MATRIX);
|
||||
RNA_def_property_float_sdna(prop, NULL, "arm_mat");
|
||||
RNA_def_property_array(prop, 16);
|
||||
RNA_def_property_ui_text(prop, "Bone Armature-Relative Matrix", "4x4 bone matrix relative to armature.");
|
||||
|
||||
prop= RNA_def_property(srna, "tail", PROP_FLOAT, PROP_TRANSLATION);
|
||||
RNA_def_property_float_sdna(prop, NULL, "tail");
|
||||
RNA_def_property_array(prop, 3);
|
||||
RNA_def_property_ui_text(prop, "Tail", "Location of tail end of the bone.");
|
||||
|
||||
prop= RNA_def_property(srna, "armature_tail", PROP_FLOAT, PROP_TRANSLATION);
|
||||
RNA_def_property_float_sdna(prop, NULL, "arm_tail");
|
||||
RNA_def_property_array(prop, 3);
|
||||
RNA_def_property_ui_text(prop, "Armature-Relative Tail", "Location of tail end of the bone relative to armature.");
|
||||
|
||||
prop= RNA_def_property(srna, "head", PROP_FLOAT, PROP_TRANSLATION);
|
||||
RNA_def_property_float_sdna(prop, NULL, "head");
|
||||
RNA_def_property_array(prop, 3);
|
||||
RNA_def_property_ui_text(prop, "Head", "Location of head end of the bone.");
|
||||
|
||||
prop= RNA_def_property(srna, "armature_head", PROP_FLOAT, PROP_TRANSLATION);
|
||||
RNA_def_property_float_sdna(prop, NULL, "arm_head");
|
||||
RNA_def_property_array(prop, 3);
|
||||
RNA_def_property_ui_text(prop, "Armature-Relative Head", "Location of head end of the bone relative to armature.");
|
||||
}
|
||||
|
||||
static void rna_def_edit_bone(BlenderRNA *brna)
|
||||
|
@@ -144,6 +144,29 @@ static EnumPropertyItem *rna_Image_source_itemf(bContext *C, PointerRNA *ptr, in
|
||||
return item;
|
||||
}
|
||||
|
||||
static int rna_Image_has_data_get(PointerRNA *ptr)
|
||||
{
|
||||
Image *im= (Image*)ptr->data;
|
||||
|
||||
if (im->ibufs.first)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rna_Image_depth_get(PointerRNA *ptr)
|
||||
{
|
||||
Image *im= (Image*)ptr->data;
|
||||
ImBuf *ibuf= BKE_image_get_ibuf(im, NULL);
|
||||
|
||||
if (!ibuf) return 0;
|
||||
|
||||
if (ibuf->rect_float)
|
||||
return 128;
|
||||
|
||||
return ibuf->depth;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void rna_def_imageuser(BlenderRNA *brna)
|
||||
@@ -356,6 +379,22 @@ static void rna_def_image(BlenderRNA *brna)
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "tpageflag", IMA_CLAMP_V);
|
||||
RNA_def_property_ui_text(prop, "Clamp Y", "Disable texture repeating vertically.");
|
||||
RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL);
|
||||
|
||||
/*
|
||||
Image.has_data and Image.depth are temporary,
|
||||
Update import_obj.py when they are replaced (Arystan)
|
||||
*/
|
||||
prop= RNA_def_property(srna, "has_data", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_funcs(prop, "rna_Image_has_data_get", NULL);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "Has data", "True if this image has data.");
|
||||
|
||||
prop= RNA_def_property(srna, "depth", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_funcs(prop, "rna_Image_depth_get", NULL, NULL);
|
||||
RNA_def_property_ui_text(prop, "Depth", "Image bit depth.");
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
|
||||
RNA_api_image(srna);
|
||||
}
|
||||
|
||||
void RNA_def_image(BlenderRNA *brna)
|
||||
|
82
source/blender/makesrna/intern/rna_image_api.c
Normal file
82
source/blender/makesrna/intern/rna_image_api.c
Normal file
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2009 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
*
|
||||
* Contributor(s): Arystanbek Dyussenov
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "RNA_define.h"
|
||||
#include "RNA_types.h"
|
||||
|
||||
#include "DNA_object_types.h"
|
||||
|
||||
#ifdef RNA_RUNTIME
|
||||
|
||||
#include "BKE_utildefines.h"
|
||||
#include "BKE_image.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
/*
|
||||
User should check if returned path exists before copying a file there.
|
||||
|
||||
TODO: it would be better to return a (abs, rel) tuple.
|
||||
*/
|
||||
static char *rna_Image_get_export_path(Image *image, char *dest_dir, int rel)
|
||||
{
|
||||
int length = FILE_MAX;
|
||||
char *path= MEM_callocN(length, "image file path");
|
||||
|
||||
if (!BKE_get_image_export_path(image, dest_dir, rel ? NULL : path, length, rel ? path : NULL, length )) {
|
||||
MEM_freeN(path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void RNA_api_image(StructRNA *srna)
|
||||
{
|
||||
FunctionRNA *func;
|
||||
PropertyRNA *parm;
|
||||
|
||||
func= RNA_def_function(srna, "get_export_path", "rna_Image_get_export_path");
|
||||
RNA_def_function_ui_description(func, "Produce image export path.");
|
||||
parm= RNA_def_string(func, "dest_dir", "", 0, "", "Destination directory.");
|
||||
RNA_def_property_flag(parm, PROP_REQUIRED);
|
||||
parm= RNA_def_boolean(func, "get_rel_path", 1, "", "Return relative path if True.");
|
||||
RNA_def_property_flag(parm, PROP_REQUIRED);
|
||||
parm= RNA_def_string(func, "path", "", 0, "", "Absolute export path.");
|
||||
RNA_def_function_return(func, parm);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -200,8 +200,11 @@ void rna_Mesh_update_draw(struct bContext *C, struct PointerRNA *ptr);
|
||||
|
||||
/* API functions */
|
||||
|
||||
void RNA_api_action(StructRNA *srna);
|
||||
void RNA_api_image(struct StructRNA *srna);
|
||||
void RNA_api_keyingset(struct StructRNA *srna);
|
||||
void RNA_api_main(struct StructRNA *srna);
|
||||
void RNA_api_material(StructRNA *srna);
|
||||
void RNA_api_mesh(struct StructRNA *srna);
|
||||
void RNA_api_object(struct StructRNA *srna);
|
||||
void RNA_api_scene(struct StructRNA *srna);
|
||||
@@ -209,6 +212,7 @@ void RNA_api_text(struct StructRNA *srna);
|
||||
void RNA_api_ui_layout(struct StructRNA *srna);
|
||||
void RNA_api_wm(struct StructRNA *srna);
|
||||
|
||||
|
||||
/* ID Properties */
|
||||
|
||||
extern StringPropertyRNA rna_IDProperty_string;
|
||||
|
@@ -32,13 +32,21 @@
|
||||
#include "RNA_define.h"
|
||||
#include "RNA_types.h"
|
||||
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_material_types.h"
|
||||
#include "DNA_mesh_types.h"
|
||||
|
||||
#ifdef RNA_RUNTIME
|
||||
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_library.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_material.h"
|
||||
#include "BKE_image.h"
|
||||
#include "BKE_texture.h"
|
||||
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_lamp_types.h"
|
||||
|
||||
static Mesh *rna_Main_add_mesh(Main *main, char *name)
|
||||
{
|
||||
@@ -57,24 +65,145 @@ static void rna_Main_remove_mesh(Main *main, ReportList *reports, Mesh *me)
|
||||
/* XXX python now has invalid pointer? */
|
||||
}
|
||||
|
||||
static Lamp *rna_Main_add_lamp(Main *main, char *name)
|
||||
{
|
||||
Lamp *la= add_lamp(name);
|
||||
la->id.us--;
|
||||
return la;
|
||||
}
|
||||
|
||||
/*
|
||||
static void rna_Main_remove_lamp(Main *main, ReportList *reports, Lamp *la)
|
||||
{
|
||||
if(la->id.us == 0)
|
||||
free_libblock(&main->lamp, la);
|
||||
else
|
||||
BKE_report(reports, RPT_ERROR, "Lamp must have zero users to be removed.");
|
||||
}
|
||||
*/
|
||||
|
||||
static Object* rna_Main_add_object(Main *main, int type, char *name)
|
||||
{
|
||||
Object *ob= add_only_object(type, name);
|
||||
ob->id.us--;
|
||||
return ob;
|
||||
}
|
||||
|
||||
/*
|
||||
NOTE: the following example shows when this function should _not_ be called
|
||||
|
||||
ob = bpy.data.add_object()
|
||||
scene.add_object(ob)
|
||||
|
||||
# ob is freed here
|
||||
scene.remove_object(ob)
|
||||
|
||||
# don't do this since ob is already freed!
|
||||
bpy.data.remove_object(ob)
|
||||
*/
|
||||
static void rna_Main_remove_object(Main *main, ReportList *reports, Object *ob)
|
||||
{
|
||||
if(ob->id.us == 0)
|
||||
free_libblock(&main->object, ob);
|
||||
else
|
||||
BKE_report(reports, RPT_ERROR, "Object must have zero users to be removed.");
|
||||
}
|
||||
|
||||
static Material *rna_Main_add_material(Main *main, char *name)
|
||||
{
|
||||
return add_material(name);
|
||||
}
|
||||
|
||||
/* TODO: remove material? */
|
||||
|
||||
struct Tex *rna_Main_add_texture(Main *main, char *name)
|
||||
{
|
||||
return add_texture(name);
|
||||
}
|
||||
|
||||
/* TODO: remove texture? */
|
||||
|
||||
struct Image *rna_Main_add_image(Main *main, char *filename)
|
||||
{
|
||||
return BKE_add_image_file(filename, 0);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void RNA_api_main(StructRNA *srna)
|
||||
{
|
||||
FunctionRNA *func;
|
||||
PropertyRNA *prop;
|
||||
PropertyRNA *parm;
|
||||
|
||||
/* copied from rna_def_object */
|
||||
static EnumPropertyItem object_type_items[] = {
|
||||
{OB_EMPTY, "EMPTY", 0, "Empty", ""},
|
||||
{OB_MESH, "MESH", 0, "Mesh", ""},
|
||||
{OB_CURVE, "CURVE", 0, "Curve", ""},
|
||||
{OB_SURF, "SURFACE", 0, "Surface", ""},
|
||||
{OB_FONT, "TEXT", 0, "Text", ""},
|
||||
{OB_MBALL, "META", 0, "Meta", ""},
|
||||
{OB_LAMP, "LAMP", 0, "Lamp", ""},
|
||||
{OB_CAMERA, "CAMERA", 0, "Camera", ""},
|
||||
{OB_WAVE, "WAVE", 0, "Wave", ""},
|
||||
{OB_LATTICE, "LATTICE", 0, "Lattice", ""},
|
||||
{OB_ARMATURE, "ARMATURE", 0, "Armature", ""},
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
|
||||
func= RNA_def_function(srna, "add_object", "rna_Main_add_object");
|
||||
RNA_def_function_ui_description(func, "Add a new object.");
|
||||
parm= RNA_def_enum(func, "type", object_type_items, 0, "", "Type of Object.");
|
||||
RNA_def_property_flag(parm, PROP_REQUIRED);
|
||||
parm= RNA_def_string(func, "name", "Object", 0, "", "New name for the datablock.");
|
||||
RNA_def_property_flag(parm, PROP_REQUIRED);
|
||||
parm= RNA_def_pointer(func, "object", "Object", "", "New object.");
|
||||
RNA_def_function_return(func, parm);
|
||||
|
||||
func= RNA_def_function(srna, "remove_object", "rna_Main_remove_object");
|
||||
RNA_def_function_flag(func, FUNC_USE_REPORTS);
|
||||
RNA_def_function_ui_description(func, "Remove an object if it has zero users.");
|
||||
parm= RNA_def_pointer(func, "object", "Object", "", "Object to remove.");
|
||||
RNA_def_property_flag(parm, PROP_REQUIRED);
|
||||
|
||||
func= RNA_def_function(srna, "add_mesh", "rna_Main_add_mesh");
|
||||
RNA_def_function_ui_description(func, "Add a new mesh.");
|
||||
prop= RNA_def_string(func, "name", "Mesh", 0, "", "New name for the datablock.");
|
||||
prop= RNA_def_pointer(func, "mesh", "Mesh", "", "New mesh.");
|
||||
RNA_def_function_return(func, prop);
|
||||
parm= RNA_def_string(func, "name", "Mesh", 0, "", "New name for the datablock.");
|
||||
RNA_def_property_flag(parm, PROP_REQUIRED);
|
||||
parm= RNA_def_pointer(func, "mesh", "Mesh", "", "New mesh.");
|
||||
RNA_def_function_return(func, parm);
|
||||
|
||||
func= RNA_def_function(srna, "remove_mesh", "rna_Main_remove_mesh");
|
||||
RNA_def_function_flag(func, FUNC_USE_REPORTS);
|
||||
RNA_def_function_ui_description(func, "Remove a mesh if it has zero users.");
|
||||
prop= RNA_def_pointer(func, "mesh", "Mesh", "", "Mesh to remove.");
|
||||
RNA_def_property_flag(prop, PROP_REQUIRED);
|
||||
parm= RNA_def_pointer(func, "mesh", "Mesh", "", "Mesh to remove.");
|
||||
RNA_def_property_flag(parm, PROP_REQUIRED);
|
||||
|
||||
func= RNA_def_function(srna, "add_lamp", "rna_Main_add_lamp");
|
||||
RNA_def_function_ui_description(func, "Add a new lamp.");
|
||||
parm= RNA_def_string(func, "name", "Lamp", 0, "", "New name for the datablock.");
|
||||
RNA_def_property_flag(parm, PROP_REQUIRED);
|
||||
parm= RNA_def_pointer(func, "mesh", "Lamp", "", "New lamp.");
|
||||
RNA_def_function_return(func, parm);
|
||||
|
||||
func= RNA_def_function(srna, "add_material", "rna_Main_add_material");
|
||||
RNA_def_function_ui_description(func, "Add a new material.");
|
||||
parm= RNA_def_string(func, "name", "Material", 0, "", "New name for the datablock."); /* optional */
|
||||
parm= RNA_def_pointer(func, "material", "Material", "", "New material.");
|
||||
RNA_def_function_return(func, parm);
|
||||
|
||||
func= RNA_def_function(srna, "add_texture", "rna_Main_add_texture");
|
||||
RNA_def_function_ui_description(func, "Add a new texture.");
|
||||
parm= RNA_def_string(func, "name", "Tex", 0, "", "New name for the datablock."); /* optional */
|
||||
parm= RNA_def_pointer(func, "texture", "Texture", "", "New texture.");
|
||||
RNA_def_function_return(func, parm);
|
||||
|
||||
func= RNA_def_function(srna, "add_image", "rna_Main_add_image");
|
||||
RNA_def_function_ui_description(func, "Add a new image.");
|
||||
parm= RNA_def_string(func, "filename", "", 0, "", "Filename to load image from.");
|
||||
RNA_def_property_flag(parm, PROP_REQUIRED);
|
||||
parm= RNA_def_pointer(func, "image", "Image", "", "New image.");
|
||||
RNA_def_function_return(func, parm);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -1688,6 +1688,8 @@ void RNA_def_material(BlenderRNA *brna)
|
||||
rna_def_material_mtex(brna);
|
||||
rna_def_material_strand(brna);
|
||||
rna_def_material_physics(brna);
|
||||
|
||||
RNA_api_material(srna);
|
||||
}
|
||||
|
||||
void rna_def_mtex_common(StructRNA *srna, const char *begin, const char *activeget, const char *activeset, const char *structname)
|
||||
|
126
source/blender/makesrna/intern/rna_material_api.c
Normal file
126
source/blender/makesrna/intern/rna_material_api.c
Normal file
@@ -0,0 +1,126 @@
|
||||
/**
|
||||
*
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2009 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
*
|
||||
* Contributor(s): Blender Foundation
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "RNA_define.h"
|
||||
#include "RNA_types.h"
|
||||
|
||||
#include "DNA_material_types.h"
|
||||
|
||||
#ifdef RNA_RUNTIME
|
||||
|
||||
#include "BKE_material.h"
|
||||
#include "BKE_texture.h"
|
||||
|
||||
/*
|
||||
Adds material to the first free texture slot.
|
||||
If all slots are busy, replaces the first.
|
||||
*/
|
||||
static void rna_Material_add_texture(Material *ma, Tex *tex, int mapto, int texco)
|
||||
{
|
||||
int i;
|
||||
MTex *mtex;
|
||||
int slot= -1;
|
||||
|
||||
for (i= 0; i < MAX_MTEX; i++) {
|
||||
if (!ma->mtex[i]) {
|
||||
slot= i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (slot == -1)
|
||||
slot= 0;
|
||||
|
||||
if (ma->mtex[slot]) {
|
||||
ma->mtex[slot]->tex->id.us--;
|
||||
}
|
||||
else {
|
||||
ma->mtex[slot]= add_mtex();
|
||||
}
|
||||
|
||||
mtex= ma->mtex[slot];
|
||||
|
||||
mtex->tex= tex;
|
||||
id_us_plus(&tex->id);
|
||||
|
||||
mtex->texco= mapto;
|
||||
mtex->mapto= texco;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void RNA_api_material(StructRNA *srna)
|
||||
{
|
||||
FunctionRNA *func;
|
||||
PropertyRNA *parm;
|
||||
|
||||
/* copied from rna_def_material_mtex (rna_material.c) */
|
||||
static EnumPropertyItem prop_texture_coordinates_items[] = {
|
||||
{TEXCO_GLOB, "GLOBAL", 0, "Global", "Uses global coordinates for the texture coordinates."},
|
||||
{TEXCO_OBJECT, "OBJECT", 0, "Object", "Uses linked object's coordinates for texture coordinates."},
|
||||
{TEXCO_UV, "UV", 0, "UV", "Uses UV coordinates for texture coordinates."},
|
||||
{TEXCO_ORCO, "ORCO", 0, "Generated", "Uses the original undeformed coordinates of the object."},
|
||||
{TEXCO_STRAND, "STRAND", 0, "Strand", "Uses normalized strand texture coordinate (1D)."},
|
||||
{TEXCO_STICKY, "STICKY", 0, "Sticky", "Uses mesh's sticky coordinates for the texture coordinates."},
|
||||
{TEXCO_WINDOW, "WINDOW", 0, "Window", "Uses screen coordinates as texture coordinates."},
|
||||
{TEXCO_NORM, "NORMAL", 0, "Normal", "Uses normal vector as texture coordinates."},
|
||||
{TEXCO_REFL, "REFLECTION", 0, "Reflection", "Uses reflection vector as texture coordinates."},
|
||||
{TEXCO_STRESS, "STRESS", 0, "Stress", "Uses the difference of edge lengths compared to original coordinates of the mesh."},
|
||||
{TEXCO_TANGENT, "TANGENT", 0, "Tangent", "Uses the optional tangent vector as texture coordinates."},
|
||||
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
|
||||
static EnumPropertyItem prop_texture_mapto_items[] = {
|
||||
{MAP_COL, "COLOR", 0, "Color", "Causes the texture to affect basic color of the material"},
|
||||
{MAP_NORM, "NORMAL", 0, "Normal", "Causes the texture to affect the rendered normal"},
|
||||
{MAP_COLSPEC, "SPECULAR_COLOR", 0, "Specularity Color", "Causes the texture to affect the specularity color"},
|
||||
{MAP_COLMIR, "MIRROR", 0, "Mirror", "Causes the texture to affect the mirror color"},
|
||||
{MAP_REF, "REFLECTION", 0, "Reflection", "Causes the texture to affect the value of the materials reflectivity"},
|
||||
{MAP_SPEC, "SPECULARITY", 0, "Specularity", "Causes the texture to affect the value of specularity"},
|
||||
{MAP_EMIT, "EMIT", 0, "Emit", "Causes the texture to affect the emit value"},
|
||||
{MAP_ALPHA, "ALPHA", 0, "Alpha", "Causes the texture to affect the alpha value"},
|
||||
{MAP_HAR, "HARDNESS", 0, "Hardness", "Causes the texture to affect the hardness value"},
|
||||
{MAP_RAYMIRR, "RAY_MIRROR", 0, "Ray-Mirror", "Causes the texture to affect the ray-mirror value"},
|
||||
{MAP_TRANSLU, "TRANSLUCENCY", 0, "Translucency", "Causes the texture to affect the translucency value"},
|
||||
{MAP_AMB, "AMBIENT", 0, "Ambient", "Causes the texture to affect the value of ambient"},
|
||||
{MAP_DISPLACE, "DISPLACEMENT", 0, "Displacement", "Let the texture displace the surface"},
|
||||
{MAP_WARP, "WARP", 0, "Warp", "Let the texture warp texture coordinates of next channels"},
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
|
||||
func= RNA_def_function(srna, "add_texture", "rna_Material_add_texture");
|
||||
RNA_def_function_ui_description(func, "Add a texture to material's free texture slot.");
|
||||
parm= RNA_def_pointer(func, "texture", "Texture", "", "Texture to add.");
|
||||
parm= RNA_def_enum(func, "texture_coordinates", prop_texture_coordinates_items, TEXCO_UV, "", "Source of texture coordinate information."); /* optional */
|
||||
parm= RNA_def_enum(func, "map_to", prop_texture_mapto_items, MAP_COL, "", "Controls which material property the texture affects."); /* optional */
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -953,6 +953,16 @@ static void rna_def_medge(BlenderRNA *brna)
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_SHARP);
|
||||
RNA_def_property_ui_text(prop, "Sharp", "Sharp edge for the EdgeSplit modifier");
|
||||
RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
|
||||
|
||||
prop= RNA_def_property(srna, "loose", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_LOOSEEDGE);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "Loose", "Loose edge");
|
||||
|
||||
prop= RNA_def_property(srna, "fgon", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_FGON);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "Fgon", "Fgon edge");
|
||||
}
|
||||
|
||||
static void rna_def_mface(BlenderRNA *brna)
|
||||
@@ -968,10 +978,13 @@ static void rna_def_mface(BlenderRNA *brna)
|
||||
|
||||
// XXX allows creating invalid meshes
|
||||
prop= RNA_def_property(srna, "verts", PROP_INT, PROP_UNSIGNED);
|
||||
RNA_def_property_int_sdna(prop, NULL, "v1");
|
||||
RNA_def_property_array(prop, 4);
|
||||
/*
|
||||
RNA_def_property_flag(prop, PROP_DYNAMIC);
|
||||
RNA_def_property_dynamic_array_funcs(prop, "rna_MeshFace_verts_get_length");
|
||||
RNA_def_property_int_funcs(prop, "rna_MeshFace_verts_get", "rna_MeshFace_verts_set", NULL);
|
||||
*/
|
||||
RNA_def_property_ui_text(prop, "Vertices", "Vertex indices");
|
||||
|
||||
prop= RNA_def_property(srna, "material_index", PROP_INT, PROP_UNSIGNED);
|
||||
|
@@ -42,12 +42,19 @@
|
||||
#include "BKE_DerivedMesh.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_material.h"
|
||||
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
|
||||
#include "BLI_arithb.h"
|
||||
#include "BLI_edgehash.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
#include "WM_types.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
static void rna_Mesh_calc_edges(Mesh *mesh)
|
||||
{
|
||||
CustomData edata;
|
||||
@@ -102,6 +109,9 @@ static void rna_Mesh_calc_edges(Mesh *mesh)
|
||||
|
||||
static void rna_Mesh_update(Mesh *mesh, bContext *C)
|
||||
{
|
||||
Main *bmain= CTX_data_main(C);
|
||||
Object *ob;
|
||||
|
||||
if(mesh->totface && mesh->totedge == 0)
|
||||
rna_Mesh_calc_edges(mesh);
|
||||
|
||||
@@ -111,6 +121,18 @@ static void rna_Mesh_update(Mesh *mesh, bContext *C)
|
||||
WM_event_add_notifier(C, NC_GEOM|ND_DATA, mesh);
|
||||
}
|
||||
|
||||
static void rna_Mesh_transform(Mesh *me, float *mat)
|
||||
{
|
||||
|
||||
/* TODO: old API transform had recalc_normals option */
|
||||
int i;
|
||||
MVert *mvert= me->mvert;
|
||||
|
||||
for(i= 0; i < me->totvert; i++, mvert++) {
|
||||
Mat4MulVecfl((float (*)[4])mat, mvert->co);
|
||||
}
|
||||
}
|
||||
|
||||
static void rna_Mesh_add_verts(Mesh *mesh, int len)
|
||||
{
|
||||
CustomData vdata;
|
||||
@@ -141,6 +163,14 @@ static void rna_Mesh_add_verts(Mesh *mesh, int len)
|
||||
mesh->totvert= totvert;
|
||||
}
|
||||
|
||||
Mesh *rna_Mesh_create_copy(Mesh *me)
|
||||
{
|
||||
Mesh *ret= copy_mesh(me);
|
||||
ret->id.us--;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void rna_Mesh_add_edges(Mesh *mesh, int len)
|
||||
{
|
||||
CustomData edata;
|
||||
@@ -201,6 +231,12 @@ static void rna_Mesh_add_faces(Mesh *mesh, int len)
|
||||
mesh->totface= totface;
|
||||
}
|
||||
|
||||
/*
|
||||
static void rna_Mesh_add_faces(Mesh *mesh)
|
||||
{
|
||||
}
|
||||
*/
|
||||
|
||||
static void rna_Mesh_add_geometry(Mesh *mesh, int verts, int edges, int faces)
|
||||
{
|
||||
if(verts)
|
||||
@@ -211,6 +247,39 @@ static void rna_Mesh_add_geometry(Mesh *mesh, int verts, int edges, int faces)
|
||||
rna_Mesh_add_faces(mesh, faces);
|
||||
}
|
||||
|
||||
static void rna_Mesh_add_uv_texture(Mesh *me)
|
||||
{
|
||||
me->mtface= CustomData_add_layer(&me->fdata, CD_MTFACE, CD_DEFAULT, NULL, me->totface);
|
||||
}
|
||||
|
||||
static void rna_Mesh_calc_normals(Mesh *me)
|
||||
{
|
||||
mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL);
|
||||
}
|
||||
|
||||
static void rna_Mesh_add_material(Mesh *me, Material *ma)
|
||||
{
|
||||
int i;
|
||||
int totcol = me->totcol + 1;
|
||||
Material **mat;
|
||||
|
||||
/* don't add if mesh already has it */
|
||||
for (i = 0; i < me->totcol; i++)
|
||||
if (me->mat[i] == ma)
|
||||
return;
|
||||
|
||||
mat= MEM_callocN(sizeof(void*) * totcol, "newmatar");
|
||||
|
||||
if (me->totcol) memcpy(mat, me->mat, sizeof(void*) * me->totcol);
|
||||
if (me->mat) MEM_freeN(me->mat);
|
||||
|
||||
me->mat = mat;
|
||||
me->mat[me->totcol++] = ma;
|
||||
ma->id.us++;
|
||||
|
||||
test_object_materials((ID*)me);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void RNA_api_mesh(StructRNA *srna)
|
||||
@@ -218,6 +287,11 @@ void RNA_api_mesh(StructRNA *srna)
|
||||
FunctionRNA *func;
|
||||
PropertyRNA *parm;
|
||||
|
||||
func= RNA_def_function(srna, "transform", "rna_Mesh_transform");
|
||||
RNA_def_function_ui_description(func, "Transform mesh vertices by a matrix.");
|
||||
parm= RNA_def_float_matrix(func, "matrix", 4, 4, NULL, 0.0f, 0.0f, "", "Matrix.", 0.0f, 0.0f);
|
||||
RNA_def_property_flag(parm, PROP_REQUIRED);
|
||||
|
||||
func= RNA_def_function(srna, "add_geometry", "rna_Mesh_add_geometry");
|
||||
parm= RNA_def_int(func, "verts", 0, 0, INT_MAX, "Number", "Number of vertices to add.", 0, INT_MAX);
|
||||
RNA_def_property_flag(parm, PROP_REQUIRED);
|
||||
@@ -226,8 +300,24 @@ void RNA_api_mesh(StructRNA *srna)
|
||||
parm= RNA_def_int(func, "faces", 0, 0, INT_MAX, "Number", "Number of faces to add.", 0, INT_MAX);
|
||||
RNA_def_property_flag(parm, PROP_REQUIRED);
|
||||
|
||||
func= RNA_def_function(srna, "create_copy", "rna_Mesh_create_copy");
|
||||
RNA_def_function_ui_description(func, "Create a copy of this Mesh datablock.");
|
||||
parm= RNA_def_pointer(func, "mesh", "Mesh", "", "Mesh, remove it if it is only used for export.");
|
||||
RNA_def_function_return(func, parm);
|
||||
|
||||
func= RNA_def_function(srna, "add_uv_texture", "rna_Mesh_add_uv_texture");
|
||||
RNA_def_function_ui_description(func, "Add a UV texture layer to Mesh.");
|
||||
|
||||
func= RNA_def_function(srna, "calc_normals", "rna_Mesh_calc_normals");
|
||||
RNA_def_function_ui_description(func, "Calculate vertex normals.");
|
||||
|
||||
func= RNA_def_function(srna, "update", "rna_Mesh_update");
|
||||
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
|
||||
|
||||
func= RNA_def_function(srna, "add_material", "rna_Mesh_add_material");
|
||||
RNA_def_function_ui_description(func, "Add a new material to Mesh.");
|
||||
parm= RNA_def_pointer(func, "material", "Material", "", "Material to add.");
|
||||
RNA_def_property_flag(parm, PROP_REQUIRED);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -103,6 +103,12 @@ void rna_Object_update(bContext *C, PointerRNA *ptr)
|
||||
DAG_id_flush_update(ptr->id.data, OB_RECALC_OB);
|
||||
}
|
||||
|
||||
void rna_Object_matrix_update(bContext *C, PointerRNA *ptr)
|
||||
{
|
||||
ED_object_apply_obmat(ptr->id.data);
|
||||
rna_Object_update(C, ptr);
|
||||
}
|
||||
|
||||
void rna_Object_update_data(bContext *C, PointerRNA *ptr)
|
||||
{
|
||||
DAG_id_flush_update(ptr->id.data, OB_RECALC_DATA);
|
||||
@@ -1212,6 +1218,7 @@ static void rna_def_object(BlenderRNA *brna)
|
||||
RNA_def_property_float_sdna(prop, NULL, "obmat");
|
||||
RNA_def_property_multi_array(prop, 2, matrix_dimsize);
|
||||
RNA_def_property_ui_text(prop, "Matrix", "Transformation matrix.");
|
||||
RNA_def_property_update(prop, NC_OBJECT|ND_TRANSFORM, "rna_Object_matrix_update");
|
||||
|
||||
/* collections */
|
||||
prop= RNA_def_property(srna, "constraints", PROP_COLLECTION, PROP_NONE);
|
||||
@@ -1524,12 +1531,43 @@ static void rna_def_object(BlenderRNA *brna)
|
||||
RNA_api_object(srna);
|
||||
}
|
||||
|
||||
static void rna_def_dupli_object(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
srna= RNA_def_struct(brna, "DupliObject", NULL);
|
||||
RNA_def_struct_sdna(srna, "DupliObject");
|
||||
RNA_def_struct_ui_text(srna, "Dupli Object", "Dupli Object data.");
|
||||
/* RNA_def_struct_ui_icon(srna, ICON_OBJECT_DATA); */
|
||||
|
||||
prop= RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
|
||||
/* RNA_def_property_struct_type(prop, "Object"); */
|
||||
RNA_def_property_pointer_sdna(prop, NULL, "ob");
|
||||
/* RNA_def_property_pointer_funcs(prop, "rna_DupliObject_object_get", NULL, NULL); */
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "Object", "Object this DupliObject represents.");
|
||||
|
||||
prop= RNA_def_property(srna, "ob_matrix", PROP_FLOAT, PROP_MATRIX);
|
||||
RNA_def_property_float_sdna(prop, NULL, "omat");
|
||||
RNA_def_property_array(prop, 16);
|
||||
RNA_def_property_ui_text(prop, "Object Matrix", "Object transformation matrix.");
|
||||
|
||||
prop= RNA_def_property(srna, "matrix", PROP_FLOAT, PROP_MATRIX);
|
||||
RNA_def_property_float_sdna(prop, NULL, "mat");
|
||||
RNA_def_property_array(prop, 16);
|
||||
RNA_def_property_ui_text(prop, "DupliObject Matrix", "DupliObject transformation matrix.");
|
||||
|
||||
/* TODO: DupliObject has more properties that can be wrapped */
|
||||
}
|
||||
|
||||
void RNA_def_object(BlenderRNA *brna)
|
||||
{
|
||||
rna_def_object(brna);
|
||||
rna_def_object_game_settings(brna);
|
||||
rna_def_vertex_group(brna);
|
||||
rna_def_material_slot(brna);
|
||||
rna_def_dupli_object(brna);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -28,40 +28,61 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "RNA_define.h"
|
||||
#include "RNA_types.h"
|
||||
|
||||
#include "DNA_object_types.h"
|
||||
|
||||
#include "BLO_sys_types.h" /* needed for intptr_t used in ED_mesh.h */
|
||||
|
||||
#include "ED_mesh.h"
|
||||
|
||||
#ifdef RNA_RUNTIME
|
||||
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_report.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_DerivedMesh.h"
|
||||
|
||||
#include "BKE_customdata.h"
|
||||
#include "BKE_anim.h"
|
||||
#include "BKE_depsgraph.h"
|
||||
#include "BKE_displist.h"
|
||||
#include "BKE_font.h"
|
||||
#include "BKE_mball.h"
|
||||
|
||||
#include "BLI_arithb.h"
|
||||
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_meshdata_types.h"
|
||||
#include "DNA_curve_types.h"
|
||||
#include "DNA_modifier_types.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BKE_customdata.h"
|
||||
#include "BKE_DerivedMesh.h"
|
||||
#include "BKE_displist.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_mball.h"
|
||||
#include "BKE_main.h"
|
||||
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_curve_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
|
||||
/* copied from init_render_mesh (render code) */
|
||||
static Mesh *rna_Object_create_render_mesh(Object *ob, bContext *C, Scene *scene)
|
||||
/* copied from Mesh_getFromObject and adapted to RNA interface */
|
||||
/* settings: 0 - preview, 1 - render */
|
||||
static Mesh *rna_Object_create_mesh(Object *ob, bContext *C, ReportList *reports, int apply_modifiers, int settings)
|
||||
{
|
||||
CustomDataMask mask = CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL;
|
||||
Mesh *tmpmesh;
|
||||
Curve *tmpcu = NULL;
|
||||
Object *tmpobj = NULL;
|
||||
DerivedMesh *dm;
|
||||
Mesh *me;
|
||||
int render = settings, i;
|
||||
int cage = !apply_modifiers;
|
||||
Scene *sce = CTX_data_scene(C);
|
||||
|
||||
/* perform the mesh extraction based on type */
|
||||
switch (ob->type) {
|
||||
case OB_FONT:
|
||||
case OB_CURVE:
|
||||
case OB_SURF:
|
||||
{
|
||||
int cage = 0; //XXX -todo
|
||||
Curve *tmpcu = NULL;
|
||||
|
||||
/* copies object and modifiers (but not the data) */
|
||||
tmpobj= copy_object(ob);
|
||||
@@ -88,80 +109,352 @@ static Mesh *rna_Object_create_render_mesh(Object *ob, bContext *C, Scene *scene
|
||||
#endif
|
||||
|
||||
/* get updated display list, and convert to a mesh */
|
||||
makeDispListCurveTypes( scene, tmpobj, 0 );
|
||||
makeDispListCurveTypes( sce, tmpobj, 0 );
|
||||
nurbs_to_mesh( tmpobj );
|
||||
|
||||
/* nurbs_to_mesh changes the type tp a mesh, check it worked */
|
||||
/* nurbs_to_mesh changes the type to a mesh, check it worked */
|
||||
if (tmpobj->type != OB_MESH) {
|
||||
free_libblock_us( &(CTX_data_main(C)->object), tmpobj );
|
||||
printf("cant convert curve to mesh. Does the curve have any segments?" ); // XXX use report api
|
||||
free_libblock_us( &G.main->object, tmpobj );
|
||||
BKE_report(reports, RPT_ERROR, "cant convert curve to mesh. Does the curve have any segments?");
|
||||
return NULL;
|
||||
}
|
||||
me = tmpobj->data;
|
||||
free_libblock_us( &(CTX_data_main(C)->object), tmpobj );
|
||||
tmpmesh = tmpobj->data;
|
||||
free_libblock_us( &G.main->object, tmpobj );
|
||||
break;
|
||||
}
|
||||
|
||||
case OB_MBALL:
|
||||
/* metaballs don't have modifiers, so just convert to mesh */
|
||||
ob = find_basis_mball(scene, ob);
|
||||
/* todo, re-generatre for render-res */
|
||||
// metaball_polygonize(scene, ob)
|
||||
me = add_mesh("Mesh");
|
||||
mball_to_mesh( &ob->disp, me );
|
||||
ob = find_basis_mball( sce, ob );
|
||||
tmpmesh = add_mesh("Mesh");
|
||||
mball_to_mesh( &ob->disp, tmpmesh );
|
||||
break;
|
||||
|
||||
case OB_MESH:
|
||||
{
|
||||
dm= mesh_create_derived_render(scene, ob, mask);
|
||||
// dm= mesh_create_derived_view(scene, ob, mask);
|
||||
/* copies object and modifiers (but not the data) */
|
||||
if (cage) {
|
||||
/* copies the data */
|
||||
tmpmesh = copy_mesh( ob->data );
|
||||
/* if not getting the original caged mesh, get final derived mesh */
|
||||
} else {
|
||||
/* Make a dummy mesh, saves copying */
|
||||
DerivedMesh *dm;
|
||||
/* CustomDataMask mask = CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL; */
|
||||
CustomDataMask mask = CD_MASK_MESH; /* this seems more suitable, exporter,
|
||||
for example, needs CD_MASK_MDEFORMVERT */
|
||||
|
||||
if(!dm)
|
||||
return NULL;
|
||||
/* Write the display mesh into the dummy mesh */
|
||||
if (render)
|
||||
dm = mesh_create_derived_render( sce, ob, mask );
|
||||
else
|
||||
dm = mesh_create_derived_view( sce, ob, mask );
|
||||
|
||||
me= add_mesh("tmp_render_mesh");
|
||||
me->id.us--; /* we don't assign it to anything */
|
||||
DM_to_mesh(dm, me);
|
||||
tmpmesh = add_mesh( "Mesh" );
|
||||
DM_to_mesh( dm, tmpmesh );
|
||||
dm->release( dm );
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
BKE_report(reports, RPT_ERROR, "Object does not have geometry data");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Copy materials to new mesh */
|
||||
switch (ob->type) {
|
||||
case OB_SURF:
|
||||
tmpmesh->totcol = tmpcu->totcol;
|
||||
|
||||
{ /* update the material */
|
||||
short i, *totcol =give_totcolp(ob);
|
||||
/* free old material list (if it exists) and adjust user counts */
|
||||
if( tmpcu->mat ) {
|
||||
for( i = tmpcu->totcol; i-- > 0; ) {
|
||||
/* are we an object material or data based? */
|
||||
if (ob->colbits & 1<<i)
|
||||
tmpmesh->mat[i] = ob->mat[i];
|
||||
else
|
||||
tmpmesh->mat[i] = tmpcu->mat[i];
|
||||
|
||||
/* free the current material list */
|
||||
if(me->mat)
|
||||
MEM_freeN((void *)me->mat);
|
||||
if (tmpmesh->mat[i])
|
||||
tmpmesh->mat[i]->id.us++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
me->mat= (Material **)MEM_callocN(sizeof(void *)*(*totcol), "matarray");
|
||||
#if 0
|
||||
/* Crashes when assigning the new material, not sure why */
|
||||
case OB_MBALL:
|
||||
tmpmb = (MetaBall *)ob->data;
|
||||
tmpmesh->totcol = tmpmb->totcol;
|
||||
|
||||
for(i=0; i<*totcol; i++) {
|
||||
Material *mat= give_current_material(ob, i+1);
|
||||
if(mat) {
|
||||
me->mat[i]= mat;
|
||||
mat->id.us++;
|
||||
/* free old material list (if it exists) and adjust user counts */
|
||||
if( tmpmb->mat ) {
|
||||
for( i = tmpmb->totcol; i-- > 0; ) {
|
||||
tmpmesh->mat[i] = tmpmb->mat[i]; /* CRASH HERE ??? */
|
||||
if (tmpmesh->mat[i]) {
|
||||
tmpmb->mat[i]->id.us++;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
return me;
|
||||
case OB_MESH:
|
||||
if (!cage) {
|
||||
Mesh *origmesh= ob->data;
|
||||
tmpmesh->flag= origmesh->flag;
|
||||
tmpmesh->mat = MEM_dupallocN(origmesh->mat);
|
||||
tmpmesh->totcol = origmesh->totcol;
|
||||
tmpmesh->smoothresh= origmesh->smoothresh;
|
||||
if( origmesh->mat ) {
|
||||
for( i = origmesh->totcol; i-- > 0; ) {
|
||||
/* are we an object material or data based? */
|
||||
if (ob->colbits & 1<<i)
|
||||
tmpmesh->mat[i] = ob->mat[i];
|
||||
else
|
||||
tmpmesh->mat[i] = origmesh->mat[i];
|
||||
if (tmpmesh->mat[i])
|
||||
tmpmesh->mat[i]->id.us++;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
} /* end copy materials */
|
||||
|
||||
/* we don't assign it to anything */
|
||||
tmpmesh->id.us--;
|
||||
|
||||
/* make sure materials get updated in objects */
|
||||
test_object_materials( ( ID * ) tmpmesh );
|
||||
|
||||
return tmpmesh;
|
||||
}
|
||||
|
||||
/* When no longer needed, duplilist should be freed with Object.free_duplilist */
|
||||
static void rna_Object_create_duplilist(Object *ob, bContext *C, ReportList *reports)
|
||||
{
|
||||
if (!(ob->transflag & OB_DUPLI)) {
|
||||
BKE_report(reports, RPT_ERROR, "Object does not have duplis.");
|
||||
return;
|
||||
}
|
||||
|
||||
/* free duplilist if a user forgets to */
|
||||
if (ob->duplilist) {
|
||||
BKE_reportf(reports, RPT_WARNING, "Object.dupli_list has not been freed.");
|
||||
|
||||
free_object_duplilist(ob->duplilist);
|
||||
ob->duplilist= NULL;
|
||||
}
|
||||
|
||||
ob->duplilist= object_duplilist(CTX_data_scene(C), ob);
|
||||
|
||||
/* ob->duplilist should now be freed with Object.free_duplilist */
|
||||
}
|
||||
|
||||
static void rna_Object_free_duplilist(Object *ob, ReportList *reports)
|
||||
{
|
||||
if (ob->duplilist) {
|
||||
free_object_duplilist(ob->duplilist);
|
||||
ob->duplilist= NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void rna_Object_convert_to_triface(Object *ob, bContext *C, ReportList *reports, Scene *sce)
|
||||
{
|
||||
Mesh *me;
|
||||
int ob_editing = CTX_data_edit_object(C) == ob;
|
||||
|
||||
if (ob->type != OB_MESH) {
|
||||
BKE_report(reports, RPT_ERROR, "Object should be of type MESH.");
|
||||
return;
|
||||
}
|
||||
|
||||
me= (Mesh*)ob->data;
|
||||
|
||||
if (!ob_editing)
|
||||
make_editMesh(sce, ob);
|
||||
|
||||
/* select all */
|
||||
EM_select_all(me->edit_mesh);
|
||||
|
||||
convert_to_triface(me->edit_mesh, 0);
|
||||
|
||||
load_editMesh(sce, ob);
|
||||
|
||||
if (!ob_editing)
|
||||
free_editMesh(me->edit_mesh);
|
||||
|
||||
DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
|
||||
}
|
||||
|
||||
static bDeformGroup *rna_Object_add_vertex_group(Object *ob, char *group_name)
|
||||
{
|
||||
return ED_vgroup_add_name(ob, group_name);
|
||||
}
|
||||
|
||||
static void rna_Object_add_vertex_to_group(Object *ob, int vertex_index, bDeformGroup *def, float weight, int assignmode)
|
||||
{
|
||||
/* creates dverts if needed */
|
||||
ED_vgroup_vert_add(ob, def, vertex_index, weight, assignmode);
|
||||
}
|
||||
|
||||
/* copied from old API Object.makeDisplayList (Object.c) */
|
||||
static void rna_Object_make_display_list(Object *ob, bContext *C)
|
||||
{
|
||||
Scene *sce= CTX_data_scene(C);
|
||||
|
||||
if (ob->type == OB_FONT) {
|
||||
Curve *cu = ob->data;
|
||||
freedisplist(&cu->disp);
|
||||
BKE_text_to_curve(sce, ob, CU_LEFT);
|
||||
}
|
||||
|
||||
DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
|
||||
}
|
||||
|
||||
static Object *rna_Object_find_armature(Object *ob)
|
||||
{
|
||||
Object *ob_arm = NULL;
|
||||
|
||||
if (ob->type != OB_MESH) return NULL;
|
||||
|
||||
if (ob->parent && ob->partype == PARSKEL && ob->parent->type == OB_ARMATURE) {
|
||||
ob_arm = ob->parent;
|
||||
}
|
||||
else {
|
||||
ModifierData *mod = (ModifierData*)ob->modifiers.first;
|
||||
while (mod) {
|
||||
if (mod->type == eModifierType_Armature) {
|
||||
ob_arm = ((ArmatureModifierData*)mod)->object;
|
||||
}
|
||||
|
||||
mod = mod->next;
|
||||
}
|
||||
}
|
||||
|
||||
return ob_arm;
|
||||
}
|
||||
|
||||
int rna_Object_is_visible(Object *ob, bContext *C)
|
||||
{
|
||||
return ob->lay & CTX_data_scene(C)->lay;
|
||||
}
|
||||
|
||||
/*
|
||||
static void rna_Mesh_assign_verts_to_group(Object *ob, bDeformGroup *group, int *indices, int totindex, float weight, int assignmode)
|
||||
{
|
||||
if (ob->type != OB_MESH) {
|
||||
BKE_report(reports, RPT_ERROR, "Object should be of MESH type.");
|
||||
return;
|
||||
}
|
||||
|
||||
Mesh *me = (Mesh*)ob->data;
|
||||
int group_index = get_defgroup_num(ob, group);
|
||||
if (group_index == -1) {
|
||||
BKE_report(reports, RPT_ERROR, "No deform groups assigned to mesh.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (assignmode != WEIGHT_REPLACE && assignmode != WEIGHT_ADD && assignmode != WEIGHT_SUBTRACT) {
|
||||
BKE_report(reports, RPT_ERROR, "Bad assignment mode." );
|
||||
return;
|
||||
}
|
||||
|
||||
// makes a set of dVerts corresponding to the mVerts
|
||||
if (!me->dvert)
|
||||
create_dverts(&me->id);
|
||||
|
||||
// loop list adding verts to group
|
||||
for (i= 0; i < totindex; i++) {
|
||||
if(i < 0 || i >= me->totvert) {
|
||||
BKE_report(reports, RPT_ERROR, "Bad vertex index in list.");
|
||||
return;
|
||||
}
|
||||
|
||||
add_vert_defnr(ob, group_index, i, weight, assignmode);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
#else
|
||||
|
||||
void RNA_api_object(StructRNA *srna)
|
||||
{
|
||||
FunctionRNA *func;
|
||||
PropertyRNA *prop;
|
||||
PropertyRNA *parm;
|
||||
|
||||
func= RNA_def_function(srna, "create_render_mesh", "rna_Object_create_render_mesh");
|
||||
RNA_def_function_ui_description(func, "Create a Mesh datablock with all modifiers applied.");
|
||||
static EnumPropertyItem mesh_type_items[] = {
|
||||
{0, "PREVIEW", 0, "Preview", "Apply modifier preview settings."},
|
||||
{1, "RENDER", 0, "Render", "Apply modifier render settings."},
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
static EnumPropertyItem assign_mode_items[] = {
|
||||
{WEIGHT_REPLACE, "REPLACE", 0, "Replace", "Replace."}, /* TODO: more meaningful descriptions */
|
||||
{WEIGHT_ADD, "ADD", 0, "Add", "Add."},
|
||||
{WEIGHT_SUBTRACT, "SUBTRACT", 0, "Subtract", "Subtract."},
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
/* mesh */
|
||||
func= RNA_def_function(srna, "create_mesh", "rna_Object_create_mesh");
|
||||
RNA_def_function_ui_description(func, "Create a Mesh datablock with modifiers applied.");
|
||||
RNA_def_function_flag(func, FUNC_USE_CONTEXT|FUNC_USE_REPORTS);
|
||||
parm= RNA_def_boolean(func, "apply_modifiers", 0, "", "Apply modifiers.");
|
||||
RNA_def_property_flag(parm, PROP_REQUIRED);
|
||||
parm= RNA_def_enum(func, "settings", mesh_type_items, 0, "", "Modifier settings to apply.");
|
||||
RNA_def_property_flag(parm, PROP_REQUIRED);
|
||||
parm= RNA_def_pointer(func, "mesh", "Mesh", "", "Mesh created from object, remove it if it is only used for export.");
|
||||
RNA_def_function_return(func, parm);
|
||||
|
||||
func= RNA_def_function(srna, "convert_to_triface", "rna_Object_convert_to_triface");
|
||||
RNA_def_function_ui_description(func, "Convert all mesh faces to triangles.");
|
||||
RNA_def_function_flag(func, FUNC_USE_CONTEXT|FUNC_USE_REPORTS);
|
||||
parm= RNA_def_pointer(func, "scene", "Scene", "", "Scene where the object belongs.");
|
||||
RNA_def_property_flag(parm, PROP_REQUIRED);
|
||||
|
||||
/* duplis */
|
||||
func= RNA_def_function(srna, "create_dupli_list", "rna_Object_create_duplilist");
|
||||
RNA_def_function_ui_description(func, "Create a list of dupli objects for this object, needs to be freed manually with free_dupli_list.");
|
||||
RNA_def_function_flag(func, FUNC_USE_CONTEXT|FUNC_USE_REPORTS);
|
||||
|
||||
func= RNA_def_function(srna, "free_dupli_list", "rna_Object_free_duplilist");
|
||||
RNA_def_function_ui_description(func, "Free the list of dupli objects.");
|
||||
RNA_def_function_flag(func, FUNC_USE_REPORTS);
|
||||
|
||||
/* vertex groups */
|
||||
func= RNA_def_function(srna, "add_vertex_group", "rna_Object_add_vertex_group");
|
||||
RNA_def_function_ui_description(func, "Add vertex group to object.");
|
||||
parm= RNA_def_string(func, "name", "Group", 0, "", "Vertex group name."); /* optional */
|
||||
parm= RNA_def_pointer(func, "group", "VertexGroup", "", "New vertex group.");
|
||||
RNA_def_function_return(func, parm);
|
||||
|
||||
func= RNA_def_function(srna, "add_vertex_to_group", "rna_Object_add_vertex_to_group");
|
||||
RNA_def_function_ui_description(func, "Add vertex to a vertex group.");
|
||||
parm= RNA_def_int(func, "vertex_index", 0, 0, 0, "", "Vertex index.", 0, 0);
|
||||
RNA_def_property_flag(parm, PROP_REQUIRED);
|
||||
parm= RNA_def_pointer(func, "group", "VertexGroup", "", "Vertex group to add vertex to.");
|
||||
RNA_def_property_flag(parm, PROP_REQUIRED);
|
||||
parm= RNA_def_float(func, "weight", 0, 0.0f, 1.0f, "", "Vertex weight.", 0.0f, 1.0f);
|
||||
RNA_def_property_flag(parm, PROP_REQUIRED);
|
||||
parm= RNA_def_enum(func, "type", assign_mode_items, 0, "", "Vertex assign mode.");
|
||||
RNA_def_property_flag(parm, PROP_REQUIRED);
|
||||
|
||||
/* Armature */
|
||||
func= RNA_def_function(srna, "find_armature", "rna_Object_find_armature");
|
||||
RNA_def_function_ui_description(func, "Find armature influencing this object as a parent or via a modifier.");
|
||||
parm= RNA_def_pointer(func, "ob_arm", "Object", "", "Armature object influencing this object or NULL.");
|
||||
RNA_def_function_return(func, parm);
|
||||
|
||||
/* DAG */
|
||||
func= RNA_def_function(srna, "make_display_list", "rna_Object_make_display_list");
|
||||
RNA_def_function_ui_description(func, "Update object's display data."); /* XXX describe better */
|
||||
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
|
||||
prop= RNA_def_pointer(func, "scene", "Scene", "", "");
|
||||
RNA_def_property_flag(prop, PROP_REQUIRED);
|
||||
prop= RNA_def_pointer(func, "mesh", "Mesh", "", "Mesh created from object, remove it if it is only used for export.");
|
||||
RNA_def_function_return(func, prop);
|
||||
|
||||
/* View */
|
||||
func= RNA_def_function(srna, "is_visible", "rna_Object_is_visible");
|
||||
RNA_def_function_ui_description(func, "Determine if object is visible in active scene.");
|
||||
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
|
||||
parm= RNA_def_boolean(func, "is_visible", 0, "", "Object visibility.");
|
||||
RNA_def_function_return(func, parm);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -547,21 +547,25 @@ static void rna_def_pose_channel(BlenderRNA *brna)
|
||||
RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_update");
|
||||
|
||||
/* These three matrix properties await an implementation of the PROP_MATRIX subtype, which currently doesn't exist. */
|
||||
/* prop= RNA_def_property(srna, "channel_matrix", PROP_FLOAT, PROP_MATRIX);
|
||||
RNA_def_property_struct_type(prop, "chan_mat");
|
||||
prop= RNA_def_property(srna, "channel_matrix", PROP_FLOAT, PROP_MATRIX);
|
||||
RNA_def_property_float_sdna(prop, NULL, "chan_mat");
|
||||
RNA_def_property_array(prop, 16);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "Channel Matrix", "4x4 matrix, before constraints.");*/
|
||||
RNA_def_property_ui_text(prop, "Channel Matrix", "4x4 matrix, before constraints.");
|
||||
|
||||
/* kaito says this should be not user-editable; I disagree; power users should be able to force this in python; he's the boss. */
|
||||
/* prop= RNA_def_property(srna, "pose_matrix", PROP_FLOAT, PROP_MATRIX);
|
||||
RNA_def_property_struct_type(prop, "pose_mat");
|
||||
prop= RNA_def_property(srna, "pose_matrix", PROP_FLOAT, PROP_MATRIX);
|
||||
RNA_def_property_float_sdna(prop, NULL, "pose_mat");
|
||||
RNA_def_property_array(prop, 16);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "Pose Matrix", "Final 4x4 matrix for this channel.");
|
||||
|
||||
/*
|
||||
prop= RNA_def_property(srna, "constraint_inverse_matrix", PROP_FLOAT, PROP_MATRIX);
|
||||
RNA_def_property_struct_type(prop, "constinv");
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "Constraint Inverse Matrix", "4x4 matrix, defines transform from final position to unconstrained position."); */
|
||||
RNA_def_property_ui_text(prop, "Constraint Inverse Matrix", "4x4 matrix, defines transform from final position to unconstrained position.");
|
||||
*/
|
||||
|
||||
/* Head/Tail Coordinates (in Pose Space) - Automatically calculated... */
|
||||
prop= RNA_def_property(srna, "pose_head", PROP_FLOAT, PROP_TRANSLATION);
|
||||
@@ -757,6 +761,8 @@ static void rna_def_pose(BlenderRNA *brna)
|
||||
RNA_def_property_int_funcs(prop, "rna_Pose_active_bone_group_index_get", "rna_Pose_active_bone_group_index_set", "rna_Pose_active_bone_group_index_range");
|
||||
RNA_def_property_ui_text(prop, "Active Bone Group Index", "Active index in bone groups array.");
|
||||
RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_update");
|
||||
|
||||
/* RNA_api_pose(srna); */
|
||||
}
|
||||
|
||||
void RNA_def_pose(BlenderRNA *brna)
|
||||
|
56
source/blender/makesrna/intern/rna_pose_api.c
Normal file
56
source/blender/makesrna/intern/rna_pose_api.c
Normal file
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2009 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
*
|
||||
* Contributor(s): Blender Foundation
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "RNA_define.h"
|
||||
#include "RNA_types.h"
|
||||
|
||||
#include "DNA_object_types.h"
|
||||
|
||||
/* #include "BLO_sys_types.h" */
|
||||
|
||||
#ifdef RNA_RUNTIME
|
||||
|
||||
/* #include "DNA_anim_types.h" */
|
||||
#include "DNA_action_types.h" /* bPose */
|
||||
|
||||
#else
|
||||
|
||||
void RNA_api_pose(StructRNA *srna)
|
||||
{
|
||||
/* FunctionRNA *func; */
|
||||
/* PropertyRNA *parm; */
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* $Id:
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
@@ -21,7 +21,7 @@
|
||||
* All rights reserved.
|
||||
*
|
||||
*
|
||||
* Contributor(s): Joshua Leung
|
||||
* Contributor(s): Joshua Leung, Arystanbek Dyussenov
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
@@ -40,9 +40,49 @@
|
||||
#ifdef RNA_RUNTIME
|
||||
|
||||
#include "BKE_animsys.h"
|
||||
#include "BKE_scene.h"
|
||||
#include "BKE_depsgraph.h"
|
||||
|
||||
// Scene API stuff from kazanbas branch here...
|
||||
#include "ED_object.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
|
||||
static void rna_Scene_add_object(Scene *sce, ReportList *reports, Object *ob)
|
||||
{
|
||||
Base *base= object_in_scene(ob, sce);
|
||||
if (base) {
|
||||
BKE_report(reports, RPT_ERROR, "Object is already in this scene.");
|
||||
return;
|
||||
}
|
||||
base= scene_add_base(sce, ob);
|
||||
ob->id.us++;
|
||||
|
||||
/* this is similar to what object_add_type and add_object do */
|
||||
ob->lay= base->lay= sce->lay;
|
||||
ob->recalc |= OB_RECALC;
|
||||
|
||||
DAG_scene_sort(sce);
|
||||
}
|
||||
|
||||
static void rna_Scene_remove_object(Scene *sce, ReportList *reports, Object *ob)
|
||||
{
|
||||
Base *base= object_in_scene(ob, sce);
|
||||
if (!base) {
|
||||
BKE_report(reports, RPT_ERROR, "Object is not in this scene.");
|
||||
return;
|
||||
}
|
||||
/* as long as ED_base_object_free_and_unlink calls free_libblock_us, we don't have to decrement ob->id.us */
|
||||
ED_base_object_free_and_unlink(sce, base);
|
||||
}
|
||||
|
||||
static void rna_Scene_set_frame(Scene *sce, bContext *C, int frame)
|
||||
{
|
||||
sce->r.cfra= frame;
|
||||
CLAMP(sce->r.cfra, MINAFRAME, MAXFRAME);
|
||||
scene_update_for_newframe(sce, (1<<20) - 1);
|
||||
|
||||
WM_event_add_notifier(C, NC_SCENE|ND_FRAME, sce);
|
||||
}
|
||||
|
||||
static KeyingSet *rna_Scene_add_keying_set(Scene *sce, ReportList *reports,
|
||||
char name[], int absolute, int insertkey_needed, int insertkey_visual)
|
||||
@@ -78,7 +118,23 @@ void RNA_api_scene(StructRNA *srna)
|
||||
FunctionRNA *func;
|
||||
PropertyRNA *parm;
|
||||
|
||||
// Scene API stuff from kazanbas branch here...
|
||||
func= RNA_def_function(srna, "add_object", "rna_Scene_add_object");
|
||||
RNA_def_function_ui_description(func, "Add object to scene.");
|
||||
RNA_def_function_flag(func, FUNC_USE_REPORTS);
|
||||
parm= RNA_def_pointer(func, "object", "Object", "", "Object to add to scene.");
|
||||
RNA_def_property_flag(parm, PROP_REQUIRED);
|
||||
|
||||
func= RNA_def_function(srna, "remove_object", "rna_Scene_remove_object");
|
||||
RNA_def_function_ui_description(func, "Remove object from scene.");
|
||||
RNA_def_function_flag(func, FUNC_USE_REPORTS);
|
||||
parm= RNA_def_pointer(func, "object", "Object", "", "Object to remove from scene.");
|
||||
RNA_def_property_flag(parm, PROP_REQUIRED);
|
||||
|
||||
func= RNA_def_function(srna, "set_frame", "rna_Scene_set_frame");
|
||||
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
|
||||
RNA_def_function_ui_description(func, "Set scene frame updating all objects immediately.");
|
||||
parm= RNA_def_int(func, "frame", 0, MINAFRAME, MAXFRAME, "", "Frame number to set.", MINAFRAME, MAXFRAME);
|
||||
RNA_def_property_flag(parm, PROP_REQUIRED);
|
||||
|
||||
/* Add Keying Set */
|
||||
func= RNA_def_function(srna, "add_keying_set", "rna_Scene_add_keying_set");
|
||||
|
@@ -345,6 +345,27 @@ static char *pyrna_enum_as_string(PointerRNA *ptr, PropertyRNA *prop)
|
||||
return result;
|
||||
}
|
||||
|
||||
static int pyrna_string_to_enum(PyObject *item, PointerRNA *ptr, PropertyRNA *prop, int *val, const char *error_prefix)
|
||||
{
|
||||
char *param= _PyUnicode_AsString(item);
|
||||
|
||||
if (param==NULL) {
|
||||
char *enum_str= pyrna_enum_as_string(ptr, prop);
|
||||
PyErr_Format(PyExc_TypeError, "%.200s expected a string enum type in (%.200s)", error_prefix, enum_str);
|
||||
MEM_freeN(enum_str);
|
||||
return 0;
|
||||
} else {
|
||||
if (!RNA_property_enum_value(BPy_GetContext(), ptr, prop, param, val)) {
|
||||
char *enum_str= pyrna_enum_as_string(ptr, prop);
|
||||
PyErr_Format(PyExc_TypeError, "%.200s enum \"%.200s\" not found in (%.200s)", error_prefix, param, enum_str);
|
||||
MEM_freeN(enum_str);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
PyObject * pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop)
|
||||
{
|
||||
PyObject *ret;
|
||||
@@ -603,25 +624,34 @@ int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *v
|
||||
}
|
||||
case PROP_ENUM:
|
||||
{
|
||||
char *param = _PyUnicode_AsString(value);
|
||||
int val, i;
|
||||
|
||||
if (param==NULL) {
|
||||
if (PyUnicode_Check(value)) {
|
||||
if (!pyrna_string_to_enum(value, ptr, prop, &val, error_prefix))
|
||||
return -1;
|
||||
}
|
||||
else if (PyTuple_Check(value)) {
|
||||
/* tuple of enum items, concatenate all values with OR */
|
||||
val= 0;
|
||||
for (i= 0; i < PyTuple_Size(value); i++) {
|
||||
int tmpval;
|
||||
|
||||
/* PyTuple_GET_ITEM returns a borrowed reference */
|
||||
if (!pyrna_string_to_enum(PyTuple_GET_ITEM(value, i), ptr, prop, &tmpval, error_prefix))
|
||||
return -1;
|
||||
|
||||
val |= tmpval;
|
||||
}
|
||||
}
|
||||
else {
|
||||
char *enum_str= pyrna_enum_as_string(ptr, prop);
|
||||
PyErr_Format(PyExc_TypeError, "%.200s expected a string enum type in (%.200s)", error_prefix, enum_str);
|
||||
PyErr_Format(PyExc_TypeError, "%.200s expected a string enum or a tuple of strings in (%.200s)", error_prefix, enum_str);
|
||||
MEM_freeN(enum_str);
|
||||
return -1;
|
||||
} else {
|
||||
int val;
|
||||
if (RNA_property_enum_value(BPy_GetContext(), ptr, prop, param, &val)) {
|
||||
}
|
||||
|
||||
if(data) *((int*)data)= val;
|
||||
else RNA_property_enum_set(ptr, prop, val);
|
||||
} else {
|
||||
char *enum_str= pyrna_enum_as_string(ptr, prop);
|
||||
PyErr_Format(PyExc_TypeError, "%.200s enum \"%.200s\" not found in (%.200s)", error_prefix, param, enum_str);
|
||||
MEM_freeN(enum_str);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
Reference in New Issue
Block a user