Merge from 2.5 r20991 through r21037

This commit is contained in:
Arystanbek Dyussenov
2009-06-20 16:48:58 +00:00
60 changed files with 2139 additions and 1641 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 173 KiB

After

Width:  |  Height:  |  Size: 172 KiB

286
release/io/export_ply.py Normal file
View File

@@ -0,0 +1,286 @@
import bpy
__author__ = "Bruce Merry"
__version__ = "0.93"
__bpydoc__ = """\
This script exports Stanford PLY files from Blender. It supports normals,
colours, and texture coordinates per face or per vertex.
Only one mesh can be exported at a time.
"""
# Copyright (C) 2004, 2005: Bruce Merry, bmerry@cs.uct.ac.za
#
# 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.
# Vector rounding se we can use as keys
#
# Updated on Aug 11, 2008 by Campbell Barton
# - added 'comment' prefix to comments - Needed to comply with the PLY spec.
#
# Updated on Jan 1, 2007 by Gabe Ghearing
# - fixed normals so they are correctly smooth/flat
# - fixed crash when the model doesn't have uv coords or vertex colors
# - fixed crash when the model has vertex colors but doesn't have uv coords
# - changed float32 to float and uint8 to uchar for compatibility
# Errata/Notes as of Jan 1, 2007
# - script exports texture coords if they exist even if TexFace isn't selected (not a big deal to me)
# - ST(R) should probably be renamed UV(T) like in most PLY files (importer needs to be updated to take either)
#
# Updated on Jan 3, 2007 by Gabe Ghearing
# - fixed "sticky" vertex UV exporting
# - added pupmenu to enable/disable exporting normals, uv coords, and colors
# Errata/Notes as of Jan 3, 2007
# - ST(R) coords should probably be renamed UV(T) like in most PLY files (importer needs to be updated to take either)
# - edges should be exported since PLY files support them
# - code is getting spaghettish, it should be refactored...
#
def rvec3d(v): return round(v[0], 6), round(v[1], 6), round(v[2], 6)
def rvec2d(v): return round(v[0], 6), round(v[1], 6)
def write(filename, scene, ob, \
EXPORT_APPLY_MODIFIERS= True,\
EXPORT_NORMALS= True,\
EXPORT_UV= True,\
EXPORT_COLORS= True\
):
if not filename.lower().endswith('.ply'):
filename += '.ply'
if not ob:
raise Exception("Error, Select 1 active object")
return
file = open(filename, 'wb')
#EXPORT_EDGES = Draw.Create(0)
"""
is_editmode = Blender.Window.EditMode()
if is_editmode:
Blender.Window.EditMode(0, '', 0)
Window.WaitCursor(1)
"""
#mesh = BPyMesh.getMeshFromObject(ob, None, EXPORT_APPLY_MODIFIERS, False, scn) # XXX
if EXPORT_APPLY_MODIFIERS:
mesh = ob.create_render_mesh(scene)
else:
mesh = ob.data
if not mesh:
raise ("Error, could not get mesh data from active object")
return
# mesh.transform(ob.matrixWorld) # XXX
faceUV = len(mesh.uv_layers) > 0
vertexUV = len(mesh.sticky) > 0
vertexColors = len(mesh.vcol_layers) > 0
if (not faceUV) and (not vertexUV): EXPORT_UV = False
if not vertexColors: EXPORT_COLORS = False
if not EXPORT_UV: faceUV = vertexUV = False
if not EXPORT_COLORS: vertexColors = False
if faceUV:
active_uv_layer = None
for lay in mesh.uv_layers:
if lay.active:
active_uv_layer= lay.data
break
if not active_uv_layer:
EXPORT_UV = False
faceUV = None
if vertexColors:
active_col_layer = None
for lay in mesh.vcol_layers:
if lay.active:
active_col_layer= lay.data
if not active_col_layer:
EXPORT_COLORS = False
vertexColors = None
# incase
color = uvcoord = uvcoord_key = normal = normal_key = None
mesh_verts = mesh.verts # save a lookup
ply_verts = [] # list of dictionaries
# vdict = {} # (index, normal, uv) -> new index
vdict = [{} for i in xrange(len(mesh_verts))]
ply_faces = [[] for f in xrange(len(mesh.faces))]
vert_count = 0
for i, f in enumerate(mesh.faces):
smooth = f.smooth
# XXX need face normals
"""
if not smooth:
normal = tuple(f.no)
normal_key = rvec3d(normal)
"""
if faceUV:
uv = active_uv_layer[i]
uv = uv.uv1, uv.uv2, uv.uv3, uv.uv4 # XXX - crufty :/
if vertexColors:
col = active_col_layer[i]
col = col.color1, col.color2, col.color3, col.color4
f_verts= list(f.verts)
if not f_verts[3]: f_verts.pop() # XXX face length should be 3/4, not always 4
pf= ply_faces[i]
for j, vidx in enumerate(f_verts):
v = mesh_verts[vidx]
"""
if smooth:
normal= tuple(v.no)
normal_key = rvec3d(normal)
"""
normal_key = None # XXX
if faceUV:
uvcoord= uv[j][0], 1.0-uv[j][1]
uvcoord_key = rvec2d(uvcoord)
elif vertexUV:
uvcoord= v.uvco[0], 1.0-v.uvco[1]
uvcoord_key = rvec2d(uvcoord)
if vertexColors:
color= col[j]
color= int(color[0]*255.0), int(color[1]*255.0), int(color[2]*255.0)
key = normal_key, uvcoord_key, color
vdict_local = vdict[vidx]
pf_vidx = vdict_local.get(key) # Will be None initially
if pf_vidx == None: # same as vdict_local.has_key(key)
pf_vidx = vdict_local[key] = vert_count;
ply_verts.append((vidx, normal, uvcoord, color))
vert_count += 1
pf.append(pf_vidx)
file.write('ply\n')
file.write('format ascii 1.0\n')
version = "2.5" # Blender.Get('version')
file.write('comment Created by Blender3D %s - www.blender.org, source file: %s\n' % (version, bpy.data.filename.split('/')[-1].split('\\')[-1] ))
file.write('element vertex %d\n' % len(ply_verts))
file.write('property float x\n')
file.write('property float y\n')
file.write('property float z\n')
# XXX
"""
if EXPORT_NORMALS:
file.write('property float nx\n')
file.write('property float ny\n')
file.write('property float nz\n')
"""
if EXPORT_UV:
file.write('property float s\n')
file.write('property float t\n')
if EXPORT_COLORS:
file.write('property uchar red\n')
file.write('property uchar green\n')
file.write('property uchar blue\n')
file.write('element face %d\n' % len(mesh.faces))
file.write('property list uchar uint vertex_indices\n')
file.write('end_header\n')
for i, v in enumerate(ply_verts):
file.write('%.6f %.6f %.6f ' % tuple(mesh_verts[v[0]].co)) # co
"""
if EXPORT_NORMALS:
file.write('%.6f %.6f %.6f ' % v[1]) # no
"""
if EXPORT_UV: file.write('%.6f %.6f ' % v[2]) # uv
if EXPORT_COLORS: file.write('%u %u %u' % v[3]) # col
file.write('\n')
for pf in ply_faces:
if len(pf)==3: file.write('3 %d %d %d\n' % tuple(pf))
else: file.write('4 %d %d %d %d\n' % tuple(pf))
file.close()
print("writing", filename, "done")
if EXPORT_APPLY_MODIFIERS:
bpy.data.remove_mesh(mesh)
# XXX
"""
if is_editmode:
Blender.Window.EditMode(1, '', 0)
"""
class EXPORT_OT_ply(bpy.types.Operator):
'''
Operator documentatuon text, will be used for the operator tooltip and python docs.
'''
__label__ = "Export PLY"
# 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 PLY file", maxlen= 1024, default= ""),
bpy.props.BoolProperty(attr="use_modifiers", name="Apply Modifiers", description="Apply Modifiers to the exported mesh", default= True),
bpy.props.BoolProperty(attr="use_normals", name="Export Normals", description="Export Normals for smooth and hard shaded faces", default= True),
bpy.props.BoolProperty(attr="use_uvs", name="Export UVs", description="Exort the active UV layer", default= True),
bpy.props.BoolProperty(attr="use_colors", name="Export Vertex Colors", description="Exort the active vertex color layer", default= True)
]
def poll(self, context):
print("Poll")
return context.active_object != None
def execute(self, context):
# print("Selected: " + context.active_object.name)
if not self.filename:
raise Exception("filename not set")
write(self.filename, context.scene, context.active_object,\
EXPORT_APPLY_MODIFIERS = self.use_modifiers,
EXPORT_NORMALS = self.use_normals,
EXPORT_UV = self.use_uvs,
EXPORT_COLORS = self.use_colors,
)
return ('FINISHED',)
def invoke(self, context, event):
wm = context.manager
wm.add_fileselect(self.__operator__)
return ('RUNNING_MODAL',)
bpy.ops.add(EXPORT_OT_ply)
if __name__ == "__main__":
bpy.ops.EXPORT_OT_ply(filename="/tmp/test.ply")

View File

@@ -1,228 +0,0 @@
#!BPY
"""
Name: 'Stanford PLY (*.ply)...'
Blender: 241
Group: 'Export'
Tooltip: 'Export active object to Stanford PLY format'
"""
import bpy
import Blender
from Blender import Mesh, Scene, Window, sys, Image, Draw
import BPyMesh
__author__ = "Bruce Merry"
__version__ = "0.93"
__bpydoc__ = """\
This script exports Stanford PLY files from Blender. It supports normals,
colours, and texture coordinates per face or per vertex.
Only one mesh can be exported at a time.
"""
# Copyright (C) 2004, 2005: Bruce Merry, bmerry@cs.uct.ac.za
#
# 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.
# Vector rounding se we can use as keys
#
# Updated on Aug 11, 2008 by Campbell Barton
# - added 'comment' prefix to comments - Needed to comply with the PLY spec.
#
# Updated on Jan 1, 2007 by Gabe Ghearing
# - fixed normals so they are correctly smooth/flat
# - fixed crash when the model doesn't have uv coords or vertex colors
# - fixed crash when the model has vertex colors but doesn't have uv coords
# - changed float32 to float and uint8 to uchar for compatibility
# Errata/Notes as of Jan 1, 2007
# - script exports texture coords if they exist even if TexFace isn't selected (not a big deal to me)
# - ST(R) should probably be renamed UV(T) like in most PLY files (importer needs to be updated to take either)
#
# Updated on Jan 3, 2007 by Gabe Ghearing
# - fixed "sticky" vertex UV exporting
# - added pupmenu to enable/disable exporting normals, uv coords, and colors
# Errata/Notes as of Jan 3, 2007
# - ST(R) coords should probably be renamed UV(T) like in most PLY files (importer needs to be updated to take either)
# - edges should be exported since PLY files support them
# - code is getting spaghettish, it should be refactored...
#
def rvec3d(v): return round(v[0], 6), round(v[1], 6), round(v[2], 6)
def rvec2d(v): return round(v[0], 6), round(v[1], 6)
def file_callback(filename):
if not filename.lower().endswith('.ply'):
filename += '.ply'
scn= bpy.data.scenes.active
ob= scn.objects.active
if not ob:
Blender.Draw.PupMenu('Error%t|Select 1 active object')
return
file = open(filename, 'wb')
EXPORT_APPLY_MODIFIERS = Draw.Create(1)
EXPORT_NORMALS = Draw.Create(1)
EXPORT_UV = Draw.Create(1)
EXPORT_COLORS = Draw.Create(1)
#EXPORT_EDGES = Draw.Create(0)
pup_block = [\
('Apply Modifiers', EXPORT_APPLY_MODIFIERS, 'Use transformed mesh data.'),\
('Normals', EXPORT_NORMALS, 'Export vertex normal data.'),\
('UVs', EXPORT_UV, 'Export texface UV coords.'),\
('Colors', EXPORT_COLORS, 'Export vertex Colors.'),\
#('Edges', EXPORT_EDGES, 'Edges not connected to faces.'),\
]
if not Draw.PupBlock('Export...', pup_block):
return
is_editmode = Blender.Window.EditMode()
if is_editmode:
Blender.Window.EditMode(0, '', 0)
Window.WaitCursor(1)
EXPORT_APPLY_MODIFIERS = EXPORT_APPLY_MODIFIERS.val
EXPORT_NORMALS = EXPORT_NORMALS.val
EXPORT_UV = EXPORT_UV.val
EXPORT_COLORS = EXPORT_COLORS.val
#EXPORT_EDGES = EXPORT_EDGES.val
mesh = BPyMesh.getMeshFromObject(ob, None, EXPORT_APPLY_MODIFIERS, False, scn)
if not mesh:
Blender.Draw.PupMenu('Error%t|Could not get mesh data from active object')
return
mesh.transform(ob.matrixWorld)
faceUV = mesh.faceUV
vertexUV = mesh.vertexUV
vertexColors = mesh.vertexColors
if (not faceUV) and (not vertexUV): EXPORT_UV = False
if not vertexColors: EXPORT_COLORS = False
if not EXPORT_UV: faceUV = vertexUV = False
if not EXPORT_COLORS: vertexColors = False
# incase
color = uvcoord = uvcoord_key = normal = normal_key = None
verts = [] # list of dictionaries
# vdict = {} # (index, normal, uv) -> new index
vdict = [{} for i in xrange(len(mesh.verts))]
vert_count = 0
for i, f in enumerate(mesh.faces):
smooth = f.smooth
if not smooth:
normal = tuple(f.no)
normal_key = rvec3d(normal)
if faceUV: uv = f.uv
if vertexColors: col = f.col
for j, v in enumerate(f):
if smooth:
normal= tuple(v.no)
normal_key = rvec3d(normal)
if faceUV:
uvcoord= uv[j][0], 1.0-uv[j][1]
uvcoord_key = rvec2d(uvcoord)
elif vertexUV:
uvcoord= v.uvco[0], 1.0-v.uvco[1]
uvcoord_key = rvec2d(uvcoord)
if vertexColors: color= col[j].r, col[j].g, col[j].b
key = normal_key, uvcoord_key, color
vdict_local = vdict[v.index]
if (not vdict_local) or (not vdict_local.has_key(key)):
vdict_local[key] = vert_count;
verts.append( (tuple(v.co), normal, uvcoord, color) )
vert_count += 1
file.write('ply\n')
file.write('format ascii 1.0\n')
file.write('comment Created by Blender3D %s - www.blender.org, source file: %s\n' % (Blender.Get('version'), Blender.Get('filename').split('/')[-1].split('\\')[-1] ))
file.write('element vertex %d\n' % len(verts))
file.write('property float x\n')
file.write('property float y\n')
file.write('property float z\n')
if EXPORT_NORMALS:
file.write('property float nx\n')
file.write('property float ny\n')
file.write('property float nz\n')
if EXPORT_UV:
file.write('property float s\n')
file.write('property float t\n')
if EXPORT_COLORS:
file.write('property uchar red\n')
file.write('property uchar green\n')
file.write('property uchar blue\n')
file.write('element face %d\n' % len(mesh.faces))
file.write('property list uchar uint vertex_indices\n')
file.write('end_header\n')
for i, v in enumerate(verts):
file.write('%.6f %.6f %.6f ' % v[0]) # co
if EXPORT_NORMALS:
file.write('%.6f %.6f %.6f ' % v[1]) # no
if EXPORT_UV:
file.write('%.6f %.6f ' % v[2]) # uv
if EXPORT_COLORS:
file.write('%u %u %u' % v[3]) # col
file.write('\n')
for (i, f) in enumerate(mesh.faces):
file.write('%d ' % len(f))
smooth = f.smooth
if not smooth: no = rvec3d(f.no)
if faceUV: uv = f.uv
if vertexColors: col = f.col
for j, v in enumerate(f):
if f.smooth: normal= rvec3d(v.no)
else: normal= no
if faceUV: uvcoord= rvec2d((uv[j][0], 1.0-uv[j][1]))
elif vertexUV: uvcoord= rvec2d((v.uvco[0], 1.0-v.uvco[1]))
if vertexColors: color= col[j].r, col[j].g, col[j].b
file.write('%d ' % vdict[v.index][normal, uvcoord, color])
file.write('\n')
file.close()
if is_editmode:
Blender.Window.EditMode(1, '', 0)
def main():
Blender.Window.FileSelector(file_callback, 'PLY Export', Blender.sys.makename(ext='.ply'))
if __name__=='__main__':
main()

View File

@@ -7,7 +7,7 @@ class BoneButtonsPanel(bpy.types.Panel):
__context__ = "bone"
def poll(self, context):
return (context.bone != None)
return (context.bone or context.edit_bone)
class BONE_PT_bone(BoneButtonsPanel):
__idname__ = "BONE_PT_bone"
@@ -16,6 +16,8 @@ class BONE_PT_bone(BoneButtonsPanel):
def draw(self, context):
layout = self.layout
bone = context.bone
if not bone:
bone = context.edit_bone
split = layout.split()
@@ -40,8 +42,7 @@ class BONE_PT_bone(BoneButtonsPanel):
sub.itemL(text="Display:")
sub.itemR(bone, "draw_wire", text="Wireframe")
sub.itemR(bone, "editmode_hidden", text="Hide (EditMode)")
sub.itemR(bone, "pose_channel_hidden", text="Hide (PoseMode)")
sub.itemR(bone, "hidden", text="Hide")
sub.itemL(text="Curved Bones:")
sub.itemR(bone, "bbone_segments", text="Segments")
@@ -50,4 +51,4 @@ class BONE_PT_bone(BoneButtonsPanel):
sub.itemR(bone, "cyclic_offset")
bpy.types.register(BONE_PT_bone)
bpy.types.register(BONE_PT_bone)

View File

@@ -207,6 +207,7 @@ class DATA_PT_modifiers(DataButtonsPanel):
layout.itemR(md, "texture")
layout.itemR(md, "midlevel")
layout.itemR(md, "strength")
layout.itemR(md, "direction")
layout.itemR(md, "texture_coordinates")
if md.texture_coordinates == 'OBJECT':
layout.itemR(md, "texture_coordinate_object", text="Object")

View File

@@ -35,7 +35,7 @@ class OBJECT_PT_groups(ObjectButtonsPanel):
# layout.itemO("OBJECT_OT_add_group");
for group in bpy.data.groups:
if ob in group.objects:
if ob.name in group.objects:
col = layout.column(align=True)
row = col.box().row()

80
release/ui/space_logic.py Normal file
View File

@@ -0,0 +1,80 @@
import bpy
class LOGIC_PT_physics(bpy.types.Panel):
__space_type__ = "LOGIC_EDITOR"
__region_type__ = "UI"
__label__ = "Physics"
def draw(self, context):
layout = self.layout
ob = context.active_object
game = ob.game
flow = layout.column_flow()
flow.active = True
flow.itemR(game, "physics_type")
flow.itemR(game, "actor")
row = layout.row()
row.itemR(game, "ghost")
row.itemR(ob, "restrict_render", text="Invisible") # out of place but useful
flow = layout.column_flow()
flow.itemR(game, "mass")
flow.itemR(game, "radius")
flow.itemR(game, "no_sleeping")
flow.itemR(game, "damping")
flow.itemR(game, "rotation_damping")
flow.itemR(game, "minimum_velocity")
flow.itemR(game, "maximum_velocity")
row = layout.row()
row.itemR(game, "do_fh")
row.itemR(game, "rotation_fh")
flow = layout.column_flow()
flow.itemR(game, "form_factor")
flow.itemR(game, "anisotropic_friction")
flow = layout.column_flow()
flow.active = game.anisotropic_friction
flow.itemR(game, "friction_coefficients")
split = layout.split()
sub = split.column()
sub.itemR(game, "lock_x_axis")
sub.itemR(game, "lock_y_axis")
sub.itemR(game, "lock_z_axis")
sub = split.column()
sub.itemR(game, "lock_x_rot_axis")
sub.itemR(game, "lock_y_rot_axis")
sub.itemR(game, "lock_z_rot_axis")
class LOGIC_PT_collision_bounds(bpy.types.Panel):
__space_type__ = "LOGIC_EDITOR"
__region_type__ = "UI"
__label__ = "Collision Bounds"
def draw_header(self, context):
layout = self.layout
ob = context.active_object
game = ob.game
layout.itemR(game, "use_collision_bounds", text="")
def draw(self, context):
layout = self.layout
ob = context.scene.objects[0]
game = ob.game
flow = layout.column_flow()
flow.active = game.use_collision_bounds
flow.itemR(game, "collision_bounds")
flow.itemR(game, "collision_compound")
flow.itemR(game, "collision_margin")
bpy.types.register(LOGIC_PT_physics)
bpy.types.register(LOGIC_PT_collision_bounds)

View File

@@ -146,18 +146,20 @@ void blf_font_draw(FontBLF *font, char *str)
if (FT_Get_Kerning(font->face, g_prev_index, glyph_index, FT_KERNING_UNFITTED, &delta) == 0) {
pen_x += delta.x >> 6;
/*
if (pen_x < old_pen_x)
pen_x= old_pen_x;
*/
}
}
if (font->flags & BLF_USER_KERNING) {
old_pen_x= pen_x;
pen_x += font->kerning;
/*
if (pen_x < old_pen_x)
pen_x= old_pen_x;
*/
}
/* do not return this loop if clipped, we want every character tested */
@@ -226,18 +228,20 @@ void blf_font_boundbox(FontBLF *font, char *str, rctf *box)
if (FT_Get_Kerning(font->face, g_prev_index, glyph_index, FT_KERNING_UNFITTED, &delta) == 0) {
pen_x += delta.x >> 6;
/*
if (pen_x < old_pen_x)
old_pen_x= pen_x;
*/
}
}
if (font->flags & BLF_USER_KERNING) {
old_pen_x= pen_x;
pen_x += font->kerning;
/*
if (pen_x < old_pen_x)
old_pen_x= pen_x;
*/
}
gbox.xmin= g->box.xmin + pen_x;

View File

@@ -137,7 +137,7 @@ void framechange_poses_clear_unkeyed(void);
void what_does_obaction(struct Scene *scene, struct Object *ob, struct Object *workob, struct bPose *pose, struct bAction *act, char groupname[], float cframe);
/* exported for game engine */
void blend_poses(struct bPose *dst, struct bPose *src, float srcweight, short mode);
void game_blend_poses(struct bPose *dst, struct bPose *src, float srcweight/*, short mode*/); /* was blend_poses */
void extract_pose_from_pose(struct bPose *pose, const struct bPose *src);
/* for proxy */

View File

@@ -126,12 +126,14 @@ void CTX_wm_menu_set(bContext *C, struct ARegion *menu);
/* Data Context
- note: listbases consist of LinkData items and must be
freed with BLI_freelistN! */
- listbases consist of CollectionPointerLink items and must be
freed with BLI_freelistN!
- the dir listbase consits of LinkData items */
PointerRNA CTX_data_pointer_get(bContext *C, const char *member);
ListBase CTX_data_collection_get(bContext *C, const char *member);
void CTX_data_get(bContext *C, const char *member, PointerRNA *r_ptr, ListBase *r_lb);
PointerRNA CTX_data_pointer_get(const bContext *C, const char *member);
ListBase CTX_data_collection_get(const bContext *C, const char *member);
ListBase CTX_data_dir_get(const bContext *C);
void CTX_data_get(const bContext *C, const char *member, PointerRNA *r_ptr, ListBase *r_lb);
void CTX_data_id_pointer_set(bContextDataResult *result, struct ID *id);
void CTX_data_pointer_set(bContextDataResult *result, struct ID *id, StructRNA *type, void *data);
@@ -139,7 +141,10 @@ void CTX_data_pointer_set(bContextDataResult *result, struct ID *id, StructRNA *
void CTX_data_id_list_add(bContextDataResult *result, struct ID *id);
void CTX_data_list_add(bContextDataResult *result, struct ID *id, StructRNA *type, void *data);
void CTX_data_dir_set(bContextDataResult *result, const char **member);
int CTX_data_equals(const char *member, const char *str);
int CTX_data_dir(const char *member);
/*void CTX_data_pointer_set(bContextDataResult *result, void *data);
void CTX_data_list_add(bContextDataResult *result, void *data);*/

View File

@@ -36,6 +36,7 @@ struct Scene;
struct DagNodeQueue;
struct DagForest;
struct DagNode;
struct GHash;
/* **** DAG relation types *** */

View File

@@ -65,6 +65,7 @@ typedef struct DagNode
void * first_ancestor;
int ancestor_count;
int lay; // accumulated layers of its relations + itself
int scelay; // layers due to being in scene
int lasttime; // if lasttime != DagForest->time, this node was not evaluated yet for flushing
int BFS_dist; // BFS distance
int DFS_dist; // DFS distance
@@ -93,6 +94,7 @@ typedef struct DagNodeQueue
typedef struct DagForest
{
ListBase DagNode;
struct GHash *nodeHash;
int numNodes;
int is_acyclic;
int time; // for flushing/tagging, compare with node->lasttime

View File

@@ -581,6 +581,77 @@ void game_copy_pose(bPose **dst, bPose *src)
*dst=out;
}
/* Only allowed for Poses with identical channels */
void game_blend_poses(bPose *dst, bPose *src, float srcweight/*, short mode*/)
{
short mode= ACTSTRIPMODE_BLEND;
bPoseChannel *dchan;
const bPoseChannel *schan;
bConstraint *dcon, *scon;
float dstweight;
int i;
switch (mode){
case ACTSTRIPMODE_BLEND:
dstweight = 1.0F - srcweight;
break;
case ACTSTRIPMODE_ADD:
dstweight = 1.0F;
break;
default :
dstweight = 1.0F;
}
schan= src->chanbase.first;
for (dchan = dst->chanbase.first; dchan; dchan=dchan->next, schan= schan->next){
if (schan->flag & (POSE_ROT|POSE_LOC|POSE_SIZE)) {
/* replaced quat->matrix->quat conversion with decent quaternion interpol (ton) */
/* Do the transformation blend */
if (schan->flag & POSE_ROT) {
/* quat interpolation done separate */
if (schan->rotmode == PCHAN_ROT_QUAT) {
float dquat[4], squat[4];
QUATCOPY(dquat, dchan->quat);
QUATCOPY(squat, schan->quat);
if (mode==ACTSTRIPMODE_BLEND)
QuatInterpol(dchan->quat, dquat, squat, srcweight);
else {
QuatMulFac(squat, srcweight);
QuatMul(dchan->quat, dquat, squat);
}
NormalQuat(dchan->quat);
}
}
for (i=0; i<3; i++) {
/* blending for loc and scale are pretty self-explanatory... */
if (schan->flag & POSE_LOC)
dchan->loc[i] = (dchan->loc[i]*dstweight) + (schan->loc[i]*srcweight);
if (schan->flag & POSE_SIZE)
dchan->size[i] = 1.0f + ((dchan->size[i]-1.0f)*dstweight) + ((schan->size[i]-1.0f)*srcweight);
/* euler-rotation interpolation done here instead... */
// FIXME: are these results decent?
if ((schan->flag & POSE_ROT) && (schan->rotmode))
dchan->eul[i] = (dchan->eul[i]*dstweight) + (schan->eul[i]*srcweight);
}
dchan->flag |= schan->flag;
}
for(dcon= dchan->constraints.first, scon= schan->constraints.first; dcon && scon; dcon= dcon->next, scon= scon->next) {
/* no 'add' option for constraint blending */
dcon->enforce= dcon->enforce*(1.0f-srcweight) + scon->enforce*srcweight;
}
}
/* this pose is now in src time */
dst->ctime= src->ctime;
}
void game_free_pose(bPose *pose)
{
if (pose) {
@@ -1039,75 +1110,6 @@ static void blend_pose_offset_bone(bActionStrip *strip, bPose *dst, bPose *src,
VecAddf(dst->cyclic_offset, dst->cyclic_offset, src->cyclic_offset);
}
/* Only allowed for Poses with identical channels */
void blend_poses(bPose *dst, bPose *src, float srcweight, short mode)
{
bPoseChannel *dchan;
const bPoseChannel *schan;
bConstraint *dcon, *scon;
float dstweight;
int i;
switch (mode){
case ACTSTRIPMODE_BLEND:
dstweight = 1.0F - srcweight;
break;
case ACTSTRIPMODE_ADD:
dstweight = 1.0F;
break;
default :
dstweight = 1.0F;
}
schan= src->chanbase.first;
for (dchan = dst->chanbase.first; dchan; dchan=dchan->next, schan= schan->next){
if (schan->flag & (POSE_ROT|POSE_LOC|POSE_SIZE)) {
/* replaced quat->matrix->quat conversion with decent quaternion interpol (ton) */
/* Do the transformation blend */
if (schan->flag & POSE_ROT) {
/* quat interpolation done separate */
if (schan->rotmode == PCHAN_ROT_QUAT) {
float dquat[4], squat[4];
QUATCOPY(dquat, dchan->quat);
QUATCOPY(squat, schan->quat);
if (mode==ACTSTRIPMODE_BLEND)
QuatInterpol(dchan->quat, dquat, squat, srcweight);
else {
QuatMulFac(squat, srcweight);
QuatMul(dchan->quat, dquat, squat);
}
NormalQuat(dchan->quat);
}
}
for (i=0; i<3; i++) {
/* blending for loc and scale are pretty self-explanatory... */
if (schan->flag & POSE_LOC)
dchan->loc[i] = (dchan->loc[i]*dstweight) + (schan->loc[i]*srcweight);
if (schan->flag & POSE_SIZE)
dchan->size[i] = 1.0f + ((dchan->size[i]-1.0f)*dstweight) + ((schan->size[i]-1.0f)*srcweight);
/* euler-rotation interpolation done here instead... */
// FIXME: are these results decent?
if ((schan->flag & POSE_ROT) && (schan->rotmode))
dchan->eul[i] = (dchan->eul[i]*dstweight) + (schan->eul[i]*srcweight);
}
dchan->flag |= schan->flag;
}
for(dcon= dchan->constraints.first, scon= schan->constraints.first; dcon && scon; dcon= dcon->next, scon= scon->next) {
/* no 'add' option for constraint blending */
dcon->enforce= dcon->enforce*(1.0f-srcweight) + scon->enforce*srcweight;
}
}
/* this pose is now in src time */
dst->ctime= src->ctime;
}
typedef struct NlaIpoChannel {
struct NlaIpoChannel *next, *prev;
float val;

View File

@@ -280,6 +280,7 @@ void CTX_wm_menu_set(bContext *C, ARegion *menu)
struct bContextDataResult {
PointerRNA ptr;
ListBase list;
const char **dir;
};
static int ctx_data_get(bContext *C, const char *member, bContextDataResult *result)
@@ -360,7 +361,7 @@ static int ctx_data_collection_get(const bContext *C, const char *member, ListBa
return 0;
}
PointerRNA CTX_data_pointer_get(bContext *C, const char *member)
PointerRNA CTX_data_pointer_get(const bContext *C, const char *member)
{
bContextDataResult result;
@@ -375,7 +376,7 @@ PointerRNA CTX_data_pointer_get(bContext *C, const char *member)
}
ListBase CTX_data_collection_get(bContext *C, const char *member)
ListBase CTX_data_collection_get(const bContext *C, const char *member)
{
bContextDataResult result;
@@ -389,7 +390,7 @@ ListBase CTX_data_collection_get(bContext *C, const char *member)
}
}
void CTX_data_get(bContext *C, const char *member, PointerRNA *r_ptr, ListBase *r_lb)
void CTX_data_get(const bContext *C, const char *member, PointerRNA *r_ptr, ListBase *r_lb)
{
bContextDataResult result;
@@ -403,11 +404,75 @@ void CTX_data_get(bContext *C, const char *member, PointerRNA *r_ptr, ListBase *
}
}
static void data_dir_add(ListBase *lb, const char *member)
{
LinkData *link;
if(strcmp(member, "scene") == 0) /* exception */
return;
for(link=lb->first; link; link=link->next)
if(strcmp(link->data, member) == 0)
return;
link= MEM_callocN(sizeof(LinkData), "LinkData");
link->data= (void*)member;
BLI_addtail(lb, link);
}
ListBase CTX_data_dir_get(const bContext *C)
{
bContextDataResult result;
ListBase lb;
int a;
memset(&lb, 0, sizeof(lb));
if(C->wm.store) {
bContextStoreEntry *entry;
for(entry=C->wm.store->entries.first; entry; entry=entry->next)
data_dir_add(&lb, entry->name);
}
if(C->wm.region && C->wm.region->type && C->wm.region->type->context) {
memset(&result, 0, sizeof(result));
C->wm.region->type->context(C, "", &result);
if(result.dir)
for(a=0; result.dir[a]; a++)
data_dir_add(&lb, result.dir[a]);
}
if(C->wm.area && C->wm.area->type && C->wm.area->type->context) {
memset(&result, 0, sizeof(result));
C->wm.area->type->context(C, "", &result);
if(result.dir)
for(a=0; result.dir[a]; a++)
data_dir_add(&lb, result.dir[a]);
}
if(C->wm.screen && C->wm.screen->context) {
bContextDataCallback cb= C->wm.screen->context;
memset(&result, 0, sizeof(result));
cb(C, "", &result);
if(result.dir)
for(a=0; result.dir[a]; a++)
data_dir_add(&lb, result.dir[a]);
}
return lb;
}
int CTX_data_equals(const char *member, const char *str)
{
return (strcmp(member, str) == 0);
}
int CTX_data_dir(const char *member)
{
return (strcmp(member, "") == 0);
}
void CTX_data_id_pointer_set(bContextDataResult *result, ID *id)
{
RNA_id_pointer_create(id, &result->ptr);
@@ -451,6 +516,11 @@ int ctx_data_list_count(const bContext *C, int (*func)(const bContext*, ListBase
return 0;
}
void CTX_data_dir_set(bContextDataResult *result, const char **dir)
{
result->dir= dir;
}
/* data context */
Main *CTX_data_main(const bContext *C)

View File

@@ -61,6 +61,8 @@
#include "DNA_view2d_types.h"
#include "DNA_view3d_types.h"
#include "BLI_ghash.h"
#include "BKE_action.h"
#include "BKE_effect.h"
#include "BKE_global.h"
@@ -754,6 +756,9 @@ void free_forest(DagForest *Dag)
itN = itN->next;
MEM_freeN(tempN);
}
BLI_ghash_free(Dag->nodeHash, NULL, NULL);
Dag->nodeHash= NULL;
Dag->DagNode.first = NULL;
Dag->DagNode.last = NULL;
Dag->numNodes = 0;
@@ -762,13 +767,9 @@ void free_forest(DagForest *Dag)
DagNode * dag_find_node (DagForest *forest,void * fob)
{
DagNode *node = forest->DagNode.first;
while (node) {
if (node->ob == fob)
return node;
node = node->next;
}
if(forest->nodeHash)
return BLI_ghash_lookup(forest->nodeHash, fob);
return NULL;
}
@@ -794,7 +795,12 @@ DagNode * dag_add_node (DagForest *forest, void * fob)
forest->DagNode.first = node;
forest->numNodes = 1;
}
if(!forest->nodeHash)
forest->nodeHash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
BLI_ghash_insert(forest->nodeHash, fob, node);
}
return node;
}
@@ -1805,17 +1811,10 @@ static void flush_update_node(DagNode *node, unsigned int layer, int curtime)
/* node was checked to have lasttime != curtime , and is of type ID_OB */
static unsigned int flush_layer_node(Scene *sce, DagNode *node, int curtime)
{
Base *base;
DagAdjList *itA;
node->lasttime= curtime;
node->lay= 0;
for(base= sce->base.first; base; base= base->next) {
if(node->ob == base->object) {
node->lay= ((Object *)node->ob)->lay;
break;
}
}
node->lay= node->scelay;
for(itA = node->child; itA; itA= itA->next) {
if(itA->node->type==ID_OB) {
@@ -1860,9 +1859,10 @@ static void flush_pointcache_reset(DagNode *node, int curtime, int reset)
/* flushes all recalc flags in objects down the dependency tree */
void DAG_scene_flush_update(Scene *sce, unsigned int lay, int time)
{
DagNode *firstnode;
DagNode *firstnode, *node;
DagAdjList *itA;
Object *ob;
Base *base;
int lasttime;
if(sce->theDag==NULL) {
@@ -1879,6 +1879,15 @@ void DAG_scene_flush_update(Scene *sce, unsigned int lay, int time)
sce->theDag->time++; // so we know which nodes were accessed
lasttime= sce->theDag->time;
for(base= sce->base.first; base; base= base->next) {
node= dag_get_node(sce->theDag, base->object);
if(node)
node->scelay= base->object->lay;
else
node->scelay= 0;
}
for(itA = firstnode->child; itA; itA= itA->next)
if(itA->node->lasttime!=lasttime && itA->node->type==ID_OB)
flush_layer_node(sce, itA->node, lasttime);

View File

@@ -235,17 +235,15 @@ static char *ob_adrcodes_to_paths (int adrcode, int *array_index)
*array_index= 1; return "delta_scale";
case OB_DSIZE_Z:
*array_index= 2; return "delta_scale";
#if 0
case OB_COL_R:
poin= &(ob->col[0]); break;
case OB_COL_R:
*array_index= 0; return "color";
case OB_COL_G:
poin= &(ob->col[1]); break;
*array_index= 1; return "color";
case OB_COL_B:
poin= &(ob->col[2]); break;
*array_index= 2; return "color";
case OB_COL_A:
poin= &(ob->col[3]); break;
*array_index= 3; return "color";
#if 0
case OB_PD_FSTR:
if (ob->pd) poin= &(ob->pd->f_strength);
break;
@@ -1515,14 +1513,7 @@ void do_versions_ipos_to_animato(Main *main)
/* Add AnimData block */
adt= BKE_id_add_animdata(id);
/* IPO first */
if (ob->ipo) {
ipo_to_animdata(id, ob->ipo, NULL, NULL);
ob->ipo->id.us--;
ob->ipo= NULL;
}
/* now Action */
/* Action first - so that Action name get conserved */
if (ob->action) {
action_to_animdata(id, ob->action);
@@ -1533,6 +1524,13 @@ void do_versions_ipos_to_animato(Main *main)
}
}
/* IPO second... */
if (ob->ipo) {
ipo_to_animdata(id, ob->ipo, NULL, NULL);
ob->ipo->id.us--;
ob->ipo= NULL;
}
/* finally NLA */
// XXX todo... for now, new NLA code not hooked up yet, so keep old stuff (but not for too long!)
}

View File

@@ -92,7 +92,7 @@ void BLI_dynstr_vappendf(DynStr *ds, const char *format, va_list args)
if(len == sizeof(fixedmessage))
message= fixedmessage;
else
message= MEM_callocN(sizeof(char)*len+1, "BLI_dynstr_appendf");
message= MEM_callocN(sizeof(char)*(len+1), "BLI_dynstr_appendf");
retval= vsnprintf(message, len, format, args);
@@ -132,10 +132,54 @@ void BLI_dynstr_vappendf(DynStr *ds, const char *format, va_list args)
void BLI_dynstr_appendf(DynStr *ds, const char *format, ...)
{
va_list args;
char *message, fixedmessage[256];
int len= 256, maxlen= 65536, retval;
va_start(args, format);
BLI_dynstr_vappendf(ds, format, args);
va_end(args);
/* note that it's tempting to just call BLI_dynstr_vappendf here
* and avoid code duplication, that crashes on some system because
* va_start/va_end have to be called for each vsnprintf call */
while(1) {
if(len == sizeof(fixedmessage))
message= fixedmessage;
else
message= MEM_callocN(sizeof(char)*(len+1), "BLI_dynstr_appendf");
va_start(args, format);
retval= vsnprintf(message, len, format, args);
va_end(args);
if(retval == -1) {
/* -1 means not enough space, but on windows it may also mean
* there is a formatting error, so we impose a maximum length */
if(message != fixedmessage)
MEM_freeN(message);
message= NULL;
len *= 2;
if(len > maxlen) {
fprintf(stderr, "BLI_dynstr_append text too long or format error.\n");
break;
}
}
else if(retval > len) {
/* in C99 the actual length required is returned */
if(message != fixedmessage)
MEM_freeN(message);
message= NULL;
len= retval;
}
else
break;
}
if(message) {
BLI_dynstr_append(ds, message);
if(message != fixedmessage)
MEM_freeN(message);
}
}
int BLI_dynstr_get_len(DynStr *ds) {

View File

@@ -70,6 +70,7 @@
#define PNL_WAS_ACTIVE 4
#define PNL_ANIM_ALIGN 8
#define PNL_NEW_ADDED 16
#define PNL_FIRST 32
typedef enum uiHandlePanelState {
PANEL_STATE_DRAG,
@@ -528,7 +529,7 @@ static void rectf_scale(rctf *rect, float scale)
/* panel integrated in buttonswindow, tool/property lists etc */
void ui_draw_aligned_panel(ARegion *ar, uiStyle *style, uiBlock *block, rcti *rect)
{
Panel *panel= block->panel, *prev;
Panel *panel= block->panel;
rcti headrect;
rctf itemrect;
int ofsx;
@@ -541,14 +542,7 @@ void ui_draw_aligned_panel(ARegion *ar, uiStyle *style, uiBlock *block, rcti *re
headrect.ymin= headrect.ymax;
headrect.ymax= headrect.ymin + floor(PNL_HEADER/block->aspect + 0.001f);
/* divider only when there's a previous panel */
prev= panel->prev;
while(prev) {
if(prev->runtime_flag & PNL_ACTIVE) break;
prev= prev->prev;
}
if(panel->sortorder != 0) {
if(!(panel->runtime_flag & PNL_FIRST)) {
float minx= rect->xmin+5.0f/block->aspect;
float maxx= rect->xmax-5.0f/block->aspect;
float y= headrect.ymax;
@@ -848,7 +842,7 @@ void uiEndPanels(const bContext *C, ARegion *ar)
{
ScrArea *sa= CTX_wm_area(C);
uiBlock *block;
Panel *panot, *panew, *patest, *pa;
Panel *panot, *panew, *patest, *pa, *firstpa;
/* offset contents */
for(block= ar->uiblocks.first; block; block= block->next)
@@ -888,6 +882,16 @@ void uiEndPanels(const bContext *C, ARegion *ar)
uiAlignPanelStep(sa, ar, 1.0, 0);
}
/* tag first panel */
firstpa= NULL;
for(block= ar->uiblocks.first; block; block=block->next)
if(block->active && block->panel)
if(!firstpa || block->panel->sortorder < firstpa->sortorder)
firstpa= block->panel;
if(firstpa)
firstpa->runtime_flag |= PNL_FIRST;
/* draw panels, selected on top */
for(block= ar->uiblocks.first; block; block=block->next) {
if(block->active && block->panel && !(block->panel->flag & PNL_SELECT)) {

View File

@@ -1876,7 +1876,9 @@ static void widget_disabled(rcti *rect)
/* can't use theme TH_BACK or TH_PANEL... undefined */
glGetFloatv(GL_COLOR_CLEAR_VALUE, col);
glColor4f(col[0], col[1], col[2], 0.5f);
glRectf(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
/* need -1 and +1 to make it work right for aligned buttons,
* but problem may be somewhere else? */
glRectf(rect->xmin-1, rect->ymin, rect->xmax, rect->ymax+1);
glDisable(GL_BLEND);
}

View File

@@ -42,7 +42,15 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
Scene *scene= sc->scene;
Base *base;
if(CTX_data_equals(member, "scene")) {
if(CTX_data_dir(member)) {
static const char *dir[] = {
"scene", "selected_objects", "selected_bases", "active_base",
"active_object", "edit_object", NULL};
CTX_data_dir_set(result, dir);
return 1;
}
else if(CTX_data_equals(member, "scene")) {
CTX_data_id_pointer_set(result, &scene->id);
return 1;
}

View File

@@ -234,6 +234,9 @@ static char brush_size(Sculpt *sd)
special multiplier found experimentally to scale the strength factor. */
static float brush_strength(Sculpt *sd, StrokeCache *cache)
{
/* Primary strength input; square it to make lower values more sensitive */
float alpha = sd->brush->alpha * sd->brush->alpha;
float dir= sd->brush->flag & BRUSH_DIR_IN ? -1 : 1;
float pressure= 1;
float flip= cache->flip ? -1:1;
@@ -244,18 +247,17 @@ static float brush_strength(Sculpt *sd, StrokeCache *cache)
switch(sd->brush->sculpt_tool){
case SCULPT_TOOL_DRAW:
case SCULPT_TOOL_LAYER:
return sd->brush->alpha / 50.0f * dir * pressure * flip * anchored; /*XXX: not sure why? multiplied by G.vd->grid */;
case SCULPT_TOOL_INFLATE:
return alpha * dir * pressure * flip; /*XXX: not sure why? was multiplied by G.vd->grid */;
case SCULPT_TOOL_FLATTEN:
case SCULPT_TOOL_SMOOTH:
return sd->brush->alpha / .5 * pressure * anchored;
return alpha * 4 * pressure;
case SCULPT_TOOL_PINCH:
return sd->brush->alpha / 10.0f * dir * pressure * flip * anchored;
return alpha / 2 * dir * pressure * flip;
case SCULPT_TOOL_GRAB:
return 1;
case SCULPT_TOOL_INFLATE:
return sd->brush->alpha / 50.0f * dir * pressure * flip * anchored;
case SCULPT_TOOL_FLATTEN:
return sd->brush->alpha / 5.0f * pressure * anchored;
case SCULPT_TOOL_LAYER:
return sd->brush->alpha / 50.0f * dir * pressure * flip * anchored; /*XXX: not sure why? multiplied by G.vd->grid */;
default:
return 0;
}
@@ -354,10 +356,10 @@ static void do_draw_brush(Sculpt *sd, SculptSession *ss, const ListBase* active_
while(node){
float *co= ss->mvert[node->Index].co;
const float val[3]= {co[0]+area_normal[0]*node->Fade*ss->cache->scale[0],
co[1]+area_normal[1]*node->Fade*ss->cache->scale[1],
co[2]+area_normal[2]*node->Fade*ss->cache->scale[2]};
const float val[3]= {co[0]+area_normal[0]*ss->cache->radius*node->Fade*ss->cache->scale[0],
co[1]+area_normal[1]*ss->cache->radius*node->Fade*ss->cache->scale[1],
co[2]+area_normal[2]*ss->cache->radius*node->Fade*ss->cache->scale[2]};
sculpt_clip(ss->cache, co, val);
@@ -412,18 +414,21 @@ static void neighbor_average(SculptSession *ss, float avg[3], const int vert)
static void do_smooth_brush(SculptSession *ss, const ListBase* active_verts)
{
ActiveData *node= active_verts->first;
while(node){
float *co= ss->mvert[node->Index].co;
float avg[3], val[3];
neighbor_average(ss, avg, node->Index);
val[0] = co[0]+(avg[0]-co[0])*node->Fade;
val[1] = co[1]+(avg[1]-co[1])*node->Fade;
val[2] = co[2]+(avg[2]-co[2])*node->Fade;
sculpt_clip(ss->cache, co, val);
node= node->next;
int i;
for(i = 0; i < 2; ++i) {
while(node){
float *co= ss->mvert[node->Index].co;
float avg[3], val[3];
neighbor_average(ss, avg, node->Index);
val[0] = co[0]+(avg[0]-co[0])*node->Fade;
val[1] = co[1]+(avg[1]-co[1])*node->Fade;
val[2] = co[2]+(avg[2]-co[2])*node->Fade;
sculpt_clip(ss->cache, co, val);
node= node->next;
}
}
}
@@ -467,33 +472,33 @@ static void do_layer_brush(Sculpt *sd, SculptSession *ss, const ListBase *active
{
float area_normal[3];
ActiveData *node= active_verts->first;
const float bstr= brush_strength(sd, ss->cache);
float lim= brush_strength(sd, ss->cache);
if(sd->brush->flag & BRUSH_DIR_IN)
lim = -lim;
calc_area_normal(sd, area_normal, active_verts);
while(node){
float *disp= &ss->cache->layer_disps[node->Index];
if((bstr > 0 && *disp < bstr) ||
(bstr < 0 && *disp > bstr)) {
if((lim > 0 && *disp < lim) ||
(lim < 0 && *disp > lim)) {
float *co= ss->mvert[node->Index].co;
float val[3];
*disp+= node->Fade;
if(bstr < 0) {
if(*disp < bstr)
*disp = bstr;
} else {
if(*disp > bstr)
*disp = bstr;
}
if(lim < 0 && *disp < lim)
*disp = lim;
else if(lim > 0 && *disp > lim)
*disp = lim;
{
const float val[3]= {ss->cache->mesh_store[node->Index][0]+area_normal[0] * *disp*ss->cache->scale[0],
ss->cache->mesh_store[node->Index][1]+area_normal[1] * *disp*ss->cache->scale[1],
ss->cache->mesh_store[node->Index][2]+area_normal[2] * *disp*ss->cache->scale[2]};
sculpt_clip(ss->cache, co, val);
}
val[0] = ss->cache->mesh_store[node->Index][0]+area_normal[0] * *disp*ss->cache->scale[0];
val[1] = ss->cache->mesh_store[node->Index][1]+area_normal[1] * *disp*ss->cache->scale[1];
val[2] = ss->cache->mesh_store[node->Index][2]+area_normal[2] * *disp*ss->cache->scale[2];
//VecMulf(val, ss->cache->radius);
sculpt_clip(ss->cache, co, val);
}
node= node->next;
@@ -512,7 +517,7 @@ static void do_inflate_brush(SculptSession *ss, const ListBase *active_verts)
add[0]= no[0]/ 32767.0f;
add[1]= no[1]/ 32767.0f;
add[2]= no[2]/ 32767.0f;
VecMulf(add, node->Fade);
VecMulf(add, node->Fade * ss->cache->radius);
add[0]*= ss->cache->scale[0];
add[1]*= ss->cache->scale[1];
add[2]*= ss->cache->scale[2];

View File

@@ -54,6 +54,7 @@
#include "RNA_access.h"
#include "ED_armature.h"
#include "ED_screen.h"
#include "UI_interface.h"
@@ -249,16 +250,29 @@ static int buttons_context_path_bone(ButsContextPath *path)
{
bArmature *arm;
Bone *bone;
EditBone *edbo;
/* if we have an armature, get the active bone */
if(buttons_context_path_data(path, OB_ARMATURE)) {
arm= path->ptr[path->len-1].data;
bone= find_active_bone(arm->bonebase.first);
if(bone) {
RNA_pointer_create(&arm->id, &RNA_Bone, bone, &path->ptr[path->len]);
path->len++;
return 1;
if(arm->edbo) {
for(edbo=arm->edbo->first; edbo; edbo=edbo->next) {
if(edbo->flag & BONE_ACTIVE) {
RNA_pointer_create(&arm->id, &RNA_EditBone, edbo, &path->ptr[path->len]);
path->len++;
return 1;
}
}
}
else {
bone= find_active_bone(arm->bonebase.first);
if(bone) {
RNA_pointer_create(&arm->id, &RNA_Bone, bone, &path->ptr[path->len]);
path->len++;
return 1;
}
}
}
@@ -478,8 +492,17 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r
return 0;
/* here we handle context, getting data from precomputed path */
if(CTX_data_dir(member)) {
static const char *dir[] = {
"world", "object", "meshe", "armature", "lattice", "curve",
"meta_ball", "lamp", "camera", "material", "material_slot",
"texture", "texture_slot", "bone", "edit_bone", "particle_system",
"cloth", "soft_body", "fluid", NULL};
if(CTX_data_equals(member, "world")) {
CTX_data_dir_set(result, dir);
return 1;
}
else if(CTX_data_equals(member, "world")) {
set_pointer_type(path, result, &RNA_World);
return 1;
}
@@ -569,6 +592,10 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r
set_pointer_type(path, result, &RNA_Bone);
return 1;
}
else if(CTX_data_equals(member, "edit_bone")) {
set_pointer_type(path, result, &RNA_EditBone);
return 1;
}
else if(CTX_data_equals(member, "particle_system")) {
set_pointer_type(path, result, &RNA_ParticleSystem);
return 1;

View File

@@ -301,7 +301,11 @@ static int image_context(const bContext *C, const char *member, bContextDataResu
{
SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
if(CTX_data_equals(member, "edit_image")) {
if(CTX_data_dir(member)) {
static const char *dir[] = {"edit_image", NULL};
CTX_data_dir_set(result, dir);
}
else if(CTX_data_equals(member, "edit_image")) {
CTX_data_id_pointer_set(result, (ID*)ED_space_image(sima));
return 1;
}

View File

@@ -283,7 +283,12 @@ static int node_context(const bContext *C, const char *member, bContextDataResul
{
SpaceNode *snode= (SpaceNode*)CTX_wm_space_data(C);
if(CTX_data_equals(member, "selected_nodes")) {
if(CTX_data_dir(member)) {
static const char *dir[] = {"selected_nodes", NULL};
CTX_data_dir_set(result, dir);
return 1;
}
else if(CTX_data_equals(member, "selected_nodes")) {
bNode *node;
for(next_node(snode->edittree); (node=next_node(NULL));) {

View File

@@ -293,7 +293,12 @@ static int text_context(const bContext *C, const char *member, bContextDataResul
{
SpaceText *st= CTX_wm_space_text(C);
if(CTX_data_equals(member, "edit_text")) {
if(CTX_data_dir(member)) {
static const char *dir[] = {"edit_text", NULL};
CTX_data_dir_set(result, dir);
return 1;
}
else if(CTX_data_equals(member, "edit_text")) {
CTX_data_id_pointer_set(result, &st->text->id);
return 1;
}

View File

@@ -565,7 +565,17 @@ static int view3d_context(const bContext *C, const char *member, bContextDataRes
if(v3d==NULL) return 0;
if(CTX_data_equals(member, "selected_objects") || CTX_data_equals(member, "selected_bases")) {
if(CTX_data_dir(member)) {
static const char *dir[] = {
"selected_objects", "selected_bases" "selected_editable_objects",
"selected_editable_bases" "visible_objects", "visible_bases",
"active_base", "active_object", "visible_bones", "editable_bones",
"selected_bones", "selected_editable_bones" "visible_pchans",
"selected_pchans", "active_bone", "active_pchan", NULL};
CTX_data_dir_set(result, dir);
}
else if(CTX_data_equals(member, "selected_objects") || CTX_data_equals(member, "selected_bases")) {
int selected_objects= CTX_data_equals(member, "selected_objects");
for(base=scene->base.first; base; base=base->next) {

View File

@@ -164,6 +164,7 @@ extern StructRNA RNA_DomainFluidSettings;
extern StructRNA RNA_Driver;
extern StructRNA RNA_DriverTarget;
extern StructRNA RNA_EdgeSplitModifier;
extern StructRNA RNA_EditBone;
extern StructRNA RNA_EffectSequence;
extern StructRNA RNA_EnumProperty;
extern StructRNA RNA_EnumPropertyItem;

View File

@@ -42,6 +42,8 @@ extern "C" {
BlenderRNA *RNA_create(void);
void RNA_define_free(BlenderRNA *brna);
void RNA_free(BlenderRNA *brna);
void RNA_init(void);
void RNA_exit(void);
/* Struct */

View File

@@ -702,8 +702,10 @@ static char *rna_def_property_begin_func(FILE *f, StructRNA *srna, PropertyRNA *
else {
if(manualfunc)
fprintf(f, "\n %s(iter, ptr);\n", manualfunc);
else
else if(dp->dnapointerlevel == 0)
fprintf(f, "\n rna_iterator_listbase_begin(iter, &data->%s, NULL);\n", dp->dnaname);
else
fprintf(f, "\n rna_iterator_listbase_begin(iter, data->%s, NULL);\n", dp->dnaname);
}
getfunc= rna_alloc_function_name(srna->identifier, prop->identifier, "get");
@@ -1486,8 +1488,8 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr
if(nest != NULL) {
len= strlen(nest);
strnest= MEM_mallocN(sizeof(char)*(len+1), "rna_generate_property -> strnest");
errnest= MEM_mallocN(sizeof(char)*(len+1), "rna_generate_property -> errnest");
strnest= MEM_mallocN(sizeof(char)*(len+2), "rna_generate_property -> strnest");
errnest= MEM_mallocN(sizeof(char)*(len+2), "rna_generate_property -> errnest");
strcpy(strnest, "_"); strcat(strnest, nest);
strcpy(errnest, "."); strcat(errnest, nest);
@@ -1711,6 +1713,8 @@ static void rna_generate_struct(BlenderRNA *brna, StructRNA *srna, FILE *f)
if(func->cont.prev) fprintf(f, "(FunctionRNA*)&rna_%s_%s_func,\n", srna->identifier, ((FunctionRNA*)func->cont.prev)->identifier);
else fprintf(f, "NULL,\n");
fprintf(f, "\tNULL,\n");
parm= func->cont.properties.first;
if(parm) fprintf(f, "\t{(PropertyRNA*)&rna_%s_%s_%s, ", srna->identifier, func->identifier, parm->identifier);
else fprintf(f, "\t{NULL, ");
@@ -1742,6 +1746,8 @@ static void rna_generate_struct(BlenderRNA *brna, StructRNA *srna, FILE *f)
if(srna->cont.prev) fprintf(f, "(ContainerRNA *)&RNA_%s,\n", ((StructRNA*)srna->cont.prev)->identifier);
else fprintf(f, "NULL,\n");
fprintf(f, "\tNULL,\n");
prop= srna->cont.properties.first;
if(prop) fprintf(f, "\t{(PropertyRNA*)&rna_%s_%s, ", srna->identifier, prop->identifier);
else fprintf(f, "\t{NULL, ");

View File

@@ -218,7 +218,6 @@ static void rna_def_ID(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
FunctionRNA *func;
srna= RNA_def_struct(brna, "ID", NULL);
RNA_def_struct_ui_text(srna, "ID", "Base type for datablocks, defining a unique name, linking from other libraries and garbage collection.");

View File

@@ -32,6 +32,7 @@
#include "BLI_blenlib.h"
#include "BLI_dynstr.h"
#include "BLI_ghash.h"
#include "BKE_context.h"
#include "BKE_idprop.h"
@@ -46,10 +47,35 @@
#include "rna_internal.h"
/* Exit */
/* Init/Exit */
void RNA_init()
{
StructRNA *srna;
PropertyRNA *prop;
for(srna=BLENDER_RNA.structs.first; srna; srna=srna->cont.next) {
if(!srna->cont.prophash) {
srna->cont.prophash= BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp);
for(prop=srna->cont.properties.first; prop; prop=prop->next)
if(!(prop->flag & PROP_BUILTIN))
BLI_ghash_insert(srna->cont.prophash, (void*)prop->identifier, prop);
}
}
}
void RNA_exit()
{
StructRNA *srna;
for(srna=BLENDER_RNA.structs.first; srna; srna=srna->cont.next) {
if(srna->cont.prophash) {
BLI_ghash_free(srna->cont.prophash, NULL, NULL);
srna->cont.prophash= NULL;
}
}
RNA_free(&BLENDER_RNA);
}
@@ -388,24 +414,13 @@ int RNA_struct_is_a(StructRNA *type, StructRNA *srna)
PropertyRNA *RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
{
CollectionPropertyIterator iter;
PropertyRNA *iterprop, *prop;
int i = 0;
PropertyRNA *iterprop= RNA_struct_iterator_property(ptr->type);
PointerRNA propptr;
iterprop= RNA_struct_iterator_property(ptr->type);
RNA_property_collection_begin(ptr, iterprop, &iter);
prop= NULL;
for(; iter.valid; RNA_property_collection_next(&iter), i++) {
if(strcmp(identifier, RNA_property_identifier(iter.ptr.data)) == 0) {
prop= iter.ptr.data;
break;
}
}
RNA_property_collection_end(&iter);
return prop;
if(RNA_property_collection_lookup_string(ptr, iterprop, identifier, &propptr))
return propptr.data;
return NULL;
}
/* Find the property which uses the given nested struct */
@@ -1500,7 +1515,7 @@ void rna_iterator_listbase_begin(CollectionPropertyIterator *iter, ListBase *lb,
ListBaseIterator *internal;
internal= MEM_callocN(sizeof(ListBaseIterator), "ListBaseIterator");
internal->link= lb->first;
internal->link= (lb)? lb->first: NULL;
internal->skip= skip;
iter->internal= internal;
@@ -1643,12 +1658,18 @@ static char *rna_path_token(const char **path, char *fixedbuf, int fixedlen, int
buf= MEM_callocN(sizeof(char)*(len+1), "rna_path_token");
/* copy string, taking into account escaped ] */
for(p=*path, i=0, j=0; i<len; i++, p++) {
if(*p == '\\' && *(p+1) == ']');
else buf[j++]= *p;
}
if(bracket) {
for(p=*path, i=0, j=0; i<len; i++, p++) {
if(*p == '\\' && *(p+1) == ']');
else buf[j++]= *p;
}
buf[j]= 0;
buf[j]= 0;
}
else {
memcpy(buf, *path, sizeof(char)*len);
buf[len]= '\0';
}
/* set path to start of next token */
if(*p == ']') p++;
@@ -1660,8 +1681,7 @@ static char *rna_path_token(const char **path, char *fixedbuf, int fixedlen, int
int RNA_path_resolve(PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop)
{
CollectionPropertyIterator iter;
PropertyRNA *prop, *iterprop;
PropertyRNA *prop;
PointerRNA curptr, nextptr;
char fixedbuf[256], *token;
int len, intkey;
@@ -1676,18 +1696,7 @@ int RNA_path_resolve(PointerRNA *ptr, const char *path, PointerRNA *r_ptr, Prope
if(!token)
return 0;
iterprop= RNA_struct_iterator_property(curptr.type);
RNA_property_collection_begin(&curptr, iterprop, &iter);
prop= NULL;
for(; iter.valid; RNA_property_collection_next(&iter)) {
if(strcmp(token, RNA_property_identifier(iter.ptr.data)) == 0) {
prop= iter.ptr.data;
break;
}
}
RNA_property_collection_end(&iter);
prop= RNA_struct_find_property(&curptr, token);
if(token != fixedbuf)
MEM_freeN(token);

View File

@@ -36,25 +36,32 @@
#ifdef RNA_RUNTIME
static void rna_Bone_layer_set(PointerRNA *ptr, const int *values)
#include "ED_armature.h"
static void rna_bone_layer_set(short *layer, const int *values)
{
Bone *bone= (Bone*)ptr->data;
int i, tot= 0;
/* ensure we always have some layer selected */
for(i=0; i<20; i++)
for(i=0; i<16; i++)
if(values[i])
tot++;
if(tot==0)
return;
for(i=0; i<20; i++) {
if(values[i]) bone->layer |= (1<<i);
else bone->layer &= ~(1<<i);
for(i=0; i<16; i++) {
if(values[i]) *layer |= (1<<i);
else *layer &= ~(1<<i);
}
}
static void rna_Bone_layer_set(PointerRNA *ptr, const int *values)
{
Bone *bone= (Bone*)ptr->data;
rna_bone_layer_set(&bone->layer, values);
}
static void rna_Armature_layer_set(PointerRNA *ptr, const int *values)
{
bArmature *arm= (bArmature*)ptr->data;
@@ -102,8 +109,449 @@ static void rna_Armature_path_end_frame_set(PointerRNA *ptr, int value)
data->pathef= value;
}
PointerRNA rna_EditBone_rna_type_get(PointerRNA *ptr)
{
return rna_builtin_type_get(ptr);
}
void rna_EditBone_name_get(PointerRNA *ptr, char *value)
{
EditBone *data= (EditBone*)(ptr->data);
BLI_strncpy(value, data->name, sizeof(data->name));
}
int rna_EditBone_name_length(PointerRNA *ptr)
{
EditBone *data= (EditBone*)(ptr->data);
return strlen(data->name);
}
int rna_EditBone_active_get(PointerRNA *ptr)
{
EditBone *data= (EditBone*)(ptr->data);
return (((data->flag) & BONE_ACTIVE) != 0);
}
void rna_EditBone_active_set(PointerRNA *ptr, int value)
{
EditBone *data= (EditBone*)(ptr->data);
if(value) data->flag |= BONE_ACTIVE;
else data->flag &= ~BONE_ACTIVE;
}
float rna_EditBone_bbone_in_get(PointerRNA *ptr)
{
EditBone *data= (EditBone*)(ptr->data);
return (float)(data->ease1);
}
void rna_EditBone_bbone_in_set(PointerRNA *ptr, float value)
{
EditBone *data= (EditBone*)(ptr->data);
data->ease1= CLAMPIS(value, 0.0f, 2.0f);
}
float rna_EditBone_bbone_out_get(PointerRNA *ptr)
{
EditBone *data= (EditBone*)(ptr->data);
return (float)(data->ease2);
}
void rna_EditBone_bbone_out_set(PointerRNA *ptr, float value)
{
EditBone *data= (EditBone*)(ptr->data);
data->ease2= CLAMPIS(value, 0.0f, 2.0f);
}
int rna_EditBone_bbone_segments_get(PointerRNA *ptr)
{
EditBone *data= (EditBone*)(ptr->data);
return (int)(data->segments);
}
void rna_EditBone_bbone_segments_set(PointerRNA *ptr, int value)
{
EditBone *data= (EditBone*)(ptr->data);
data->segments= CLAMPIS(value, 1, 32);
}
void rna_EditBone_layer_get(PointerRNA *ptr, int values[16])
{
EditBone *data= (EditBone*)(ptr->data);
values[0]= ((data->layer & (1<<0)) != 0);
values[1]= ((data->layer & (1<<1)) != 0);
values[2]= ((data->layer & (1<<2)) != 0);
values[3]= ((data->layer & (1<<3)) != 0);
values[4]= ((data->layer & (1<<4)) != 0);
values[5]= ((data->layer & (1<<5)) != 0);
values[6]= ((data->layer & (1<<6)) != 0);
values[7]= ((data->layer & (1<<7)) != 0);
values[8]= ((data->layer & (1<<8)) != 0);
values[9]= ((data->layer & (1<<9)) != 0);
values[10]= ((data->layer & (1<<10)) != 0);
values[11]= ((data->layer & (1<<11)) != 0);
values[12]= ((data->layer & (1<<12)) != 0);
values[13]= ((data->layer & (1<<13)) != 0);
values[14]= ((data->layer & (1<<14)) != 0);
values[15]= ((data->layer & (1<<15)) != 0);
}
void rna_EditBone_layer_set(PointerRNA *ptr, const int values[16])
{
EditBone *data= (EditBone*)(ptr->data);
rna_bone_layer_set(&data->layer, values);
}
int rna_EditBone_connected_get(PointerRNA *ptr)
{
EditBone *data= (EditBone*)(ptr->data);
return (((data->flag) & BONE_CONNECTED) != 0);
}
void rna_EditBone_connected_set(PointerRNA *ptr, int value)
{
EditBone *data= (EditBone*)(ptr->data);
if(value) data->flag |= BONE_CONNECTED;
else data->flag &= ~BONE_CONNECTED;
}
int rna_EditBone_cyclic_offset_get(PointerRNA *ptr)
{
EditBone *data= (EditBone*)(ptr->data);
return (!((data->flag) & BONE_NO_CYCLICOFFSET) != 0);
}
void rna_EditBone_cyclic_offset_set(PointerRNA *ptr, int value)
{
EditBone *data= (EditBone*)(ptr->data);
if(!value) data->flag |= BONE_NO_CYCLICOFFSET;
else data->flag &= ~BONE_NO_CYCLICOFFSET;
}
int rna_EditBone_deform_get(PointerRNA *ptr)
{
EditBone *data= (EditBone*)(ptr->data);
return (!((data->flag) & BONE_NO_DEFORM) != 0);
}
void rna_EditBone_deform_set(PointerRNA *ptr, int value)
{
EditBone *data= (EditBone*)(ptr->data);
if(!value) data->flag |= BONE_NO_DEFORM;
else data->flag &= ~BONE_NO_DEFORM;
}
int rna_EditBone_draw_wire_get(PointerRNA *ptr)
{
EditBone *data= (EditBone*)(ptr->data);
return (((data->flag) & BONE_DRAWWIRE) != 0);
}
void rna_EditBone_draw_wire_set(PointerRNA *ptr, int value)
{
EditBone *data= (EditBone*)(ptr->data);
if(value) data->flag |= BONE_DRAWWIRE;
else data->flag &= ~BONE_DRAWWIRE;
}
float rna_EditBone_envelope_distance_get(PointerRNA *ptr)
{
EditBone *data= (EditBone*)(ptr->data);
return (float)(data->dist);
}
void rna_EditBone_envelope_distance_set(PointerRNA *ptr, float value)
{
EditBone *data= (EditBone*)(ptr->data);
data->dist= CLAMPIS(value, 0.0f, 1000.0f);
}
float rna_EditBone_envelope_weight_get(PointerRNA *ptr)
{
EditBone *data= (EditBone*)(ptr->data);
return (float)(data->weight);
}
void rna_EditBone_envelope_weight_set(PointerRNA *ptr, float value)
{
EditBone *data= (EditBone*)(ptr->data);
data->weight= CLAMPIS(value, 0.0f, 1000.0f);
}
float rna_EditBone_radius_head_get(PointerRNA *ptr)
{
EditBone *data= (EditBone*)(ptr->data);
return (float)(data->rad_head);
}
void rna_EditBone_radius_head_set(PointerRNA *ptr, float value)
{
EditBone *data= (EditBone*)(ptr->data);
data->rad_head= value;
}
float rna_EditBone_radius_tail_get(PointerRNA *ptr)
{
EditBone *data= (EditBone*)(ptr->data);
return (float)(data->rad_tail);
}
void rna_EditBone_radius_tail_set(PointerRNA *ptr, float value)
{
EditBone *data= (EditBone*)(ptr->data);
data->rad_tail= value;
}
void rna_EditBone_head_get(PointerRNA *ptr, float values[3])
{
EditBone *data= (EditBone*)(ptr->data);
values[0]= (float)(((float*)data->head)[0]);
values[1]= (float)(((float*)data->head)[1]);
values[2]= (float)(((float*)data->head)[2]);
}
void rna_EditBone_head_set(PointerRNA *ptr, const float values[3])
{
EditBone *data= (EditBone*)(ptr->data);
((float*)data->head)[0]= values[0];
((float*)data->head)[1]= values[1];
((float*)data->head)[2]= values[2];
}
int rna_EditBone_head_selected_get(PointerRNA *ptr)
{
EditBone *data= (EditBone*)(ptr->data);
return (((data->flag) & BONE_ROOTSEL) != 0);
}
void rna_EditBone_head_selected_set(PointerRNA *ptr, int value)
{
EditBone *data= (EditBone*)(ptr->data);
if(value) data->flag |= BONE_ROOTSEL;
else data->flag &= ~BONE_ROOTSEL;
}
int rna_EditBone_hidden_get(PointerRNA *ptr)
{
EditBone *data= (EditBone*)(ptr->data);
return (((data->flag) & BONE_HIDDEN_A) != 0);
}
void rna_EditBone_hidden_set(PointerRNA *ptr, int value)
{
EditBone *data= (EditBone*)(ptr->data);
if(value) data->flag |= BONE_HIDDEN_A;
else data->flag &= ~BONE_HIDDEN_A;
}
int rna_EditBone_hinge_get(PointerRNA *ptr)
{
EditBone *data= (EditBone*)(ptr->data);
return (!((data->flag) & BONE_HINGE) != 0);
}
void rna_EditBone_hinge_set(PointerRNA *ptr, int value)
{
EditBone *data= (EditBone*)(ptr->data);
if(!value) data->flag |= BONE_HINGE;
else data->flag &= ~BONE_HINGE;
}
int rna_EditBone_inherit_scale_get(PointerRNA *ptr)
{
EditBone *data= (EditBone*)(ptr->data);
return (!((data->flag) & BONE_NO_SCALE) != 0);
}
void rna_EditBone_inherit_scale_set(PointerRNA *ptr, int value)
{
EditBone *data= (EditBone*)(ptr->data);
if(!value) data->flag |= BONE_NO_SCALE;
else data->flag &= ~BONE_NO_SCALE;
}
int rna_EditBone_locked_get(PointerRNA *ptr)
{
EditBone *data= (EditBone*)(ptr->data);
return (((data->flag) & BONE_EDITMODE_LOCKED) != 0);
}
void rna_EditBone_locked_set(PointerRNA *ptr, int value)
{
EditBone *data= (EditBone*)(ptr->data);
if(value) data->flag |= BONE_EDITMODE_LOCKED;
else data->flag &= ~BONE_EDITMODE_LOCKED;
}
int rna_EditBone_multiply_vertexgroup_with_envelope_get(PointerRNA *ptr)
{
EditBone *data= (EditBone*)(ptr->data);
return (((data->flag) & BONE_MULT_VG_ENV) != 0);
}
void rna_EditBone_multiply_vertexgroup_with_envelope_set(PointerRNA *ptr, int value)
{
EditBone *data= (EditBone*)(ptr->data);
if(value) data->flag |= BONE_MULT_VG_ENV;
else data->flag &= ~BONE_MULT_VG_ENV;
}
PointerRNA rna_EditBone_parent_get(PointerRNA *ptr)
{
EditBone *data= (EditBone*)(ptr->data);
return rna_pointer_inherit_refine(ptr, &RNA_EditBone, data->parent);
}
float rna_EditBone_roll_get(PointerRNA *ptr)
{
EditBone *data= (EditBone*)(ptr->data);
return (float)(data->roll);
}
void rna_EditBone_roll_set(PointerRNA *ptr, float value)
{
EditBone *data= (EditBone*)(ptr->data);
data->roll= value;
}
void rna_EditBone_tail_get(PointerRNA *ptr, float values[3])
{
EditBone *data= (EditBone*)(ptr->data);
values[0]= (float)(((float*)data->tail)[0]);
values[1]= (float)(((float*)data->tail)[1]);
values[2]= (float)(((float*)data->tail)[2]);
}
void rna_EditBone_tail_set(PointerRNA *ptr, const float values[3])
{
EditBone *data= (EditBone*)(ptr->data);
((float*)data->tail)[0]= values[0];
((float*)data->tail)[1]= values[1];
((float*)data->tail)[2]= values[2];
}
int rna_EditBone_tail_selected_get(PointerRNA *ptr)
{
EditBone *data= (EditBone*)(ptr->data);
return (((data->flag) & BONE_TIPSEL) != 0);
}
void rna_EditBone_tail_selected_set(PointerRNA *ptr, int value)
{
EditBone *data= (EditBone*)(ptr->data);
if(value) data->flag |= BONE_TIPSEL;
else data->flag &= ~BONE_TIPSEL;
}
#else
static void rna_def_bone_common(StructRNA *srna, int editbone)
{
PropertyRNA *prop;
/* strings */
prop= RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* must be unique */
RNA_def_property_ui_text(prop, "Name", "");
RNA_def_struct_name_property(srna, prop);
if(editbone) RNA_def_property_string_funcs(prop, "rna_EditBone_name_get", "rna_EditBone_name_length", "rna_EditBone_name_set");
/* flags */
prop= RNA_def_property(srna, "layer", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_array(prop, 16);
RNA_def_property_ui_text(prop, "Bone Layers", "Layers bone exists in");
if(editbone) RNA_def_property_boolean_funcs(prop, "rna_EditBone_layer_get", "rna_EditBone_layer_set");
else {
RNA_def_property_boolean_funcs(prop, NULL, "rna_Bone_layer_set");
RNA_def_property_boolean_sdna(prop, NULL, "layer", 1);
}
prop= RNA_def_property(srna, "connected", PROP_BOOLEAN, PROP_NONE);
if(editbone) RNA_def_property_boolean_funcs(prop, "rna_EditBone_connected_get", "rna_EditBone_connected_set");
else RNA_def_property_boolean_sdna(prop, NULL, "flag", BONE_CONNECTED);
RNA_def_property_ui_text(prop, "Connected", "When bone has a parent, bone's head is struck to the parent's tail.");
prop= RNA_def_property(srna, "active", PROP_BOOLEAN, PROP_NONE);
if(editbone) RNA_def_property_boolean_funcs(prop, "rna_EditBone_active_get", "rna_EditBone_active_set");
else RNA_def_property_boolean_sdna(prop, NULL, "flag", BONE_ACTIVE);
RNA_def_property_ui_text(prop, "Active", "Bone was the last bone clicked on (most operations are applied to only this bone)");
prop= RNA_def_property(srna, "hinge", PROP_BOOLEAN, PROP_NONE);
if(editbone) RNA_def_property_boolean_funcs(prop, "rna_EditBone_hinge_get", "rna_EditBone_hinge_set");
else RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", BONE_HINGE);
RNA_def_property_ui_text(prop, "Inherit Rotation", "Bone doesn't inherit rotation or scale from parent bone.");
prop= RNA_def_property(srna, "multiply_vertexgroup_with_envelope", PROP_BOOLEAN, PROP_NONE);
if(editbone) RNA_def_property_boolean_funcs(prop, "rna_EditBone_multiply_vertexgroup_with_envelope_get", "rna_EditBone_multiply_vertexgroup_with_envelope_set");
else RNA_def_property_boolean_sdna(prop, NULL, "flag", BONE_MULT_VG_ENV);
RNA_def_property_ui_text(prop, "Multiply Vertex Group with Envelope", "When deforming bone, multiply effects of Vertex Group weights with Envelope influence.");
prop= RNA_def_property(srna, "deform", PROP_BOOLEAN, PROP_NONE);
if(editbone) RNA_def_property_boolean_funcs(prop, "rna_EditBone_deform_get", "rna_EditBone_deform_set");
else RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", BONE_NO_DEFORM);
RNA_def_property_ui_text(prop, "Deform", "Bone does not deform any geometry.");
prop= RNA_def_property(srna, "inherit_scale", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_ui_text(prop, "Inherit Scale", "Bone inherits scaling from parent bone.");
if(editbone) RNA_def_property_boolean_funcs(prop, "rna_EditBone_inherit_scale_get", "rna_EditBone_inherit_scale_set");
else RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", BONE_NO_SCALE);
prop= RNA_def_property(srna, "draw_wire", PROP_BOOLEAN, PROP_NONE);
if(editbone) RNA_def_property_boolean_funcs(prop, "rna_EditBone_draw_wire_get", "rna_EditBone_draw_wire_set");
else RNA_def_property_boolean_sdna(prop, NULL, "flag", BONE_DRAWWIRE);
RNA_def_property_ui_text(prop, "Draw Wire", "Bone is always drawn as Wireframe regardless of viewport draw mode. Useful for non-obstructive custom bone shapes.");
prop= RNA_def_property(srna, "cyclic_offset", PROP_BOOLEAN, PROP_NONE);
if(editbone) RNA_def_property_boolean_funcs(prop, "rna_EditBone_cyclic_offset_get", "rna_EditBone_cyclic_offset_set");
else RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", BONE_NO_CYCLICOFFSET);
RNA_def_property_ui_text(prop, "Cyclic Offset", "When bone doesn't have a parent, it receives cyclic offset effects.");
/* Number values */
/* envelope deform settings */
prop= RNA_def_property(srna, "envelope_distance", PROP_FLOAT, PROP_NONE);
if(editbone) RNA_def_property_float_funcs(prop, "rna_EditBone_envelope_distance_get", "rna_EditBone_envelope_distance_set", NULL);
else RNA_def_property_float_sdna(prop, NULL, "dist");
RNA_def_property_range(prop, 0.0f, 1000.0f);
RNA_def_property_ui_text(prop, "Envelope Deform Distance", "Bone deformation distance (for Envelope deform only).");
prop= RNA_def_property(srna, "envelope_weight", PROP_FLOAT, PROP_NONE);
if(editbone) RNA_def_property_float_funcs(prop, "rna_EditBone_envelope_weight_get", "rna_EditBone_envelope_weight_set", NULL);
else RNA_def_property_float_sdna(prop, NULL, "weight");
RNA_def_property_range(prop, 0.0f, 1000.0f);
RNA_def_property_ui_text(prop, "Envelope Deform Weight", "Bone deformation weight (for Envelope deform only).");
prop= RNA_def_property(srna, "radius_head", PROP_FLOAT, PROP_NONE);
if(editbone) RNA_def_property_float_funcs(prop, "rna_EditBone_radius_head_get", "rna_EditBone_radius_head_set", NULL);
else RNA_def_property_float_sdna(prop, NULL, "rad_head");
//RNA_def_property_range(prop, 0, 1000); // XXX range is 0 to lim, where lim= 10000.0f*MAX2(1.0, view3d->grid);
RNA_def_property_ui_text(prop, "Envelope Radius Head", "Radius of head of bone (for Envelope deform only).");
prop= RNA_def_property(srna, "radius_tail", PROP_FLOAT, PROP_NONE);
if(editbone) RNA_def_property_float_funcs(prop, "rna_EditBone_radius_tail_get", "rna_EditBone_radius_tail_set", NULL);
else RNA_def_property_float_sdna(prop, NULL, "rad_tail");
//RNA_def_property_range(prop, 0, 1000); // XXX range is 0 to lim, where lim= 10000.0f*MAX2(1.0, view3d->grid);
RNA_def_property_ui_text(prop, "Envelope Radius Tail", "Radius of tail of bone (for Envelope deform only).");
/* b-bones deform settings */
prop= RNA_def_property(srna, "bbone_segments", PROP_INT, PROP_NONE);
if(editbone) RNA_def_property_int_funcs(prop, "rna_EditBone_bbone_segments_get", "rna_EditBone_bbone_segments_set", NULL);
else RNA_def_property_int_sdna(prop, NULL, "segments");
RNA_def_property_range(prop, 1, 32);
RNA_def_property_ui_text(prop, "B-Bone Segments", "Number of subdivisions of bone (for B-Bones only).");
prop= RNA_def_property(srna, "bbone_in", PROP_FLOAT, PROP_NONE);
if(editbone) RNA_def_property_float_funcs(prop, "rna_EditBone_bbone_in_get", "rna_EditBone_bbone_in_set", NULL);
else RNA_def_property_float_sdna(prop, NULL, "ease1");
RNA_def_property_range(prop, 0.0f, 2.0f);
RNA_def_property_ui_text(prop, "B-Bone Ease In", "Length of first Bezier Handle (for B-Bones only).");
prop= RNA_def_property(srna, "bbone_out", PROP_FLOAT, PROP_NONE);
if(editbone) RNA_def_property_float_funcs(prop, "rna_EditBone_bbone_out_get", "rna_EditBone_bbone_out_set", NULL);
else RNA_def_property_float_sdna(prop, NULL, "ease2");
RNA_def_property_range(prop, 0.0f, 2.0f);
RNA_def_property_ui_text(prop, "B-Bone Ease Out", "Length of second Bezier Handle (for B-Bones only).");
}
// err... bones should not be directly edited (only editbones should be...)
static void rna_def_bone(BlenderRNA *brna)
{
@@ -126,128 +574,64 @@ static void rna_def_bone(BlenderRNA *brna)
RNA_def_property_collection_sdna(prop, NULL, "childbase", NULL);
RNA_def_property_struct_type(prop, "Bone");
RNA_def_property_ui_text(prop, "Children", "Bones which are children of this bone");
/* strings */
prop= RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* must be unique */
RNA_def_property_ui_text(prop, "Name", "");
RNA_def_struct_name_property(srna, prop);
/* flags */
/* layer */
prop= RNA_def_property(srna, "layer", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "layer", 1);
RNA_def_property_array(prop, 16);
RNA_def_property_ui_text(prop, "Bone Layers", "Layers bone exists in");
RNA_def_property_boolean_funcs(prop, NULL, "rna_Bone_layer_set");
/* flag */
rna_def_bone_common(srna, 0);
// XXX should we define this in PoseChannel wrapping code instead? but PoseChannels directly get some of their flags from here...
prop= RNA_def_property(srna, "hidden", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BONE_HIDDEN_P);
RNA_def_property_ui_text(prop, "Hidden", "Bone is not visible when it is not in Edit Mode (i.e. in Object or Pose Modes).");
prop= RNA_def_property(srna, "selected", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BONE_SELECTED);
RNA_def_property_ui_text(prop, "Selected", "");
}
static void rna_def_edit_bone(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
srna= RNA_def_struct(brna, "EditBone", NULL);
RNA_def_struct_ui_text(srna, "Edit Bone", "Editmode bone in an Armature datablock.");
RNA_def_struct_ui_icon(srna, ICON_BONE_DATA);
prop= RNA_def_property(srna, "parent", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "EditBone");
RNA_def_property_pointer_funcs(prop, "rna_EditBone_parent_get", NULL, NULL);
RNA_def_property_ui_text(prop, "Parent", "Parent edit bone (in same Armature).");
prop= RNA_def_property(srna, "roll", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_funcs(prop, "rna_EditBone_roll_get", "rna_EditBone_roll_set", NULL);
RNA_def_property_ui_text(prop, "Roll", "Bone rotation around head-tail axis.");
prop= RNA_def_property(srna, "head", PROP_FLOAT, PROP_VECTOR);
RNA_def_property_array(prop, 3);
RNA_def_property_float_funcs(prop, "rna_EditBone_head_get", "rna_EditBone_head_set", NULL);
RNA_def_property_ui_text(prop, "Head", "Location of head end of the bone.");
prop= RNA_def_property(srna, "tail", PROP_FLOAT, PROP_VECTOR);
RNA_def_property_array(prop, 3);
RNA_def_property_float_funcs(prop, "rna_EditBone_tail_get", "rna_EditBone_tail_set", NULL);
RNA_def_property_ui_text(prop, "Tail", "Location of tail end of the bone.");
rna_def_bone_common(srna, 1);
prop= RNA_def_property(srna, "hidden", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_funcs(prop, "rna_EditBone_hidden_get", "rna_EditBone_hidden_set");
RNA_def_property_ui_text(prop, "Hidden", "Bone is not visible when in Edit Mode");
prop= RNA_def_property(srna, "locked", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_funcs(prop, "rna_EditBone_locked_get", "rna_EditBone_locked_set");
RNA_def_property_ui_text(prop, "Locked", "Bone is not able to be transformed when in Edit Mode.");
prop= RNA_def_property(srna, "head_selected", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BONE_ROOTSEL);
RNA_def_property_boolean_funcs(prop, "rna_EditBone_head_selected_get", "rna_EditBone_head_selected_set");
RNA_def_property_ui_text(prop, "Head Selected", "");
prop= RNA_def_property(srna, "tail_selected", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BONE_TIPSEL);
RNA_def_property_boolean_funcs(prop, "rna_EditBone_tail_selected_get", "rna_EditBone_tail_selected_set");
RNA_def_property_ui_text(prop, "Tail Selected", "");
prop= RNA_def_property(srna, "connected", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BONE_CONNECTED);
RNA_def_property_ui_text(prop, "Connected", "When bone has a parent, bone's head is struck to the parent's tail.");
// XXX should we define this in PoseChannel wrapping code instead? but PoseChannels directly get some of their flags from here...
prop= RNA_def_property(srna, "pose_channel_hidden", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BONE_HIDDEN_P);
RNA_def_property_ui_text(prop, "Pose Channel Hidden", "Bone is not visible when it is not in Edit Mode (i.e. in Object or Pose Modes).");
prop= RNA_def_property(srna, "active", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BONE_ACTIVE);
RNA_def_property_ui_text(prop, "Active", "Bone was the last bone clicked on (most operations are applied to only this bone)");
prop= RNA_def_property(srna, "hinge", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", BONE_HINGE);
RNA_def_property_ui_text(prop, "Inherit Rotation", "Bone doesn't inherit rotation or scale from parent bone.");
prop= RNA_def_property(srna, "editmode_hidden", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BONE_HIDDEN_A);
RNA_def_property_ui_text(prop, "Edit Mode Hidden", "Bone is not visible when in Edit Mode");
prop= RNA_def_property(srna, "multiply_vertexgroup_with_envelope", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BONE_MULT_VG_ENV);
RNA_def_property_ui_text(prop, "Multiply Vertex Group with Envelope", "When deforming bone, multiply effects of Vertex Group weights with Envelope influence.");
prop= RNA_def_property(srna, "deform", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", BONE_NO_DEFORM);
RNA_def_property_ui_text(prop, "Deform", "Bone does not deform any geometry.");
prop= RNA_def_property(srna, "inherit_scale", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", BONE_NO_SCALE);
RNA_def_property_ui_text(prop, "Inherit Scale", "Bone inherits scaling from parent bone.");
prop= RNA_def_property(srna, "draw_wire", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BONE_DRAWWIRE);
RNA_def_property_ui_text(prop, "Draw Wire", "Bone is always drawn as Wireframe regardless of viewport draw mode. Useful for non-obstructive custom bone shapes.");
prop= RNA_def_property(srna, "cyclic_offset", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", BONE_NO_CYCLICOFFSET);
RNA_def_property_ui_text(prop, "Cyclic Offset", "When bone doesn't have a parent, it receives cyclic offset effects.");
prop= RNA_def_property(srna, "editmode_locked", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BONE_EDITMODE_LOCKED);
RNA_def_property_ui_text(prop, "Edit Mode Locked", "Bone is not able to be transformed when in Edit Mode.");
/* Number values */
/* envelope deform settings */
prop= RNA_def_property(srna, "envelope_distance", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "dist");
RNA_def_property_range(prop, 0.0f, 1000.0f);
RNA_def_property_ui_text(prop, "Envelope Deform Distance", "Bone deformation distance (for Envelope deform only).");
prop= RNA_def_property(srna, "envelope_weight", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "weight");
RNA_def_property_range(prop, 0.0f, 1000.0f);
RNA_def_property_ui_text(prop, "Envelope Deform Weight", "Bone deformation weight (for Envelope deform only).");
prop= RNA_def_property(srna, "radius_head", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "rad_head");
//RNA_def_property_range(prop, 0, 1000); // XXX range is 0 to lim, where lim= 10000.0f*MAX2(1.0, view3d->grid);
RNA_def_property_ui_text(prop, "Envelope Radius Head", "Radius of head of bone (for Envelope deform only).");
prop= RNA_def_property(srna, "radius_tail", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "rad_tail");
//RNA_def_property_range(prop, 0, 1000); // XXX range is 0 to lim, where lim= 10000.0f*MAX2(1.0, view3d->grid);
RNA_def_property_ui_text(prop, "Envelope Radius Tail", "Radius of tail of bone (for Envelope deform only).");
/* b-bones deform settings */
prop= RNA_def_property(srna, "bbone_segments", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "segments");
RNA_def_property_range(prop, 1, 32);
RNA_def_property_ui_text(prop, "B-Bone Segments", "Number of subdivisions of bone (for B-Bones only).");
prop= RNA_def_property(srna, "bbone_in", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "ease1");
RNA_def_property_range(prop, 0.0f, 2.0f);
RNA_def_property_ui_text(prop, "B-Bone Ease In", "Length of first Bezier Handle (for B-Bones only).");
prop= RNA_def_property(srna, "bbone_out", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "ease2");
RNA_def_property_range(prop, 0.0f, 2.0f);
RNA_def_property_ui_text(prop, "B-Bone Ease Out", "Length of second Bezier Handle (for B-Bones only).");
/* editmode bone coordinates */
// XXX not sure if we want to wrap these here... besides, changing these requires changing the matrix?
prop= RNA_def_property(srna, "head", PROP_FLOAT, PROP_VECTOR);
RNA_def_property_ui_text(prop, "Bone Head Location", "In Edit Mode, the location of the 'head' of the bone.");
prop= RNA_def_property(srna, "tail", PROP_FLOAT, PROP_VECTOR);
RNA_def_property_ui_text(prop, "Bone Tail Location", "In Edit Mode, the location of the 'head' of the bone.");
prop= RNA_def_property(srna, "roll", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0f, 2.0f);
RNA_def_property_ui_text(prop, "Bone Roll", "In Edit Mode, the 'roll' (i.e. rotation around the bone vector, equivalent to local Y-axis rotation).");
}
void rna_def_armature(BlenderRNA *brna)
@@ -278,6 +662,11 @@ void rna_def_armature(BlenderRNA *brna)
RNA_def_property_collection_sdna(prop, NULL, "bonebase", NULL);
RNA_def_property_struct_type(prop, "Bone");
RNA_def_property_ui_text(prop, "Bones", "");
prop= RNA_def_property(srna, "edit_bones", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "edbo", NULL);
RNA_def_property_struct_type(prop, "EditBone");
RNA_def_property_ui_text(prop, "Edit Bones", "");
/* Enum values */
prop= RNA_def_property(srna, "drawtype", PROP_ENUM, PROP_NONE);
@@ -436,6 +825,7 @@ void RNA_def_armature(BlenderRNA *brna)
{
rna_def_armature(brna);
rna_def_bone(brna);
rna_def_edit_bone(brna);
}
#endif

View File

@@ -38,6 +38,8 @@
#include "RNA_define.h"
#include "RNA_types.h"
#include "BLI_ghash.h"
#include "rna_internal.h"
/* Global used during defining */
@@ -557,6 +559,7 @@ StructRNA *RNA_def_struct(BlenderRNA *brna, const char *identifier, const char *
/* copy from struct to derive stuff, a bit clumsy since we can't
* use MEM_dupallocN, data structs may not be alloced but builtin */
memcpy(srna, srnafrom, sizeof(StructRNA));
srna->cont.prophash= NULL;
srna->cont.properties.first= srna->cont.properties.last= NULL;
srna->functions.first= srna->functions.last= NULL;
srna->py_type= NULL;
@@ -604,7 +607,7 @@ StructRNA *RNA_def_struct(BlenderRNA *brna, const char *identifier, const char *
if(DefRNA.preprocess) {
RNA_def_property_struct_type(prop, "Property");
RNA_def_property_collection_funcs(prop, "rna_builtin_properties_begin", "rna_builtin_properties_next", "rna_iterator_listbase_end", "rna_builtin_properties_get", 0, 0, 0, 0, 0);
RNA_def_property_collection_funcs(prop, "rna_builtin_properties_begin", "rna_builtin_properties_next", "rna_iterator_listbase_end", "rna_builtin_properties_get", 0, 0, "rna_builtin_properties_lookup_string", 0, 0);
}
else {
#ifdef RNA_RUNTIME
@@ -923,8 +926,13 @@ PropertyRNA *RNA_def_property(StructOrFunctionRNA *cont_, const char *identifier
break;
}
}
else
else {
prop->flag |= PROP_IDPROPERTY|PROP_RUNTIME;
#ifdef RNA_RUNTIME
if(cont->prophash)
BLI_ghash_insert(cont->prophash, (void*)prop->identifier, prop);
#endif
}
rna_addtail(&cont->properties, prop);

View File

@@ -217,6 +217,7 @@ void rna_builtin_properties_begin(struct CollectionPropertyIterator *iter, struc
void rna_builtin_properties_next(struct CollectionPropertyIterator *iter);
PointerRNA rna_builtin_properties_get(struct CollectionPropertyIterator *iter);
PointerRNA rna_builtin_type_get(struct PointerRNA *ptr);
PointerRNA rna_builtin_properties_lookup_string(PointerRNA *ptr, const char *key);
/* Iterators */

View File

@@ -37,6 +37,7 @@ struct ReportList;
struct CollectionPropertyIterator;
struct bContext;
struct IDProperty;
struct GHash;
#define RNA_MAX_ARRAY 32
@@ -83,6 +84,7 @@ typedef PointerRNA (*PropCollectionLookupStringFunc)(struct PointerRNA *ptr, con
typedef struct ContainerRNA {
void *next, *prev;
struct GHash *prophash;
ListBase properties;
} ContainerRNA;

View File

@@ -38,11 +38,14 @@
#ifdef RNA_RUNTIME
/*static float rna_MeshVertex_no_get(PointerRNA *ptr, int index)
static void rna_MeshVertex_normal_get(PointerRNA *ptr, float *value)
{
MVert *mvert= (MVert*)ptr->data;
return mvert->no[index]/32767.0f;
}*/
value[0]= mvert->no[0]/32767.0f;
value[1]= mvert->no[1]/32767.0f;
value[2]= mvert->no[2]/32767.0f;
}
static float rna_MeshVertex_bevel_weight_get(PointerRNA *ptr)
{
@@ -80,76 +83,77 @@ static void rna_MEdge_crease_set(PointerRNA *ptr, float value)
medge->crease= (char)(CLAMPIS(value*255.0f, 0, 255));
}
/* notice red and blue are swapped */
static void rna_MeshColor_color1_get(PointerRNA *ptr, float *values)
{
MCol *mcol= (MCol*)ptr->data;
values[0]= (&mcol[0].r)[0]/255.0f;
values[2]= (&mcol[0].r)[0]/255.0f;
values[1]= (&mcol[0].r)[1]/255.0f;
values[2]= (&mcol[0].r)[2]/255.0f;
values[0]= (&mcol[0].r)[2]/255.0f;
}
static void rna_MeshColor_color1_set(PointerRNA *ptr, const float *values)
{
MCol *mcol= (MCol*)ptr->data;
(&mcol[0].r)[0]= (char)(CLAMPIS(values[0]*255.0f, 0, 255));
(&mcol[0].r)[2]= (char)(CLAMPIS(values[0]*255.0f, 0, 255));
(&mcol[0].r)[1]= (char)(CLAMPIS(values[1]*255.0f, 0, 255));
(&mcol[0].r)[2]= (char)(CLAMPIS(values[2]*255.0f, 0, 255));
(&mcol[0].r)[0]= (char)(CLAMPIS(values[2]*255.0f, 0, 255));
}
static void rna_MeshColor_color2_get(PointerRNA *ptr, float *values)
{
MCol *mcol= (MCol*)ptr->data;
values[0]= (&mcol[1].r)[0]/255.0f;
values[2]= (&mcol[1].r)[0]/255.0f;
values[1]= (&mcol[1].r)[1]/255.0f;
values[2]= (&mcol[1].r)[2]/255.0f;
values[0]= (&mcol[1].r)[2]/255.0f;
}
static void rna_MeshColor_color2_set(PointerRNA *ptr, const float *values)
{
MCol *mcol= (MCol*)ptr->data;
(&mcol[1].r)[0]= (char)(CLAMPIS(values[0]*255.0f, 0, 255));
(&mcol[1].r)[2]= (char)(CLAMPIS(values[0]*255.0f, 0, 255));
(&mcol[1].r)[1]= (char)(CLAMPIS(values[1]*255.0f, 0, 255));
(&mcol[1].r)[2]= (char)(CLAMPIS(values[2]*255.0f, 0, 255));
(&mcol[1].r)[0]= (char)(CLAMPIS(values[2]*255.0f, 0, 255));
}
static void rna_MeshColor_color3_get(PointerRNA *ptr, float *values)
{
MCol *mcol= (MCol*)ptr->data;
values[0]= (&mcol[2].r)[0]/255.0f;
values[2]= (&mcol[2].r)[0]/255.0f;
values[1]= (&mcol[2].r)[1]/255.0f;
values[2]= (&mcol[2].r)[2]/255.0f;
values[0]= (&mcol[2].r)[2]/255.0f;
}
static void rna_MeshColor_color3_set(PointerRNA *ptr, const float *values)
{
MCol *mcol= (MCol*)ptr->data;
(&mcol[2].r)[0]= (char)(CLAMPIS(values[0]*255.0f, 0, 255));
(&mcol[2].r)[2]= (char)(CLAMPIS(values[0]*255.0f, 0, 255));
(&mcol[2].r)[1]= (char)(CLAMPIS(values[1]*255.0f, 0, 255));
(&mcol[2].r)[2]= (char)(CLAMPIS(values[2]*255.0f, 0, 255));
(&mcol[2].r)[0]= (char)(CLAMPIS(values[2]*255.0f, 0, 255));
}
static void rna_MeshColor_color4_get(PointerRNA *ptr, float *values)
{
MCol *mcol= (MCol*)ptr->data;
values[0]= (&mcol[3].r)[0]/255.0f;
values[2]= (&mcol[3].r)[0]/255.0f;
values[1]= (&mcol[3].r)[1]/255.0f;
values[2]= (&mcol[3].r)[2]/255.0f;
values[0]= (&mcol[3].r)[2]/255.0f;
}
static void rna_MeshColor_color4_set(PointerRNA *ptr, const float *values)
{
MCol *mcol= (MCol*)ptr->data;
(&mcol[3].r)[0]= (char)(CLAMPIS(values[0]*255.0f, 0, 255));
(&mcol[3].r)[2]= (char)(CLAMPIS(values[0]*255.0f, 0, 255));
(&mcol[3].r)[1]= (char)(CLAMPIS(values[1]*255.0f, 0, 255));
(&mcol[3].r)[2]= (char)(CLAMPIS(values[2]*255.0f, 0, 255));
(&mcol[3].r)[0]= (char)(CLAMPIS(values[2]*255.0f, 0, 255));
}
static int rna_Mesh_texspace_editable(PointerRNA *ptr)
@@ -628,10 +632,11 @@ static void rna_def_mvert(BlenderRNA *brna)
prop= RNA_def_property(srna, "co", PROP_FLOAT, PROP_VECTOR);
RNA_def_property_ui_text(prop, "Location", "");
/*prop= RNA_def_property(srna, "no", PROP_FLOAT, PROP_VECTOR);
RNA_def_property_float_funcs(prop, "rna_MeshVertex_no_get", NULL, NULL);
prop= RNA_def_property(srna, "normal", PROP_FLOAT, PROP_VECTOR);
RNA_def_property_float_sdna(prop, NULL, "no");
RNA_def_property_float_funcs(prop, "rna_MeshVertex_normal_get", NULL, NULL);
RNA_def_property_ui_text(prop, "Normal", "Vertex Normal");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);*/
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop= RNA_def_property(srna, "selected", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SELECT);
@@ -907,21 +912,25 @@ static void rna_def_mcol(BlenderRNA *brna)
prop= RNA_def_property(srna, "color1", PROP_FLOAT, PROP_COLOR);
RNA_def_property_array(prop, 3);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_float_funcs(prop, "rna_MeshColor_color1_get", "rna_MeshColor_color1_set", NULL);
RNA_def_property_ui_text(prop, "Color 1", "");
prop= RNA_def_property(srna, "color2", PROP_FLOAT, PROP_COLOR);
RNA_def_property_array(prop, 3);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_float_funcs(prop, "rna_MeshColor_color2_get", "rna_MeshColor_color2_set", NULL);
RNA_def_property_ui_text(prop, "Color 2", "");
prop= RNA_def_property(srna, "color3", PROP_FLOAT, PROP_COLOR);
RNA_def_property_array(prop, 3);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_float_funcs(prop, "rna_MeshColor_color3_get", "rna_MeshColor_color3_set", NULL);
RNA_def_property_ui_text(prop, "Color 3", "");
prop= RNA_def_property(srna, "color4", PROP_FLOAT, PROP_COLOR);
RNA_def_property_array(prop, 3);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_float_funcs(prop, "rna_MeshColor_color4_get", "rna_MeshColor_color4_set", NULL);
RNA_def_property_ui_text(prop, "Color 4", "");
}

View File

@@ -92,7 +92,7 @@ static void rna_Object_data_set(PointerRNA *ptr, PointerRNA value)
ob->data= id;
test_object_materials(id);
if(GS(id->name)==ID_CU )
if(GS(id->name)==ID_CU)
test_curve_type(ob);
else if(ob->type==OB_ARMATURE)
armature_rebuild_pose(ob, ob->data);
@@ -522,6 +522,49 @@ static void rna_def_object_game_settings(BlenderRNA *brna)
RNA_def_property_range(prop, 0.0, 1.0);
RNA_def_property_ui_text(prop, "Rotation Damping", "General rotation damping.");
prop= RNA_def_property(srna, "minimum_velocity", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "min_vel");
RNA_def_property_range(prop, 0.0, 1000.0);
RNA_def_property_ui_text(prop, "Velocity Min", "Clamp velocity to this minimum speed (except when totally still).");
prop= RNA_def_property(srna, "maximum_velocity", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "max_vel");
RNA_def_property_range(prop, 0.0, 1000.0);
RNA_def_property_ui_text(prop, "Velocity Max", "Clamp velocity to this maximum speed.");
/* lock position */
prop= RNA_def_property(srna, "lock_x_axis", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "gameflag2", OB_LOCK_RIGID_BODY_X_AXIS);
RNA_def_property_ui_text(prop, "Lock X Axis", "Disable simulation of linear motion along the X axis.");
prop= RNA_def_property(srna, "lock_y_axis", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "gameflag2", OB_LOCK_RIGID_BODY_Y_AXIS);
RNA_def_property_ui_text(prop, "Lock Y Axis", "Disable simulation of linear motion along the Y axis.");
prop= RNA_def_property(srna, "lock_z_axis", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "gameflag2", OB_LOCK_RIGID_BODY_Z_AXIS);
RNA_def_property_ui_text(prop, "Lock Z Axis", "Disable simulation of linear motion along the Z axis.");
/* lock rotation */
prop= RNA_def_property(srna, "lock_x_rot_axis", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "gameflag2", OB_LOCK_RIGID_BODY_X_ROT_AXIS);
RNA_def_property_ui_text(prop, "Lock X Rotation Axis", "Disable simulation of angular motion along the X axis.");
prop= RNA_def_property(srna, "lock_y_rot_axis", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "gameflag2", OB_LOCK_RIGID_BODY_Y_ROT_AXIS);
RNA_def_property_ui_text(prop, "Lock Y Rotation Axis", "Disable simulation of angular motion along the Y axis.");
prop= RNA_def_property(srna, "lock_z_rot_axis", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "gameflag2", OB_LOCK_RIGID_BODY_Z_ROT_AXIS);
RNA_def_property_ui_text(prop, "Lock Z Rotation Axis", "Disable simulation of angular motion along the Z axis.");
/* is this used anywhere ? */
prop= RNA_def_property(srna, "use_activity_culling", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "gameflag2", OB_NEVER_DO_ACTIVITY_CULLING);
RNA_def_property_ui_text(prop, "Lock Z Rotation Axis", "Disable simulation of angular motion along the Z axis.");
prop= RNA_def_property(srna, "do_fh", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "gameflag", OB_DO_FH);
RNA_def_property_ui_text(prop, "Do Fh", "Use Fh settings in materials.");

View File

@@ -34,6 +34,8 @@
#ifdef RNA_RUNTIME
#include "BLI_ghash.h"
/* Struct */
static void rna_Struct_identifier_get(PointerRNA *ptr, char *value)
@@ -277,6 +279,51 @@ PointerRNA rna_builtin_properties_get(CollectionPropertyIterator *iter)
return rna_Struct_properties_get(iter);
}
PointerRNA rna_builtin_properties_lookup_string(PointerRNA *ptr, const char *key)
{
StructRNA *srna;
PropertyRNA *prop;
IDProperty *group, *idp;
PointerRNA propptr;
memset(&propptr, 0, sizeof(propptr));
srna= ptr->type;
do {
if(srna->cont.prophash) {
prop= BLI_ghash_lookup(srna->cont.prophash, (void*)key);
if(prop) {
propptr.type= &RNA_Property;
propptr.data= prop;
return propptr;
}
}
for(prop=srna->cont.properties.first; prop; prop=prop->next) {
if(!(prop->flag & PROP_BUILTIN) && strcmp(prop->identifier, key)==0) {
propptr.type= &RNA_Property;
propptr.data= prop;
return propptr;
}
}
} while((srna=srna->base));
group= RNA_struct_idproperties(ptr, 0);
if(group) {
for(idp=group->data.group.first; idp; idp=idp->next) {
if(strcmp(idp->name, key) == 0) {
propptr.type= &RNA_Property;
propptr.data= idp;
return propptr;
}
}
}
return propptr;
}
PointerRNA rna_builtin_type_get(PointerRNA *ptr)
{
return rna_pointer_inherit_refine(ptr, &RNA_Struct, ptr->type);

View File

@@ -62,7 +62,7 @@ EnumPropertyItem space_type_items[] = {
#define DC_ALPHA {SI_SHOW_ALPHA, "ALPHA", ICON_IMAGE_ALPHA, "Alpha", "Draw alpha transparency channel."}
#define DC_Z {SI_SHOW_ZBUF, "Z_BUFFER", ICON_IMAGE_ZDEPTH, "Z-Buffer", "Draw Z-buffer associated with image (mapped from camera clip start to end)."}
#ifdef WITH_LCMS
#define DC_LCMS SI_COLOR_CORRECTION, "COLOR_CORRECTED", ICON_IMAGE_ALPHA, "Color Corrected", "Display color corrected image."}
#define DC_LCMS {SI_COLOR_CORRECTION, "COLOR_CORRECTED", ICON_IMAGE_ALPHA, "Color Corrected", "Display color corrected image."}
#else
#define DC_LCMS {0, NULL, 0, NULL, NULL}
#endif

View File

@@ -36,65 +36,53 @@
//-------------------------DOC STRINGS ---------------------------
static char M_Mathutils_doc[] = "The Blender Mathutils module\n\n";
static char M_Mathutils_Vector_doc[] = "() - create a new vector object from a list of floats";
static char M_Mathutils_Matrix_doc[] = "() - create a new matrix object from a list of floats";
static char M_Mathutils_Quaternion_doc[] = "() - create a quaternion from a list or an axis of rotation and an angle";
static char M_Mathutils_Euler_doc[] = "() - create and return a new euler object";
static char M_Mathutils_Rand_doc[] = "() - return a random number";
static char M_Mathutils_CrossVecs_doc[] = "() - returns a vector perpedicular to the 2 vectors crossed";
static char M_Mathutils_CopyVec_doc[] = "() - create a copy of vector";
static char M_Mathutils_DotVecs_doc[] = "() - return the dot product of two vectors";
static char M_Mathutils_AngleBetweenVecs_doc[] = "() - returns the angle between two vectors in degrees";
static char M_Mathutils_MidpointVecs_doc[] = "() - return the vector to the midpoint between two vectors";
static char M_Mathutils_MatMultVec_doc[] = "() - multiplies a matrix by a column vector";
static char M_Mathutils_VecMultMat_doc[] = "() - multiplies a row vector by a matrix";
static char M_Mathutils_ProjectVecs_doc[] = "() - returns the projection vector from the projection of vecA onto vecB";
static char M_Mathutils_RotationMatrix_doc[] = "() - construct a rotation matrix from an angle and axis of rotation";
static char M_Mathutils_ScaleMatrix_doc[] = "() - construct a scaling matrix from a scaling factor";
static char M_Mathutils_OrthoProjectionMatrix_doc[] = "() - construct a orthographic projection matrix from a selected plane";
static char M_Mathutils_ShearMatrix_doc[] = "() - construct a shearing matrix from a plane of shear and a shear factor";
static char M_Mathutils_CopyMat_doc[] = "() - create a copy of a matrix";
static char M_Mathutils_TranslationMatrix_doc[] = "(vec) - create a translation matrix from a vector";
static char M_Mathutils_CopyQuat_doc[] = "() - copy quatB to quatA";
static char M_Mathutils_CopyEuler_doc[] = "() - copy eulB to eultA";
static char M_Mathutils_CrossQuats_doc[] = "() - return the mutliplication of two quaternions";
static char M_Mathutils_DotQuats_doc[] = "() - return the dot product of two quaternions";
static char M_Mathutils_Slerp_doc[] = "() - returns the interpolation between two quaternions";
static char M_Mathutils_DifferenceQuats_doc[] = "() - return the angular displacment difference between two quats";
static char M_Mathutils_RotateEuler_doc[] = "() - rotate euler by an axis and angle";
static char M_Mathutils_Intersect_doc[] = "(v1, v2, v3, ray, orig, clip=1) - returns the intersection between a ray and a triangle, if possible, returns None otherwise";
static char M_Mathutils_TriangleArea_doc[] = "(v1, v2, v3) - returns the area size of the 2D or 3D triangle defined";
static char M_Mathutils_TriangleNormal_doc[] = "(v1, v2, v3) - returns the normal of the 3D triangle defined";
static char M_Mathutils_QuadNormal_doc[] = "(v1, v2, v3, v4) - returns the normal of the 3D quad defined";
static char M_Mathutils_LineIntersect_doc[] = "(v1, v2, v3, v4) - returns a tuple with the points on each line respectively closest to the other";
//-----------------------METHOD DEFINITIONS ----------------------
static PyObject *M_Mathutils_Rand(PyObject * self, PyObject * args);
static PyObject *M_Mathutils_AngleBetweenVecs(PyObject * self, PyObject * args);
static PyObject *M_Mathutils_MidpointVecs(PyObject * self, PyObject * args);
static PyObject *M_Mathutils_ProjectVecs(PyObject * self, PyObject * args);
static PyObject *M_Mathutils_RotationMatrix(PyObject * self, PyObject * args);
static PyObject *M_Mathutils_TranslationMatrix(PyObject * self, VectorObject * value);
static PyObject *M_Mathutils_ScaleMatrix(PyObject * self, PyObject * args);
static PyObject *M_Mathutils_OrthoProjectionMatrix(PyObject * self, PyObject * args);
static PyObject *M_Mathutils_ShearMatrix(PyObject * self, PyObject * args);
static PyObject *M_Mathutils_DifferenceQuats(PyObject * self, PyObject * args);
static PyObject *M_Mathutils_Slerp(PyObject * self, PyObject * args);
static PyObject *M_Mathutils_Intersect( PyObject * self, PyObject * args );
static PyObject *M_Mathutils_TriangleArea( PyObject * self, PyObject * args );
static PyObject *M_Mathutils_TriangleNormal( PyObject * self, PyObject * args );
static PyObject *M_Mathutils_QuadNormal( PyObject * self, PyObject * args );
static PyObject *M_Mathutils_LineIntersect( PyObject * self, PyObject * args );
struct PyMethodDef M_Mathutils_methods[] = {
{"Rand", (PyCFunction) M_Mathutils_Rand, METH_VARARGS, M_Mathutils_Rand_doc},
{"Vector", (PyCFunction) M_Mathutils_Vector, METH_VARARGS, M_Mathutils_Vector_doc},
{"CrossVecs", (PyCFunction) M_Mathutils_CrossVecs, METH_VARARGS, M_Mathutils_CrossVecs_doc},
{"DotVecs", (PyCFunction) M_Mathutils_DotVecs, METH_VARARGS, M_Mathutils_DotVecs_doc},
{"AngleBetweenVecs", (PyCFunction) M_Mathutils_AngleBetweenVecs, METH_VARARGS, M_Mathutils_AngleBetweenVecs_doc},
{"MidpointVecs", (PyCFunction) M_Mathutils_MidpointVecs, METH_VARARGS, M_Mathutils_MidpointVecs_doc},
{"VecMultMat", (PyCFunction) M_Mathutils_VecMultMat, METH_VARARGS, M_Mathutils_VecMultMat_doc},
{"ProjectVecs", (PyCFunction) M_Mathutils_ProjectVecs, METH_VARARGS, M_Mathutils_ProjectVecs_doc},
{"CopyVec", (PyCFunction) M_Mathutils_CopyVec, METH_VARARGS, M_Mathutils_CopyVec_doc},
{"Matrix", (PyCFunction) M_Mathutils_Matrix, METH_VARARGS, M_Mathutils_Matrix_doc},
{"RotationMatrix", (PyCFunction) M_Mathutils_RotationMatrix, METH_VARARGS, M_Mathutils_RotationMatrix_doc},
{"ScaleMatrix", (PyCFunction) M_Mathutils_ScaleMatrix, METH_VARARGS, M_Mathutils_ScaleMatrix_doc},
{"ShearMatrix", (PyCFunction) M_Mathutils_ShearMatrix, METH_VARARGS, M_Mathutils_ShearMatrix_doc},
{"TranslationMatrix", (PyCFunction) M_Mathutils_TranslationMatrix, METH_O, M_Mathutils_TranslationMatrix_doc},
{"CopyMat", (PyCFunction) M_Mathutils_CopyMat, METH_VARARGS, M_Mathutils_CopyMat_doc},
{"OrthoProjectionMatrix", (PyCFunction) M_Mathutils_OrthoProjectionMatrix, METH_VARARGS, M_Mathutils_OrthoProjectionMatrix_doc},
{"MatMultVec", (PyCFunction) M_Mathutils_MatMultVec, METH_VARARGS, M_Mathutils_MatMultVec_doc},
{"Quaternion", (PyCFunction) M_Mathutils_Quaternion, METH_VARARGS, M_Mathutils_Quaternion_doc},
{"CopyQuat", (PyCFunction) M_Mathutils_CopyQuat, METH_VARARGS, M_Mathutils_CopyQuat_doc},
{"CrossQuats", (PyCFunction) M_Mathutils_CrossQuats, METH_VARARGS, M_Mathutils_CrossQuats_doc},
{"DotQuats", (PyCFunction) M_Mathutils_DotQuats, METH_VARARGS, M_Mathutils_DotQuats_doc},
{"DifferenceQuats", (PyCFunction) M_Mathutils_DifferenceQuats, METH_VARARGS,M_Mathutils_DifferenceQuats_doc},
{"Slerp", (PyCFunction) M_Mathutils_Slerp, METH_VARARGS, M_Mathutils_Slerp_doc},
{"Euler", (PyCFunction) M_Mathutils_Euler, METH_VARARGS, M_Mathutils_Euler_doc},
{"CopyEuler", (PyCFunction) M_Mathutils_CopyEuler, METH_VARARGS, M_Mathutils_CopyEuler_doc},
{"RotateEuler", (PyCFunction) M_Mathutils_RotateEuler, METH_VARARGS, M_Mathutils_RotateEuler_doc},
{"Intersect", ( PyCFunction ) M_Mathutils_Intersect, METH_VARARGS, M_Mathutils_Intersect_doc},
{"TriangleArea", ( PyCFunction ) M_Mathutils_TriangleArea, METH_VARARGS, M_Mathutils_TriangleArea_doc},
{"TriangleNormal", ( PyCFunction ) M_Mathutils_TriangleNormal, METH_VARARGS, M_Mathutils_TriangleNormal_doc},
@@ -102,6 +90,7 @@ struct PyMethodDef M_Mathutils_methods[] = {
{"LineIntersect", ( PyCFunction ) M_Mathutils_LineIntersect, METH_VARARGS, M_Mathutils_LineIntersect_doc},
{NULL, NULL, 0, NULL}
};
/*----------------------------MODULE INIT-------------------------*/
/* from can be Blender.Mathutils or GameLogic.Mathutils for the BGE */
@@ -142,6 +131,12 @@ PyObject *Mathutils_Init(const char *from)
submodule = Py_InitModule3(from, M_Mathutils_methods, M_Mathutils_doc);
#endif
/* each type has its own new() function */
PyModule_AddObject( submodule, "Vector", (PyObject *)&vector_Type );
PyModule_AddObject( submodule, "Matrix", (PyObject *)&matrix_Type );
PyModule_AddObject( submodule, "Euler", (PyObject *)&euler_Type );
PyModule_AddObject( submodule, "Quaternion", (PyObject *)&quaternion_Type );
return (submodule);
}
@@ -272,7 +267,7 @@ PyObject *quat_rotation(PyObject *arg1, PyObject *arg2)
//----------------------------------Mathutils.Rand() --------------------
//returns a random number between a high and low value
PyObject *M_Mathutils_Rand(PyObject * self, PyObject * args)
static PyObject *M_Mathutils_Rand(PyObject * self, PyObject * args)
{
float high, low, range;
double drand;
@@ -300,108 +295,9 @@ PyObject *M_Mathutils_Rand(PyObject * self, PyObject * args)
return PyFloat_FromDouble(drand);
}
//----------------------------------VECTOR FUNCTIONS---------------------
//----------------------------------Mathutils.Vector() ------------------
// Supports 2D, 3D, and 4D vector objects both int and float values
// accepted. Mixed float and int values accepted. Ints are parsed to float
PyObject *M_Mathutils_Vector(PyObject * self, PyObject * args)
{
PyObject *listObject = NULL;
int size, i;
float vec[4], f;
PyObject *v;
size = PySequence_Length(args);
if (size == 1) {
listObject = PySequence_GetItem(args, 0);
if (PySequence_Check(listObject)) {
size = PySequence_Length(listObject);
} else { // Single argument was not a sequence
Py_XDECREF(listObject);
PyErr_SetString(PyExc_TypeError, "Mathutils.Vector(): 2-4 floats or ints expected (optionally in a sequence)\n");
return NULL;
}
} else if (size == 0) {
//returns a new empty 3d vector
return newVectorObject(NULL, 3, Py_NEW);
} else {
Py_INCREF(args);
listObject = args;
}
if (size<2 || size>4) { // Invalid vector size
Py_XDECREF(listObject);
PyErr_SetString(PyExc_AttributeError, "Mathutils.Vector(): 2-4 floats or ints expected (optionally in a sequence)\n");
return NULL;
}
for (i=0; i<size; i++) {
v=PySequence_GetItem(listObject, i);
if (v==NULL) { // Failed to read sequence
Py_XDECREF(listObject);
PyErr_SetString(PyExc_RuntimeError, "Mathutils.Vector(): 2-4 floats or ints expected (optionally in a sequence)\n");
return NULL;
}
f= PyFloat_AsDouble(v);
if(f==-1 && PyErr_Occurred()) { // parsed item not a number
Py_DECREF(v);
Py_XDECREF(listObject);
PyErr_SetString(PyExc_TypeError, "Mathutils.Vector(): 2-4 floats or ints expected (optionally in a sequence)\n");
return NULL;
}
vec[i]= f;
Py_DECREF(v);
}
Py_DECREF(listObject);
return newVectorObject(vec, size, Py_NEW);
}
//----------------------------------Mathutils.CrossVecs() ---------------
//finds perpendicular vector - only 3D is supported
PyObject *M_Mathutils_CrossVecs(PyObject * self, PyObject * args)
{
PyObject *vecCross = NULL;
VectorObject *vec1 = NULL, *vec2 = NULL;
if(!PyArg_ParseTuple(args, "O!O!", &vector_Type, &vec1, &vector_Type, &vec2)) {
PyErr_SetString(PyExc_TypeError, "Mathutils.CrossVecs(): expects (2) 3D vector objects\n");
return NULL;
}
if(vec1->size != 3 || vec2->size != 3) {
PyErr_SetString(PyExc_AttributeError, "Mathutils.CrossVecs(): expects (2) 3D vector objects\n");
return NULL;
}
vecCross = newVectorObject(NULL, 3, Py_NEW);
Crossf(((VectorObject*)vecCross)->vec, vec1->vec, vec2->vec);
return vecCross;
}
//----------------------------------Mathutils.DotVec() -------------------
//calculates the dot product of two vectors
PyObject *M_Mathutils_DotVecs(PyObject * self, PyObject * args)
{
VectorObject *vec1 = NULL, *vec2 = NULL;
double dot = 0.0f;
int x;
if(!PyArg_ParseTuple(args, "O!O!", &vector_Type, &vec1, &vector_Type, &vec2)) {
PyErr_SetString(PyExc_TypeError, "Mathutils.DotVecs(): expects (2) vector objects of the same size\n");
return NULL;
}
if(vec1->size != vec2->size) {
PyErr_SetString(PyExc_AttributeError, "Mathutils.DotVecs(): expects (2) vector objects of the same size\n");
return NULL;
}
for(x = 0; x < vec1->size; x++) {
dot += vec1->vec[x] * vec2->vec[x];
}
return PyFloat_FromDouble(dot);
}
//----------------------------------Mathutils.AngleBetweenVecs() ---------
//calculates the angle between 2 vectors
PyObject *M_Mathutils_AngleBetweenVecs(PyObject * self, PyObject * args)
static PyObject *M_Mathutils_AngleBetweenVecs(PyObject * self, PyObject * args)
{
VectorObject *vec1 = NULL, *vec2 = NULL;
double dot = 0.0f, angleRads, test_v1 = 0.0f, test_v2 = 0.0f;
@@ -443,7 +339,7 @@ AttributeError2:
}
//----------------------------------Mathutils.MidpointVecs() -------------
//calculates the midpoint between 2 vectors
PyObject *M_Mathutils_MidpointVecs(PyObject * self, PyObject * args)
static PyObject *M_Mathutils_MidpointVecs(PyObject * self, PyObject * args)
{
VectorObject *vec1 = NULL, *vec2 = NULL;
float vec[4];
@@ -465,7 +361,7 @@ PyObject *M_Mathutils_MidpointVecs(PyObject * self, PyObject * args)
}
//----------------------------------Mathutils.ProjectVecs() -------------
//projects vector 1 onto vector 2
PyObject *M_Mathutils_ProjectVecs(PyObject * self, PyObject * args)
static PyObject *M_Mathutils_ProjectVecs(PyObject * self, PyObject * args)
{
VectorObject *vec1 = NULL, *vec2 = NULL;
float vec[4];
@@ -497,94 +393,10 @@ PyObject *M_Mathutils_ProjectVecs(PyObject * self, PyObject * args)
return newVectorObject(vec, size, Py_NEW);
}
//----------------------------------MATRIX FUNCTIONS--------------------
//----------------------------------Mathutils.Matrix() -----------------
//mat is a 1D array of floats - row[0][0],row[0][1], row[1][0], etc.
//create a new matrix type
PyObject *M_Mathutils_Matrix(PyObject * self, PyObject * args)
{
PyObject *listObject = NULL;
PyObject *argObject, *m, *s, *f;
MatrixObject *mat;
int argSize, seqSize = 0, i, j;
float matrix[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
argSize = PySequence_Length(args);
if(argSize > 4){ //bad arg nums
PyErr_SetString(PyExc_AttributeError, "Mathutils.Matrix(): expects 0-4 numeric sequences of the same size\n");
return NULL;
} else if (argSize == 0) { //return empty 4D matrix
return (PyObject *) newMatrixObject(NULL, 4, 4, Py_NEW);
}else if (argSize == 1){
//copy constructor for matrix objects
argObject = PySequence_GetItem(args, 0);
if(MatrixObject_Check(argObject)){
mat = (MatrixObject*)argObject;
argSize = mat->rowSize; //rows
seqSize = mat->colSize; //col
for(i = 0; i < (seqSize * argSize); i++){
matrix[i] = mat->contigPtr[i];
}
}
Py_DECREF(argObject);
}else{ //2-4 arguments (all seqs? all same size?)
for(i =0; i < argSize; i++){
argObject = PySequence_GetItem(args, i);
if (PySequence_Check(argObject)) { //seq?
if(seqSize){ //0 at first
if(PySequence_Length(argObject) != seqSize){ //seq size not same
Py_DECREF(argObject);
PyErr_SetString(PyExc_AttributeError, "Mathutils.Matrix(): expects 0-4 numeric sequences of the same size\n");
return NULL;
}
}
seqSize = PySequence_Length(argObject);
}else{ //arg not a sequence
Py_XDECREF(argObject);
PyErr_SetString(PyExc_TypeError, "Mathutils.Matrix(): expects 0-4 numeric sequences of the same size\n");
return NULL;
}
Py_DECREF(argObject);
}
//all is well... let's continue parsing
listObject = args;
for (i = 0; i < argSize; i++){
m = PySequence_GetItem(listObject, i);
if (m == NULL) { // Failed to read sequence
PyErr_SetString(PyExc_RuntimeError, "Mathutils.Matrix(): failed to parse arguments...\n");
return NULL;
}
for (j = 0; j < seqSize; j++) {
s = PySequence_GetItem(m, j);
if (s == NULL) { // Failed to read sequence
Py_DECREF(m);
PyErr_SetString(PyExc_RuntimeError, "Mathutils.Matrix(): failed to parse arguments...\n");
return NULL;
}
f = PyNumber_Float(s);
if(f == NULL) { // parsed item is not a number
Py_DECREF(m);
Py_DECREF(s);
PyErr_SetString(PyExc_AttributeError, "Mathutils.Matrix(): expects 0-4 numeric sequences of the same size\n");
return NULL;
}
matrix[(seqSize*i)+j]=(float)PyFloat_AS_DOUBLE(f);
Py_DECREF(f);
Py_DECREF(s);
}
Py_DECREF(m);
}
}
return newMatrixObject(matrix, argSize, seqSize, Py_NEW);
}
//----------------------------------Mathutils.RotationMatrix() ----------
//mat is a 1D array of floats - row[0][0],row[0][1], row[1][0], etc.
//creates a rotation matrix
PyObject *M_Mathutils_RotationMatrix(PyObject * self, PyObject * args)
static PyObject *M_Mathutils_RotationMatrix(PyObject * self, PyObject * args)
{
VectorObject *vec = NULL;
char *axis = NULL;
@@ -713,7 +525,7 @@ PyObject *M_Mathutils_RotationMatrix(PyObject * self, PyObject * args)
}
//----------------------------------Mathutils.TranslationMatrix() -------
//creates a translation matrix
PyObject *M_Mathutils_TranslationMatrix(PyObject * self, VectorObject * vec)
static PyObject *M_Mathutils_TranslationMatrix(PyObject * self, VectorObject * vec)
{
float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
@@ -737,7 +549,7 @@ PyObject *M_Mathutils_TranslationMatrix(PyObject * self, VectorObject * vec)
//----------------------------------Mathutils.ScaleMatrix() -------------
//mat is a 1D array of floats - row[0][0],row[0][1], row[1][0], etc.
//creates a scaling matrix
PyObject *M_Mathutils_ScaleMatrix(PyObject * self, PyObject * args)
static PyObject *M_Mathutils_ScaleMatrix(PyObject * self, PyObject * args)
{
VectorObject *vec = NULL;
float norm = 0.0f, factor;
@@ -811,7 +623,7 @@ PyObject *M_Mathutils_ScaleMatrix(PyObject * self, PyObject * args)
//----------------------------------Mathutils.OrthoProjectionMatrix() ---
//mat is a 1D array of floats - row[0][0],row[0][1], row[1][0], etc.
//creates an ortho projection matrix
PyObject *M_Mathutils_OrthoProjectionMatrix(PyObject * self, PyObject * args)
static PyObject *M_Mathutils_OrthoProjectionMatrix(PyObject * self, PyObject * args)
{
VectorObject *vec = NULL;
char *plane;
@@ -909,7 +721,7 @@ PyObject *M_Mathutils_OrthoProjectionMatrix(PyObject * self, PyObject * args)
}
//----------------------------------Mathutils.ShearMatrix() -------------
//creates a shear matrix
PyObject *M_Mathutils_ShearMatrix(PyObject * self, PyObject * args)
static PyObject *M_Mathutils_ShearMatrix(PyObject * self, PyObject * args)
{
int matSize;
char *plane;
@@ -975,167 +787,10 @@ PyObject *M_Mathutils_ShearMatrix(PyObject * self, PyObject * args)
return newMatrixObject(mat, matSize, matSize, Py_NEW);
}
//----------------------------------QUATERNION FUNCTIONS-----------------
//----------------------------------Mathutils.Quaternion() --------------
PyObject *M_Mathutils_Quaternion(PyObject * self, PyObject * args)
{
PyObject *listObject = NULL, *n, *q, *f;
int size, i;
float quat[4];
double norm = 0.0f, angle = 0.0f;
size = PySequence_Length(args);
if (size == 1 || size == 2) { //seq?
listObject = PySequence_GetItem(args, 0);
if (PySequence_Check(listObject)) {
size = PySequence_Length(listObject);
if ((size == 4 && PySequence_Length(args) !=1) ||
(size == 3 && PySequence_Length(args) !=2) || (size >4 || size < 3)) {
// invalid args/size
Py_DECREF(listObject);
PyErr_SetString(PyExc_AttributeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
return NULL;
}
if(size == 3){ //get angle in axis/angle
n = PySequence_GetItem(args, 1);
if(n == NULL) { // parsed item not a number or getItem fail
Py_DECREF(listObject);
PyErr_SetString(PyExc_TypeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
return NULL;
}
angle = PyFloat_AsDouble(n);
Py_DECREF(n);
if (angle==-1 && PyErr_Occurred()) {
Py_DECREF(listObject);
PyErr_SetString(PyExc_TypeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
return NULL;
}
}
}else{
Py_DECREF(listObject); /* assume the list is teh second arg */
listObject = PySequence_GetItem(args, 1);
if (size>1 && PySequence_Check(listObject)) {
size = PySequence_Length(listObject);
if (size != 3) {
// invalid args/size
Py_DECREF(listObject);
PyErr_SetString(PyExc_AttributeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
return NULL;
}
n = PySequence_GetItem(args, 0);
if(n == NULL) { // parsed item not a number or getItem fail
Py_DECREF(listObject);
PyErr_SetString(PyExc_TypeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
return NULL;
}
angle = PyFloat_AsDouble(n);
Py_DECREF(n);
if (angle==-1 && PyErr_Occurred()) {
Py_DECREF(listObject);
PyErr_SetString(PyExc_TypeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
return NULL;
}
} else { // argument was not a sequence
Py_XDECREF(listObject);
PyErr_SetString(PyExc_TypeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
return NULL;
}
}
} else if (size == 0) { //returns a new empty quat
return newQuaternionObject(NULL, Py_NEW);
} else {
Py_INCREF(args);
listObject = args;
}
if (size == 3) { // invalid quat size
if(PySequence_Length(args) != 2){
Py_DECREF(listObject);
PyErr_SetString(PyExc_AttributeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
return NULL;
}
}else{
if(size != 4){
Py_DECREF(listObject);
PyErr_SetString(PyExc_AttributeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
return NULL;
}
}
for (i=0; i<size; i++) { //parse
q = PySequence_GetItem(listObject, i);
if (q == NULL) { // Failed to read sequence
Py_DECREF(listObject);
PyErr_SetString(PyExc_RuntimeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
return NULL;
}
f = PyNumber_Float(q);
if(f == NULL) { // parsed item not a number
Py_DECREF(q);
Py_DECREF(listObject);
PyErr_SetString(PyExc_TypeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
return NULL;
}
quat[i] = (float)PyFloat_AS_DOUBLE(f);
Py_DECREF(f);
Py_DECREF(q);
}
if(size == 3){ //calculate the quat based on axis/angle
norm = sqrt(quat[0] * quat[0] + quat[1] * quat[1] + quat[2] * quat[2]);
quat[0] /= (float)norm;
quat[1] /= (float)norm;
quat[2] /= (float)norm;
angle = angle * (Py_PI / 180);
quat[3] =(float) (sin(angle/ 2.0f)) * quat[2];
quat[2] =(float) (sin(angle/ 2.0f)) * quat[1];
quat[1] =(float) (sin(angle/ 2.0f)) * quat[0];
quat[0] =(float) (cos(angle/ 2.0f));
}
Py_DECREF(listObject);
return newQuaternionObject(quat, Py_NEW);
}
//----------------------------------Mathutils.CrossQuats() ----------------
//quaternion multiplication - associate not commutative
PyObject *M_Mathutils_CrossQuats(PyObject * self, PyObject * args)
{
QuaternionObject *quatU = NULL, *quatV = NULL;
float quat[4];
if(!PyArg_ParseTuple(args, "O!O!", &quaternion_Type, &quatU, &quaternion_Type, &quatV)) {
PyErr_SetString(PyExc_TypeError,"Mathutils.CrossQuats(): expected Quaternion types");
return NULL;
}
QuatMul(quat, quatU->quat, quatV->quat);
return newQuaternionObject(quat, Py_NEW);
}
//----------------------------------Mathutils.DotQuats() ----------------
//returns the dot product of 2 quaternions
PyObject *M_Mathutils_DotQuats(PyObject * self, PyObject * args)
{
QuaternionObject *quatU = NULL, *quatV = NULL;
double dot = 0.0f;
int x;
if(!PyArg_ParseTuple(args, "O!O!", &quaternion_Type, &quatU, &quaternion_Type, &quatV)) {
PyErr_SetString(PyExc_TypeError, "Mathutils.DotQuats(): expected Quaternion types");
return NULL;
}
for(x = 0; x < 4; x++) {
dot += quatU->quat[x] * quatV->quat[x];
}
return PyFloat_FromDouble(dot);
}
//----------------------------------Mathutils.DifferenceQuats() ---------
//returns the difference between 2 quaternions
PyObject *M_Mathutils_DifferenceQuats(PyObject * self, PyObject * args)
static PyObject *M_Mathutils_DifferenceQuats(PyObject * self, PyObject * args)
{
QuaternionObject *quatU = NULL, *quatV = NULL;
float quat[4], tempQuat[4];
@@ -1162,7 +817,7 @@ PyObject *M_Mathutils_DifferenceQuats(PyObject * self, PyObject * args)
}
//----------------------------------Mathutils.Slerp() ------------------
//attemps to interpolate 2 quaternions and return the result
PyObject *M_Mathutils_Slerp(PyObject * self, PyObject * args)
static PyObject *M_Mathutils_Slerp(PyObject * self, PyObject * args)
{
QuaternionObject *quatU = NULL, *quatV = NULL;
float quat[4], quat_u[4], quat_v[4], param;
@@ -1218,67 +873,9 @@ PyObject *M_Mathutils_Slerp(PyObject * self, PyObject * args)
return newQuaternionObject(quat, Py_NEW);
}
//----------------------------------EULER FUNCTIONS----------------------
//----------------------------------Mathutils.Euler() -------------------
//makes a new euler for you to play with
PyObject *M_Mathutils_Euler(PyObject * self, PyObject * args)
{
PyObject *listObject = NULL;
int size, i;
float eul[3];
PyObject *e, *f;
size = PySequence_Length(args);
if (size == 1) {
listObject = PySequence_GetItem(args, 0);
if (PySequence_Check(listObject)) {
size = PySequence_Length(listObject);
} else { // Single argument was not a sequence
Py_DECREF(listObject);
PyErr_SetString(PyExc_TypeError, "Mathutils.Euler(): 3d numeric sequence expected\n");
return NULL;
}
} else if (size == 0) {
//returns a new empty 3d euler
return newEulerObject(NULL, Py_NEW);
} else {
Py_INCREF(args);
listObject = args;
}
if (size != 3) { // Invalid euler size
Py_DECREF(listObject);
PyErr_SetString(PyExc_AttributeError, "Mathutils.Euler(): 3d numeric sequence expected\n");
return NULL;
}
for (i=0; i<size; i++) {
e = PySequence_GetItem(listObject, i);
if (e == NULL) { // Failed to read sequence
Py_DECREF(listObject);
PyErr_SetString(PyExc_RuntimeError, "Mathutils.Euler(): 3d numeric sequence expected\n");
return NULL;
}
f = PyNumber_Float(e);
if(f == NULL) { // parsed item not a number
Py_DECREF(e);
Py_DECREF(listObject);
PyErr_SetString(PyExc_TypeError, "Mathutils.Euler(): 3d numeric sequence expected\n");
return NULL;
}
eul[i]=(float)PyFloat_AS_DOUBLE(f);
Py_DECREF(f);
Py_DECREF(e);
}
Py_DECREF(listObject);
return newEulerObject(eul, Py_NEW);
}
//---------------------------------INTERSECTION FUNCTIONS--------------------
//----------------------------------Mathutils.Intersect() -------------------
PyObject *M_Mathutils_Intersect( PyObject * self, PyObject * args )
static PyObject *M_Mathutils_Intersect( PyObject * self, PyObject * args )
{
VectorObject *ray, *ray_off, *vec1, *vec2, *vec3;
float dir[3], orig[3], v1[3], v2[3], v3[3], e1[3], e2[3], pvec[3], tvec[3], qvec[3];
@@ -1348,7 +945,7 @@ PyObject *M_Mathutils_Intersect( PyObject * self, PyObject * args )
}
//----------------------------------Mathutils.LineIntersect() -------------------
/* Line-Line intersection using algorithm from mathworld.wolfram.com */
PyObject *M_Mathutils_LineIntersect( PyObject * self, PyObject * args )
static PyObject *M_Mathutils_LineIntersect( PyObject * self, PyObject * args )
{
PyObject * tuple;
VectorObject *vec1, *vec2, *vec3, *vec4;
@@ -1412,7 +1009,7 @@ PyObject *M_Mathutils_LineIntersect( PyObject * self, PyObject * args )
//---------------------------------NORMALS FUNCTIONS--------------------
//----------------------------------Mathutils.QuadNormal() -------------------
PyObject *M_Mathutils_QuadNormal( PyObject * self, PyObject * args )
static PyObject *M_Mathutils_QuadNormal( PyObject * self, PyObject * args )
{
VectorObject *vec1;
VectorObject *vec2;
@@ -1459,7 +1056,7 @@ PyObject *M_Mathutils_QuadNormal( PyObject * self, PyObject * args )
}
//----------------------------Mathutils.TriangleNormal() -------------------
PyObject *M_Mathutils_TriangleNormal( PyObject * self, PyObject * args )
static PyObject *M_Mathutils_TriangleNormal( PyObject * self, PyObject * args )
{
VectorObject *vec1, *vec2, *vec3;
float v1[3], v2[3], v3[3], e1[3], e2[3], n[3];
@@ -1493,7 +1090,7 @@ PyObject *M_Mathutils_TriangleNormal( PyObject * self, PyObject * args )
//--------------------------------- AREA FUNCTIONS--------------------
//----------------------------------Mathutils.TriangleArea() -------------------
PyObject *M_Mathutils_TriangleArea( PyObject * self, PyObject * args )
static PyObject *M_Mathutils_TriangleArea( PyObject * self, PyObject * args )
{
VectorObject *vec1, *vec2, *vec3;
float v1[3], v2[3], v3[3];
@@ -1533,145 +1130,6 @@ PyObject *M_Mathutils_TriangleArea( PyObject * self, PyObject * args )
return NULL;
}
}
//#############################DEPRECATED################################
//#######################################################################
//----------------------------------Mathutils.CopyMat() -----------------
//copies a matrix into a new matrix
PyObject *M_Mathutils_CopyMat(PyObject * self, PyObject * args)
{
PyObject *matrix = NULL;
static char warning = 1;
if( warning ) {
printf("Mathutils.CopyMat(): deprecated :use Mathutils.Matrix() to copy matrices\n");
--warning;
}
matrix = M_Mathutils_Matrix(self, args);
if(matrix == NULL)
return NULL; //error string already set if we get here
else
return matrix;
}
//----------------------------------Mathutils.CopyVec() -----------------
//makes a new vector that is a copy of the input
PyObject *M_Mathutils_CopyVec(PyObject * self, PyObject * args)
{
PyObject *vec = NULL;
static char warning = 1;
if( warning ) {
printf("Mathutils.CopyVec(): Deprecated: use Mathutils.Vector() to copy vectors\n");
--warning;
}
vec = M_Mathutils_Vector(self, args);
if(vec == NULL)
return NULL; //error string already set if we get here
else
return vec;
}
//----------------------------------Mathutils.CopyQuat() --------------
//Copies a quaternion to a new quat
PyObject *M_Mathutils_CopyQuat(PyObject * self, PyObject * args)
{
PyObject *quat = NULL;
static char warning = 1;
if( warning ) {
printf("Mathutils.CopyQuat(): Deprecated: use Mathutils.Quaternion() to copy vectors\n");
--warning;
}
quat = M_Mathutils_Quaternion(self, args);
if(quat == NULL)
return NULL; //error string already set if we get here
else
return quat;
}
//----------------------------------Mathutils.CopyEuler() ---------------
//copies a euler to a new euler
PyObject *M_Mathutils_CopyEuler(PyObject * self, PyObject * args)
{
PyObject *eul = NULL;
static char warning = 1;
if( warning ) {
printf("Mathutils.CopyEuler(): deprecated:use Mathutils.Euler() to copy vectors\n");
--warning;
}
eul = M_Mathutils_Euler(self, args);
if(eul == NULL)
return NULL; //error string already set if we get here
else
return eul;
}
//----------------------------------Mathutils.RotateEuler() ------------
//rotates a euler a certain amount and returns the result
//should return a unique euler rotation (i.e. no 720 degree pitches :)
PyObject *M_Mathutils_RotateEuler(PyObject * self, PyObject * args)
{
EulerObject *Eul = NULL;
float angle;
char *axis;
static char warning = 1;
if( warning ) {
printf("Mathutils.RotateEuler(): Deprecated:use Euler.rotate() to rotate a euler\n");
--warning;
}
if(!PyArg_ParseTuple(args, "O!fs", &euler_Type, &Eul, &angle, &axis)) {
PyErr_SetString(PyExc_TypeError, "Mathutils.RotateEuler(): expected euler type & float & string");
return NULL;
}
Euler_Rotate(Eul, Py_BuildValue("fs", angle, axis));
Py_RETURN_NONE;
}
//----------------------------------Mathutils.MatMultVec() --------------
//COLUMN VECTOR Multiplication (Matrix X Vector)
PyObject *M_Mathutils_MatMultVec(PyObject * self, PyObject * args)
{
MatrixObject *mat = NULL;
VectorObject *vec = NULL;
static char warning = 1;
if( warning ) {
printf("Mathutils.MatMultVec(): Deprecated: use matrix * vec to perform column vector multiplication\n");
--warning;
}
//get pyObjects
if(!PyArg_ParseTuple(args, "O!O!", &matrix_Type, &mat, &vector_Type, &vec)) {
PyErr_SetString(PyExc_TypeError, "Mathutils.MatMultVec(): MatMultVec() expects a matrix and a vector object - in that order\n");
return NULL;
}
return column_vector_multiplication(mat, vec);
}
//----------------------------------Mathutils.VecMultMat() ---------------
//ROW VECTOR Multiplication - Vector X Matrix
PyObject *M_Mathutils_VecMultMat(PyObject * self, PyObject * args)
{
MatrixObject *mat = NULL;
VectorObject *vec = NULL;
static char warning = 1;
if( warning ) {
printf("Mathutils.VecMultMat(): Deprecated: use vec * matrix to perform row vector multiplication\n");
--warning;
}
//get pyObjects
if(!PyArg_ParseTuple(args, "O!O!", &vector_Type, &vec, &matrix_Type, &mat)) {
PyErr_SetString(PyExc_TypeError, "Mathutils.VecMultMat(): VecMultMat() expects a vector and matrix object - in that order\n");
return NULL;
}
return row_vector_multiplication(vec, mat);
}
/* Utility functions */

View File

@@ -44,39 +44,6 @@ PyObject *row_vector_multiplication(VectorObject* vec, MatrixObject * mat);
PyObject *column_vector_multiplication(MatrixObject * mat, VectorObject* vec);
PyObject *quat_rotation(PyObject *arg1, PyObject *arg2);
PyObject *M_Mathutils_Rand(PyObject * self, PyObject * args);
PyObject *M_Mathutils_Vector(PyObject * self, PyObject * args);
PyObject *M_Mathutils_AngleBetweenVecs(PyObject * self, PyObject * args);
PyObject *M_Mathutils_MidpointVecs(PyObject * self, PyObject * args);
PyObject *M_Mathutils_ProjectVecs(PyObject * self, PyObject * args);
PyObject *M_Mathutils_Matrix(PyObject * self, PyObject * args);
PyObject *M_Mathutils_RotationMatrix(PyObject * self, PyObject * args);
PyObject *M_Mathutils_TranslationMatrix(PyObject * self, VectorObject * value);
PyObject *M_Mathutils_ScaleMatrix(PyObject * self, PyObject * args);
PyObject *M_Mathutils_OrthoProjectionMatrix(PyObject * self, PyObject * args);
PyObject *M_Mathutils_ShearMatrix(PyObject * self, PyObject * args);
PyObject *M_Mathutils_Quaternion(PyObject * self, PyObject * args);
PyObject *M_Mathutils_DifferenceQuats(PyObject * self, PyObject * args);
PyObject *M_Mathutils_Slerp(PyObject * self, PyObject * args);
PyObject *M_Mathutils_Euler(PyObject * self, PyObject * args);
PyObject *M_Mathutils_Intersect( PyObject * self, PyObject * args );
PyObject *M_Mathutils_TriangleArea( PyObject * self, PyObject * args );
PyObject *M_Mathutils_TriangleNormal( PyObject * self, PyObject * args );
PyObject *M_Mathutils_QuadNormal( PyObject * self, PyObject * args );
PyObject *M_Mathutils_LineIntersect( PyObject * self, PyObject * args );
//DEPRECATED
PyObject *M_Mathutils_CopyMat(PyObject * self, PyObject * args);
PyObject *M_Mathutils_CopyVec(PyObject * self, PyObject * args);
PyObject *M_Mathutils_CopyQuat(PyObject * self, PyObject * args);
PyObject *M_Mathutils_CopyEuler(PyObject * self, PyObject * args);
PyObject *M_Mathutils_RotateEuler(PyObject * self, PyObject * args);
PyObject *M_Mathutils_MatMultVec(PyObject * self, PyObject * args);
PyObject *M_Mathutils_VecMultMat(PyObject * self, PyObject * args);
PyObject *M_Mathutils_CrossVecs(PyObject * self, PyObject * args);
PyObject *M_Mathutils_DotVecs(PyObject * self, PyObject * args);
PyObject *M_Mathutils_CrossQuats(PyObject * self, PyObject * args);
PyObject *M_Mathutils_DotQuats(PyObject * self, PyObject * args);
int EXPP_FloatsAreEqual(float A, float B, int floatSteps);
int EXPP_VectorsAreEqual(float *vecA, float *vecB, int size, int floatSteps);

View File

@@ -34,15 +34,24 @@
//-------------------------DOC STRINGS ---------------------------
char Euler_Zero_doc[] = "() - set all values in the euler to 0";
char Euler_Unique_doc[] ="() - sets the euler rotation a unique shortest arc rotation - tests for gimbal lock";
char Euler_ToMatrix_doc[] = "() - returns a rotation matrix representing the euler rotation";
char Euler_ToQuat_doc[] = "() - returns a quaternion representing the euler rotation";
char Euler_Rotate_doc[] = "() - rotate a euler by certain amount around an axis of rotation";
char Euler_copy_doc[] = "() - returns a copy of the euler.";
char Euler_MakeCompatible_doc[] = "(euler) - Make this user compatible with another (no axis flipping).";
static char Euler_Zero_doc[] = "() - set all values in the euler to 0";
static char Euler_Unique_doc[] ="() - sets the euler rotation a unique shortest arc rotation - tests for gimbal lock";
static char Euler_ToMatrix_doc[] = "() - returns a rotation matrix representing the euler rotation";
static char Euler_ToQuat_doc[] = "() - returns a quaternion representing the euler rotation";
static char Euler_Rotate_doc[] = "() - rotate a euler by certain amount around an axis of rotation";
static char Euler_copy_doc[] = "() - returns a copy of the euler.";
static char Euler_MakeCompatible_doc[] = "(euler) - Make this user compatible with another (no axis flipping).";
static PyObject *Euler_Zero( EulerObject * self );
static PyObject *Euler_Unique( EulerObject * self );
static PyObject *Euler_ToMatrix( EulerObject * self );
static PyObject *Euler_ToQuat( EulerObject * self );
static PyObject *Euler_Rotate( EulerObject * self, PyObject *args );
static PyObject *Euler_MakeCompatible( EulerObject * self, EulerObject *value );
static PyObject *Euler_copy( EulerObject * self, PyObject *args );
//-----------------------METHOD DEFINITIONS ----------------------
struct PyMethodDef Euler_methods[] = {
static struct PyMethodDef Euler_methods[] = {
{"zero", (PyCFunction) Euler_Zero, METH_NOARGS, Euler_Zero_doc},
{"unique", (PyCFunction) Euler_Unique, METH_NOARGS, Euler_Unique_doc},
{"toMatrix", (PyCFunction) Euler_ToMatrix, METH_NOARGS, Euler_ToMatrix_doc},
@@ -53,10 +62,63 @@ struct PyMethodDef Euler_methods[] = {
{"copy", (PyCFunction) Euler_copy, METH_VARARGS, Euler_copy_doc},
{NULL, NULL, 0, NULL}
};
//----------------------------------Mathutils.Euler() -------------------
//makes a new euler for you to play with
static PyObject *Euler_new(PyObject * self, PyObject * args)
{
PyObject *listObject = NULL;
int size, i;
float eul[3], scalar;
PyObject *e;
size = PyTuple_GET_SIZE(args);
if (size == 1) {
listObject = PyTuple_GET_ITEM(args, 0);
if (PySequence_Check(listObject)) {
size = PySequence_Length(listObject);
} else { // Single argument was not a sequence
PyErr_SetString(PyExc_TypeError, "Mathutils.Euler(): 3d numeric sequence expected\n");
return NULL;
}
} else if (size == 0) {
//returns a new empty 3d euler
return newEulerObject(NULL, Py_NEW);
} else {
listObject = args;
}
if (size != 3) { // Invalid euler size
PyErr_SetString(PyExc_AttributeError, "Mathutils.Euler(): 3d numeric sequence expected\n");
return NULL;
}
for (i=0; i<size; i++) {
e = PySequence_GetItem(listObject, i);
if (e == NULL) { // Failed to read sequence
Py_DECREF(listObject);
PyErr_SetString(PyExc_RuntimeError, "Mathutils.Euler(): 3d numeric sequence expected\n");
return NULL;
}
scalar= (float)PyFloat_AsDouble(e);
Py_DECREF(e);
if(scalar==-1 && PyErr_Occurred()) { // parsed item is not a number
PyErr_SetString(PyExc_TypeError, "Mathutils.Euler(): 3d numeric sequence expected\n");
return NULL;
}
eul[i]= scalar;
}
return newEulerObject(eul, Py_NEW);
}
//-----------------------------METHODS----------------------------
//----------------------------Euler.toQuat()----------------------
//return a quaternion representation of the euler
PyObject *Euler_ToQuat(EulerObject * self)
static PyObject *Euler_ToQuat(EulerObject * self)
{
float eul[3], quat[4];
int x;
@@ -69,7 +131,7 @@ PyObject *Euler_ToQuat(EulerObject * self)
}
//----------------------------Euler.toMatrix()---------------------
//return a matrix representation of the euler
PyObject *Euler_ToMatrix(EulerObject * self)
static PyObject *Euler_ToMatrix(EulerObject * self)
{
float eul[3];
float mat[9] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
@@ -83,7 +145,7 @@ PyObject *Euler_ToMatrix(EulerObject * self)
}
//----------------------------Euler.unique()-----------------------
//sets the x,y,z values to a unique euler rotation
PyObject *Euler_Unique(EulerObject * self)
static PyObject *Euler_Unique(EulerObject * self)
{
double heading, pitch, bank;
double pi2 = Py_PI * 2.0f;
@@ -134,7 +196,7 @@ PyObject *Euler_Unique(EulerObject * self)
}
//----------------------------Euler.zero()-------------------------
//sets the euler to 0,0,0
PyObject *Euler_Zero(EulerObject * self)
static PyObject *Euler_Zero(EulerObject * self)
{
self->eul[0] = 0.0;
self->eul[1] = 0.0;
@@ -146,7 +208,7 @@ PyObject *Euler_Zero(EulerObject * self)
//----------------------------Euler.rotate()-----------------------
//rotates a euler a certain amount and returns the result
//should return a unique euler rotation (i.e. no 720 degree pitches :)
PyObject *Euler_Rotate(EulerObject * self, PyObject *args)
static PyObject *Euler_Rotate(EulerObject * self, PyObject *args)
{
float angle = 0.0f;
char *axis;
@@ -176,7 +238,7 @@ PyObject *Euler_Rotate(EulerObject * self, PyObject *args)
return (PyObject *)self;
}
PyObject *Euler_MakeCompatible(EulerObject * self, EulerObject *value)
static PyObject *Euler_MakeCompatible(EulerObject * self, EulerObject *value)
{
float eul_from_rad[3];
int x;
@@ -203,7 +265,7 @@ PyObject *Euler_MakeCompatible(EulerObject * self, EulerObject *value)
//----------------------------Euler.rotate()-----------------------
// return a copy of the euler
PyObject *Euler_copy(EulerObject * self, PyObject *args)
static PyObject *Euler_copy(EulerObject * self, PyObject *args)
{
return newEulerObject(self->eul, Py_NEW);
}
@@ -509,7 +571,7 @@ PyTypeObject euler_Type = {
0, //tp_dictoffset
0, //tp_init
0, //tp_alloc
0, //tp_new
Euler_new, //tp_new
0, //tp_free
0, //tp_is_gc
0, //tp_bases

View File

@@ -54,13 +54,6 @@ be stored in py_data) or be a wrapper for data allocated through
blender (stored in blend_data). This is an either/or struct not both*/
//prototypes
PyObject *Euler_Zero( EulerObject * self );
PyObject *Euler_Unique( EulerObject * self );
PyObject *Euler_ToMatrix( EulerObject * self );
PyObject *Euler_ToQuat( EulerObject * self );
PyObject *Euler_Rotate( EulerObject * self, PyObject *args );
PyObject *Euler_MakeCompatible( EulerObject * self, EulerObject *value );
PyObject *Euler_copy( EulerObject * self, PyObject *args );
PyObject *newEulerObject( float *eul, int type );
#endif /* EXPP_euler_h */

View File

@@ -32,20 +32,34 @@
#include "BLI_blenlib.h"
/*-------------------------DOC STRINGS ---------------------------*/
char Matrix_Zero_doc[] = "() - set all values in the matrix to 0";
char Matrix_Identity_doc[] = "() - set the square matrix to it's identity matrix";
char Matrix_Transpose_doc[] = "() - set the matrix to it's transpose";
char Matrix_Determinant_doc[] = "() - return the determinant of the matrix";
char Matrix_Invert_doc[] = "() - set the matrix to it's inverse if an inverse is possible";
char Matrix_TranslationPart_doc[] = "() - return a vector encompassing the translation of the matrix";
char Matrix_RotationPart_doc[] = "() - return a vector encompassing the rotation of the matrix";
char Matrix_scalePart_doc[] = "() - convert matrix to a 3D vector";
char Matrix_Resize4x4_doc[] = "() - resize the matrix to a 4x4 square matrix";
char Matrix_toEuler_doc[] = "(eul_compat) - convert matrix to a euler angle rotation, optional euler argument that the new euler will be made compatible with.";
char Matrix_toQuat_doc[] = "() - convert matrix to a quaternion rotation";
char Matrix_copy_doc[] = "() - return a copy of the matrix";
static char Matrix_Zero_doc[] = "() - set all values in the matrix to 0";
static char Matrix_Identity_doc[] = "() - set the square matrix to it's identity matrix";
static char Matrix_Transpose_doc[] = "() - set the matrix to it's transpose";
static char Matrix_Determinant_doc[] = "() - return the determinant of the matrix";
static char Matrix_Invert_doc[] = "() - set the matrix to it's inverse if an inverse is possible";
static char Matrix_TranslationPart_doc[] = "() - return a vector encompassing the translation of the matrix";
static char Matrix_RotationPart_doc[] = "() - return a vector encompassing the rotation of the matrix";
static char Matrix_scalePart_doc[] = "() - convert matrix to a 3D vector";
static char Matrix_Resize4x4_doc[] = "() - resize the matrix to a 4x4 square matrix";
static char Matrix_toEuler_doc[] = "(eul_compat) - convert matrix to a euler angle rotation, optional euler argument that the new euler will be made compatible with.";
static char Matrix_toQuat_doc[] = "() - convert matrix to a quaternion rotation";
static char Matrix_copy_doc[] = "() - return a copy of the matrix";
static PyObject *Matrix_Zero( MatrixObject * self );
static PyObject *Matrix_Identity( MatrixObject * self );
static PyObject *Matrix_Transpose( MatrixObject * self );
static PyObject *Matrix_Determinant( MatrixObject * self );
static PyObject *Matrix_Invert( MatrixObject * self );
static PyObject *Matrix_TranslationPart( MatrixObject * self );
static PyObject *Matrix_RotationPart( MatrixObject * self );
static PyObject *Matrix_scalePart( MatrixObject * self );
static PyObject *Matrix_Resize4x4( MatrixObject * self );
static PyObject *Matrix_toEuler( MatrixObject * self, PyObject *args );
static PyObject *Matrix_toQuat( MatrixObject * self );
static PyObject *Matrix_copy( MatrixObject * self );
/*-----------------------METHOD DEFINITIONS ----------------------*/
struct PyMethodDef Matrix_methods[] = {
static struct PyMethodDef Matrix_methods[] = {
{"zero", (PyCFunction) Matrix_Zero, METH_NOARGS, Matrix_Zero_doc},
{"identity", (PyCFunction) Matrix_Identity, METH_NOARGS, Matrix_Identity_doc},
{"transpose", (PyCFunction) Matrix_Transpose, METH_NOARGS, Matrix_Transpose_doc},
@@ -61,9 +75,86 @@ struct PyMethodDef Matrix_methods[] = {
{"__copy__", (PyCFunction) Matrix_copy, METH_NOARGS, Matrix_copy_doc},
{NULL, NULL, 0, NULL}
};
//----------------------------------Mathutils.Matrix() -----------------
//mat is a 1D array of floats - row[0][0],row[0][1], row[1][0], etc.
//create a new matrix type
static PyObject *Matrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyObject *argObject, *m, *s;
MatrixObject *mat;
int argSize, seqSize = 0, i, j;
float matrix[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
float scalar;
argSize = PyTuple_GET_SIZE(args);
if(argSize > 4){ //bad arg nums
PyErr_SetString(PyExc_AttributeError, "Mathutils.Matrix(): expects 0-4 numeric sequences of the same size\n");
return NULL;
} else if (argSize == 0) { //return empty 4D matrix
return (PyObject *) newMatrixObject(NULL, 4, 4, Py_NEW);
}else if (argSize == 1){
//copy constructor for matrix objects
argObject = PyTuple_GET_ITEM(args, 0);
if(MatrixObject_Check(argObject)){
mat = (MatrixObject*)argObject;
argSize = mat->rowSize; //rows
seqSize = mat->colSize; //col
for(i = 0; i < (seqSize * argSize); i++){
matrix[i] = mat->contigPtr[i];
}
}
}else{ //2-4 arguments (all seqs? all same size?)
for(i =0; i < argSize; i++){
argObject = PyTuple_GET_ITEM(args, i);
if (PySequence_Check(argObject)) { //seq?
if(seqSize){ //0 at first
if(PySequence_Length(argObject) != seqSize){ //seq size not same
PyErr_SetString(PyExc_AttributeError, "Mathutils.Matrix(): expects 0-4 numeric sequences of the same size\n");
return NULL;
}
}
seqSize = PySequence_Length(argObject);
}else{ //arg not a sequence
PyErr_SetString(PyExc_TypeError, "Mathutils.Matrix(): expects 0-4 numeric sequences of the same size\n");
return NULL;
}
}
//all is well... let's continue parsing
for (i = 0; i < argSize; i++){
m = PyTuple_GET_ITEM(args, i);
if (m == NULL) { // Failed to read sequence
PyErr_SetString(PyExc_RuntimeError, "Mathutils.Matrix(): failed to parse arguments...\n");
return NULL;
}
for (j = 0; j < seqSize; j++) {
s = PySequence_GetItem(m, j);
if (s == NULL) { // Failed to read sequence
PyErr_SetString(PyExc_RuntimeError, "Mathutils.Matrix(): failed to parse arguments...\n");
return NULL;
}
scalar= (float)PyFloat_AsDouble(s);
Py_DECREF(s);
if(scalar==-1 && PyErr_Occurred()) { // parsed item is not a number
PyErr_SetString(PyExc_AttributeError, "Mathutils.Matrix(): expects 0-4 numeric sequences of the same size\n");
return NULL;
}
matrix[(seqSize*i)+j]= scalar;
}
}
}
return newMatrixObject(matrix, argSize, seqSize, Py_NEW);
}
/*-----------------------------METHODS----------------------------*/
/*---------------------------Matrix.toQuat() ---------------------*/
PyObject *Matrix_toQuat(MatrixObject * self)
static PyObject *Matrix_toQuat(MatrixObject * self)
{
float quat[4];
@@ -387,7 +478,6 @@ PyObject *Matrix_copy(MatrixObject * self)
/*free the py_object*/
static void Matrix_dealloc(MatrixObject * self)
{
Py_XDECREF(self->coerced_object);
PyMem_Free(self->matrix);
/*only free py_data*/
if(self->data.py_data){
@@ -395,35 +485,7 @@ static void Matrix_dealloc(MatrixObject * self)
}
PyObject_DEL(self);
}
/*----------------------------getattr()(internal) ----------------*/
/*object.attribute access (get)*/
static PyObject *Matrix_getattr(MatrixObject * self, char *name)
{
if(STREQ(name, "rowSize")) {
return PyLong_FromLong((long) self->rowSize);
} else if(STREQ(name, "colSize")) {
return PyLong_FromLong((long) self->colSize);
}
if(STREQ(name, "wrapped")){
if(self->wrapped == Py_WRAP)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
#if 0 //XXX
return Py_FindMethod(Matrix_methods, (PyObject *) self, name);
#else
PyErr_SetString(PyExc_AttributeError, "blender 2.5 is not finished yet");
return NULL;
#endif
}
/*----------------------------setattr()(internal) ----------------*/
/*object.attribute access (set)*/
static int Matrix_setattr(MatrixObject * self, char *name, PyObject * v)
{
/* This is not supported. */
return (-1);
}
/*----------------------------print object (internal)-------------*/
/*print the object to screen*/
static PyObject *Matrix_repr(MatrixObject * self)
@@ -672,7 +734,7 @@ static PyObject *Matrix_add(PyObject * m1, PyObject * m2)
mat1 = (MatrixObject*)m1;
mat2 = (MatrixObject*)m2;
if(mat1->coerced_object || mat2->coerced_object){
if(!MatrixObject_Check(m1) || !MatrixObject_Check(m2)) {
PyErr_SetString(PyExc_AttributeError, "Matrix addition: arguments not valid for this operation....");
return NULL;
}
@@ -701,7 +763,7 @@ static PyObject *Matrix_sub(PyObject * m1, PyObject * m2)
mat1 = (MatrixObject*)m1;
mat2 = (MatrixObject*)m2;
if(mat1->coerced_object || mat2->coerced_object){
if(!MatrixObject_Check(m1) || !MatrixObject_Check(m2)) {
PyErr_SetString(PyExc_AttributeError, "Matrix addition: arguments not valid for this operation....");
return NULL;
}
@@ -728,22 +790,31 @@ static PyObject *Matrix_mul(PyObject * m1, PyObject * m2)
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
double dot = 0.0f;
MatrixObject *mat1 = NULL, *mat2 = NULL;
PyObject *f = NULL;
mat1 = (MatrixObject*)m1;
mat2 = (MatrixObject*)m2;
if(MatrixObject_Check(m1)) mat1 = (MatrixObject*)m1;
if(MatrixObject_Check(m2)) mat2 = (MatrixObject*)m2;
if(mat1->coerced_object){
if (PyFloat_Check(mat1->coerced_object) ||
PyLong_Check(mat1->coerced_object)){ /*FLOAT/INT * MATRIX*/
f = PyNumber_Float(mat1->coerced_object);
if(f == NULL) { /*parsed item not a number*/
PyErr_SetString(PyExc_TypeError, "Matrix multiplication: arguments not acceptable for this operation");
return NULL;
if(mat1 && mat2) { /*MATRIX * MATRIX*/
if(mat1->colSize != mat2->rowSize){
PyErr_SetString(PyExc_AttributeError,"Matrix multiplication: matrix A rowsize must equal matrix B colsize");
return NULL;
}
for(x = 0; x < mat1->rowSize; x++) {
for(y = 0; y < mat2->colSize; y++) {
for(z = 0; z < mat1->colSize; z++) {
dot += (mat1->matrix[x][z] * mat2->matrix[z][y]);
}
mat[((x * mat1->rowSize) + y)] = (float)dot;
dot = 0.0f;
}
scalar = (float)PyFloat_AS_DOUBLE(f);
Py_DECREF(f);
}
return newMatrixObject(mat, mat1->rowSize, mat2->colSize, Py_NEW);
}
if(mat1==NULL){
scalar=PyFloat_AsDouble(m1); // may not be a float...
if ((scalar == -1.0 && PyErr_Occurred())==0) { /*FLOAT/INT * MATRIX, this line annoys theeth, lets see if he finds it */
for(x = 0; x < mat2->rowSize; x++) {
for(y = 0; y < mat2->colSize; y++) {
mat[((x * mat2->colSize) + y)] = scalar * mat2->matrix[x][y];
@@ -751,22 +822,18 @@ static PyObject *Matrix_mul(PyObject * m1, PyObject * m2)
}
return newMatrixObject(mat, mat2->rowSize, mat2->colSize, Py_NEW);
}
}else{
if(mat2->coerced_object){
/* MATRIX * VECTOR operation is now being done by vector */
/*if(VectorObject_Check(mat2->coerced_object)){
vec = (VectorObject*)mat2->coerced_object;
return column_vector_multiplication(mat1, vec);
}else */
if (PyFloat_Check(mat2->coerced_object) || PyLong_Check(mat2->coerced_object)){ /*MATRIX * FLOAT/INT*/
f = PyNumber_Float(mat2->coerced_object);
if(f == NULL) { /*parsed item not a number*/
PyErr_SetString(PyExc_TypeError, "Matrix multiplication: arguments not acceptable for this operation\n");
return NULL;
}
scalar = (float)PyFloat_AS_DOUBLE(f);
Py_DECREF(f);
PyErr_SetString(PyExc_TypeError, "Matrix multiplication: arguments not acceptable for this operation");
return NULL;
}
else /* if(mat1) { */ {
if(VectorObject_Check(m2)) { /* MATRIX*VECTOR */
return column_vector_multiplication(mat1, (VectorObject *)m2);
}
else {
scalar= PyFloat_AsDouble(m2);
if ((scalar == -1.0 && PyErr_Occurred())==0) { /* MATRIX*FLOAT/INT */
for(x = 0; x < mat1->rowSize; x++) {
for(y = 0; y < mat1->colSize; y++) {
mat[((x * mat1->colSize) + y)] = scalar * mat1->matrix[x][y];
@@ -774,22 +841,9 @@ static PyObject *Matrix_mul(PyObject * m1, PyObject * m2)
}
return newMatrixObject(mat, mat1->rowSize, mat1->colSize, Py_NEW);
}
}else{ /*MATRIX * MATRIX*/
if(mat1->colSize != mat2->rowSize){
PyErr_SetString(PyExc_AttributeError,"Matrix multiplication: matrix A rowsize must equal matrix B colsize");
return NULL;
}
for(x = 0; x < mat1->rowSize; x++) {
for(y = 0; y < mat2->colSize; y++) {
for(z = 0; z < mat1->colSize; z++) {
dot += (mat1->matrix[x][z] * mat2->matrix[z][y]);
}
mat[((x * mat1->rowSize) + y)] = (float)dot;
dot = 0.0f;
}
}
return newMatrixObject(mat, mat1->rowSize, mat2->colSize, Py_NEW);
}
PyErr_SetString(PyExc_TypeError, "Matrix multiplication: arguments not acceptable for this operation");
return NULL;
}
PyErr_SetString(PyExc_TypeError, "Matrix multiplication: arguments not acceptable for this operation\n");
@@ -799,29 +853,7 @@ static PyObject* Matrix_inv(MatrixObject *self)
{
return Matrix_Invert(self);
}
/*------------------------coerce(obj, obj)-----------------------
coercion of unknown types to type MatrixObject for numeric protocols.
Coercion() is called whenever a math operation has 2 operands that
it doesn't understand how to evaluate. 2+Matrix for example. We want to
evaluate some of these operations like: (vector * 2), however, for math
to proceed, the unknown operand must be cast to a type that python math will
understand. (e.g. in the case above case, 2 must be cast to a vector and
then call vector.multiply(vector, scalar_cast_as_vector)*/
static int Matrix_coerce(PyObject ** m1, PyObject ** m2)
{
if(VectorObject_Check(*m2) || PyFloat_Check(*m2) || PyLong_Check(*m2)) {
PyObject *coerced = (PyObject *)(*m2);
Py_INCREF(coerced);
*m2 = newMatrixObject(NULL,3,3,Py_NEW);
((MatrixObject*)*m2)->coerced_object = coerced;
Py_INCREF (*m1);
return 0;
}
PyErr_SetString(PyExc_TypeError, "matrix.coerce(): unknown operand - can't coerce for numeric protocols");
return -1;
}
/*-----------------PROTOCOL DECLARATIONS--------------------------*/
static PySequenceMethods Matrix_SeqMethods = {
(inquiry) Matrix_len, /* sq_length */
@@ -850,17 +882,42 @@ static PyNumberMethods Matrix_NumMethods = {
(binaryfunc) 0, /* __and__ */
(binaryfunc) 0, /* __xor__ */
(binaryfunc) 0, /* __or__ */
#if 0 // XXX 2.5
(coercion) Matrix_coerce, /* __coerce__ */
#else
0,
#endif
/*(coercion)*/ 0, /* __coerce__ */
(unaryfunc) 0, /* __int__ */
(unaryfunc) 0, /* __long__ */
(unaryfunc) 0, /* __float__ */
(unaryfunc) 0, /* __oct__ */
(unaryfunc) 0, /* __hex__ */
};
static PyObject *Matrix_getRowSize( MatrixObject * self, void *type )
{
return PyLong_FromLong((long) self->rowSize);
}
static PyObject *Matrix_getColSize( MatrixObject * self, void *type )
{
return PyLong_FromLong((long) self->colSize);
}
static PyObject *Matrix_getWrapped( MatrixObject * self, void *type )
{
if (self->wrapped == Py_WRAP)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
/*****************************************************************************/
/* Python attributes get/set structure: */
/*****************************************************************************/
static PyGetSetDef Matrix_getseters[] = {
{"rowSize", (getter)Matrix_getRowSize, (setter)NULL, "", NULL},
{"colSize", (getter)Matrix_getColSize, (setter)NULL, "", NULL},
{"wrapped", (getter)Matrix_getWrapped, (setter)NULL, "", NULL},
{NULL,NULL,NULL,NULL,NULL} /* Sentinel */
};
/*------------------PY_OBECT DEFINITION--------------------------*/
PyTypeObject matrix_Type = {
#if (PY_VERSION_HEX >= 0x02060000)
@@ -875,8 +932,8 @@ PyTypeObject matrix_Type = {
0, /*tp_itemsize*/
(destructor)Matrix_dealloc, /*tp_dealloc*/
0, /*tp_print*/
(getattrfunc)Matrix_getattr, /*tp_getattr*/
(setattrfunc) Matrix_setattr, /*tp_setattr*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
(reprfunc) Matrix_repr, /*tp_repr*/
&Matrix_NumMethods, /*tp_as_number*/
@@ -896,9 +953,9 @@ PyTypeObject matrix_Type = {
0, /*tp_weaklistoffset*/
0, /*tp_iter*/
0, /*tp_iternext*/
0, /*tp_methods*/
Matrix_methods, /*tp_methods*/
0, /*tp_members*/
0, /*tp_getset*/
Matrix_getseters, /*tp_getset*/
0, /*tp_base*/
0, /*tp_dict*/
0, /*tp_descr_get*/
@@ -906,7 +963,7 @@ PyTypeObject matrix_Type = {
0, /*tp_dictoffset*/
0, /*tp_init*/
0, /*tp_alloc*/
0, /*tp_new*/
Matrix_new, /*tp_new*/
0, /*tp_free*/
0, /*tp_is_gc*/
0, /*tp_bases*/
@@ -949,7 +1006,6 @@ PyObject *newMatrixObject(float *mat, int rowSize, int colSize, int type)
self->data.py_data = NULL;
self->rowSize = rowSize;
self->colSize = colSize;
self->coerced_object = NULL;
if(type == Py_WRAP){
self->data.blend_data = mat;

View File

@@ -48,11 +48,7 @@ typedef struct _Matrix {
int rowSize;
int colSize;
int wrapped; /*is wrapped data?*/
PyObject *coerced_object;
} MatrixObject;
/*coerced_object is a pointer to the object that it was
coerced from when a dummy vector needs to be created from
the coerce() function for numeric protocol operations*/
/*struct data contains a pointer to the actual data that the
object uses. It can use either PyMem allocated data (which will
@@ -60,18 +56,6 @@ be stored in py_data) or be a wrapper for data allocated through
blender (stored in blend_data). This is an either/or struct not both*/
/*prototypes*/
PyObject *Matrix_Zero( MatrixObject * self );
PyObject *Matrix_Identity( MatrixObject * self );
PyObject *Matrix_Transpose( MatrixObject * self );
PyObject *Matrix_Determinant( MatrixObject * self );
PyObject *Matrix_Invert( MatrixObject * self );
PyObject *Matrix_TranslationPart( MatrixObject * self );
PyObject *Matrix_RotationPart( MatrixObject * self );
PyObject *Matrix_scalePart( MatrixObject * self );
PyObject *Matrix_Resize4x4( MatrixObject * self );
PyObject *Matrix_toEuler( MatrixObject * self, PyObject *args );
PyObject *Matrix_toQuat( MatrixObject * self );
PyObject *Matrix_copy( MatrixObject * self );
PyObject *newMatrixObject(float *mat, int rowSize, int colSize, int type);
#endif /* EXPP_matrix_H */

View File

@@ -34,18 +34,30 @@
//-------------------------DOC STRINGS ---------------------------
char Quaternion_Identity_doc[] = "() - set the quaternion to it's identity (1, vector)";
char Quaternion_Negate_doc[] = "() - set all values in the quaternion to their negative";
char Quaternion_Conjugate_doc[] = "() - set the quaternion to it's conjugate";
char Quaternion_Inverse_doc[] = "() - set the quaternion to it's inverse";
char Quaternion_Normalize_doc[] = "() - normalize the vector portion of the quaternion";
char Quaternion_ToEuler_doc[] = "(eul_compat) - return a euler rotation representing the quaternion, optional euler argument that the new euler will be made compatible with.";
char Quaternion_ToMatrix_doc[] = "() - return a rotation matrix representing the quaternion";
char Quaternion_Cross_doc[] = "(other) - return the cross product between this quaternion and another";
char Quaternion_Dot_doc[] = "(other) - return the dot product between this quaternion and another";
char Quaternion_copy_doc[] = "() - return a copy of the quat";
static char Quaternion_Identity_doc[] = "() - set the quaternion to it's identity (1, vector)";
static char Quaternion_Negate_doc[] = "() - set all values in the quaternion to their negative";
static char Quaternion_Conjugate_doc[] = "() - set the quaternion to it's conjugate";
static char Quaternion_Inverse_doc[] = "() - set the quaternion to it's inverse";
static char Quaternion_Normalize_doc[] = "() - normalize the vector portion of the quaternion";
static char Quaternion_ToEuler_doc[] = "(eul_compat) - return a euler rotation representing the quaternion, optional euler argument that the new euler will be made compatible with.";
static char Quaternion_ToMatrix_doc[] = "() - return a rotation matrix representing the quaternion";
static char Quaternion_Cross_doc[] = "(other) - return the cross product between this quaternion and another";
static char Quaternion_Dot_doc[] = "(other) - return the dot product between this quaternion and another";
static char Quaternion_copy_doc[] = "() - return a copy of the quat";
static PyObject *Quaternion_Identity( QuaternionObject * self );
static PyObject *Quaternion_Negate( QuaternionObject * self );
static PyObject *Quaternion_Conjugate( QuaternionObject * self );
static PyObject *Quaternion_Inverse( QuaternionObject * self );
static PyObject *Quaternion_Normalize( QuaternionObject * self );
static PyObject *Quaternion_ToEuler( QuaternionObject * self, PyObject *args );
static PyObject *Quaternion_ToMatrix( QuaternionObject * self );
static PyObject *Quaternion_Cross( QuaternionObject * self, QuaternionObject * value );
static PyObject *Quaternion_Dot( QuaternionObject * self, QuaternionObject * value );
static PyObject *Quaternion_copy( QuaternionObject * self );
//-----------------------METHOD DEFINITIONS ----------------------
struct PyMethodDef Quaternion_methods[] = {
static struct PyMethodDef Quaternion_methods[] = {
{"identity", (PyCFunction) Quaternion_Identity, METH_NOARGS, Quaternion_Identity_doc},
{"negate", (PyCFunction) Quaternion_Negate, METH_NOARGS, Quaternion_Negate_doc},
{"conjugate", (PyCFunction) Quaternion_Conjugate, METH_NOARGS, Quaternion_Conjugate_doc},
@@ -59,10 +71,117 @@ struct PyMethodDef Quaternion_methods[] = {
{"copy", (PyCFunction) Quaternion_copy, METH_NOARGS, Quaternion_copy_doc},
{NULL, NULL, 0, NULL}
};
//----------------------------------Mathutils.Quaternion() --------------
static PyObject *Quaternion_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyObject *listObject = NULL, *n, *q, *f;
int size, i;
float quat[4], scalar;
double norm = 0.0f, angle = 0.0f;
size = PyTuple_GET_SIZE(args);
if (size == 1 || size == 2) { //seq?
listObject = PyTuple_GET_ITEM(args, 0);
if (PySequence_Check(listObject)) {
size = PySequence_Length(listObject);
if ((size == 4 && PySequence_Length(args) !=1) ||
(size == 3 && PySequence_Length(args) !=2) || (size >4 || size < 3)) {
// invalid args/size
PyErr_SetString(PyExc_AttributeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
return NULL;
}
if(size == 3){ //get angle in axis/angle
n = PySequence_GetItem(args, 1);
if(n == NULL) { // parsed item not a number or getItem fail
PyErr_SetString(PyExc_TypeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
return NULL;
}
angle = PyFloat_AsDouble(n);
Py_DECREF(n);
if (angle==-1 && PyErr_Occurred()) {
PyErr_SetString(PyExc_TypeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
return NULL;
}
}
}else{
listObject = PyTuple_GET_ITEM(args, 1);
if (size>1 && PySequence_Check(listObject)) {
size = PySequence_Length(listObject);
if (size != 3) {
// invalid args/size
PyErr_SetString(PyExc_AttributeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
return NULL;
}
angle = PyFloat_AsDouble(PyTuple_GET_ITEM(args, 0));
if (angle==-1 && PyErr_Occurred()) {
PyErr_SetString(PyExc_TypeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
return NULL;
}
} else { // argument was not a sequence
PyErr_SetString(PyExc_TypeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
return NULL;
}
}
} else if (size == 0) { //returns a new empty quat
return newQuaternionObject(NULL, Py_NEW);
} else {
listObject = args;
}
if (size == 3) { // invalid quat size
if(PySequence_Length(args) != 2){
PyErr_SetString(PyExc_AttributeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
return NULL;
}
}else{
if(size != 4){
PyErr_SetString(PyExc_AttributeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
return NULL;
}
}
for (i=0; i<size; i++) { //parse
q = PySequence_GetItem(listObject, i);
if (q == NULL) { // Failed to read sequence
PyErr_SetString(PyExc_RuntimeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
return NULL;
}
scalar = PyFloat_AsDouble(q);
if (scalar==-1 && PyErr_Occurred()) {
Py_DECREF(q);
PyErr_SetString(PyExc_TypeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
return NULL;
}
quat[i] = scalar;
Py_DECREF(f);
Py_DECREF(q);
}
if(size == 3){ //calculate the quat based on axis/angle
norm = sqrt(quat[0] * quat[0] + quat[1] * quat[1] + quat[2] * quat[2]);
quat[0] /= (float)norm;
quat[1] /= (float)norm;
quat[2] /= (float)norm;
angle = angle * (Py_PI / 180);
quat[3] =(float) (sin(angle/ 2.0f)) * quat[2];
quat[2] =(float) (sin(angle/ 2.0f)) * quat[1];
quat[1] =(float) (sin(angle/ 2.0f)) * quat[0];
quat[0] =(float) (cos(angle/ 2.0f));
}
return newQuaternionObject(quat, Py_NEW);
}
//-----------------------------METHODS------------------------------
//----------------------------Quaternion.toEuler()------------------
//return the quat as a euler
PyObject *Quaternion_ToEuler(QuaternionObject * self, PyObject *args)
static PyObject *Quaternion_ToEuler(QuaternionObject * self, PyObject *args)
{
float eul[3];
EulerObject *eul_compat = NULL;
@@ -93,7 +212,7 @@ PyObject *Quaternion_ToEuler(QuaternionObject * self, PyObject *args)
}
//----------------------------Quaternion.toMatrix()------------------
//return the quat as a matrix
PyObject *Quaternion_ToMatrix(QuaternionObject * self)
static PyObject *Quaternion_ToMatrix(QuaternionObject * self)
{
float mat[9] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
QuatToMat3(self->quat, (float (*)[3]) mat);
@@ -103,7 +222,7 @@ PyObject *Quaternion_ToMatrix(QuaternionObject * self)
//----------------------------Quaternion.cross(other)------------------
//return the cross quat
PyObject *Quaternion_Cross(QuaternionObject * self, QuaternionObject * value)
static PyObject *Quaternion_Cross(QuaternionObject * self, QuaternionObject * value)
{
float quat[4];
@@ -118,7 +237,7 @@ PyObject *Quaternion_Cross(QuaternionObject * self, QuaternionObject * value)
//----------------------------Quaternion.dot(other)------------------
//return the dot quat
PyObject *Quaternion_Dot(QuaternionObject * self, QuaternionObject * value)
static PyObject *Quaternion_Dot(QuaternionObject * self, QuaternionObject * value)
{
int x;
double dot = 0.0;
@@ -136,7 +255,7 @@ PyObject *Quaternion_Dot(QuaternionObject * self, QuaternionObject * value)
//----------------------------Quaternion.normalize()----------------
//normalize the axis of rotation of [theta,vector]
PyObject *Quaternion_Normalize(QuaternionObject * self)
static PyObject *Quaternion_Normalize(QuaternionObject * self)
{
NormalQuat(self->quat);
Py_INCREF(self);
@@ -144,7 +263,7 @@ PyObject *Quaternion_Normalize(QuaternionObject * self)
}
//----------------------------Quaternion.inverse()------------------
//invert the quat
PyObject *Quaternion_Inverse(QuaternionObject * self)
static PyObject *Quaternion_Inverse(QuaternionObject * self)
{
double mag = 0.0f;
int x;
@@ -165,7 +284,7 @@ PyObject *Quaternion_Inverse(QuaternionObject * self)
}
//----------------------------Quaternion.identity()-----------------
//generate the identity quaternion
PyObject *Quaternion_Identity(QuaternionObject * self)
static PyObject *Quaternion_Identity(QuaternionObject * self)
{
self->quat[0] = 1.0;
self->quat[1] = 0.0;
@@ -177,7 +296,7 @@ PyObject *Quaternion_Identity(QuaternionObject * self)
}
//----------------------------Quaternion.negate()-------------------
//negate the quat
PyObject *Quaternion_Negate(QuaternionObject * self)
static PyObject *Quaternion_Negate(QuaternionObject * self)
{
int x;
for(x = 0; x < 4; x++) {
@@ -188,7 +307,7 @@ PyObject *Quaternion_Negate(QuaternionObject * self)
}
//----------------------------Quaternion.conjugate()----------------
//negate the vector part
PyObject *Quaternion_Conjugate(QuaternionObject * self)
static PyObject *Quaternion_Conjugate(QuaternionObject * self)
{
int x;
for(x = 1; x < 4; x++) {
@@ -199,7 +318,7 @@ PyObject *Quaternion_Conjugate(QuaternionObject * self)
}
//----------------------------Quaternion.copy()----------------
//return a copy of the quat
PyObject *Quaternion_copy(QuaternionObject * self)
static PyObject *Quaternion_copy(QuaternionObject * self)
{
return newQuaternionObject(self->quat, Py_NEW);
}
@@ -208,7 +327,6 @@ PyObject *Quaternion_copy(QuaternionObject * self)
//free the py_object
static void Quaternion_dealloc(QuaternionObject * self)
{
Py_XDECREF(self->coerced_object);
//only free py_data
if(self->data.py_data){
PyMem_Free(self->data.py_data);
@@ -377,13 +495,14 @@ static PyObject *Quaternion_add(PyObject * q1, PyObject * q2)
float quat[4];
QuaternionObject *quat1 = NULL, *quat2 = NULL;
quat1 = (QuaternionObject*)q1;
quat2 = (QuaternionObject*)q2;
if(quat1->coerced_object || quat2->coerced_object){
if(!QuaternionObject_Check(q1) || !QuaternionObject_Check(q2)) {
PyErr_SetString(PyExc_AttributeError, "Quaternion addition: arguments not valid for this operation....\n");
return NULL;
}
quat1 = (QuaternionObject*)q1;
quat2 = (QuaternionObject*)q2;
for(x = 0; x < 4; x++) {
quat[x] = quat1->quat[x] + quat2->quat[x];
}
@@ -398,13 +517,14 @@ static PyObject *Quaternion_sub(PyObject * q1, PyObject * q2)
float quat[4];
QuaternionObject *quat1 = NULL, *quat2 = NULL;
quat1 = (QuaternionObject*)q1;
quat2 = (QuaternionObject*)q2;
if(quat1->coerced_object || quat2->coerced_object){
if(!QuaternionObject_Check(q1) || !QuaternionObject_Check(q2)) {
PyErr_SetString(PyExc_AttributeError, "Quaternion addition: arguments not valid for this operation....\n");
return NULL;
}
quat1 = (QuaternionObject*)q1;
quat2 = (QuaternionObject*)q2;
for(x = 0; x < 4; x++) {
quat[x] = quat1->quat[x] - quat2->quat[x];
}
@@ -419,86 +539,53 @@ static PyObject *Quaternion_mul(PyObject * q1, PyObject * q2)
float quat[4], scalar;
double dot = 0.0f;
QuaternionObject *quat1 = NULL, *quat2 = NULL;
PyObject *f = NULL;
VectorObject *vec = NULL;
quat1 = (QuaternionObject*)q1;
quat2 = (QuaternionObject*)q2;
if(quat1->coerced_object){
if (PyFloat_Check(quat1->coerced_object) ||
PyLong_Check(quat1->coerced_object)){ // FLOAT/INT * QUAT
f = PyNumber_Float(quat1->coerced_object);
if(f == NULL) { // parsed item not a number
PyErr_SetString(PyExc_TypeError, "Quaternion multiplication: arguments not acceptable for this operation\n");
return NULL;
}
scalar = (float)PyFloat_AS_DOUBLE(f);
Py_DECREF(f);
if(QuaternionObject_Check(q1) && QuaternionObject_Check(q2)) { /* QUAT*QUAT (dot product) */
for(x = 0; x < 4; x++) {
dot += quat1->quat[x] * quat1->quat[x];
}
return PyFloat_FromDouble(dot);
}
/* the only case this can happen (for a supported type is "FLOAT*QUAT" ) */
if(!QuaternionObject_Check(q1)) {
scalar= PyFloat_AsDouble(q1);
if ((scalar == -1.0 && PyErr_Occurred())==0) { /* FLOAT*QUAT */
for(x = 0; x < 4; x++) {
quat[x] = quat2->quat[x] * scalar;
}
return newQuaternionObject(quat, Py_NEW);
}
}else{
if(quat2->coerced_object){
if (PyFloat_Check(quat2->coerced_object) ||
PyLong_Check(quat2->coerced_object)){ // QUAT * FLOAT/INT
f = PyNumber_Float(quat2->coerced_object);
if(f == NULL) { // parsed item not a number
PyErr_SetString(PyExc_TypeError, "Quaternion multiplication: arguments not acceptable for this operation\n");
return NULL;
}
scalar = (float)PyFloat_AS_DOUBLE(f);
Py_DECREF(f);
for(x = 0; x < 4; x++) {
quat[x] = quat1->quat[x] * scalar;
}
return newQuaternionObject(quat, Py_NEW);
}else if(VectorObject_Check(quat2->coerced_object)){ //QUAT * VEC
vec = (VectorObject*)quat2->coerced_object;
if(vec->size != 3){
PyErr_SetString(PyExc_TypeError, "Quaternion multiplication: only 3D vector rotations currently supported\n");
return NULL;
}
return quat_rotation((PyObject*)quat1, (PyObject*)vec);
PyErr_SetString(PyExc_TypeError, "Quaternion multiplication: val * quat, val is not an acceptable type");
return NULL;
}
else { /* QUAT*SOMETHING */
if(VectorObject_Check(q2)){ /* QUAT*VEC */
vec = (VectorObject*)q2;
if(vec->size != 3){
PyErr_SetString(PyExc_TypeError, "Quaternion multiplication: only 3D vector rotations currently supported\n");
return NULL;
}
}else{ //QUAT * QUAT (dot product)
return quat_rotation((PyObject*)quat1, (PyObject*)vec);
}
scalar= PyFloat_AsDouble(q2);
if ((scalar == -1.0 && PyErr_Occurred())==0) { /* QUAT*FLOAT */
for(x = 0; x < 4; x++) {
dot += quat1->quat[x] * quat1->quat[x];
quat[x] = quat1->quat[x] * scalar;
}
return PyFloat_FromDouble(dot);
return newQuaternionObject(quat, Py_NEW);
}
}
PyErr_SetString(PyExc_TypeError, "Quaternion multiplication: arguments not acceptable for this operation\n");
return NULL;
}
//------------------------coerce(obj, obj)-----------------------
//coercion of unknown types to type QuaternionObject for numeric protocols
/*Coercion() is called whenever a math operation has 2 operands that
it doesn't understand how to evaluate. 2+Matrix for example. We want to
evaluate some of these operations like: (vector * 2), however, for math
to proceed, the unknown operand must be cast to a type that python math will
understand. (e.g. in the case above case, 2 must be cast to a vector and
then call vector.multiply(vector, scalar_cast_as_vector)*/
static int Quaternion_coerce(PyObject ** q1, PyObject ** q2)
{
if(VectorObject_Check(*q2) || PyFloat_Check(*q2) || PyLong_Check(*q2)) {
PyObject *coerced = (PyObject *)(*q2);
Py_INCREF(coerced);
*q2 = newQuaternionObject(NULL,Py_NEW);
((QuaternionObject*)*q2)->coerced_object = coerced;
Py_INCREF (*q1);
return 0;
}
PyErr_SetString(PyExc_TypeError, "quaternion.coerce(): unknown operand - can't coerce for numeric protocols");
return -1;
}
//-----------------PROTOCOL DECLARATIONS--------------------------
static PySequenceMethods Quaternion_SeqMethods = {
(inquiry) Quaternion_len, /* sq_length */
@@ -527,11 +614,7 @@ static PyNumberMethods Quaternion_NumMethods = {
(binaryfunc) 0, /* __and__ */
(binaryfunc) 0, /* __xor__ */
(binaryfunc) 0, /* __or__ */
#if 0 //XXX 2.5
(coercion) Quaternion_coerce, /* __coerce__ */
#else
0,
#endif
/*(coercion)*/ 0, /* __coerce__ */
(unaryfunc) 0, /* __int__ */
(unaryfunc) 0, /* __long__ */
(unaryfunc) 0, /* __float__ */
@@ -716,7 +799,7 @@ PyTypeObject quaternion_Type = {
0, //tp_dictoffset
0, //tp_init
0, //tp_alloc
0, //tp_new
Quaternion_new, //tp_new
0, //tp_free
0, //tp_is_gc
0, //tp_bases
@@ -740,7 +823,6 @@ PyObject *newQuaternionObject(float *quat, int type)
self = PyObject_NEW(QuaternionObject, &quaternion_Type);
self->data.blend_data = NULL;
self->data.py_data = NULL;
self->coerced_object = NULL;
if(type == Py_WRAP){
self->data.blend_data = quat;

View File

@@ -46,11 +46,7 @@ typedef struct {
}data;
float *quat; //1D array of data (alias)
int wrapped; //is wrapped data?
PyObject *coerced_object;
} QuaternionObject;
/*coerced_object is a pointer to the object that it was
coerced from when a dummy vector needs to be created from
the coerce() function for numeric protocol operations*/
/*struct data contains a pointer to the actual data that the
object uses. It can use either PyMem allocated data (which will
@@ -58,16 +54,6 @@ be stored in py_data) or be a wrapper for data allocated through
blender (stored in blend_data). This is an either/or struct not both*/
//prototypes
PyObject *Quaternion_Identity( QuaternionObject * self );
PyObject *Quaternion_Negate( QuaternionObject * self );
PyObject *Quaternion_Conjugate( QuaternionObject * self );
PyObject *Quaternion_Inverse( QuaternionObject * self );
PyObject *Quaternion_Normalize( QuaternionObject * self );
PyObject *Quaternion_ToEuler( QuaternionObject * self, PyObject *args );
PyObject *Quaternion_ToMatrix( QuaternionObject * self );
PyObject *Quaternion_Cross( QuaternionObject * self, QuaternionObject * value );
PyObject *Quaternion_Dot( QuaternionObject * self, QuaternionObject * value );
PyObject *Quaternion_copy( QuaternionObject * self );
PyObject *newQuaternionObject( float *quat, int type );
#endif /* EXPP_quat_h */

View File

@@ -40,20 +40,32 @@
#define SWIZZLE_AXIS 0x3
/*-------------------------DOC STRINGS ---------------------------*/
char Vector_Zero_doc[] = "() - set all values in the vector to 0";
char Vector_Normalize_doc[] = "() - normalize the vector";
char Vector_Negate_doc[] = "() - changes vector to it's additive inverse";
char Vector_Resize2D_doc[] = "() - resize a vector to [x,y]";
char Vector_Resize3D_doc[] = "() - resize a vector to [x,y,z]";
char Vector_Resize4D_doc[] = "() - resize a vector to [x,y,z,w]";
char Vector_ToTrackQuat_doc[] = "(track, up) - extract a quaternion from the vector and the track and up axis";
char Vector_Reflect_doc[] = "(mirror) - return a vector reflected on the mirror normal";
char Vector_Cross_doc[] = "(other) - return the cross product between this vector and another";
char Vector_Dot_doc[] = "(other) - return the dot product between this vector and another";
char Vector_copy_doc[] = "() - return a copy of the vector";
char Vector_swizzle_doc[] = "Swizzle: Get or set axes in specified order";
static char Vector_Zero_doc[] = "() - set all values in the vector to 0";
static char Vector_Normalize_doc[] = "() - normalize the vector";
static char Vector_Negate_doc[] = "() - changes vector to it's additive inverse";
static char Vector_Resize2D_doc[] = "() - resize a vector to [x,y]";
static char Vector_Resize3D_doc[] = "() - resize a vector to [x,y,z]";
static char Vector_Resize4D_doc[] = "() - resize a vector to [x,y,z,w]";
static char Vector_ToTrackQuat_doc[] = "(track, up) - extract a quaternion from the vector and the track and up axis";
static char Vector_Reflect_doc[] = "(mirror) - return a vector reflected on the mirror normal";
static char Vector_Cross_doc[] = "(other) - return the cross product between this vector and another";
static char Vector_Dot_doc[] = "(other) - return the dot product between this vector and another";
static char Vector_copy_doc[] = "() - return a copy of the vector";
static char Vector_swizzle_doc[] = "Swizzle: Get or set axes in specified order";
/*-----------------------METHOD DEFINITIONS ----------------------*/
struct PyMethodDef Vector_methods[] = {
static PyObject *Vector_Zero( VectorObject * self );
static PyObject *Vector_Normalize( VectorObject * self );
static PyObject *Vector_Negate( VectorObject * self );
static PyObject *Vector_Resize2D( VectorObject * self );
static PyObject *Vector_Resize3D( VectorObject * self );
static PyObject *Vector_Resize4D( VectorObject * self );
static PyObject *Vector_ToTrackQuat( VectorObject * self, PyObject * args );
static PyObject *Vector_Reflect( VectorObject * self, PyObject * value );
static PyObject *Vector_Cross( VectorObject * self, VectorObject * value );
static PyObject *Vector_Dot( VectorObject * self, VectorObject * value );
static PyObject *Vector_copy( VectorObject * self );
static struct PyMethodDef Vector_methods[] = {
{"zero", (PyCFunction) Vector_Zero, METH_NOARGS, Vector_Zero_doc},
{"normalize", (PyCFunction) Vector_Normalize, METH_NOARGS, Vector_Normalize_doc},
{"negate", (PyCFunction) Vector_Negate, METH_NOARGS, Vector_Negate_doc},
@@ -69,10 +81,61 @@ struct PyMethodDef Vector_methods[] = {
{NULL, NULL, 0, NULL}
};
//----------------------------------Mathutils.Vector() ------------------
// Supports 2D, 3D, and 4D vector objects both int and float values
// accepted. Mixed float and int values accepted. Ints are parsed to float
static PyObject *Vector_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyObject *listObject = NULL;
int size, i;
float vec[4], f;
PyObject *v;
size = PyTuple_GET_SIZE(args); /* we know its a tuple because its an arg */
if (size == 1) {
listObject = PyTuple_GET_ITEM(args, 0);
if (PySequence_Check(listObject)) {
size = PySequence_Length(listObject);
} else { // Single argument was not a sequence
PyErr_SetString(PyExc_TypeError, "Mathutils.Vector(): 2-4 floats or ints expected (optionally in a sequence)\n");
return NULL;
}
} else if (size == 0) {
//returns a new empty 3d vector
return newVectorObject(NULL, 3, Py_NEW);
} else {
listObject = args;
}
if (size<2 || size>4) { // Invalid vector size
PyErr_SetString(PyExc_AttributeError, "Mathutils.Vector(): 2-4 floats or ints expected (optionally in a sequence)\n");
return NULL;
}
for (i=0; i<size; i++) {
v=PySequence_GetItem(listObject, i);
if (v==NULL) { // Failed to read sequence
PyErr_SetString(PyExc_RuntimeError, "Mathutils.Vector(): 2-4 floats or ints expected (optionally in a sequence)\n");
return NULL;
}
f= PyFloat_AsDouble(v);
if(f==-1 && PyErr_Occurred()) { // parsed item not a number
Py_DECREF(v);
PyErr_SetString(PyExc_TypeError, "Mathutils.Vector(): 2-4 floats or ints expected (optionally in a sequence)\n");
return NULL;
}
vec[i]= f;
Py_DECREF(v);
}
return newVectorObject(vec, size, Py_NEW);
}
/*-----------------------------METHODS---------------------------- */
/*----------------------------Vector.zero() ----------------------
set the vector data to 0,0,0 */
PyObject *Vector_Zero(VectorObject * self)
static PyObject *Vector_Zero(VectorObject * self)
{
int i;
for(i = 0; i < self->size; i++) {
@@ -83,7 +146,7 @@ PyObject *Vector_Zero(VectorObject * self)
}
/*----------------------------Vector.normalize() -----------------
normalize the vector data to a unit vector */
PyObject *Vector_Normalize(VectorObject * self)
static PyObject *Vector_Normalize(VectorObject * self)
{
int i;
float norm = 0.0f;
@@ -102,7 +165,7 @@ PyObject *Vector_Normalize(VectorObject * self)
/*----------------------------Vector.resize2D() ------------------
resize the vector to x,y */
PyObject *Vector_Resize2D(VectorObject * self)
static PyObject *Vector_Resize2D(VectorObject * self)
{
if(self->wrapped==Py_WRAP) {
PyErr_SetString(PyExc_TypeError, "vector.resize2d(): cannot resize wrapped data - only python vectors\n");
@@ -120,7 +183,7 @@ PyObject *Vector_Resize2D(VectorObject * self)
}
/*----------------------------Vector.resize3D() ------------------
resize the vector to x,y,z */
PyObject *Vector_Resize3D(VectorObject * self)
static PyObject *Vector_Resize3D(VectorObject * self)
{
if (self->wrapped==Py_WRAP) {
PyErr_SetString(PyExc_TypeError, "vector.resize3d(): cannot resize wrapped data - only python vectors\n");
@@ -141,7 +204,7 @@ PyObject *Vector_Resize3D(VectorObject * self)
}
/*----------------------------Vector.resize4D() ------------------
resize the vector to x,y,z,w */
PyObject *Vector_Resize4D(VectorObject * self)
static PyObject *Vector_Resize4D(VectorObject * self)
{
if(self->wrapped==Py_WRAP) {
PyErr_SetString(PyExc_TypeError, "vector.resize4d(): cannot resize wrapped data - only python vectors");
@@ -164,7 +227,7 @@ PyObject *Vector_Resize4D(VectorObject * self)
}
/*----------------------------Vector.toTrackQuat(track, up) ----------------------
extract a quaternion from the vector and the track and up axis */
PyObject *Vector_ToTrackQuat( VectorObject * self, PyObject * args )
static PyObject *Vector_ToTrackQuat( VectorObject * self, PyObject * args )
{
float vec[3], quat[4];
char *strack, *sup;
@@ -279,7 +342,7 @@ PyObject *Vector_ToTrackQuat( VectorObject * self, PyObject * args )
return a reflected vector on the mirror normal
((2 * DotVecs(vec, mirror)) * mirror) - vec
using arithb.c would be nice here */
PyObject *Vector_Reflect( VectorObject * self, PyObject * value )
static PyObject *Vector_Reflect( VectorObject * self, PyObject * value )
{
VectorObject *mirrvec;
float mirror[3];
@@ -326,7 +389,7 @@ PyObject *Vector_Reflect( VectorObject * self, PyObject * value )
return newVectorObject(reflect, self->size, Py_NEW);
}
PyObject *Vector_Cross( VectorObject * self, VectorObject * value )
static PyObject *Vector_Cross( VectorObject * self, VectorObject * value )
{
VectorObject *vecCross = NULL;
@@ -345,7 +408,7 @@ PyObject *Vector_Cross( VectorObject * self, VectorObject * value )
return (PyObject *)vecCross;
}
PyObject *Vector_Dot( VectorObject * self, VectorObject * value )
static PyObject *Vector_Dot( VectorObject * self, VectorObject * value )
{
double dot = 0.0;
int x;
@@ -368,7 +431,7 @@ PyObject *Vector_Dot( VectorObject * self, VectorObject * value )
/*----------------------------Vector.copy() --------------------------------------
return a copy of the vector */
PyObject *Vector_copy(VectorObject * self)
static PyObject *Vector_copy(VectorObject * self)
{
return newVectorObject(self->vec, self->size, Py_NEW);
}
@@ -428,8 +491,8 @@ static PyObject *Vector_item(VectorObject * self, int i)
sequence accessor (set)*/
static int Vector_ass_item(VectorObject * self, int i, PyObject * ob)
{
if(!(PyNumber_Check(ob))) { /* parsed item not a number */
float scalar= (float)PyFloat_AsDouble(ob);
if(scalar==-1.0f && PyErr_Occurred()) { /* parsed item not a number */
PyErr_SetString(PyExc_TypeError, "vector[index] = x: index argument not a number\n");
return -1;
}
@@ -438,7 +501,7 @@ static int Vector_ass_item(VectorObject * self, int i, PyObject * ob)
PyErr_SetString(PyExc_IndexError, "vector[index] = x: assignment index out of range\n");
return -1;
}
self->vec[i] = (float)PyFloat_AsDouble(ob);
self->vec[i] = scalar;
return 0;
}
@@ -468,7 +531,7 @@ static int Vector_ass_slice(VectorObject * self, int begin, int end,
PyObject * seq)
{
int i, y, size = 0;
float vec[4];
float vec[4], scalar;
PyObject *v;
CLAMP(begin, 0, self->size);
@@ -489,13 +552,14 @@ static int Vector_ass_slice(VectorObject * self, int begin, int end,
return -1;
}
if(!PyNumber_Check(v)) { /* parsed item not a number */
scalar= (float)PyFloat_AsDouble(v);
if(scalar==-1.0f && PyErr_Occurred()) { /* parsed item not a number */
Py_DECREF(v);
PyErr_SetString(PyExc_TypeError, "vector[begin:end] = []: sequence argument not a number\n");
return -1;
}
vec[i] = (float)PyFloat_AsDouble(v);
vec[i] = scalar;
Py_DECREF(v);
}
/*parsed well - now set in vector*/
@@ -628,6 +692,7 @@ static PyObject *Vector_isub(PyObject * v1, PyObject * v2)
static PyObject *Vector_mul(PyObject * v1, PyObject * v2)
{
VectorObject *vec1 = NULL, *vec2 = NULL;
float scalar;
if VectorObject_Check(v1)
vec1= (VectorObject *)v1;
@@ -658,23 +723,9 @@ static PyObject *Vector_mul(PyObject * v1, PyObject * v2)
v2= v1;
}
if (PyNumber_Check(v2)) {
/* VEC * NUM */
int i;
float vec[4];
float scalar = (float)PyFloat_AsDouble( v2 );
for(i = 0; i < vec1->size; i++) {
vec[i] = vec1->vec[i] * scalar;
}
return newVectorObject(vec, vec1->size, Py_NEW);
} else if (MatrixObject_Check(v2)) {
if (MatrixObject_Check(v2)) {
/* VEC * MATRIX */
if (v1==v2) /* mat*vec, we have swapped the order */
return column_vector_multiplication((MatrixObject*)v2, vec1);
else /* vec*mat */
return row_vector_multiplication(vec1, (MatrixObject*)v2);
return row_vector_multiplication(vec1, (MatrixObject*)v2);
} else if (QuaternionObject_Check(v2)) {
QuaternionObject *quat = (QuaternionObject*)v2;
if(vec1->size != 3) {
@@ -683,6 +734,16 @@ static PyObject *Vector_mul(PyObject * v1, PyObject * v2)
}
return quat_rotation((PyObject*)vec1, (PyObject*)quat);
}
else if (((scalar= PyFloat_AsDouble(v2)) == -1.0 && PyErr_Occurred())==0) { /* VEC*FLOAT */
int i;
float vec[4];
for(i = 0; i < vec1->size; i++) {
vec[i] = vec1->vec[i] * scalar;
}
return newVectorObject(vec, vec1->size, Py_NEW);
}
PyErr_SetString(PyExc_TypeError, "Vector multiplication: arguments not acceptable for this operation\n");
return NULL;
@@ -694,21 +755,11 @@ static PyObject *Vector_imul(PyObject * v1, PyObject * v2)
{
VectorObject *vec = (VectorObject *)v1;
int i;
float scalar;
/* only support vec*=float and vec*=mat
vec*=vec result is a float so that wont work */
if (PyNumber_Check(v2)) {
/* VEC * NUM */
float scalar = (float)PyFloat_AsDouble( v2 );
for(i = 0; i < vec->size; i++) {
vec->vec[i] *= scalar;
}
Py_INCREF( v1 );
return v1;
} else if (MatrixObject_Check(v2)) {
if (MatrixObject_Check(v2)) {
float vecCopy[4];
int x,y, size = vec->size;
MatrixObject *mat= (MatrixObject*)v2;
@@ -739,6 +790,17 @@ static PyObject *Vector_imul(PyObject * v1, PyObject * v2)
Py_INCREF( v1 );
return v1;
}
else if (((scalar= PyFloat_AsDouble(v2)) == -1.0 && PyErr_Occurred())==0) { /* VEC*=FLOAT */
for(i = 0; i < vec->size; i++) {
vec->vec[i] *= scalar;
}
Py_INCREF( v1 );
return v1;
}
PyErr_SetString(PyExc_TypeError, "Vector multiplication: arguments not acceptable for this operation\n");
return NULL;
}
@@ -747,7 +809,7 @@ static PyObject *Vector_imul(PyObject * v1, PyObject * v2)
divide*/
static PyObject *Vector_div(PyObject * v1, PyObject * v2)
{
int i, size;
int i;
float vec[4], scalar;
VectorObject *vec1 = NULL;
@@ -757,28 +819,28 @@ static PyObject *Vector_div(PyObject * v1, PyObject * v2)
}
vec1 = (VectorObject*)v1; /* vector */
if(!PyNumber_Check(v2)) { /* parsed item not a number */
scalar = (float)PyFloat_AsDouble(v2);
if(scalar== -1.0f && PyErr_Occurred()) { /* parsed item not a number */
PyErr_SetString(PyExc_TypeError, "Vector division: Vector must be divided by a float\n");
return NULL;
}
scalar = (float)PyFloat_AsDouble(v2);
if(scalar==0.0) { /* not a vector */
PyErr_SetString(PyExc_ZeroDivisionError, "Vector division: divide by zero error.\n");
return NULL;
}
size = vec1->size;
for(i = 0; i < size; i++) {
for(i = 0; i < vec1->size; i++) {
vec[i] = vec1->vec[i] / scalar;
}
return newVectorObject(vec, size, Py_NEW);
return newVectorObject(vec, vec1->size, Py_NEW);
}
/*------------------------obj / obj------------------------------
/*------------------------obj /= obj------------------------------
divide*/
static PyObject *Vector_idiv(PyObject * v1, PyObject * v2)
{
int i, size;
int i;
float scalar;
VectorObject *vec1 = NULL;
@@ -788,20 +850,18 @@ static PyObject *Vector_idiv(PyObject * v1, PyObject * v2)
}*/
vec1 = (VectorObject*)v1; /* vector */
if(!PyNumber_Check(v2)) { /* parsed item not a number */
scalar = (float)PyFloat_AsDouble(v2);
if(scalar==-1.0f && PyErr_Occurred()) { /* parsed item not a number */
PyErr_SetString(PyExc_TypeError, "Vector division: Vector must be divided by a float\n");
return NULL;
}
scalar = (float)PyFloat_AsDouble(v2);
if(scalar==0.0) { /* not a vector */
PyErr_SetString(PyExc_ZeroDivisionError, "Vector division: divide by zero error.\n");
return NULL;
}
size = vec1->size;
for(i = 0; i < size; i++) {
for(i = 0; i < vec1->size; i++) {
vec1->vec[i] /= scalar;
}
Py_INCREF( v1 );
@@ -820,24 +880,6 @@ static PyObject *Vector_neg(VectorObject *self)
return newVectorObject(vec, self->size, Py_NEW);
}
/*------------------------coerce(obj, obj)-----------------------
coercion of unknown types to type VectorObject for numeric protocols
Coercion() is called whenever a math operation has 2 operands that
it doesn't understand how to evaluate. 2+Matrix for example. We want to
evaluate some of these operations like: (vector * 2), however, for math
to proceed, the unknown operand must be cast to a type that python math will
understand. (e.g. in the case above case, 2 must be cast to a vector and
then call vector.multiply(vector, scalar_cast_as_vector)*/
static int Vector_coerce(PyObject ** v1, PyObject ** v2)
{
/* Just incref, each functon must raise errors for bad types */
Py_INCREF (*v1);
Py_INCREF (*v2);
return 0;
}
/*------------------------tp_doc*/
static char VectorObject_doc[] = "This is a wrapper for vector objects.";
@@ -860,7 +902,7 @@ static double vec_magnitude_nosqrt(float *data, int size)
/*------------------------tp_richcmpr
returns -1 execption, 0 false, 1 true */
PyObject* Vector_richcmpr(PyObject *objectA, PyObject *objectB, int comparison_type)
static PyObject* Vector_richcmpr(PyObject *objectA, PyObject *objectB, int comparison_type)
{
VectorObject *vecA = NULL, *vecB = NULL;
int result = 0;
@@ -949,15 +991,6 @@ static PySequenceMethods Vector_SeqMethods = {
(ssizeobjargproc) Vector_ass_item, /* sq_ass_item */
(ssizessizeobjargproc) Vector_ass_slice, /* sq_ass_slice */
};
/* For numbers without flag bit Py_TPFLAGS_CHECKTYPES set, all
arguments are guaranteed to be of the object's type (modulo
coercion hacks -- i.e. if the type's coercion function
returns other types, then these are allowed as well). Numbers that
have the Py_TPFLAGS_CHECKTYPES flag bit set should check *both*
arguments for proper type and implement the necessary conversions
in the slot functions themselves. */
static PyNumberMethods Vector_NumMethods = {
(binaryfunc) Vector_add, /* __add__ */
@@ -977,11 +1010,7 @@ static PyNumberMethods Vector_NumMethods = {
(binaryfunc) NULL, /* __and__ */
(binaryfunc) NULL, /* __xor__ */
(binaryfunc) NULL, /* __or__ */
#if 0 //XXX 2.5
(coercion) Vector_coerce, /* __coerce__ */
#else
0,
#endif
/*(coercion)*/ NULL, /* __coerce__ */
(unaryfunc) NULL, /* __int__ */
(unaryfunc) NULL, /* __long__ */
(unaryfunc) NULL, /* __float__ */
@@ -1095,11 +1124,11 @@ static int Vector_setLength( VectorObject * self, PyObject * value )
double dot = 0.0f, param;
int i;
if (!PyNumber_Check(value)) {
PyErr_SetString( PyExc_TypeError, "expected a number for the vector axis" );
param= PyFloat_AsDouble( value );
if(param==-1.0 && PyErr_Occurred()) {
PyErr_SetString(PyExc_TypeError, "length must be set to a number");
return -1;
}
param= PyFloat_AsDouble( value );
if (param < 0) {
PyErr_SetString( PyExc_TypeError, "cannot set a vectors length to a negative value" );
@@ -1229,12 +1258,13 @@ static int Vector_setSwizzle(VectorObject * self, PyObject * value, void *closur
while (swizzleClosure & SWIZZLE_VALID_AXIS && axisB < listLen)
{
item = PyList_GetItem(value, axisB);
if (!PyNumber_Check(item))
{
scalarVal = (float)PyFloat_AsDouble(item);
if (scalarVal==-1.0 && PyErr_Occurred()) {
PyErr_SetString(PyExc_AttributeError, "Error: vector does not have specified axis.\n");
return -1;
}
scalarVal = (float)PyFloat_AsDouble(item);
axisA = swizzleClosure & SWIZZLE_AXIS;
vecTemp[axisA] = scalarVal;
@@ -1245,10 +1275,9 @@ static int Vector_setSwizzle(VectorObject * self, PyObject * value, void *closur
memcpy(self->vec, vecTemp, axisB * sizeof(float));
return 0;
}
else if (PyNumber_Check(value))
else if (((scalarVal = (float)PyFloat_AsDouble(value)) == -1.0 && PyErr_Occurred())==0)
{
/* Assign the same value to each axis. */
scalarVal = (float)PyFloat_AsDouble(value);
swizzleClosure = (unsigned int) closure;
while (swizzleClosure & SWIZZLE_VALID_AXIS)
{
@@ -1729,12 +1758,7 @@ PyTypeObject vector_Type = {
NULL, /* PyBufferProcs *tp_as_buffer; */
/*** Flags to define presence of optional/expanded features ***/
#if 0 //XXX 2.5
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /* long tp_flags; */
#else
Py_TPFLAGS_DEFAULT,
#endif
VectorObject_doc, /* char *tp_doc; Documentation string */
/*** Assigned meaning in release 2.0 ***/
/* call function for all accessible objects */
@@ -1766,7 +1790,7 @@ PyTypeObject vector_Type = {
0, /* long tp_dictoffset; */
NULL, /* initproc tp_init; */
NULL, /* allocfunc tp_alloc; */
NULL, /* newfunc tp_new; */
Vector_new, /* newfunc tp_new; */
/* Low-level free-memory routine */
NULL, /* freefunc tp_free; */
/* For PyObject_IS_GC */
@@ -1824,7 +1848,7 @@ PyObject *newVectorObject(float *vec, int size, int type)
#######################################################################
----------------------------Vector.negate() --------------------
set the vector to it's negative -x, -y, -z */
PyObject *Vector_Negate(VectorObject * self)
static PyObject *Vector_Negate(VectorObject * self)
{
int i;
for(i = 0; i < self->size; i++) {

View File

@@ -45,17 +45,6 @@ typedef struct {
} VectorObject;
/*prototypes*/
PyObject *Vector_Zero( VectorObject * self );
PyObject *Vector_Normalize( VectorObject * self );
PyObject *Vector_Negate( VectorObject * self );
PyObject *Vector_Resize2D( VectorObject * self );
PyObject *Vector_Resize3D( VectorObject * self );
PyObject *Vector_Resize4D( VectorObject * self );
PyObject *Vector_ToTrackQuat( VectorObject * self, PyObject * args );
PyObject *Vector_Reflect( VectorObject * self, PyObject * value );
PyObject *Vector_Cross( VectorObject * self, VectorObject * value );
PyObject *Vector_Dot( VectorObject * self, VectorObject * value );
PyObject *Vector_copy( VectorObject * self );
PyObject *newVectorObject(float *vec, int size, int type);
#endif /* EXPP_vector_h */

View File

@@ -771,12 +771,12 @@ static int pyrna_prop_contains(BPy_PropertyRNA * self, PyObject *value)
char *keyname = _PyUnicode_AsString(value);
if(keyname==NULL) {
PyErr_SetString(PyExc_SystemError, "PropertyRNA - key in prop, key must be a string type");
PyErr_SetString(PyExc_TypeError, "PropertyRNA - key in prop, key must be a string type");
return -1;
}
if (RNA_property_type(self->prop) != PROP_COLLECTION) {
PyErr_SetString(PyExc_SystemError, "PropertyRNA - key in prop, is only valid for collection types");
PyErr_SetString(PyExc_TypeError, "PropertyRNA - key in prop, is only valid for collection types");
return -1;
}
@@ -875,6 +875,19 @@ static PyObject *pyrna_struct_dir(BPy_StructRNA * self)
RNA_property_collection_end(&iter);
}
if(self->ptr.type == &RNA_Context) {
ListBase lb = CTX_data_dir_get(self->ptr.data);
LinkData *link;
for(link=lb.first; link; link=link->next) {
pystring = PyUnicode_FromString(link->data);
PyList_Append(ret, pystring);
Py_DECREF(pystring);
}
BLI_freelistN(&lb);
}
return ret;
}
@@ -1011,22 +1024,30 @@ PyObject *pyrna_prop_items(BPy_PropertyRNA *self)
CollectionPropertyIterator iter;
PropertyRNA *nameprop;
char name[256], *nameptr;
int i= 0;
ret = PyList_New(0);
RNA_property_collection_begin(&self->ptr, self->prop, &iter);
for(; iter.valid; RNA_property_collection_next(&iter)) {
if(iter.ptr.data && (nameprop = RNA_struct_name_property(iter.ptr.type))) {
nameptr= RNA_property_string_get_alloc(&iter.ptr, nameprop, name, sizeof(name));
if(iter.ptr.data) {
/* add to python list */
item = Py_BuildValue("(NN)", PyUnicode_FromString( nameptr ), pyrna_struct_CreatePyObject(&iter.ptr));
item= PyTuple_New(2);
if(nameprop = RNA_struct_name_property(iter.ptr.type)) {
nameptr= RNA_property_string_get_alloc(&iter.ptr, nameprop, name, sizeof(name));
PyTuple_SET_ITEM(item, 0, PyUnicode_FromString( nameptr ));
if ((char *)&name != nameptr)
MEM_freeN(nameptr);
}
else {
PyTuple_SET_ITEM(item, 0, PyLong_FromSsize_t(i)); /* a bit strange but better then returning an empty list */
}
PyTuple_SET_ITEM(item, 1, pyrna_struct_CreatePyObject(&iter.ptr));
PyList_Append(ret, item);
Py_DECREF(item);
/* done */
if ((char *)&name != nameptr)
MEM_freeN(nameptr);
i++;
}
}
RNA_property_collection_end(&iter);
@@ -1039,23 +1060,22 @@ PyObject *pyrna_prop_items(BPy_PropertyRNA *self)
PyObject *pyrna_prop_values(BPy_PropertyRNA *self)
{
PyObject *ret;
if (RNA_property_type(self->prop) != PROP_COLLECTION) {
PyErr_SetString( PyExc_TypeError, "values() is only valid for collection types" );
ret = NULL;
} else {
PyObject *item;
CollectionPropertyIterator iter;
PropertyRNA *nameprop;
PropertyRNA *iterprop;
ret = PyList_New(0);
//iterprop= RNA_struct_iterator_property(self->ptr.type);
RNA_property_collection_begin(&self->ptr, self->prop, &iter);
for(; iter.valid; RNA_property_collection_next(&iter)) {
if(iter.ptr.data && (nameprop = RNA_struct_name_property(iter.ptr.type))) {
item = pyrna_struct_CreatePyObject(&iter.ptr);
PyList_Append(ret, item);
Py_DECREF(item);
}
item = pyrna_struct_CreatePyObject(&iter.ptr);
PyList_Append(ret, item);
Py_DECREF(item);
}
RNA_property_collection_end(&iter);
}

View File

@@ -373,7 +373,7 @@ static struct PyMethodDef ui_methods[] = {
#if PY_VERSION_HEX >= 0x03000000
static struct PyModuleDef ui_module = {
PyModuleDef_HEAD_INIT,
"bpyui",
"bpy.ui",
"",
-1,/* multiple "initialization" just copies the module dict. */
ui_methods,

View File

@@ -77,6 +77,8 @@
#include "WM_api.h"
#include "RNA_define.h"
#include "GPU_draw.h"
#include "GPU_extensions.h"
@@ -310,11 +312,13 @@ int main(int argc, char **argv)
BLI_where_am_i(bprogname, argv[0]);
RNA_init();
/* Hack - force inclusion of the plugin api functions,
* see blenpluginapi:pluginapi.c
*/
pluginapi_force_ref();
init_nodesystem();
initglobals(); /* blender.c */

View File

@@ -409,7 +409,7 @@ bool BL_ActionActuator::Update(double curtime, bool frame)
/* Find percentages */
newweight = (m_blendframe/(float)m_blendin);
// XXX blend_poses(m_pose, m_blendpose, 1.0 - newweight, ACTSTRIPMODE_BLEND);
game_blend_poses(m_pose, m_blendpose, 1.0 - newweight);
/* Increment current blending percentage */
m_blendframe = (curtime - m_blendstart)*KX_KetsjiEngine::GetAnimFrameRate();

View File

@@ -43,6 +43,9 @@ float BL_ScalarInterpolator::GetValue(float currentTime) const {
}
BL_InterpolatorList::BL_InterpolatorList(struct AnimData *adt) {
if(adt->action==NULL)
return;
for(FCurve *fcu= (FCurve *)adt->action->curves.first; fcu; fcu= (FCurve *)fcu->next) {
if(fcu->rna_path) {
BL_ScalarInterpolator *new_ipo = new BL_ScalarInterpolator(fcu);

View File

@@ -18,9 +18,10 @@
#include "StringValue.h"
#include "VoidValue.h"
#include <algorithm>
#include <stdint.h>
#include "BoolValue.h"
#include "BLO_sys_types.h" /* for intptr_t support */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

View File

@@ -3,7 +3,7 @@ Import ('env')
sources = env.Glob('*.cpp')
incs ='. #source/kernel/gen_system #intern/string #intern/moto/include #source/gameengine/SceneGraph'
incs ='. #source/kernel/gen_system #intern/string #intern/moto/include #source/gameengine/SceneGraph #source/blender/blenloader'
incs += ' ' + env['BF_PYTHON_INC']
cxxflags = []

View File

@@ -51,6 +51,7 @@ SET(INC
../../../../source/blender
../../../../source/blender/include
../../../../source/blender/makesdna
../../../../source/blender/makesrna
../../../../source/gameengine/Rasterizer
../../../../source/gameengine/GameLogic
../../../../source/gameengine/Expressions

View File

@@ -86,6 +86,8 @@ extern "C"
#include "BKE_main.h"
#include "BKE_utildefines.h"
#include "RNA_define.h"
#ifdef WIN32
#include <windows.h>
#ifdef NDEBUG
@@ -344,6 +346,8 @@ int main(int argc, char** argv)
*/
#endif // __APPLE__
RNA_init();
init_nodesystem();
initglobals();

View File

@@ -68,6 +68,7 @@ CPPFLAGS += -I../../../blender/blenlib
CPPFLAGS += -I../../../blender/blenloader
CPPFLAGS += -I../../../blender/imbuf
CPPFLAGS += -I../../../blender/makesdna
CPPFLAGS += -I../../../blender/makesrna
CPPFLAGS += -I../../../blender/readblenfile
CPPFLAGS += -I../../../blender/gpu

View File

@@ -26,6 +26,7 @@ incs = ['.',
'#source/blender',
'#source/blender/include',
'#source/blender/makesdna',
'#source/blender/makesrna',
'#source/gameengine/BlenderRoutines',
'#source/gameengine/Rasterizer',
'#source/gameengine/GameLogic',