merge with trunk at r27259 and commit of a patch by anthony jones to fix msvc (though further work may be needed because changes made by the merge

This commit is contained in:
2010-03-09 04:32:40 +00:00
2116 changed files with 76457 additions and 47789 deletions

View File

@@ -15,7 +15,7 @@
*
* 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.
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.

View File

@@ -12,40 +12,37 @@
#
# 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.
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# The Original Code is Copyright (C) 2006, Blender Foundation
# All rights reserved.
#
# The Original Code is: all of this file.
#
# Contributor(s): Jacques Beaurain.
# Contributor(s): Jacques Beaurainm, Campbell Barton
#
# ***** END GPL LICENSE BLOCK *****
ADD_SUBDIRECTORY(generic)
FILE(GLOB SRC intern/*.c)
FILE(GLOB GENSRC generic/*.c)
SET(INC
. ../../../intern/guardedalloc ../blenlib ../makesdna ../makesrna
../blenkernel ../editors/include ../windowmanager ${PYTHON_INC}
../../../extern/glew/include
.
../blenlib
../makesdna
../makesrna
../blenkernel
../windowmanager
../editors/include
../../../intern/guardedalloc
${PYTHON_INC}
)
IF(WITH_OPENEXR)
ADD_DEFINITIONS(-DWITH_OPENEXR)
ENDIF(WITH_OPENEXR)
IF(WITH_QUICKTIME)
SET(INC ${INC} ${QUICKTIME_INC})
ADD_DEFINITIONS(-DWITH_QUICKTIME)
ENDIF(WITH_QUICKTIME)
IF(WITH_FFMPEG)
SET(INC ${INC} ${FFMPEG_INC})
ADD_DEFINITIONS(-DWITH_FFMPEG)
ENDIF(WITH_FFMPEG)
# only to check if buildinfo is available
IF(WITH_BUILDINFO)
ADD_DEFINITIONS(-DBUILD_DATE)
ENDIF(WITH_BUILDINFO)
BLENDERLIB(bf_python "${SRC}" "${INC}")
BLENDERLIB(bf_gen_python "${GENSRC}" "${INC}")

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,189 @@
# Blender.Geometry module and its subtypes
"""
The Blender.Geometry submodule.
Geometry
========
(when accessing it from the Game Engine use Geometry instead of Blender.Geometry)
This new module provides access to a geometry function.
"""
def Intersect(vec1, vec2, vec3, ray, orig, clip=1):
"""
Return the intersection between a ray and a triangle, if possible, return None otherwise.
@type vec1: Vector object.
@param vec1: A 3d vector, one corner of the triangle.
@type vec2: Vector object.
@param vec2: A 3d vector, one corner of the triangle.
@type vec3: Vector object.
@param vec3: A 3d vector, one corner of the triangle.
@type ray: Vector object.
@param ray: A 3d vector, the orientation of the ray. the length of the ray is not used, only the direction.
@type orig: Vector object.
@param orig: A 3d vector, the origin of the ray.
@type clip: integer
@param clip: if 0, don't restrict the intersection to the area of the triangle, use the infinite plane defined by the triangle.
@rtype: Vector object
@return: The intersection between a ray and a triangle, if possible, None otherwise.
"""
def TriangleArea(vec1, vec2, vec3):
"""
Return the area size of the 2D or 3D triangle defined.
@type vec1: Vector object.
@param vec1: A 2d or 3d vector, one corner of the triangle.
@type vec2: Vector object.
@param vec2: A 2d or 3d vector, one corner of the triangle.
@type vec3: Vector object.
@param vec3: A 2d or 3d vector, one corner of the triangle.
@rtype: float
@return: The area size of the 2D or 3D triangle defined.
"""
def TriangleNormal(vec1, vec2, vec3):
"""
Return the normal of the 3D triangle defined.
@type vec1: Vector object.
@param vec1: A 3d vector, one corner of the triangle.
@type vec2: Vector object.
@param vec2: A 3d vector, one corner of the triangle.
@type vec3: Vector object.
@param vec3: A 3d vector, one corner of the triangle.
@rtype: float
@return: The normal of the 3D triangle defined.
"""
def QuadNormal(vec1, vec2, vec3, vec4):
"""
Return the normal of the 3D quad defined.
@type vec1: Vector object.
@param vec1: A 3d vector, the first vertex of the quad.
@type vec2: Vector object.
@param vec2: A 3d vector, the second vertex of the quad.
@type vec3: Vector object.
@param vec3: A 3d vector, the third vertex of the quad.
@type vec4: Vector object.
@param vec4: A 3d vector, the fourth vertex of the quad.
@rtype: float
@return: The normal of the 3D quad defined.
"""
def LineIntersect(vec1, vec2, vec3, vec4):
"""
Return a tuple with the points on each line respectively closest to the other
(when both lines intersect, both vector hold the same value).
The lines are evaluated as infinite lines in space, the values returned may not be between the 2 points given for each line.
@type vec1: Vector object.
@param vec1: A 3d vector, one point on the first line.
@type vec2: Vector object.
@param vec2: A 3d vector, another point on the first line.
@type vec3: Vector object.
@param vec3: A 3d vector, one point on the second line.
@type vec4: Vector object.
@param vec4: A 3d vector, another point on the second line.
@rtype: (Vector object, Vector object)
@return: A tuple with the points on each line respectively closest to the other.
"""
def PolyFill(polylines):
"""
Takes a list of polylines and calculates triangles that would fill in the polylines.
Multiple lines can be used to make holes inside a polyline, or fill in 2 seperate lines at once.
@type polylines: List of lists containing vectors, each representing a closed polyline.
@rtype: list
@return: a list if tuples each a tuple of 3 ints representing a triangle indexing the points given.
@note: 2D Vectors will have an assumed Z axis of zero, 4D Vectors W axis is ignored.
@note: The order of points in a polyline effect the direction returned triangles face, reverse the order of a polyline to flip the normal of returned faces.
I{B{Example:}}
The example below creates 2 polylines and fills them in with faces, then makes a mesh in the current scene::
import Blender
Vector= Blender.Mathutils.Vector
# Outline of 5 points
polyline1= [Vector(-2.0, 1.0, 1.0), Vector(-1.0, 2.0, 1.0), Vector(1.0, 2.0, 1.0), Vector(1.0, -1.0, 1.0), Vector(-1.0, -1.0, 1.0)]
polyline2= [Vector(-1, 1, 1.0), Vector(0, 1, 1.0), Vector(0, 0, 1.0), Vector(-1.0, 0.0, 1.0)]
fill= Blender.Geometry.PolyFill([polyline1, polyline2])
# Make a new mesh and add the truangles into it
me= Blender.Mesh.New()
me.verts.extend(polyline1)
me.verts.extend(polyline2)
me.faces.extend(fill) # Add the faces, they reference the verts in polyline 1 and 2
scn = Blender.Scene.GetCurrent()
ob = scn.objects.new(me)
Blender.Redraw()
"""
def LineIntersect2D(vec1, vec2, vec3, vec4):
"""
Takes 2 lines vec1, vec2 for the 2 points of the first line and vec2, vec3 for the 2 points of the second line.
@rtype: Vector
@return: a 2D Vector for the intersection or None where there is no intersection.
"""
def ClosestPointOnLine(pt, vec1, vec2):
"""
Takes 2 lines vec1, vec2 for the 2 points of the first line and vec2, vec3 for the 2 points of the second line.
@rtype: tuple
@return: a tuple containing a vector and a float, the vector is the closest point on the line, the float is the position on the line, between 0 and 1 the point is on the line.
"""
def PointInTriangle2D(pt, tri_pt1, tri_pt2, tri_pt3):
"""
Takes 4 vectors (one for the test point and 3 for the triangle)
This is a 2d function so only X and Y are used, Z and W will be ignored.
@rtype: int
@return: 1 for a clockwise intersection, -1 for counter clockwise intersection, 0 when there is no intersection.
"""
def PointInQuad2D(pt, quad_pt1, quad_pt2, quad_pt3):
"""
Takes 5 vectors (one for the test point and 5 for the quad)
This is a 2d function so only X and Y are used, Z and W will be ignored.
@rtype: int
@return: 1 for a clockwise intersection, -1 for counter clockwise intersection, 0 when there is no intersection.
"""
def BoxPack2D(boxlist):
"""
Takes a list of 2D boxes and packs them into a square.
Each box in boxlist must be a list of at least 4 items - [x,y,w,h], after running this script,
the X and Y values in each box will be moved to packed, non overlapping locations.
Example::
# Make 500 random boxes, pack them and make a mesh from it
from Blender import Geometry, Scene, Mesh
import random
boxes = []
for i in xrange(500):
boxes.append( [0,0, random.random()+0.1, random.random()+0.1] )
boxsize = Geometry.BoxPack2D(boxes)
print 'BoxSize', boxsize
me = Mesh.New()
for x in boxes:
me.verts.extend([(x[0],x[1], 0), (x[0],x[1]+x[3], 0), (x[0]+x[2],x[1]+x[3], 0), (x[0]+x[2],x[1], 0) ])
v1= me.verts[-1]
v2= me.verts[-2]
v3= me.verts[-3]
v4= me.verts[-4]
me.faces.extend([(v1,v2,v3,v4)])
scn = Scene.GetCurrent()
scn.objects.new(me)
@note: Each boxlist item can be longer then 4, the extra items are ignored and stay untouched.
@rtype: tuple
@return: a tuple pair - (width, height) of all the packed boxes.
"""
def BezierInterp(vec_knot_1, vec_handle_1, vec_handle_2, vec_knot_2, resolution):
"""
Takes 4 vectors representing a bezier curve and returns a list of vector points.
@note: any vector size is supported, the largest dimension from the input will be used for all returned vectors/
@rtype: list
@return: a list of vectors the size of resolution including the start and end points (vec_knot_1 and vec_knot_2)
"""

View File

@@ -0,0 +1,132 @@
class IDGroup:
"""
The IDGroup Type
================
This type supports both iteration and the []
operator to get child ID properties.
You can also add new properties using the [] operator.
For example::
group['a float!'] = 0.0
group['an int!'] = 0
group['a string!'] = "hi!"
group['an array!'] = [0, 0, 1.0, 0]
group['a subgroup!] = {"float": 0.0, "an int": 1.0, "an array": [1, 2],
"another subgroup": {"a": 0.0, "str": "bleh"}}
Note that for arrays, the array type defaults to int unless a float is found
while scanning the template list; if any floats are found, then the whole
array is float. Note that double-precision floating point numbers are used for
python-created float ID properties and arrays (though the internal C api does
support single-precision floats, and the python code will read them).
You can also delete properties with the del operator. For example:
del group['property']
To get the type of a property, use the type() operator, for example::
if type(group['bleh']) == str: pass
To tell if the property is a group or array type, import the Blender.Types module and test
against IDGroupType and IDArrayType, like so::
from Blender.Types import IDGroupType, IDArrayType.
if type(group['bleghr']) == IDGroupType:
(do something)
@ivar name: The name of the property
@type name: string
"""
def pop(item):
"""
Pop an item from the group property.
@type item: string
@param item: The item name.
@rtype: can be dict, list, int, float or string.
@return: The removed property.
"""
def update(updatedict):
"""
Updates items in the dict, similar to normal python
dictionary method .update().
@type updatedict: dict
@param updatedict: A dict of simple types to derive updated/new IDProperties from.
@rtype: None
@return: None
"""
def keys():
"""
Returns a list of the keys in this property group.
@rtype: list of strings.
@return: a list of the keys in this property group.
"""
def values():
"""
Returns a list of the values in this property group.
Note that unless a value is itself a property group or an array, you
cannot change it by changing the values in this list, you must change them
in the parent property group.
For example,
group['some_property'] = new_value
. . .is correct, while,
values = group.values()
values[0] = new_value
. . .is wrong.
@rtype: list of strings.
@return: a list of the values in this property group.
"""
def iteritems():
"""
Implements the python dictionary iteritmes method.
For example::
for k, v in group.iteritems():
print "Property name: " + k
print "Property value: " + str(v)
@rtype: an iterator that spits out items of the form [key, value]
@return: an iterator.
"""
def convert_to_pyobject():
"""
Converts the entire property group to a purely python form.
@rtype: dict
@return: A python dictionary representing the property group
"""
class IDArray:
"""
The IDArray Type
================
@ivar type: returns the type of the array, can be either IDP_Int or IDP_Float
"""
def __getitem__(index):
pass
def __setitem__(index, value):
pass
def __len__():
pass

View File

@@ -0,0 +1,156 @@
# Blender.Mathutils module and its subtypes
class Vector:
"""
@attention: Vector data can be wrapped or non-wrapped. When a object is wrapped it
means that the object will give you direct access to the data inside of blender. Modification
of this object will directly change the data inside of blender. To copy a wrapped object
you need to use the object's constructor. If you copy and object by assignment you will not get
a second copy but a second reference to the same data. Only certain functions will return
wrapped data. This will be indicated in the method description.
"""
def __init__(list = None):
"""
Create a new 2d, 3d, or 4d Vector object from a list of floating point numbers.
@note: that python uses higher precission floating point numbers, so values assigned to a vector may have some rounding error.
Example::
v = Vector(1,0,0)
v = Vector(myVec)
v = Vector(list)
@type list: PyList of float or int
@param list: The list of values for the Vector object. Can be a sequence or raw numbers.
Must be 2, 3, or 4 values. The list is mapped to the parameters as [x,y,z,w].
@rtype: Vector object.
@return: It depends wheter a parameter was passed:
- (list): Vector object initialized with the given values;
- (): An empty 3 dimensional vector.
"""
class Euler:
"""
The Euler object
================
This object gives access to Eulers in Blender.
@note: You can access a euler object like a sequence
- x = euler[0]
@note: Comparison operators can be done:
- ==, != test numeric values within epsilon
@attention: Euler data can be wrapped or non-wrapped. When a object is wrapped it
means that the object will give you direct access to the data inside of blender. Modification
of this object will directly change the data inside of blender. To copy a wrapped object
you need to use the object's constructor. If you copy and object by assignment you will not get
a second copy but a second reference to the same data. Only certain functions will return
wrapped data. This will be indicated in the method description.
"""
def __init__(list = None):
"""
Create a new euler object.
Example::
euler = Euler(45,0,0)
euler = Euler(myEuler)
euler = Euler(sequence)
@type list: PyList of float/int
@param list: 3d list to initialize euler
@rtype: Euler object
@return: Euler representing heading, pitch, bank.
@note: Values are in degrees.
"""
class Quaternion:
"""
The Quaternion object
=====================
This object gives access to Quaternions in Blender.
@note: Comparison operators can be done:
- ==, != test numeric values within epsilon
@note: Math can be performed on Quaternion classes
- quat + quat
- quat - quat
- quat * float/int
- quat * vec
- quat * quat
@note: You can access a quaternion object like a sequence
- x = quat[0]
@attention: Quaternion data can be wrapped or non-wrapped. When a object is wrapped it
means that the object will give you direct access to the data inside of blender. Modification
of this object will directly change the data inside of blender. To copy a wrapped object
you need to use the object's constructor. If you copy and object by assignment you will not get
a second copy but a second reference to the same data. Only certain functions will return
wrapped data. This will be indicated in the method description.
"""
def __init__(list, angle = None):
"""
Create a new quaternion object from initialized values.
Example::
quat = Quaternion(1,2,3,4)
quat = Quaternion(axis, angle)
quat = Quaternion()
quat = Quaternion(180, list)
@type list: PyList of int/float
@param list: A 3d or 4d list to initialize quaternion.
4d if intializing [w,x,y,z], 3d if used as an axis of rotation.
@type angle: float (optional)
@param angle: An arbitrary rotation amount around 'list'.
List is used as an axis of rotation in this case.
@rtype: New quaternion object.
@return: It depends wheter a parameter was passed:
- (list/angle): Quaternion object initialized with the given values;
- (): An identity 4 dimensional quaternion.
"""
class Matrix:
"""
The Matrix Object
=================
@note: Math can be performed on Matrix classes
- mat + mat
- mat - mat
- mat * float/int
- mat * vec
- mat * mat
@note: Comparison operators can be done:
- ==, != test numeric values within epsilon
@note: You can access a quaternion object like a 2d sequence
- x = matrix[0][1]
- vector = matrix[2]
@attention: Quaternion data can be wrapped or non-wrapped. When a object is wrapped it
means that the object will give you direct access to the data inside of blender. Modification
of this object will directly change the data inside of blender. To copy a wrapped object
you need to use the object's constructor. If you copy and object by assignment you will not get
a second copy but a second reference to the same data. Only certain functions will return
wrapped data. This will be indicated in the method description.
"""
def __init__(list1 = None, list2 = None, list3 = None, list4 = None):
"""
Create a new matrix object from initialized values.
Example::
matrix = Matrix([1,1,1],[0,1,0],[1,0,0])
matrix = Matrix(mat)
matrix = Matrix(seq1, seq2, vector)
@type list1: PyList of int/float
@param list1: A 2d,3d or 4d list.
@type list2: PyList of int/float
@param list2: A 2d,3d or 4d list.
@type list3: PyList of int/float
@param list3: A 2d,3d or 4d list.
@type list4: PyList of int/float
@param list4: A 2d,3d or 4d list.
@rtype: New matrix object.
@return: It depends wheter a parameter was passed:
- (list1, etc.): Matrix object initialized with the given values;
- (): An empty 3 dimensional matrix.
"""

View File

@@ -0,0 +1,45 @@
# Testing the BGL module
import Blender
from Blender.BGL import *
from Blender import Draw
R = G = B = 0
A = 1
instructions = "Hold mouse buttons to change the background color."
quitting = " Press ESC or q to quit."
def show_win():
glClearColor(R,G,B,A) # define color used to clear buffers
glClear(GL_COLOR_BUFFER_BIT) # use it to clear the color buffer
glColor3f(1,1,1) # change default color
glRasterPos2i(50,100) # move cursor to x = 50, y = 100
Draw.Text("Testing BGL + Draw") # draw this text there
glRasterPos2i(350,20) # move cursor again
Draw.Text(instructions + quitting) # draw another msg
glBegin(GL_LINE_LOOP) # begin a vertex-data list
glVertex2i(46,92)
glVertex2i(120,92)
glVertex2i(120,115)
glVertex2i(46,115)
glEnd() # close this list
glColor3f(0.35,0.18,0.92) # change default color again
glBegin(GL_POLYGON) # another list, for a polygon
glVertex2i(315, 292)
glVertex2i(412, 200)
glVertex2i(264, 256)
glEnd()
Draw.Redraw(1) # make changes visible.
def ev(evt, val): # this is a callback for Draw.Register()
global R,G,B,A # it handles input events
if evt == Draw.ESCKEY or evt == Draw.QKEY:
Draw.Exit() # this quits the script
elif evt == Draw.LEFTMOUSE: R = 1 - R
elif evt == Draw.MIDDLEMOUSE: G = 1 - G
elif evt == Draw.RIGHTMOUSE: B = 1 - B
else:
Draw.Register(show_win, ev, None)
Draw.Register(show_win, ev, None) # start the main loop

View File

@@ -0,0 +1,3 @@
import Mathutils
# todo

View File

@@ -0,0 +1,3 @@
import Mathutils
# todo

View File

@@ -0,0 +1,3 @@
import Mathutils
# todo

View File

@@ -0,0 +1,55 @@
import Mathutils
# zero length vector
vec = Mathutils.Vector(0, 0, 1)
# unit length vector
vec_a = vec.copy().normalize()
vec_b = Mathutils.Vector(0, 1, 2)
vec2d = Mathutils.Vector(1, 2)
vec3d = Mathutils.Vector([1, 0, 0])
vec4d = vec_a.copy().resize4D()
# other mathutuls types
quat = Mathutils.Quaternion()
matrix = Mathutils.Matrix()
# Comparison operators can be done on Vector classes:
# greater and less then test vector length.
vec_a > vec_b
vec_a >= vec_b
vec_a < vec_b
vec_a <= vec_b
# ==, != test vector values e.g. 1,2,3 != 3,2,1 even if they are the same length
vec_a == vec_b
vec_a != vec_b
# Math can be performed on Vector classes
vec_a + vec_b
vec_a - vec_b
vec_a * vec_b
vec_a * 10.0
vec_a * matrix
vec_a * vec_b
vec_a * quat
-vec_a
# You can access a vector object like a sequence
x = vec_a[0]
len(vec)
vec_a[:] = vec_b
vec2d[:] = vec3d[:2]
# Vectors support 'swizzle' operations
# See http://en.wikipedia.org/wiki/Swizzling_(computer_graphics)
vec.xyz = vec.zyx
vec.xy = vec4d.zw
vec.xyz = vec4d.wzz
vec4d.wxyz = vec.yxyx

View File

@@ -0,0 +1,17 @@
import Mathutils
vec = Mathutils.Vector(1.0, 2.0, 3.0)
mat_rot = Mathutils.RotationMatrix(90, 4, 'X')
mat_trans = Mathutils.TranslationMatrix(vec)
mat = mat_trans * mat_rot
mat.invert()
mat3 = mat.rotation_part()
quat1 = mat.to_quat()
quat2 = mat3.to_quat()
angle = quat1.difference(quat2)
print(angle)

View File

@@ -0,0 +1,560 @@
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# Contributor(s): Campbell Barton
#
# #**** END GPL LICENSE BLOCK #****
script_help_msg = '''
Usage,
run this script from blenders root path once you have compiled blender
./blender.bin -b -P /b/source/blender/python/doc/sphinx_doc_gen.py
This will generate python files in "./source/blender/python/doc/sphinx-in"
Generate html docs by running...
sphinx-build source/blender/python/doc/sphinx-in source/blender/python/doc/sphinx-out
For PDF generation
sphinx-build -b latex source/blender/python/doc/sphinx-in source/blender/python/doc/sphinx-out
cd source/blender/python/doc/sphinx-out
make
'''
import os
import inspect
import bpy
import rna_info
reload(rna_info)
EXAMPLE_SET = set()
EXAMPLE_SET_USED = set()
def range_str(val):
if val < -10000000: return '-inf'
if val > 10000000: return 'inf'
if type(val)==float:
return '%g' % val
else:
return str(val)
def write_example_ref(ident, fw, example_id, ext=".py"):
if example_id in EXAMPLE_SET:
fw("%s.. literalinclude:: ../examples/%s%s\n\n" % (ident, example_id, ext))
EXAMPLE_SET_USED.add(example_id)
else:
if bpy.app.debug:
print("\tskipping example:", example_id)
def write_indented_lines(ident, fn, text, strip=True):
if text is None:
return
for l in text.split("\n"):
if strip:
fn(ident + l.strip() + "\n")
else:
fn(ident + l + "\n")
def pymethod2sphinx(ident, fw, identifier, py_func):
'''
class method to sphinx
'''
arg_str = inspect.formatargspec(*inspect.getargspec(py_func))
if arg_str.startswith("(self, "):
arg_str = "(" + arg_str[7:]
func_type = "method"
elif arg_str.startswith("(cls, "):
arg_str = "(" + arg_str[6:]
func_type = "classmethod"
else:
func_type = "staticmethod"
fw(ident + ".. %s:: %s%s\n\n" % (func_type, identifier, arg_str))
if py_func.__doc__:
write_indented_lines(ident + " ", fw, py_func.__doc__)
fw("\n")
def pyfunc2sphinx(ident, fw, identifier, py_func, is_class=True):
'''
function or class method to sphinx
'''
arg_str = inspect.formatargspec(*inspect.getargspec(py_func))
if not is_class:
func_type = "function"
# ther rest are class methods
elif arg_str.startswith("(self, "):
arg_str = "(" + arg_str[7:]
func_type = "method"
elif arg_str.startswith("(cls, "):
arg_str = "(" + arg_str[6:]
func_type = "classmethod"
else:
func_type = "staticmethod"
fw(ident + ".. %s:: %s%s\n\n" % (func_type, identifier, arg_str))
if py_func.__doc__:
write_indented_lines(ident + " ", fw, py_func.__doc__.strip())
fw("\n")
def py_c_func2sphinx(ident, fw, identifier, py_func, is_class=True):
'''
c defined function to sphinx.
'''
# dump the docstring, assume its formatted correctly
if py_func.__doc__:
write_indented_lines(ident, fw, py_func.__doc__, False)
fw("\n")
else:
fw(ident + ".. function:: %s()\n\n" % identifier)
fw(ident + " Undocumented function.\n\n" % identifier)
def pyprop2sphinx(ident, fw, identifier, py_prop):
'''
python property to sphinx
'''
fw(ident + ".. attribute:: %s\n\n" % identifier)
write_indented_lines(ident + " ", fw, py_prop.__doc__)
if py_prop.fset is None:
fw(ident + " (readonly)\n\n")
def pymodule2sphinx(BASEPATH, module_name, module, title):
import types
# lame, python wont give some access
MethodDescriptorType = type(dict.get)
GetSetDescriptorType = type(int.real)
filepath = os.path.join(BASEPATH, module_name + ".rst")
file = open(filepath, "w")
fw = file.write
fw(title + "\n")
fw(("=" * len(title)) + "\n\n")
fw(".. module:: %s\n\n" % module_name)
if module.__doc__:
# Note, may contain sphinx syntax, dont mangle!
fw(module.__doc__.strip())
fw("\n\n")
write_example_ref("", fw, module_name)
# write members of the module
# only tested with PyStructs which are not exactly modules
for attribute, descr in sorted(type(module).__dict__.items()):
if type(descr) == types.MemberDescriptorType:
if descr.__doc__:
fw(".. data:: %s\n\n" % attribute)
write_indented_lines(" ", fw, descr.__doc__, False)
fw("\n")
classes = []
for attribute in dir(module):
if not attribute.startswith("_"):
value = getattr(module, attribute)
value_type = type(value)
if value_type == types.FunctionType:
pyfunc2sphinx("", fw, attribute, value, is_class=False)
elif value_type in (types.BuiltinMethodType, types.BuiltinFunctionType): # both the same at the moment but to be future proof
# note: can't get args from these, so dump the string as is
# this means any module used like this must have fully formatted docstrings.
py_c_func2sphinx("", fw, attribute, value, is_class=False)
elif value_type == type:
classes.append((attribute, value))
# TODO, more types...
# write collected classes now
for (attribute, value) in classes:
# May need to be its own function
fw(".. class:: %s\n\n" % attribute)
if value.__doc__:
write_indented_lines(" ", fw, value.__doc__, False)
fw("\n")
write_example_ref(" ", fw, module_name + "." + attribute)
for key in sorted(value.__dict__.keys()):
if key.startswith("__"):
continue
descr = value.__dict__[key]
if type(descr) == GetSetDescriptorType:
if descr.__doc__:
fw(" .. attribute:: %s\n\n" % key)
write_indented_lines(" ", fw, descr.__doc__, False)
write_example_ref(" ", fw, module_name + "." + attribute + "." + key)
fw("\n")
for key in sorted(value.__dict__.keys()):
if key.startswith("__"):
continue
descr = value.__dict__[key]
if type(descr) == MethodDescriptorType: # GetSetDescriptorType, GetSetDescriptorType's are not documented yet
if descr.__doc__:
write_indented_lines(" ", fw, descr.__doc__, False)
write_example_ref(" ", fw, module_name + "." + attribute + "." + key)
fw("\n")
fw("\n\n")
file.close()
def rna2sphinx(BASEPATH):
structs, funcs, ops, props = rna_info.BuildRNAInfo()
try:
os.mkdir(BASEPATH)
except:
pass
# conf.py - empty for now
filepath = os.path.join(BASEPATH, "conf.py")
file = open(filepath, "w")
fw = file.write
version_string = bpy.app.version_string.split("(")[0]
if bpy.app.build_revision != "Unknown":
version_string = version_string + " r" + bpy.app.build_revision
fw("project = 'Blender 3D'\n")
# fw("master_doc = 'index'\n")
fw("copyright = u'Blender Foundation'\n")
fw("version = '%s - UNSTABLE API'\n" % version_string)
fw("release = '%s - UNSTABLE API'\n" % version_string)
# not helpful since the source us generated, adds to upload size.
fw("html_copy_source = False\n")
fw("\n")
# needed for latex, pdf gen
fw("latex_documents = [ ('contents', 'contents.tex', 'Blender Index', 'Blender Foundation', 'manual'), ]\n")
fw("latex_paper_size = 'a4paper'\n")
file.close()
filepath = os.path.join(BASEPATH, "contents.rst")
file = open(filepath, "w")
fw = file.write
fw("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n")
fw(" Blender Documentation contents\n")
fw("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n")
fw("\n")
fw("This document is an API reference for Blender %s. built %s.\n" % (version_string, bpy.app.build_date))
fw("\n")
fw("An introduction to blender and python can be found at <http://wiki.blender.org/index.php/Dev:2.5/Py/API/Intro>\n")
fw("\n")
fw(".. warning:: The Python API in Blender is **UNSTABLE**, It should only be used for testing, any script written now may break in future releases.\n")
fw(" \n")
fw(" The following areas are subject to change.\n")
fw(" * operator names and arguments\n")
fw(" * function calls with the data api (any function calls with values accessed from bpy.data), including functions for importing and exporting meshes\n")
fw(" * class registration (Operator, Panels, Menus, Headers)\n")
fw(" * modules: bpy.props, blf)\n")
fw(" * members in the bpy.context have to be reviewed\n")
fw(" * python defined modal operators, especially drawing callbacks are highly experemental\n")
fw(" \n")
fw(" These parts of the API are relatively stable and are unlikely to change significantly\n")
fw(" * data API, access to attributes of blender data such as mesh verts, material color, timeline frames and scene objects\n")
fw(" * user interface functions for defining buttons, creation of menus, headers, panels\n")
fw(" * modules: bgl, Mathutils and Geometry\n")
fw("\n")
fw(".. toctree::\n")
fw(" :maxdepth: 1\n\n")
fw(" bpy.ops.rst\n\n")
fw(" bpy.types.rst\n\n")
# py modules
fw(" bpy.utils.rst\n\n")
fw(" bpy.app.rst\n\n")
# C modules
fw(" bpy.props.rst\n\n")
fw(" Mathutils.rst\n\n")
fw(" blf.rst\n\n")
file.close()
# internal modules
filepath = os.path.join(BASEPATH, "bpy.ops.rst")
file = open(filepath, "w")
fw = file.write
fw("Blender Operators (bpy.ops)\n")
fw("===========================\n\n")
fw(".. toctree::\n")
fw(" :glob:\n\n")
fw(" bpy.ops.*\n\n")
file.close()
filepath = os.path.join(BASEPATH, "bpy.types.rst")
file = open(filepath, "w")
fw = file.write
fw("Blender Types (bpy.types)\n")
fw("=========================\n\n")
fw(".. toctree::\n")
fw(" :glob:\n\n")
fw(" bpy.types.*\n\n")
file.close()
# python modules
from bpy import utils as module
pymodule2sphinx(BASEPATH, "bpy.utils", module, "Utilities (bpy.utils)")
# C modules
from bpy import app as module
pymodule2sphinx(BASEPATH, "bpy.app", module, "Application Data (bpy.app)")
from bpy import props as module
pymodule2sphinx(BASEPATH, "bpy.props", module, "Property Definitions (bpy.props)")
import Mathutils as module
pymodule2sphinx(BASEPATH, "Mathutils", module, "Math Types & Utilities (Mathutils)")
del module
import blf as module
pymodule2sphinx(BASEPATH, "blf", module, "Blender Font Drawing (blf)")
del module
if 0:
filepath = os.path.join(BASEPATH, "bpy.rst")
file = open(filepath, "w")
fw = file.write
fw("\n")
title = ":mod:`bpy` --- Blender Python Module"
fw("%s\n%s\n\n" % (title, "=" * len(title)))
fw(".. module:: bpy.types\n\n")
file.close()
def write_param(ident, fw, prop, is_return=False):
if is_return:
id_name = "return"
id_type = "rtype"
kwargs = {"as_ret": True, "class_fmt": ":class:`%s`"}
identifier = ""
else:
id_name = "arg"
id_type = "type"
kwargs = {"as_arg": True, "class_fmt": ":class:`%s`"}
identifier = " %s" % prop.identifier
type_descr = prop.get_type_description(**kwargs)
if prop.name or prop.description:
fw(ident + ":%s%s: %s\n" % (id_name, identifier, ", ".join([val for val in (prop.name, prop.description) if val])))
fw(ident + ":%s%s: %s\n" % (id_type, identifier, type_descr))
def write_struct(struct):
#if not struct.identifier.startswith("Sc") and not struct.identifier.startswith("I"):
# return
#if not struct.identifier == "Object":
# return
filepath = os.path.join(BASEPATH, "bpy.types.%s.rst" % struct.identifier)
file = open(filepath, "w")
fw = file.write
if struct.base:
title = "%s(%s)" % (struct.identifier, struct.base.identifier)
else:
title = struct.identifier
fw("%s\n%s\n\n" % (title, "=" * len(title)))
fw(".. module:: bpy.types\n\n")
bases = struct.get_bases()
if bases:
if len(bases) > 1:
fw("base classes --- ")
else:
fw("base class --- ")
fw(", ".join([(":class:`%s`" % base.identifier) for base in reversed(bases)]))
fw("\n\n")
subclasses = [s for s in structs.values() if s.base is struct]
if subclasses:
fw("subclasses --- \n")
fw(", ".join([(":class:`%s`" % s.identifier) for s in subclasses]))
fw("\n\n")
if struct.base:
fw(".. class:: %s(%s)\n\n" % (struct.identifier, struct.base.identifier))
else:
fw(".. class:: %s\n\n" % struct.identifier)
fw(" %s\n\n" % struct.description)
for prop in struct.properties:
fw(" .. attribute:: %s\n\n" % prop.identifier)
if prop.description:
fw(" %s\n\n" % prop.description)
type_descr = prop.get_type_description(class_fmt=":class:`%s`")
fw(" *type* %s\n\n" % type_descr)
# python attributes
py_properties = struct.get_py_properties()
py_prop = None
for identifier, py_prop in py_properties:
pyprop2sphinx(" ", fw, identifier, py_prop)
del py_properties, py_prop
for func in struct.functions:
args_str = ", ".join([prop.get_arg_default(force=False) for prop in func.args])
fw(" .. method:: %s(%s)\n\n" % (func.identifier, args_str))
fw(" %s\n\n" % func.description)
for prop in func.args:
write_param(" ", fw, prop)
if len(func.return_values) == 1:
write_param(" ", fw, func.return_values[0], is_return=True)
elif func.return_values: # multiple return values
fw(" :return (%s):\n" % ", ".join([prop.identifier for prop in func.return_values]))
for prop in func.return_values:
type_descr = prop.get_type_description(as_ret=True, class_fmt=":class:`%s`")
descr = prop.description
if not descr:
descr = prop.name
fw(" `%s`, %s, %s\n\n" % (prop.identifier, descr, type_descr))
fw("\n")
# python methods
py_funcs = struct.get_py_functions()
py_func = None
for identifier, py_func in py_funcs:
pyfunc2sphinx(" ", fw, identifier, py_func, is_class=True)
del py_funcs, py_func
if struct.references:
# use this otherwise it gets in the index for a normal heading.
fw(".. rubric:: References\n\n")
for ref in struct.references:
ref_split = ref.split(".")
if len(ref_split) > 2:
ref = ref_split[-2] + "." + ref_split[-1]
fw("* :class:`%s`\n" % ref)
fw("\n")
for struct in structs.values():
# TODO, rna_info should filter these out!
if "_OT_" in struct.identifier:
continue
write_struct(struct)
# oeprators
def write_ops():
fw = None
last_mod = ''
for op_key in sorted(ops.keys()):
op = ops[op_key]
if last_mod != op.module_name:
filepath = os.path.join(BASEPATH, "bpy.ops.%s.rst" % op.module_name)
file = open(filepath, "w")
fw = file.write
title = "%s Operators" % (op.module_name[0].upper() + op.module_name[1:])
fw("%s\n%s\n\n" % (title, "=" * len(title)))
fw(".. module:: bpy.ops.%s\n\n" % op.module_name)
last_mod = op.module_name
args_str = ", ".join([prop.get_arg_default(force=True) for prop in op.args])
fw(".. function:: %s(%s)\n\n" % (op.func_name, args_str))
if op.description:
fw(" %s\n\n" % op.description)
for prop in op.args:
write_param(" ", fw, prop)
if op.args:
fw("\n")
location = op.get_location()
if location != (None, None):
fw(" *python operator source --- `%s:%d`* \n\n" % location)
write_ops()
file.close()
if __name__ == '__main__':
if 'bpy' not in dir():
print("\nError, this script must run from inside blender2.5")
print(script_help_msg)
else:
import shutil
path_in = 'source/blender/python/doc/sphinx-in'
path_out = 'source/blender/python/doc/sphinx-in'
path_examples = 'source/blender/python/doc/examples'
shutil.rmtree(path_in, True)
shutil.rmtree(path_out, True)
for f in os.listdir(path_examples):
if f.endswith(".py"):
EXAMPLE_SET.add(os.path.splitext(f)[0])
rna2sphinx(path_in)
# for fast module testing
# os.system("rm source/blender/python/doc/sphinx-in/bpy.types.*.rst")
# os.system("rm source/blender/python/doc/sphinx-in/bpy.ops.*.rst")
EXAMPLE_SET_UNUSED = EXAMPLE_SET - EXAMPLE_SET_USED
if EXAMPLE_SET_UNUSED:
print("\nUnused examples found in '%s'..." % path_examples)
for f in EXAMPLE_SET_UNUSED:
print(" %s.py" % f)
print(" %d total\n" % len(EXAMPLE_SET_UNUSED))
import sys
sys.exit()

View File

@@ -0,0 +1,34 @@
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# Contributor(s): Campbell Barton
#
# ***** END GPL LICENSE BLOCK *****
FILE(GLOB SRC *.c)
SET(INC
.
../../blenlib
../../makesdna
../../blenkernel
../../editors/include
../../../../intern/guardedalloc
../../../../extern/glew/include
${PYTHON_INC}
)
BLENDERLIB(bf_gen_python "${SRC}" "${INC}")

View File

@@ -15,7 +15,7 @@
*
* 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.
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
@@ -47,19 +47,14 @@
#define SWAP_FLOAT(a,b,tmp) tmp=a; a=b; b=tmp
#define eps 0.000001
/*-- forward declarations -- */
static PyObject *M_Geometry_PolyFill( PyObject * self, PyObject * polyLineSeq );
static PyObject *M_Geometry_LineIntersect2D( PyObject * self, PyObject * args );
static PyObject *M_Geometry_ClosestPointOnLine( PyObject * self, PyObject * args );
static PyObject *M_Geometry_PointInTriangle2D( PyObject * self, PyObject * args );
static PyObject *M_Geometry_PointInQuad2D( PyObject * self, PyObject * args );
static PyObject *M_Geometry_BoxPack2D( PyObject * self, PyObject * args );
static PyObject *M_Geometry_BezierInterp( PyObject * self, PyObject * args );
static PyObject *M_Geometry_BarycentricTransform( PyObject * self, PyObject * args );
/*-------------------------DOC STRINGS ---------------------------*/
static char M_Geometry_doc[] = "The Blender Geometry module\n\n";
static char M_Geometry_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_Geometry_TriangleArea_doc[] = "(v1, v2, v3) - returns the area size of the 2D or 3D triangle defined";
static char M_Geometry_TriangleNormal_doc[] = "(v1, v2, v3) - returns the normal of the 3D triangle defined";
static char M_Geometry_QuadNormal_doc[] = "(v1, v2, v3, v4) - returns the normal of the 3D quad defined";
static char M_Geometry_LineIntersect_doc[] = "(v1, v2, v3, v4) - returns a tuple with the points on each line respectively closest to the other";
static char M_Geometry_PolyFill_doc[] = "(veclist_list) - takes a list of polylines (each point a vector) and returns the point indicies for a polyline filled with triangles";
static char M_Geometry_LineIntersect2D_doc[] = "(lineA_p1, lineA_p2, lineB_p1, lineB_p2) - takes 2 lines (as 4 vectors) and returns a vector for their point of intersection or None";
static char M_Geometry_ClosestPointOnLine_doc[] = "(pt, line_p1, line_p2) - takes a point and a line and returns a (Vector, float) for the point on the line, and the bool so you can know if the point was between the 2 points";
@@ -67,40 +62,280 @@ static char M_Geometry_PointInTriangle2D_doc[] = "(pt, tri_p1, tri_p2, tri_p3) -
static char M_Geometry_PointInQuad2D_doc[] = "(pt, quad_p1, quad_p2, quad_p3, quad_p4) - takes 5 vectors, one is the point and the next 4 define the quad, only the x and y are used from the vectors";
static char M_Geometry_BoxPack2D_doc[] = "";
static char M_Geometry_BezierInterp_doc[] = "";
/*-----------------------METHOD DEFINITIONS ----------------------*/
struct PyMethodDef M_Geometry_methods[] = {
{"PolyFill", ( PyCFunction ) M_Geometry_PolyFill, METH_O, M_Geometry_PolyFill_doc},
{"LineIntersect2D", ( PyCFunction ) M_Geometry_LineIntersect2D, METH_VARARGS, M_Geometry_LineIntersect2D_doc},
{"ClosestPointOnLine", ( PyCFunction ) M_Geometry_ClosestPointOnLine, METH_VARARGS, M_Geometry_ClosestPointOnLine_doc},
{"PointInTriangle2D", ( PyCFunction ) M_Geometry_PointInTriangle2D, METH_VARARGS, M_Geometry_PointInTriangle2D_doc},
{"PointInQuad2D", ( PyCFunction ) M_Geometry_PointInQuad2D, METH_VARARGS, M_Geometry_PointInQuad2D_doc},
{"BoxPack2D", ( PyCFunction ) M_Geometry_BoxPack2D, METH_O, M_Geometry_BoxPack2D_doc},
{"BezierInterp", ( PyCFunction ) M_Geometry_BezierInterp, METH_VARARGS, M_Geometry_BezierInterp_doc},
{"BarycentricTransform", ( PyCFunction ) M_Geometry_BarycentricTransform, METH_VARARGS, NULL},
{NULL, NULL, 0, NULL}
};
static struct PyModuleDef M_Geometry_module_def = {
PyModuleDef_HEAD_INIT,
"Geometry", /* m_name */
M_Geometry_doc, /* m_doc */
0, /* m_size */
M_Geometry_methods, /* m_methods */
0, /* m_reload */
0, /* m_traverse */
0, /* m_clear */
0, /* m_free */
};
/*----------------------------MODULE INIT-------------------------*/
PyObject *Geometry_Init(void)
//---------------------------------INTERSECTION FUNCTIONS--------------------
//----------------------------------Mathutils.Intersect() -------------------
static PyObject *M_Geometry_Intersect( PyObject * self, PyObject * args )
{
PyObject *submodule;
submodule = PyModule_Create(&M_Geometry_module_def);
PyDict_SetItemString(PySys_GetObject("modules"), M_Geometry_module_def.m_name, submodule);
return (submodule);
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];
float det, inv_det, u, v, t;
int clip = 1;
if(!PyArg_ParseTuple(args, "O!O!O!O!O!|i", &vector_Type, &vec1, &vector_Type, &vec2, &vector_Type, &vec3, &vector_Type, &ray, &vector_Type, &ray_off , &clip)) {
PyErr_SetString( PyExc_TypeError, "expected 5 vector types\n" );
return NULL;
}
if(vec1->size != 3 || vec2->size != 3 || vec3->size != 3 || ray->size != 3 || ray_off->size != 3) {
PyErr_SetString( PyExc_TypeError, "only 3D vectors for all parameters\n");
return NULL;
}
if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2) || !BaseMath_ReadCallback(vec3) || !BaseMath_ReadCallback(ray) || !BaseMath_ReadCallback(ray_off))
return NULL;
VECCOPY(v1, vec1->vec);
VECCOPY(v2, vec2->vec);
VECCOPY(v3, vec3->vec);
VECCOPY(dir, ray->vec);
normalize_v3(dir);
VECCOPY(orig, ray_off->vec);
/* find vectors for two edges sharing v1 */
sub_v3_v3v3(e1, v2, v1);
sub_v3_v3v3(e2, v3, v1);
/* begin calculating determinant - also used to calculated U parameter */
cross_v3_v3v3(pvec, dir, e2);
/* if determinant is near zero, ray lies in plane of triangle */
det = dot_v3v3(e1, pvec);
if (det > -0.000001 && det < 0.000001) {
Py_RETURN_NONE;
}
inv_det = 1.0f / det;
/* calculate distance from v1 to ray origin */
sub_v3_v3v3(tvec, orig, v1);
/* calculate U parameter and test bounds */
u = dot_v3v3(tvec, pvec) * inv_det;
if (clip && (u < 0.0f || u > 1.0f)) {
Py_RETURN_NONE;
}
/* prepare to test the V parameter */
cross_v3_v3v3(qvec, tvec, e1);
/* calculate V parameter and test bounds */
v = dot_v3v3(dir, qvec) * inv_det;
if (clip && (v < 0.0f || u + v > 1.0f)) {
Py_RETURN_NONE;
}
/* calculate t, ray intersects triangle */
t = dot_v3v3(e2, qvec) * inv_det;
mul_v3_fl(dir, t);
add_v3_v3v3(pvec, orig, dir);
return newVectorObject(pvec, 3, Py_NEW, NULL);
}
//----------------------------------Mathutils.LineIntersect() -------------------
/* Line-Line intersection using algorithm from mathworld.wolfram.com */
static PyObject *M_Geometry_LineIntersect( PyObject * self, PyObject * args )
{
PyObject * tuple;
VectorObject *vec1, *vec2, *vec3, *vec4;
float v1[3], v2[3], v3[3], v4[3], i1[3], i2[3];
if( !PyArg_ParseTuple( args, "O!O!O!O!", &vector_Type, &vec1, &vector_Type, &vec2, &vector_Type, &vec3, &vector_Type, &vec4 ) ) {
PyErr_SetString( PyExc_TypeError, "expected 4 vector types\n" );
return NULL;
}
if( vec1->size != vec2->size || vec1->size != vec3->size || vec3->size != vec2->size) {
PyErr_SetString( PyExc_TypeError,"vectors must be of the same size\n" );
return NULL;
}
if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2) || !BaseMath_ReadCallback(vec3) || !BaseMath_ReadCallback(vec4))
return NULL;
if( vec1->size == 3 || vec1->size == 2) {
int result;
if (vec1->size == 3) {
VECCOPY(v1, vec1->vec);
VECCOPY(v2, vec2->vec);
VECCOPY(v3, vec3->vec);
VECCOPY(v4, vec4->vec);
}
else {
v1[0] = vec1->vec[0];
v1[1] = vec1->vec[1];
v1[2] = 0.0f;
v2[0] = vec2->vec[0];
v2[1] = vec2->vec[1];
v2[2] = 0.0f;
v3[0] = vec3->vec[0];
v3[1] = vec3->vec[1];
v3[2] = 0.0f;
v4[0] = vec4->vec[0];
v4[1] = vec4->vec[1];
v4[2] = 0.0f;
}
result = isect_line_line_v3(v1, v2, v3, v4, i1, i2);
if (result == 0) {
/* colinear */
Py_RETURN_NONE;
}
else {
tuple = PyTuple_New( 2 );
PyTuple_SetItem( tuple, 0, newVectorObject(i1, vec1->size, Py_NEW, NULL) );
PyTuple_SetItem( tuple, 1, newVectorObject(i2, vec1->size, Py_NEW, NULL) );
return tuple;
}
}
else {
PyErr_SetString( PyExc_TypeError, "2D/3D vectors only\n" );
return NULL;
}
}
//---------------------------------NORMALS FUNCTIONS--------------------
//----------------------------------Mathutils.QuadNormal() -------------------
static PyObject *M_Geometry_QuadNormal( PyObject * self, PyObject * args )
{
VectorObject *vec1;
VectorObject *vec2;
VectorObject *vec3;
VectorObject *vec4;
float v1[3], v2[3], v3[3], v4[3], e1[3], e2[3], n1[3], n2[3];
if( !PyArg_ParseTuple( args, "O!O!O!O!", &vector_Type, &vec1, &vector_Type, &vec2, &vector_Type, &vec3, &vector_Type, &vec4 ) ) {
PyErr_SetString( PyExc_TypeError, "expected 4 vector types\n" );
return NULL;
}
if( vec1->size != vec2->size || vec1->size != vec3->size || vec1->size != vec4->size) {
PyErr_SetString( PyExc_TypeError,"vectors must be of the same size\n" );
return NULL;
}
if( vec1->size != 3 ) {
PyErr_SetString( PyExc_TypeError, "only 3D vectors\n" );
return NULL;
}
if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2) || !BaseMath_ReadCallback(vec3) || !BaseMath_ReadCallback(vec4))
return NULL;
VECCOPY(v1, vec1->vec);
VECCOPY(v2, vec2->vec);
VECCOPY(v3, vec3->vec);
VECCOPY(v4, vec4->vec);
/* find vectors for two edges sharing v2 */
sub_v3_v3v3(e1, v1, v2);
sub_v3_v3v3(e2, v3, v2);
cross_v3_v3v3(n1, e2, e1);
normalize_v3(n1);
/* find vectors for two edges sharing v4 */
sub_v3_v3v3(e1, v3, v4);
sub_v3_v3v3(e2, v1, v4);
cross_v3_v3v3(n2, e2, e1);
normalize_v3(n2);
/* adding and averaging the normals of both triangles */
add_v3_v3v3(n1, n2, n1);
normalize_v3(n1);
return newVectorObject(n1, 3, Py_NEW, NULL);
}
//----------------------------Mathutils.TriangleNormal() -------------------
static PyObject *M_Geometry_TriangleNormal( PyObject * self, PyObject * args )
{
VectorObject *vec1, *vec2, *vec3;
float v1[3], v2[3], v3[3], e1[3], e2[3], n[3];
if( !PyArg_ParseTuple( args, "O!O!O!", &vector_Type, &vec1, &vector_Type, &vec2, &vector_Type, &vec3 ) ) {
PyErr_SetString( PyExc_TypeError, "expected 3 vector types\n" );
return NULL;
}
if( vec1->size != vec2->size || vec1->size != vec3->size ) {
PyErr_SetString( PyExc_TypeError, "vectors must be of the same size\n" );
return NULL;
}
if( vec1->size != 3 ) {
PyErr_SetString( PyExc_TypeError, "only 3D vectors\n" );
return NULL;
}
if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2) || !BaseMath_ReadCallback(vec3))
return NULL;
VECCOPY(v1, vec1->vec);
VECCOPY(v2, vec2->vec);
VECCOPY(v3, vec3->vec);
/* find vectors for two edges sharing v2 */
sub_v3_v3v3(e1, v1, v2);
sub_v3_v3v3(e2, v3, v2);
cross_v3_v3v3(n, e2, e1);
normalize_v3(n);
return newVectorObject(n, 3, Py_NEW, NULL);
}
//--------------------------------- AREA FUNCTIONS--------------------
//----------------------------------Mathutils.TriangleArea() -------------------
static PyObject *M_Geometry_TriangleArea( PyObject * self, PyObject * args )
{
VectorObject *vec1, *vec2, *vec3;
float v1[3], v2[3], v3[3];
if( !PyArg_ParseTuple
( args, "O!O!O!", &vector_Type, &vec1, &vector_Type, &vec2
, &vector_Type, &vec3 ) ) {
PyErr_SetString( PyExc_TypeError, "expected 3 vector types\n");
return NULL;
}
if( vec1->size != vec2->size || vec1->size != vec3->size ) {
PyErr_SetString( PyExc_TypeError, "vectors must be of the same size\n" );
return NULL;
}
if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2) || !BaseMath_ReadCallback(vec3))
return NULL;
if (vec1->size == 3) {
VECCOPY(v1, vec1->vec);
VECCOPY(v2, vec2->vec);
VECCOPY(v3, vec3->vec);
return PyFloat_FromDouble( area_tri_v3(v1, v2, v3) );
}
else if (vec1->size == 2) {
v1[0] = vec1->vec[0];
v1[1] = vec1->vec[1];
v2[0] = vec2->vec[0];
v2[1] = vec2->vec[1];
v3[0] = vec3->vec[0];
v3[1] = vec3->vec[1];
return PyFloat_FromDouble( area_tri_v2(v1, v2, v3) );
}
else {
PyErr_SetString( PyExc_TypeError, "only 2D,3D vectors are supported\n" );
return NULL;
}
}
/*----------------------------------Geometry.PolyFill() -------------------*/
@@ -569,3 +804,43 @@ static PyObject *M_Geometry_BarycentricTransform(PyObject * self, PyObject * arg
return newVectorObject(vec, 3, Py_NEW, NULL);
}
struct PyMethodDef M_Geometry_methods[] = {
{"Intersect", ( PyCFunction ) M_Geometry_Intersect, METH_VARARGS, M_Geometry_Intersect_doc},
{"TriangleArea", ( PyCFunction ) M_Geometry_TriangleArea, METH_VARARGS, M_Geometry_TriangleArea_doc},
{"TriangleNormal", ( PyCFunction ) M_Geometry_TriangleNormal, METH_VARARGS, M_Geometry_TriangleNormal_doc},
{"QuadNormal", ( PyCFunction ) M_Geometry_QuadNormal, METH_VARARGS, M_Geometry_QuadNormal_doc},
{"LineIntersect", ( PyCFunction ) M_Geometry_LineIntersect, METH_VARARGS, M_Geometry_LineIntersect_doc},
{"PolyFill", ( PyCFunction ) M_Geometry_PolyFill, METH_O, M_Geometry_PolyFill_doc},
{"LineIntersect2D", ( PyCFunction ) M_Geometry_LineIntersect2D, METH_VARARGS, M_Geometry_LineIntersect2D_doc},
{"ClosestPointOnLine", ( PyCFunction ) M_Geometry_ClosestPointOnLine, METH_VARARGS, M_Geometry_ClosestPointOnLine_doc},
{"PointInTriangle2D", ( PyCFunction ) M_Geometry_PointInTriangle2D, METH_VARARGS, M_Geometry_PointInTriangle2D_doc},
{"PointInQuad2D", ( PyCFunction ) M_Geometry_PointInQuad2D, METH_VARARGS, M_Geometry_PointInQuad2D_doc},
{"BoxPack2D", ( PyCFunction ) M_Geometry_BoxPack2D, METH_O, M_Geometry_BoxPack2D_doc},
{"BezierInterp", ( PyCFunction ) M_Geometry_BezierInterp, METH_VARARGS, M_Geometry_BezierInterp_doc},
{"BarycentricTransform", ( PyCFunction ) M_Geometry_BarycentricTransform, METH_VARARGS, NULL},
{NULL, NULL, 0, NULL}
};
static struct PyModuleDef M_Geometry_module_def = {
PyModuleDef_HEAD_INIT,
"Geometry", /* m_name */
M_Geometry_doc, /* m_doc */
0, /* m_size */
M_Geometry_methods, /* m_methods */
0, /* m_reload */
0, /* m_traverse */
0, /* m_clear */
0, /* m_free */
};
/*----------------------------MODULE INIT-------------------------*/
PyObject *Geometry_Init(void)
{
PyObject *submodule;
submodule = PyModule_Create(&M_Geometry_module_def);
PyDict_SetItemString(PySys_GetObject("modules"), M_Geometry_module_def.m_name, submodule);
return (submodule);
}

View File

@@ -15,7 +15,7 @@
*
* 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.
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.

View File

@@ -15,7 +15,7 @@
*
* 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.
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*
* Contributor(s): Joseph Eagar, Campbell Barton
@@ -75,6 +75,29 @@ PyObject *BPy_IDGroup_WrapData( ID *id, IDProperty *prop )
array->prop = prop;
return (PyObject*) array;
}
case IDP_IDPARRAY: /* this could be better a internal type */
{
PyObject *seq = PyList_New(prop->len), *wrap;
IDProperty *array= IDP_IDPArray(prop);
int i;
if (!seq) {
PyErr_Format( PyExc_RuntimeError, "BPy_IDGroup_MapDataToPy, IDP_IDPARRAY: PyList_New(%d) failed", prop->len);
return NULL;
}
for (i=0; i<prop->len; i++) {
wrap= BPy_IDGroup_WrapData(id, array++);
if (!wrap) /* BPy_IDGroup_MapDataToPy sets the error */
return NULL;
PyList_SET_ITEM(seq, i, wrap);
}
return seq;
}
/* case IDP_IDPARRAY: TODO */
}
Py_RETURN_NONE;
}
@@ -210,6 +233,46 @@ static PyObject *BPy_IDGroup_Map_GetItem(BPy_IDProperty *self, PyObject *item)
}
/*returns NULL on success, error string on failure*/
static int idp_sequence_type(PyObject *seq)
{
PyObject *item;
int type= IDP_INT;
int i, len = PySequence_Length(seq);
for (i=0; i < len; i++) {
item = PySequence_GetItem(seq, i);
if (PyFloat_Check(item)) {
if(type == IDP_IDPARRAY) { /* mixed dict/int */
Py_DECREF(item);
return -1;
}
type= IDP_DOUBLE;
}
else if (PyLong_Check(item)) {
if(type == IDP_IDPARRAY) { /* mixed dict/int */
Py_DECREF(item);
return -1;
}
}
else if (PyMapping_Check(item)) {
if(i != 0 && (type != IDP_IDPARRAY)) { /* mixed dict/int */
Py_DECREF(item);
return -1;
}
type= IDP_IDPARRAY;
}
else {
Py_XDECREF(item);
return -1;
}
Py_DECREF(item);
}
return type;
}
/* note: group can be a pointer array or a group */
char *BPy_IDProperty_Map_ValidateAndCreate(char *name, IDProperty *group, PyObject *ob)
{
IDProperty *prop = NULL;
@@ -231,29 +294,44 @@ char *BPy_IDProperty_Map_ValidateAndCreate(char *name, IDProperty *group, PyObje
PyObject *item;
int i;
if((val.array.type= idp_sequence_type(ob)) == -1)
return "only floats, ints and dicts are allowed in ID property arrays";
/*validate sequence and derive type.
we assume IDP_INT unless we hit a float
number; then we assume it's */
val.array.type = IDP_INT;
val.array.len = PySequence_Length(ob);
for (i=0; i<val.array.len; i++) {
item = PySequence_GetItem(ob, i);
if (PyFloat_Check(item)) val.array.type = IDP_DOUBLE;
else if (!PyLong_Check(item)) {
Py_XDECREF(item);
return "only floats and ints are allowed in ID property arrays";
}
Py_XDECREF(item);
}
prop = IDP_New(IDP_ARRAY, val, name);
for (i=0; i<val.array.len; i++) {
item = PySequence_GetItem(ob, i);
if (val.array.type == IDP_INT) {
((int*)prop->data.pointer)[i] = (int)PyLong_AsSsize_t(item);
} else {
val.array.len = PySequence_Length(ob);
switch(val.array.type) {
case IDP_DOUBLE:
prop = IDP_New(IDP_ARRAY, val, name);
for (i=0; i<val.array.len; i++) {
item = PySequence_GetItem(ob, i);
((double*)prop->data.pointer)[i] = (float)PyFloat_AsDouble(item);
Py_DECREF(item);
}
break;
case IDP_INT:
prop = IDP_New(IDP_ARRAY, val, name);
for (i=0; i<val.array.len; i++) {
item = PySequence_GetItem(ob, i);
((int*)prop->data.pointer)[i] = (int)PyLong_AsSsize_t(item);
Py_DECREF(item);
}
break;
case IDP_IDPARRAY:
prop= IDP_NewIDPArray(name);
for (i=0; i<val.array.len; i++) {
char *error;
item = PySequence_GetItem(ob, i);
error= BPy_IDProperty_Map_ValidateAndCreate("", prop, item);
Py_DECREF(item);
if(error)
return error;
}
break;
}
} else if (PyMapping_Check(ob)) {
PyObject *keys, *vals, *key, *pval;
@@ -294,7 +372,14 @@ char *BPy_IDProperty_Map_ValidateAndCreate(char *name, IDProperty *group, PyObje
Py_XDECREF(vals);
} else return "invalid property value";
IDP_ReplaceInGroup(group, prop);
if(group->type==IDP_IDPARRAY) {
IDP_AppendArray(group, prop);
// IDP_FreeProperty(item); // IDP_AppendArray does a shallow copy (memcpy), only free memory
MEM_freeN(prop);
} else {
IDP_ReplaceInGroup(group, prop);
}
return NULL;
}
@@ -371,7 +456,7 @@ static PyObject *BPy_IDGroup_MapDataToPy(IDProperty *prop)
int i;
if (!seq) {
PyErr_SetString( PyExc_RuntimeError, "PyList_New() failed" );
PyErr_Format( PyExc_RuntimeError, "BPy_IDGroup_MapDataToPy, IDP_ARRAY: PyList_New(%d) failed", prop->len);
return NULL;
}
@@ -389,22 +474,37 @@ static PyObject *BPy_IDGroup_MapDataToPy(IDProperty *prop)
}
return seq;
}
case IDP_IDPARRAY:
{
PyObject *seq = PyList_New(prop->len), *wrap;
IDProperty *array= IDP_IDPArray(prop);
int i;
if (!seq) {
PyErr_Format( PyExc_RuntimeError, "BPy_IDGroup_MapDataToPy, IDP_IDPARRAY: PyList_New(%d) failed", prop->len);
return NULL;
}
for (i=0; i<prop->len; i++) {
wrap= BPy_IDGroup_MapDataToPy(array++);
if (!wrap) /* BPy_IDGroup_MapDataToPy sets the error */
return NULL;
PyList_SET_ITEM(seq, i, wrap);
}
return seq;
}
case IDP_GROUP:
{
PyObject *dict = PyDict_New(), *wrap;
IDProperty *loop;
if (!dict) {
PyErr_SetString( PyExc_RuntimeError, "PyDict_New() failed" );
return NULL;
}
for (loop=prop->data.group.first; loop; loop=loop->next) {
wrap = BPy_IDGroup_MapDataToPy(loop);
if (!wrap) {
PyErr_SetString( PyExc_RuntimeError, "BPy_IDGroup_MapDataToPy() failed" );
if (!wrap) /* BPy_IDGroup_MapDataToPy sets the error */
return NULL;
}
PyDict_SetItemString(dict, loop->name, wrap);
}
@@ -412,7 +512,7 @@ static PyObject *BPy_IDGroup_MapDataToPy(IDProperty *prop)
}
}
PyErr_SetString( PyExc_RuntimeError, "eek!! a property exists with a bad type code!!!" );
PyErr_Format(PyExc_RuntimeError, "eek!! '%s' property exists with a bad type code '%d' !!!", prop->name, prop->type);
return NULL;
}
@@ -480,10 +580,13 @@ PyObject *BPy_Wrap_GetKeys(IDProperty *prop)
IDProperty *loop;
int i;
for (i=0, loop=prop->data.group.first; loop; loop=loop->next, i++)
for (i=0, loop=prop->data.group.first; loop && (i < prop->len); loop=loop->next, i++)
PyList_SET_ITEM(seq, i, PyUnicode_FromString(loop->name));
if (i != prop->len) {
/* if the id prop is corrupt, count the remaining */
for (; loop; loop=loop->next, i++) {}
if (i != prop->len) { /* if the loop didnt finish, we know the length is wrong */
BPy_IDGroup_CorrectListLen(prop, seq, i);
Py_DECREF(seq); /*free the list*/
/*call self again*/
@@ -611,21 +714,21 @@ PyObject* BPy_IDGroup_Get(BPy_IDProperty *self, PyObject *args)
static struct PyMethodDef BPy_IDGroup_methods[] = {
{"pop", (PyCFunction)BPy_IDGroup_Pop, METH_O,
"pop an item from the group; raises KeyError if the item doesn't exist."},
"pop an item from the group; raises KeyError if the item doesn't exist"},
{"iteritems", (PyCFunction)BPy_IDGroup_IterItems, METH_NOARGS,
"iterate through the items in the dict; behaves like dictionary method iteritems."},
"iterate through the items in the dict; behaves like dictionary method iteritems"},
{"keys", (PyCFunction)BPy_IDGroup_GetKeys, METH_NOARGS,
"get the keys associated with this group as a list of strings."},
"get the keys associated with this group as a list of strings"},
{"values", (PyCFunction)BPy_IDGroup_GetValues, METH_NOARGS,
"get the values associated with this group."},
"get the values associated with this group"},
{"items", (PyCFunction)BPy_IDGroup_GetItems, METH_NOARGS,
"get the items associated with this group."},
"get the items associated with this group"},
{"update", (PyCFunction)BPy_IDGroup_Update, METH_O,
"updates the values in the group with the values of another or a dict."},
"updates the values in the group with the values of another or a dict"},
{"get", (PyCFunction)BPy_IDGroup_Get, METH_VARARGS,
"idprop.get(k[,d]) -> idprop[k] if k in idprop, else d. d defaults to None."},
"idprop.get(k[,d]) -> idprop[k] if k in idprop, else d. d defaults to None"},
{"convert_to_pyobject", (PyCFunction)BPy_IDGroup_ConvertToPy, METH_NOARGS,
"return a purely python version of the group."},
"return a purely python version of the group"},
{0, NULL, 0, NULL}
};
@@ -758,7 +861,7 @@ static PyObject *BPy_IDArray_ConvertToPy(BPy_IDArray *self)
static PyMethodDef BPy_IDArray_methods[] = {
{"convert_to_pyobject", (PyCFunction)BPy_IDArray_ConvertToPy, METH_NOARGS,
"return a purely python version of the group."},
"return a purely python version of the group"},
{0, NULL, 0, NULL}
};

View File

@@ -15,7 +15,7 @@
*
* 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.
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Joseph Eagar, Campbell Barton
*
@@ -49,14 +49,14 @@ typedef struct BPy_IDGroup_Iter {
} BPy_IDGroup_Iter;
PyObject *BPy_Wrap_IDProperty(struct ID *id, struct IDProperty *prop, struct IDProperty *parent);
PyObject *BPy_Wrap_GetKeys(IDProperty *prop);
PyObject *BPy_Wrap_GetValues(ID *id, IDProperty *prop);
PyObject *BPy_Wrap_GetItems(ID *id, IDProperty *prop);
int BPy_Wrap_SetMapItem(IDProperty *prop, PyObject *key, PyObject *val);
PyObject *BPy_Wrap_GetKeys(struct IDProperty *prop);
PyObject *BPy_Wrap_GetValues(struct ID *id, struct IDProperty *prop);
PyObject *BPy_Wrap_GetItems(struct ID *id, struct IDProperty *prop);
int BPy_Wrap_SetMapItem(struct IDProperty *prop, PyObject *key, PyObject *val);
PyObject *BPy_IDGroup_WrapData( ID *id, IDProperty *prop );
char *BPy_IDProperty_Map_ValidateAndCreate(char *name, IDProperty *group, PyObject *ob);
PyObject *BPy_IDGroup_WrapData(struct ID *id, struct IDProperty *prop );
char *BPy_IDProperty_Map_ValidateAndCreate(char *name, struct IDProperty *group, PyObject *ob);
void IDProp_Init_Types(void);

File diff suppressed because it is too large Load Diff

View File

@@ -15,7 +15,7 @@
*
* 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.
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
@@ -32,15 +32,17 @@
#define EXPP_Mathutils_H
#include <Python.h>
#include "vector.h"
#include "matrix.h"
#include "quat.h"
#include "euler.h"
/* #define USE_MATHUTILS_DEG - for backwards compat */
/* Can cast different mathutils types to this, use for generic funcs */
extern char BaseMathObject_Wrapped_doc[];
extern char BaseMathObject_Owner_doc[];
typedef struct {
PyObject_VAR_HEAD
float *data; /*array of data (alias), wrapped status depends on wrapped status */

View File

@@ -0,0 +1,196 @@
/**
* $Id:
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Campbell Barton
*
* ***** END GPL LICENSE BLOCK *****
*/
#include <Python.h>
#include "blf.h"
#include "../../blenfont/BLF_api.h"
static char py_blf_position_doc[] =
".. function:: position(x, y, z)\n"
"\n"
" Set the position for drawing text.";
static PyObject *py_blf_position(PyObject *self, PyObject *args)
{
float x, y, z;
if (!PyArg_ParseTuple(args, "fff:BLF.position", &x, &y, &z))
return NULL;
BLF_position(x, y, z);
Py_RETURN_NONE;
}
static char py_blf_size_doc[] =
".. function:: size(size, dpi)\n"
"\n"
" Set the size and dpi for drawing text.\n"
"\n"
" :arg size: Point size of the font.\n"
" :type size: int\n"
" :arg dpi: dots per inch value to use for drawing.\n"
" :type dpi: int\n";
static PyObject *py_blf_size(PyObject *self, PyObject *args)
{
int size, dpi;
if (!PyArg_ParseTuple(args, "ii:BLF.size", &size, &dpi))
return NULL;
BLF_size(size, dpi);
Py_RETURN_NONE;
}
static char py_blf_aspect_doc[] =
".. function:: aspect(aspect)\n"
"\n"
" Set the aspect for drawing text.\n"
"\n"
" :arg aspect: The aspect ratio for text drawing to use.\n"
" :type aspect: float\n";
static PyObject *py_blf_aspect(PyObject *self, PyObject *args)
{
float aspect;
if (!PyArg_ParseTuple(args, "f:BLF.aspect", &aspect))
return NULL;
BLF_aspect(aspect);
Py_RETURN_NONE;
}
static char py_blf_blur_doc[] =
".. function:: blur(radius)\n"
"\n"
" Set the blur radius for drawing text.\n"
"\n"
" :arg radius: The radius for blurring text (in pixels).\n"
" :type radius: int\n";
static PyObject *py_blf_blur(PyObject *self, PyObject *args)
{
int blur;
if (!PyArg_ParseTuple(args, "i:BLF.blur", &blur))
return NULL;
BLF_blur(blur);
Py_RETURN_NONE;
}
static char py_blf_draw_doc[] =
".. function:: draw(text)\n"
"\n"
" Draw text in the current context.\n"
"\n"
" :arg text: the text to draw.\n"
" :type text: string\n";
static PyObject *py_blf_draw(PyObject *self, PyObject *args)
{
char *text;
if (!PyArg_ParseTuple(args, "s:BLF.draw", &text))
return NULL;
BLF_draw(text);
Py_RETURN_NONE;
}
static char py_blf_dimensions_doc[] =
".. function:: dimensions(text)\n"
"\n"
" Return the width and hight of the text.\n"
"\n"
" :arg text: the text to draw.\n"
" :type text: string\n"
" :return: the width and height of the text.\n"
" :rtype: tuple of 2 floats\n";
static PyObject *py_blf_dimensions(PyObject *self, PyObject *args)
{
char *text;
float r_width, r_height;
PyObject *ret;
if (!PyArg_ParseTuple(args, "s:BLF.dimensions", &text))
return NULL;
BLF_width_and_height(text, &r_width, &r_height);
ret= PyTuple_New(2);
PyTuple_SET_ITEM(ret, 0, PyFloat_FromDouble(r_width));
PyTuple_SET_ITEM(ret, 1, PyFloat_FromDouble(r_height));
return ret;
}
/*----------------------------MODULE INIT-------------------------*/
struct PyMethodDef BLF_methods[] = {
{"position", (PyCFunction)py_blf_position, METH_VARARGS, py_blf_position_doc},
{"size", (PyCFunction) py_blf_size, METH_VARARGS, py_blf_size_doc},
{"aspect", (PyCFunction) py_blf_aspect, METH_VARARGS, py_blf_aspect_doc},
{"blur", (PyCFunction) py_blf_blur, METH_VARARGS, py_blf_blur_doc},
{"draw", (PyCFunction) py_blf_draw, METH_VARARGS, py_blf_draw_doc},
{"dimensions", (PyCFunction) py_blf_dimensions, METH_VARARGS, py_blf_dimensions_doc},
{NULL, NULL, 0, NULL}
};
static char BLF_doc[] =
"This module provides access to blenders text drawing functions.\n";
static struct PyModuleDef BLF_module_def = {
PyModuleDef_HEAD_INIT,
"blf", /* m_name */
BLF_doc, /* m_doc */
0, /* m_size */
BLF_methods, /* m_methods */
0, /* m_reload */
0, /* m_traverse */
0, /* m_clear */
0, /* m_free */
};
PyObject *BLF_Init(void)
{
PyObject *submodule;
submodule = PyModule_Create(&BLF_module_def);
PyDict_SetItemString(PySys_GetObject("modules"), BLF_module_def.m_name, submodule);
return (submodule);
}

View File

@@ -0,0 +1,26 @@
/**
* $Id:
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Campbell Barton
*
* ***** END GPL LICENSE BLOCK *****
*/
PyObject *BLF_Init(void);

View File

@@ -14,7 +14,7 @@
*
* 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.
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.

View File

@@ -14,7 +14,7 @@
*
* 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.
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.

View File

@@ -15,7 +15,7 @@
*
* 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.
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
@@ -32,29 +32,7 @@
#include "BKE_utildefines.h"
#include "BLI_blenlib.h"
//-------------------------DOC STRINGS ---------------------------
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 ----------------------
static struct PyMethodDef Euler_methods[] = {
{"zero", (PyCFunction) Euler_Zero, METH_NOARGS, NULL},
{"unique", (PyCFunction) Euler_Unique, METH_NOARGS, NULL},
{"toMatrix", (PyCFunction) Euler_ToMatrix, METH_NOARGS, NULL},
{"toQuat", (PyCFunction) Euler_ToQuat, METH_NOARGS, NULL},
{"rotate", (PyCFunction) Euler_Rotate, METH_VARARGS, NULL},
{"makeCompatible", (PyCFunction) Euler_MakeCompatible, METH_O, NULL},
{"__copy__", (PyCFunction) Euler_copy, METH_VARARGS, NULL},
{"copy", (PyCFunction) Euler_copy, METH_VARARGS, NULL},
{NULL, NULL, 0, NULL}
};
#include "BLO_sys_types.h"
//----------------------------------Mathutils.Euler() -------------------
//makes a new euler for you to play with
@@ -64,6 +42,7 @@ static PyObject *Euler_new(PyTypeObject * type, PyObject * args, PyObject * kwar
int size, i;
float eul[3];
PyObject *e;
short order= 0; // TODO, add order option
size = PyTuple_GET_SIZE(args);
if (size == 1) {
@@ -76,7 +55,7 @@ static PyObject *Euler_new(PyTypeObject * type, PyObject * args, PyObject * kwar
}
} else if (size == 0) {
//returns a new empty 3d euler
return newEulerObject(NULL, Py_NEW, NULL);
return newEulerObject(NULL, order, Py_NEW, NULL);
} else {
listObject = args;
}
@@ -102,36 +81,60 @@ static PyObject *Euler_new(PyTypeObject * type, PyObject * args, PyObject * kwar
return NULL;
}
}
return newEulerObject(eul, Py_NEW, NULL);
return newEulerObject(eul, order, Py_NEW, NULL);
}
short euler_order_from_string(const char *str, const char *error_prefix)
{
if((str[0] && str[1] && str[2] && str[3]=='\0')) {
switch(*((int32_t *)str)) {
case 'X'|'Y'<<8|'Z'<<16: return 0;
case 'X'|'Z'<<8|'Y'<<16: return 1;
case 'Y'|'X'<<8|'Z'<<16: return 2;
case 'Y'|'Z'<<8|'X'<<16: return 3;
case 'Z'|'X'<<8|'Y'<<16: return 4;
case 'Z'|'Y'<<8|'X'<<16: return 5;
}
}
PyErr_Format(PyExc_TypeError, "%s: invalid euler order '%s'", error_prefix, str);
return -1;
}
//-----------------------------METHODS----------------------------
//----------------------------Euler.toQuat()----------------------
//return a quaternion representation of the euler
static char Euler_ToQuat_doc[] =
".. method:: to_quat()\n"
"\n"
" Return a quaternion representation of the euler.\n"
"\n"
" :return: Quaternion representation of the euler.\n"
" :rtype: :class:`Quaternion`\n";
static PyObject *Euler_ToQuat(EulerObject * self)
{
float quat[4];
#ifdef USE_MATHUTILS_DEG
float eul[3];
int x;
#endif
if(!BaseMath_ReadCallback(self))
return NULL;
#ifdef USE_MATHUTILS_DEG
for(x = 0; x < 3; x++) {
eul[x] = self->eul[x] * ((float)Py_PI / 180);
}
eul_to_quat( quat,eul);
#else
eul_to_quat( quat,self->eul);
#endif
if(self->order==0) eul_to_quat(quat, self->eul);
else eulO_to_quat(quat, self->eul, self->order);
return newQuaternionObject(quat, Py_NEW, NULL);
}
//----------------------------Euler.toMatrix()---------------------
//return a matrix representation of the euler
static char Euler_ToMatrix_doc[] =
".. method:: to_matrix()\n"
"\n"
" Return a matrix representation of the euler.\n"
"\n"
" :return: A 3x3 roation matrix representation of the euler.\n"
" :rtype: :class:`Matrix`\n";
static PyObject *Euler_ToMatrix(EulerObject * self)
{
float mat[9] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
@@ -139,23 +142,22 @@ static PyObject *Euler_ToMatrix(EulerObject * self)
if(!BaseMath_ReadCallback(self))
return NULL;
#ifdef USE_MATHUTILS_DEG
{
float eul[3];
int x;
for(x = 0; x < 3; x++) {
eul[x] = self->eul[x] * ((float)Py_PI / 180);
}
eul_to_mat3( (float (*)[3]) mat,eul);
}
#else
eul_to_mat3( (float (*)[3]) mat,self->eul);
#endif
if(self->order==0) eul_to_mat3((float (*)[3])mat, self->eul);
else eulO_to_mat3((float (*)[3])mat, self->eul, self->order);
return newMatrixObject(mat, 3, 3 , Py_NEW, NULL);
}
//----------------------------Euler.unique()-----------------------
//sets the x,y,z values to a unique euler rotation
// TODO, check if this works with rotation order!!!
static char Euler_Unique_doc[] =
".. method:: unique()\n"
"\n"
" Calculate a unique rotation for this euler. Avoids gimble lock.\n"
"\n"
" :return: an instance of itself\n"
" :rtype: :class:`Euler`\n";
static PyObject *Euler_Unique(EulerObject * self)
{
#define PI_2 (Py_PI * 2.0)
@@ -167,16 +169,9 @@ static PyObject *Euler_Unique(EulerObject * self)
if(!BaseMath_ReadCallback(self))
return NULL;
#ifdef USE_MATHUTILS_DEG
//radians
heading = self->eul[0] * (float)Py_PI / 180;
pitch = self->eul[1] * (float)Py_PI / 180;
bank = self->eul[2] * (float)Py_PI / 180;
#else
heading = self->eul[0];
pitch = self->eul[1];
bank = self->eul[2];
#endif
//wrap heading in +180 / -180
pitch += Py_PI;
@@ -207,19 +202,20 @@ static PyObject *Euler_Unique(EulerObject * self)
heading -= (floor(heading * PI_INV)) * PI_2;
heading -= Py_PI;
#ifdef USE_MATHUTILS_DEG
//back to degrees
self->eul[0] = (float)(heading * 180 / (float)Py_PI);
self->eul[1] = (float)(pitch * 180 / (float)Py_PI);
self->eul[2] = (float)(bank * 180 / (float)Py_PI);
#endif
BaseMath_WriteCallback(self);
Py_INCREF(self);
return (PyObject *)self;
}
//----------------------------Euler.zero()-------------------------
//sets the euler to 0,0,0
static char Euler_Zero_doc[] =
".. method:: zero()\n"
"\n"
" Set all values to zero.\n"
"\n"
" :return: an instance of itself\n"
" :rtype: :class:`Euler`\n";
static PyObject *Euler_Zero(EulerObject * self)
{
self->eul[0] = 0.0;
@@ -250,66 +246,43 @@ static PyObject *Euler_Rotate(EulerObject * self, PyObject *args)
if(!BaseMath_ReadCallback(self))
return NULL;
#ifdef USE_MATHUTILS_DEG
{
int x;
//covert to radians
angle *= ((float)Py_PI / 180);
for(x = 0; x < 3; x++) {
self->eul[x] *= ((float)Py_PI / 180);
}
}
#endif
rotate_eul(self->eul, *axis, angle);
#ifdef USE_MATHUTILS_DEG
{
int x;
//convert back from radians
for(x = 0; x < 3; x++) {
self->eul[x] *= (180 / (float)Py_PI);
}
}
#endif
if(self->order == 0) rotate_eul(self->eul, *axis, angle);
else rotate_eulO(self->eul, self->order, *axis, angle);
BaseMath_WriteCallback(self);
Py_INCREF(self);
return (PyObject *)self;
}
static char Euler_MakeCompatible_doc[] =
".. method:: make_compatible(other)\n"
"\n"
" Make this euler compatible with another, so interpolating between them works as intended.\n"
"\n"
" :arg other: make compatible with this rotation.\n"
" :type other: :class:`Euler`\n"
" :return: an instance of itself.\n"
" :rtype: :class:`Euler`\n"
"\n"
" .. note:: the order of eulers must match or an exception is raised.\n";
static PyObject *Euler_MakeCompatible(EulerObject * self, EulerObject *value)
{
#ifdef USE_MATHUTILS_DEG
float eul_from_rad[3];
int x;
#endif
if(!EulerObject_Check(value)) {
PyErr_SetString(PyExc_TypeError, "euler.makeCompatible(euler):expected a single euler argument.");
PyErr_SetString(PyExc_TypeError, "euler.make_compatible(euler): expected a single euler argument.");
return NULL;
}
if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value))
return NULL;
#ifdef USE_MATHUTILS_DEG
//covert to radians
for(x = 0; x < 3; x++) {
self->eul[x] = self->eul[x] * ((float)Py_PI / 180);
eul_from_rad[x] = value->eul[x] * ((float)Py_PI / 180);
if(self->order != value->order) {
PyErr_SetString(PyExc_ValueError, "euler.make_compatible(euler): rotation orders don't match\n");
return NULL;
}
compatible_eul(self->eul, eul_from_rad);
#else
compatible_eul(self->eul, value->eul);
#endif
#ifdef USE_MATHUTILS_DEG
//convert back from radians
for(x = 0; x < 3; x++) {
self->eul[x] *= (180 / (float)Py_PI);
}
#endif
compatible_eul(self->eul, value->eul);
BaseMath_WriteCallback(self);
Py_INCREF(self);
return (PyObject *)self;
@@ -317,12 +290,23 @@ static PyObject *Euler_MakeCompatible(EulerObject * self, EulerObject *value)
//----------------------------Euler.rotate()-----------------------
// return a copy of the euler
static char Euler_copy_doc[] =
".. function:: copy()\n"
"\n"
" Returns a copy of this euler.\n"
"\n"
" :return: A copy of the euler.\n"
" :rtype: :class:`Euler`\n"
"\n"
" .. note:: use this to get a copy of a wrapped euler with no reference to the original data.\n";
static PyObject *Euler_copy(EulerObject * self, PyObject *args)
{
if(!BaseMath_ReadCallback(self))
return NULL;
return newEulerObject(self->eul, Py_NEW, Py_TYPE(self));
return newEulerObject(self->eul, self->order, Py_NEW, Py_TYPE(self));
}
//----------------------------print object (internal)--------------
@@ -370,12 +354,7 @@ static PyObject* Euler_richcmpr(PyObject *objectA, PyObject *objectB, int compar
result = EXPP_VectorsAreEqual(eulA->eul, eulB->eul, 3, 1);
break;
case Py_NE:
result = EXPP_VectorsAreEqual(eulA->eul, eulB->eul, 3, 1);
if (result == 0){
result = 1;
}else{
result = 0;
}
result = !EXPP_VectorsAreEqual(eulA->eul, eulB->eul, 3, 1);
break;
default:
printf("The result of the comparison could not be evaluated");
@@ -521,7 +500,6 @@ static PySequenceMethods Euler_SeqMethods = {
/*
* vector axis, vector.x/y/z/w
*/
static PyObject *Euler_getAxis( EulerObject * self, void *type )
{
return Euler_item(self, GET_INT_FROM_POINTER(type));
@@ -532,20 +510,62 @@ static int Euler_setAxis( EulerObject * self, PyObject * value, void * type )
return Euler_ass_item(self, GET_INT_FROM_POINTER(type), value);
}
/* rotation order */
static PyObject *Euler_getOrder(EulerObject *self, void *type)
{
static char order[][4] = {"XYZ", "XZY", "YXZ", "YZX", "ZXY", "ZYX"};
return PyUnicode_FromString(order[self->order]);
}
static int Euler_setOrder( EulerObject * self, PyObject * value, void * type )
{
char *order_str= _PyUnicode_AsString(value);
short order= euler_order_from_string(order_str, "euler.order");
if(order < 0)
return -1;
if(self->cb_user) {
PyErr_SetString(PyExc_TypeError, "euler.order: assignment is not allowed on eulers with an owner");
return -1;
}
self->order= order;
return 0;
}
/*****************************************************************************/
/* Python attributes get/set structure: */
/*****************************************************************************/
static PyGetSetDef Euler_getseters[] = {
{"x", (getter)Euler_getAxis, (setter)Euler_setAxis, "Euler X axis", (void *)0},
{"y", (getter)Euler_getAxis, (setter)Euler_setAxis, "Euler Y axis", (void *)1},
{"z", (getter)Euler_getAxis, (setter)Euler_setAxis, "Euler Z axis", (void *)2},
{"x", (getter)Euler_getAxis, (setter)Euler_setAxis, "Euler X axis in radians. **type** float", (void *)0},
{"y", (getter)Euler_getAxis, (setter)Euler_setAxis, "Euler Y axis in radians. **type** float", (void *)1},
{"z", (getter)Euler_getAxis, (setter)Euler_setAxis, "Euler Z axis in radians. **type** float", (void *)2},
{"order", (getter)Euler_getOrder, (setter)Euler_setOrder, "Euler rotation order. **type** string in ['XYZ', 'XZY', 'YXZ', 'YZX', 'ZXY', 'ZYX']", (void *)NULL},
{"wrapped", (getter)BaseMathObject_getWrapped, (setter)NULL, "True when this wraps blenders internal data", NULL},
{"_owner", (getter)BaseMathObject_getOwner, (setter)NULL, "Read only owner for vectors that depend on another object", NULL},
{"is_wrapped", (getter)BaseMathObject_getWrapped, (setter)NULL, BaseMathObject_Wrapped_doc, NULL},
{"_owner", (getter)BaseMathObject_getOwner, (setter)NULL, BaseMathObject_Owner_doc, NULL},
{NULL,NULL,NULL,NULL,NULL} /* Sentinel */
};
//-----------------------METHOD DEFINITIONS ----------------------
static struct PyMethodDef Euler_methods[] = {
{"zero", (PyCFunction) Euler_Zero, METH_NOARGS, Euler_Zero_doc},
{"unique", (PyCFunction) Euler_Unique, METH_NOARGS, Euler_Unique_doc},
{"to_matrix", (PyCFunction) Euler_ToMatrix, METH_NOARGS, Euler_ToMatrix_doc},
{"to_quat", (PyCFunction) Euler_ToQuat, METH_NOARGS, Euler_ToQuat_doc},
{"rotate", (PyCFunction) Euler_Rotate, METH_VARARGS, NULL},
{"make_compatible", (PyCFunction) Euler_MakeCompatible, METH_O, Euler_MakeCompatible_doc},
{"__copy__", (PyCFunction) Euler_copy, METH_VARARGS, Euler_copy_doc},
{"copy", (PyCFunction) Euler_copy, METH_VARARGS, Euler_copy_doc},
{NULL, NULL, 0, NULL}
};
//------------------PY_OBECT DEFINITION--------------------------
static char euler_doc[] =
"This object gives access to Eulers in Blender.";
PyTypeObject euler_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"euler", //tp_name
@@ -567,7 +587,7 @@ PyTypeObject euler_Type = {
0, //tp_setattro
0, //tp_as_buffer
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, //tp_flags
0, //tp_doc
euler_doc, //tp_doc
0, //tp_traverse
0, //tp_clear
(richcmpfunc)Euler_richcmpr, //tp_richcompare
@@ -600,7 +620,7 @@ PyTypeObject euler_Type = {
(i.e. it was allocated elsewhere by MEM_mallocN())
pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON
(i.e. it must be created here with PyMEM_malloc())*/
PyObject *newEulerObject(float *eul, int type, PyTypeObject *base_type)
PyObject *newEulerObject(float *eul, short order, int type, PyTypeObject *base_type)
{
EulerObject *self;
int x;
@@ -628,12 +648,14 @@ PyObject *newEulerObject(float *eul, int type, PyTypeObject *base_type)
}else{ //bad type
return NULL;
}
self->order= order;
return (PyObject *)self;
}
PyObject *newEulerObject_cb(PyObject *cb_user, int cb_type, int cb_subtype)
PyObject *newEulerObject_cb(PyObject *cb_user, short order, int cb_type, int cb_subtype)
{
EulerObject *self= (EulerObject *)newEulerObject(NULL, Py_NEW, NULL);
EulerObject *self= (EulerObject *)newEulerObject(NULL, order, Py_NEW, NULL);
if(self) {
Py_INCREF(cb_user);
self->cb_user= cb_user;

View File

@@ -15,7 +15,7 @@
*
* 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.
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
@@ -45,6 +45,8 @@ typedef struct {
unsigned char wrapped; /* wrapped data type? */
/* end BaseMathObject */
unsigned char order; /* rotation order */
} EulerObject;
/*struct data contains a pointer to the actual data that the
@@ -53,7 +55,10 @@ 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 *newEulerObject( float *eul, int type, PyTypeObject *base_type);
PyObject *newEulerObject_cb(PyObject *cb_user, int cb_type, int cb_subtype);
PyObject *newEulerObject( float *eul, short order, int type, PyTypeObject *base_type);
PyObject *newEulerObject_cb(PyObject *cb_user, short order, int cb_type, int cb_subtype);
short euler_order_from_string(const char *str, const char *error_prefix);
#endif /* EXPP_euler_h */

View File

@@ -15,7 +15,7 @@
*
* 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.
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
@@ -105,39 +105,6 @@ Mathutils_Callback mathutils_matrix_vector_cb = {
};
/* matrix vector callbacks, this is so you can do matrix[i][j] = val */
/*-------------------------DOC STRINGS ---------------------------*/
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 ----------------------*/
static struct PyMethodDef Matrix_methods[] = {
{"zero", (PyCFunction) Matrix_Zero, METH_NOARGS, NULL},
{"identity", (PyCFunction) Matrix_Identity, METH_NOARGS, NULL},
{"transpose", (PyCFunction) Matrix_Transpose, METH_NOARGS, NULL},
{"determinant", (PyCFunction) Matrix_Determinant, METH_NOARGS, NULL},
{"invert", (PyCFunction) Matrix_Invert, METH_NOARGS, NULL},
{"translationPart", (PyCFunction) Matrix_TranslationPart, METH_NOARGS, NULL},
{"rotationPart", (PyCFunction) Matrix_RotationPart, METH_NOARGS, NULL},
{"scalePart", (PyCFunction) Matrix_scalePart, METH_NOARGS, NULL},
{"resize4x4", (PyCFunction) Matrix_Resize4x4, METH_NOARGS, NULL},
{"toEuler", (PyCFunction) Matrix_toEuler, METH_VARARGS, NULL},
{"toQuat", (PyCFunction) Matrix_toQuat, METH_NOARGS, NULL},
{"copy", (PyCFunction) Matrix_copy, METH_NOARGS, NULL},
{"__copy__", (PyCFunction) Matrix_copy, METH_NOARGS, NULL},
{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
@@ -214,8 +181,33 @@ static PyObject *Matrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
return newMatrixObject(matrix, argSize, seqSize, Py_NEW, NULL);
}
/* assumes rowsize == colsize is checked and the read callback has run */
static float matrix_determinant(MatrixObject * self)
{
if(self->rowSize == 2) {
return determinant_m2(self->matrix[0][0], self->matrix[0][1],
self->matrix[1][0], self->matrix[1][1]);
} else if(self->rowSize == 3) {
return determinant_m3(self->matrix[0][0], self->matrix[0][1],
self->matrix[0][2], self->matrix[1][0],
self->matrix[1][1], self->matrix[1][2],
self->matrix[2][0], self->matrix[2][1],
self->matrix[2][2]);
} else {
return determinant_m4((float (*)[4])self->contigPtr);
}
}
/*-----------------------------METHODS----------------------------*/
/*---------------------------Matrix.toQuat() ---------------------*/
static char Matrix_toQuat_doc[] =
".. method:: to_quat()\n"
"\n"
" Return a quaternion representation of the rotation matrix.\n"
"\n"
" :return: Quaternion representation of the rotation matrix.\n"
" :rtype: :class:`Quaternion`\n";
static PyObject *Matrix_toQuat(MatrixObject * self)
{
float quat[4];
@@ -225,69 +217,92 @@ static PyObject *Matrix_toQuat(MatrixObject * self)
/*must be 3-4 cols, 3-4 rows, square matrix*/
if(self->colSize < 3 || self->rowSize < 3 || (self->colSize != self->rowSize)) {
PyErr_SetString(PyExc_AttributeError, "Matrix.toQuat(): inappropriate matrix size - expects 3x3 or 4x4 matrix");
PyErr_SetString(PyExc_AttributeError, "Matrix.to_quat(): inappropriate matrix size - expects 3x3 or 4x4 matrix");
return NULL;
}
if(self->colSize == 3){
mat3_to_quat( quat,(float (*)[3])*self->matrix);
mat3_to_quat( quat,(float (*)[3])self->contigPtr);
}else{
mat4_to_quat( quat,(float (*)[4])*self->matrix);
mat4_to_quat( quat,(float (*)[4])self->contigPtr);
}
return newQuaternionObject(quat, Py_NEW, NULL);
}
/*---------------------------Matrix.toEuler() --------------------*/
static char Matrix_toEuler_doc[] =
".. method:: to_euler(order, euler_compat)\n"
"\n"
" Return an Euler representation of the rotation matrix (3x3 or 4x4 matrix only).\n"
"\n"
" :arg order: Optional rotation order argument in ['XYZ', 'XZY', 'YXZ', 'YZX', 'ZXY', 'ZYX'].\n"
" :type order: string\n"
" :arg euler_compat: Optional euler argument the new euler will be made compatible with (no axis flipping between them). Useful for converting a series of matrices to animation curves.\n"
" :type euler_compat: :class:`Euler`\n"
" :return: Euler representation of the matrix.\n"
" :rtype: :class:`Euler`\n";
PyObject *Matrix_toEuler(MatrixObject * self, PyObject *args)
{
char *order_str= NULL;
short order= 0;
float eul[3], eul_compatf[3];
EulerObject *eul_compat = NULL;
#ifdef USE_MATHUTILS_DEG
int x;
#endif
float tmat[3][3];
float (*mat)[3];
if(!BaseMath_ReadCallback(self))
return NULL;
if(!PyArg_ParseTuple(args, "|O!:toEuler", &euler_Type, &eul_compat))
if(!PyArg_ParseTuple(args, "|sO!:to_euler", &order_str, &euler_Type, &eul_compat))
return NULL;
if(eul_compat) {
if(!BaseMath_ReadCallback(eul_compat))
return NULL;
#ifdef USE_MATHUTILS_DEG
for(x = 0; x < 3; x++) {
eul_compatf[x] = eul_compat->eul[x] * ((float)Py_PI / 180);
}
#else
VECCOPY(eul_compatf, eul_compat->eul);
#endif
}
/*must be 3-4 cols, 3-4 rows, square matrix*/
if(self->colSize ==3 && self->rowSize ==3) {
if(eul_compat) mat3_to_compatible_eul( eul, eul_compatf,(float (*)[3])*self->matrix);
else mat3_to_eul( eul,(float (*)[3])*self->matrix);
mat= (float (*)[3])self->contigPtr;
}else if (self->colSize ==4 && self->rowSize ==4) {
float tempmat3[3][3];
copy_m3_m4(tempmat3, (float (*)[4])*self->matrix);
mat3_to_eul( eul,tempmat3);
if(eul_compat) mat3_to_compatible_eul( eul, eul_compatf,tempmat3);
else mat3_to_eul( eul,tempmat3);
copy_m3_m4(tmat, (float (*)[4])self->contigPtr);
mat= tmat;
}else {
PyErr_SetString(PyExc_AttributeError, "Matrix.toEuler(): inappropriate matrix size - expects 3x3 or 4x4 matrix\n");
PyErr_SetString(PyExc_AttributeError, "Matrix.to_euler(): inappropriate matrix size - expects 3x3 or 4x4 matrix\n");
return NULL;
}
#ifdef USE_MATHUTILS_DEG
/*have to convert to degrees*/
for(x = 0; x < 3; x++) {
eul[x] *= (float) (180 / Py_PI);
if(order_str) {
order= euler_order_from_string(order_str, "Matrix.to_euler()");
if(order < 0)
return NULL;
}
#endif
return newEulerObject(eul, Py_NEW, NULL);
if(eul_compat) {
if(order == 0) mat3_to_compatible_eul( eul, eul_compatf, mat);
else mat3_to_compatible_eulO(eul, eul_compatf, order, mat);
}
else {
if(order == 0) mat3_to_eul(eul, mat);
else mat3_to_eulO(eul, order, mat);
}
return newEulerObject(eul, order, Py_NEW, NULL);
}
/*---------------------------Matrix.resize4x4() ------------------*/
static char Matrix_Resize4x4_doc[] =
".. method:: resize4x4()\n"
"\n"
" Resize the matrix to 4x4.\n"
"\n"
" :return: an instance of itself.\n"
" :rtype: :class:`Matrix`\n";
PyObject *Matrix_Resize4x4(MatrixObject * self)
{
int x, first_row_elem, curr_pos, new_pos, blank_columns, blank_rows, index;
@@ -344,26 +359,93 @@ PyObject *Matrix_Resize4x4(MatrixObject * self)
Py_INCREF(self);
return (PyObject *)self;
}
static char Matrix_to_4x4_doc[] =
".. method:: to_4x4()\n"
"\n"
" Return a 4x4 copy of this matrix.\n"
"\n"
" :return: a new matrix.\n"
" :rtype: :class:`Matrix`\n";
PyObject *Matrix_to_4x4(MatrixObject * self)
{
if(!BaseMath_ReadCallback(self))
return NULL;
if(self->colSize==4 && self->rowSize==4) {
return (PyObject *)newMatrixObject(self->contigPtr, 4, 4, Py_NEW, Py_TYPE(self));
}
else if(self->colSize==3 && self->rowSize==3) {
float mat[4][4];
copy_m4_m3(mat, (float (*)[3])self->contigPtr);
return (PyObject *)newMatrixObject((float *)mat, 4, 4, Py_NEW, Py_TYPE(self));
}
/* TODO, 2x2 matrix */
PyErr_SetString(PyExc_TypeError, "Matrix.to_4x4(): inappropriate matrix size");
return NULL;
}
static char Matrix_to_3x3_doc[] =
".. method:: to_3x3()\n"
"\n"
" Return a 3x3 copy of this matrix.\n"
"\n"
" :return: a new matrix.\n"
" :rtype: :class:`Matrix`\n";
PyObject *Matrix_to_3x3(MatrixObject * self)
{
if(!BaseMath_ReadCallback(self))
return NULL;
if(self->colSize==3 && self->rowSize==3) {
return (PyObject *)newMatrixObject(self->contigPtr, 3, 3, Py_NEW, Py_TYPE(self));
}
else if(self->colSize==4 && self->rowSize==4) {
float mat[3][3];
copy_m3_m4(mat, (float (*)[4])self->contigPtr);
return (PyObject *)newMatrixObject((float *)mat, 3, 3, Py_NEW, Py_TYPE(self));
}
/* TODO, 2x2 matrix */
PyErr_SetString(PyExc_TypeError, "Matrix.to_3x3(): inappropriate matrix size");
return NULL;
}
/*---------------------------Matrix.translationPart() ------------*/
static char Matrix_TranslationPart_doc[] =
".. method:: translation_part()\n"
"\n"
" Return a the translation part of a 4 row matrix.\n"
"\n"
" :return: Return a the translation of a matrix.\n"
" :rtype: :class:`Matrix`\n"
"\n"
" .. note:: Note that the (4,4) element of a matrix can be used for uniform scaling too.\n";
PyObject *Matrix_TranslationPart(MatrixObject * self)
{
float vec[4];
if(!BaseMath_ReadCallback(self))
return NULL;
if(self->colSize < 3 || self->rowSize < 4){
PyErr_SetString(PyExc_AttributeError, "Matrix.translationPart: inappropriate matrix size");
PyErr_SetString(PyExc_AttributeError, "Matrix.translation_part(): inappropriate matrix size");
return NULL;
}
vec[0] = self->matrix[3][0];
vec[1] = self->matrix[3][1];
vec[2] = self->matrix[3][2];
return newVectorObject(vec, 3, Py_NEW, NULL);
return newVectorObject(self->matrix[3], 3, Py_NEW, NULL);
}
/*---------------------------Matrix.rotationPart() ---------------*/
static char Matrix_RotationPart_doc[] =
".. method:: rotation_part()\n"
"\n"
" Return the 3d submatrix corresponding to the linear term of the embedded affine transformation in 3d. This matrix represents rotation and scale.\n"
"\n"
" :return: Return the 3d matrix for rotation and scale.\n"
" :rtype: :class:`Matrix`\n"
"\n"
" .. note:: Note that the (4,4) element of a matrix can be used for uniform scaling too.\n";
PyObject *Matrix_RotationPart(MatrixObject * self)
{
float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
@@ -373,7 +455,7 @@ PyObject *Matrix_RotationPart(MatrixObject * self)
return NULL;
if(self->colSize < 3 || self->rowSize < 3){
PyErr_SetString(PyExc_AttributeError, "Matrix.rotationPart: inappropriate matrix size\n");
PyErr_SetString(PyExc_AttributeError, "Matrix.rotation_part(): inappropriate matrix size\n");
return NULL;
}
@@ -390,6 +472,16 @@ PyObject *Matrix_RotationPart(MatrixObject * self)
return newMatrixObject(mat, 3, 3, Py_NEW, Py_TYPE(self));
}
/*---------------------------Matrix.scalePart() --------------------*/
static char Matrix_scalePart_doc[] =
".. method:: scale_part()\n"
"\n"
" Return a the scale part of a 3x3 or 4x4 matrix.\n"
"\n"
" :return: Return a the scale of a matrix.\n"
" :rtype: :class:`Vector`\n"
"\n"
" .. note:: This method does not return negative a scale on any axis because it is not possible to obtain this data from the matrix alone.\n";
PyObject *Matrix_scalePart(MatrixObject * self)
{
float scale[3], rot[3];
@@ -400,11 +492,11 @@ PyObject *Matrix_scalePart(MatrixObject * self)
/*must be 3-4 cols, 3-4 rows, square matrix*/
if(self->colSize == 4 && self->rowSize == 4)
copy_m3_m4(mat, (float (*)[4])*self->matrix);
copy_m3_m4(mat, (float (*)[4])self->contigPtr);
else if(self->colSize == 3 && self->rowSize == 3)
copy_m3_m3(mat, (float (*)[3])*self->matrix);
copy_m3_m3(mat, (float (*)[3])self->contigPtr);
else {
PyErr_SetString(PyExc_AttributeError, "Matrix.scalePart(): inappropriate matrix size - expects 3x3 or 4x4 matrix\n");
PyErr_SetString(PyExc_AttributeError, "Matrix.scale_part(): inappropriate matrix size - expects 3x3 or 4x4 matrix\n");
return NULL;
}
/* functionality copied from editobject.c apply_obmat */
@@ -419,12 +511,23 @@ PyObject *Matrix_scalePart(MatrixObject * self)
return newVectorObject(scale, 3, Py_NEW, NULL);
}
/*---------------------------Matrix.invert() ---------------------*/
static char Matrix_Invert_doc[] =
".. method:: invert()\n"
"\n"
" Set the matrix to its inverse.\n"
"\n"
" :return: an instance of itself.\n"
" :rtype: :class:`Matrix`\n"
"\n"
" .. note:: :exc:`ValueError` exception is raised.\n"
"\n"
" .. seealso:: <http://en.wikipedia.org/wiki/Inverse_matrix>\n";
PyObject *Matrix_Invert(MatrixObject * self)
{
int x, y, z = 0;
float det = 0.0f;
PyObject *f = NULL;
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};
@@ -437,9 +540,7 @@ PyObject *Matrix_Invert(MatrixObject * self)
}
/*calculate the determinant*/
f = Matrix_Determinant(self);
det = (float)PyFloat_AS_DOUBLE(f); /*Increfs, so we need to decref*/
Py_DECREF(f);
det = matrix_determinant(self);
if(det != 0) {
/*calculate the classical adjoint*/
@@ -449,9 +550,9 @@ PyObject *Matrix_Invert(MatrixObject * self)
mat[2] = -self->matrix[1][0];
mat[3] = self->matrix[0][0];
} else if(self->rowSize == 3) {
adjoint_m3_m3((float (*)[3]) mat,(float (*)[3]) *self->matrix);
adjoint_m3_m3((float (*)[3]) mat,(float (*)[3])self->contigPtr);
} else if(self->rowSize == 4) {
adjoint_m4_m4((float (*)[4]) mat, (float (*)[4]) *self->matrix);
adjoint_m4_m4((float (*)[4]) mat, (float (*)[4])self->contigPtr);
}
/*divide by determinate*/
for(x = 0; x < (self->rowSize * self->colSize); x++) {
@@ -478,10 +579,18 @@ PyObject *Matrix_Invert(MatrixObject * self)
/*---------------------------Matrix.determinant() ----------------*/
static char Matrix_Determinant_doc[] =
".. method:: determinant()\n"
"\n"
" Return the determinant of a matrix.\n"
"\n"
" :return: Return a the determinant of a matrix.\n"
" :rtype: float\n"
"\n"
" .. seealso:: <http://en.wikipedia.org/wiki/Determinant>\n";
PyObject *Matrix_Determinant(MatrixObject * self)
{
float det = 0.0f;
if(!BaseMath_ReadCallback(self))
return NULL;
@@ -490,22 +599,19 @@ PyObject *Matrix_Determinant(MatrixObject * self)
return NULL;
}
if(self->rowSize == 2) {
det = determinant_m2(self->matrix[0][0], self->matrix[0][1],
self->matrix[1][0], self->matrix[1][1]);
} else if(self->rowSize == 3) {
det = determinant_m3(self->matrix[0][0], self->matrix[0][1],
self->matrix[0][2], self->matrix[1][0],
self->matrix[1][1], self->matrix[1][2],
self->matrix[2][0], self->matrix[2][1],
self->matrix[2][2]);
} else {
det = determinant_m4((float (*)[4]) *self->matrix);
}
return PyFloat_FromDouble( (double) det );
return PyFloat_FromDouble((double)matrix_determinant(self));
}
/*---------------------------Matrix.transpose() ------------------*/
static char Matrix_Transpose_doc[] =
".. method:: transpose()\n"
"\n"
" Set the matrix to its transpose.\n"
"\n"
" :return: an instance of itself\n"
" :rtype: :class:`Matrix`\n"
"\n"
" .. seealso:: <http://en.wikipedia.org/wiki/Transpose>\n";
PyObject *Matrix_Transpose(MatrixObject * self)
{
float t = 0.0f;
@@ -523,9 +629,9 @@ PyObject *Matrix_Transpose(MatrixObject * self)
self->matrix[1][0] = self->matrix[0][1];
self->matrix[0][1] = t;
} else if(self->rowSize == 3) {
transpose_m3((float (*)[3])*self->matrix);
transpose_m3((float (*)[3])self->contigPtr);
} else {
transpose_m4((float (*)[4])*self->matrix);
transpose_m4((float (*)[4])self->contigPtr);
}
BaseMath_WriteCallback(self);
@@ -535,6 +641,14 @@ PyObject *Matrix_Transpose(MatrixObject * self)
/*---------------------------Matrix.zero() -----------------------*/
static char Matrix_Zero_doc[] =
".. method:: zero()\n"
"\n"
" Set all the matrix values to zero.\n"
"\n"
" :return: an instance of itself\n"
" :rtype: :class:`Matrix`\n";
PyObject *Matrix_Zero(MatrixObject * self)
{
int row, col;
@@ -552,6 +666,18 @@ PyObject *Matrix_Zero(MatrixObject * self)
return (PyObject *)self;
}
/*---------------------------Matrix.identity(() ------------------*/
static char Matrix_Identity_doc[] =
".. method:: identity()\n"
"\n"
" Set the matrix to the identity matrix.\n"
"\n"
" :return: an instance of itself\n"
" :rtype: :class:`Matrix`\n"
"\n"
" .. note:: An object with zero location and rotation, a scale of one, will have an identity matrix.\n"
"\n"
" .. seealso:: <http://en.wikipedia.org/wiki/Identity_matrix>\n";
PyObject *Matrix_Identity(MatrixObject * self)
{
if(!BaseMath_ReadCallback(self))
@@ -568,9 +694,9 @@ PyObject *Matrix_Identity(MatrixObject * self)
self->matrix[1][0] = 0.0f;
self->matrix[1][1] = 1.0f;
} else if(self->rowSize == 3) {
unit_m3((float (*)[3]) *self->matrix);
unit_m3((float (*)[3])self->contigPtr);
} else {
unit_m4((float (*)[4]) *self->matrix);
unit_m4((float (*)[4])self->contigPtr);
}
if(!BaseMath_WriteCallback(self))
@@ -580,13 +706,21 @@ PyObject *Matrix_Identity(MatrixObject * self)
return (PyObject *)self;
}
/*---------------------------Matrix.inverted() ------------------*/
/*---------------------------Matrix.copy() ------------------*/
static char Matrix_copy_doc[] =
".. method:: copy()\n"
"\n"
" Returns a copy of this matrix.\n"
"\n"
" :return: an instance of itself\n"
" :rtype: :class:`Matrix`\n";
PyObject *Matrix_copy(MatrixObject * self)
{
if(!BaseMath_ReadCallback(self))
return NULL;
return (PyObject*)newMatrixObject((float (*))*self->matrix, self->rowSize, self->colSize, Py_NEW, Py_TYPE(self));
return (PyObject*)newMatrixObject((float (*))self->contigPtr, self->rowSize, self->colSize, Py_NEW, Py_TYPE(self));
}
/*----------------------------print object (internal)-------------*/
@@ -1138,9 +1272,9 @@ static PyObject *Matrix_getMedianScale( MatrixObject * self, void *type )
/*must be 3-4 cols, 3-4 rows, square matrix*/
if(self->colSize == 4 && self->rowSize == 4)
copy_m3_m4(mat, (float (*)[4])*self->matrix);
copy_m3_m4(mat, (float (*)[4])self->contigPtr);
else if(self->colSize == 3 && self->rowSize == 3)
copy_m3_m3(mat, (float (*)[3])*self->matrix);
copy_m3_m3(mat, (float (*)[3])self->contigPtr);
else {
PyErr_SetString(PyExc_AttributeError, "Matrix.median_scale: inappropriate matrix size - expects 3x3 or 4x4 matrix\n");
return NULL;
@@ -1149,20 +1283,60 @@ static PyObject *Matrix_getMedianScale( MatrixObject * self, void *type )
return PyFloat_FromDouble(mat3_to_scale(mat));
}
static PyObject *Matrix_getIsNegative( MatrixObject * self, void *type )
{
if(!BaseMath_ReadCallback(self))
return NULL;
/*must be 3-4 cols, 3-4 rows, square matrix*/
if(self->colSize == 4 && self->rowSize == 4)
return PyBool_FromLong(is_negative_m4((float (*)[4])self->contigPtr));
else if(self->colSize == 3 && self->rowSize == 3)
return PyBool_FromLong(is_negative_m3((float (*)[3])self->contigPtr));
else {
PyErr_SetString(PyExc_AttributeError, "Matrix.is_negative: inappropriate matrix size - expects 3x3 or 4x4 matrix\n");
return NULL;
}
}
/*****************************************************************************/
/* Python attributes get/set structure: */
/*****************************************************************************/
static PyGetSetDef Matrix_getseters[] = {
{"row_size", (getter)Matrix_getRowSize, (setter)NULL, "", NULL},
{"col_size", (getter)Matrix_getColSize, (setter)NULL, "", NULL},
{"median_scale", (getter)Matrix_getMedianScale, (setter)NULL, "", NULL},
{"wrapped", (getter)BaseMathObject_getWrapped, (setter)NULL, "", NULL},
{"_owner",(getter)BaseMathObject_getOwner, (setter)NULL, "",
NULL},
{"row_size", (getter)Matrix_getRowSize, (setter)NULL, "The row size of the matrix (readonly). **type** int", NULL},
{"col_size", (getter)Matrix_getColSize, (setter)NULL, "The column size of the matrix (readonly). **type** int", NULL},
{"median_scale", (getter)Matrix_getMedianScale, (setter)NULL, "The average scale applied to each axis (readonly). **type** float", NULL},
{"is_negative", (getter)Matrix_getIsNegative, (setter)NULL, "True if this matrix results in a negative scale, 3x3 and 4x4 only, (readonly). **type** bool", NULL},
{"is_wrapped", (getter)BaseMathObject_getWrapped, (setter)NULL, BaseMathObject_Wrapped_doc, NULL},
{"_owner",(getter)BaseMathObject_getOwner, (setter)NULL, BaseMathObject_Owner_doc, NULL},
{NULL,NULL,NULL,NULL,NULL} /* Sentinel */
};
/*-----------------------METHOD DEFINITIONS ----------------------*/
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},
{"determinant", (PyCFunction) Matrix_Determinant, METH_NOARGS, Matrix_Determinant_doc},
{"invert", (PyCFunction) Matrix_Invert, METH_NOARGS, Matrix_Invert_doc},
{"translation_part", (PyCFunction) Matrix_TranslationPart, METH_NOARGS, Matrix_TranslationPart_doc},
{"rotation_part", (PyCFunction) Matrix_RotationPart, METH_NOARGS, Matrix_RotationPart_doc},
{"scale_part", (PyCFunction) Matrix_scalePart, METH_NOARGS, Matrix_scalePart_doc},
{"resize4x4", (PyCFunction) Matrix_Resize4x4, METH_NOARGS, Matrix_Resize4x4_doc},
{"to_4x4", (PyCFunction) Matrix_to_4x4, METH_NOARGS, Matrix_to_4x4_doc},
{"to_3x3", (PyCFunction) Matrix_to_3x3, METH_NOARGS, Matrix_to_3x3_doc},
{"to_euler", (PyCFunction) Matrix_toEuler, METH_VARARGS, Matrix_toEuler_doc},
{"to_quat", (PyCFunction) Matrix_toQuat, METH_NOARGS, Matrix_toQuat_doc},
{"copy", (PyCFunction) Matrix_copy, METH_NOARGS, Matrix_copy_doc},
{"__copy__", (PyCFunction) Matrix_copy, METH_NOARGS, Matrix_copy_doc},
{NULL, NULL, 0, NULL}
};
/*------------------PY_OBECT DEFINITION--------------------------*/
static char matrix_doc[] =
"This object gives access to Matrices in Blender.";
PyTypeObject matrix_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"matrix", /*tp_name*/
@@ -1184,7 +1358,7 @@ PyTypeObject matrix_Type = {
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
0, /*tp_doc*/
matrix_doc, /*tp_doc*/
0, /*tp_traverse*/
0, /*tp_clear*/
(richcmpfunc)Matrix_richcmpr, /*tp_richcompare*/

View File

@@ -14,7 +14,7 @@
*
* 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.
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.

View File

@@ -15,7 +15,7 @@
*
* 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.
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
@@ -32,187 +32,66 @@
#include "BKE_utildefines.h"
#include "BLI_blenlib.h"
//-------------------------DOC STRINGS ---------------------------
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 ----------------------
static struct PyMethodDef Quaternion_methods[] = {
{"identity", (PyCFunction) Quaternion_Identity, METH_NOARGS, NULL},
{"negate", (PyCFunction) Quaternion_Negate, METH_NOARGS, NULL},
{"conjugate", (PyCFunction) Quaternion_Conjugate, METH_NOARGS, NULL},
{"inverse", (PyCFunction) Quaternion_Inverse, METH_NOARGS, NULL},
{"normalize", (PyCFunction) Quaternion_Normalize, METH_NOARGS, NULL},
{"toEuler", (PyCFunction) Quaternion_ToEuler, METH_VARARGS, NULL},
{"toMatrix", (PyCFunction) Quaternion_ToMatrix, METH_NOARGS, NULL},
{"cross", (PyCFunction) Quaternion_Cross, METH_O, NULL},
{"dot", (PyCFunction) Quaternion_Dot, METH_O, NULL},
{"__copy__", (PyCFunction) Quaternion_copy, METH_NOARGS, NULL},
{"copy", (PyCFunction) Quaternion_copy, METH_NOARGS, NULL},
{NULL, NULL, 0, NULL}
};
//----------------------------------Mathutils.Quaternion() --------------
static PyObject *Quaternion_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyObject *listObject = NULL, *n, *q;
int size, i;
float quat[4];
double 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, NULL);
} 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;
}
quat[i] = PyFloat_AsDouble(q);
Py_DECREF(q);
if (quat[i]==-1 && PyErr_Occurred()) {
PyErr_SetString(PyExc_TypeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
return NULL;
}
}
if(size == 3) //calculate the quat based on axis/angle
#ifdef USE_MATHUTILS_DEG
axis_angle_to_quat(quat, quat, angle * (Py_PI / 180));
#else
axis_angle_to_quat(quat, quat, angle);
#endif
return newQuaternionObject(quat, Py_NEW, NULL);
}
//-----------------------------METHODS------------------------------
//----------------------------Quaternion.toEuler()------------------
//return the quat as a euler
static char Quaternion_ToEuler_doc[] =
".. method:: to_euler(order, euler_compat)\n"
"\n"
" Return Euler representation of the quaternion.\n"
"\n"
" :arg order: Optional rotation order argument in ['XYZ', 'XZY', 'YXZ', 'YZX', 'ZXY', 'ZYX'].\n"
" :type order: string\n"
" :arg euler_compat: Optional euler argument the new euler will be made compatible with (no axis flipping between them). Useful for converting a series of matrices to animation curves.\n"
" :type euler_compat: :class:`Euler`\n"
" :return: Euler representation of the quaternion.\n"
" :rtype: :class:`Euler`\n";
static PyObject *Quaternion_ToEuler(QuaternionObject * self, PyObject *args)
{
float eul[3];
char *order_str= NULL;
short order= 0;
EulerObject *eul_compat = NULL;
if(!PyArg_ParseTuple(args, "|O!:toEuler", &euler_Type, &eul_compat))
if(!PyArg_ParseTuple(args, "|sO!:to_euler", &order_str, &euler_Type, &eul_compat))
return NULL;
if(!BaseMath_ReadCallback(self))
return NULL;
if(order_str) {
order= euler_order_from_string(order_str, "Matrix.to_euler()");
if(order < 0)
return NULL;
}
if(eul_compat) {
float mat[3][3];
if(!BaseMath_ReadCallback(eul_compat))
return NULL;
quat_to_mat3( mat,self->quat);
quat_to_mat3(mat, self->quat);
#ifdef USE_MATHUTILS_DEG
{
float eul_compatf[3];
int x;
for(x = 0; x < 3; x++) {
eul_compatf[x] = eul_compat->eul[x] * ((float)Py_PI / 180);
}
mat3_to_compatible_eul( eul, eul_compatf,mat);
}
#else
mat3_to_compatible_eul( eul, eul_compat->eul,mat);
#endif
if(order == 0) mat3_to_compatible_eul(eul, eul_compat->eul, mat);
else mat3_to_compatible_eulO(eul, eul_compat->eul, order, mat);
}
else {
quat_to_eul( eul,self->quat);
if(order == 0) quat_to_eul(eul, self->quat);
else quat_to_eulO(eul, order, self->quat);
}
#ifdef USE_MATHUTILS_DEG
{
int x;
for(x = 0; x < 3; x++) {
eul[x] *= (180 / (float)Py_PI);
}
}
#endif
return newEulerObject(eul, Py_NEW, NULL);
return newEulerObject(eul, order, Py_NEW, NULL);
}
//----------------------------Quaternion.toMatrix()------------------
//return the quat as a matrix
static char Quaternion_ToMatrix_doc[] =
".. method:: to_matrix(other)\n"
"\n"
" Return a matrix representation of the quaternion.\n"
"\n"
" :return: A 3x3 rotation matrix representation of the quaternion.\n"
" :rtype: :class:`Matrix`\n";
static PyObject *Quaternion_ToMatrix(QuaternionObject * self)
{
float mat[9]; /* all values are set */
@@ -225,7 +104,16 @@ static PyObject *Quaternion_ToMatrix(QuaternionObject * self)
}
//----------------------------Quaternion.cross(other)------------------
//return the cross quat
static char Quaternion_Cross_doc[] =
".. method:: cross(other)\n"
"\n"
" Return the cross product of this quaternion and another.\n"
"\n"
" :arg other: The other quaternion to perform the cross product with.\n"
" :type other: :class:`Quaternion`\n"
" :return: The cross product.\n"
" :rtype: :class:`Quaternion`\n";
static PyObject *Quaternion_Cross(QuaternionObject * self, QuaternionObject * value)
{
float quat[4];
@@ -243,7 +131,16 @@ static PyObject *Quaternion_Cross(QuaternionObject * self, QuaternionObject * va
}
//----------------------------Quaternion.dot(other)------------------
//return the dot quat
static char Quaternion_Dot_doc[] =
".. method:: dot(other)\n"
"\n"
" Return the dot product of this quaternion and another.\n"
"\n"
" :arg other: The other quaternion to perform the dot product with.\n"
" :type other: :class:`Quaternion`\n"
" :return: The dot product.\n"
" :rtype: :class:`Quaternion`\n";
static PyObject *Quaternion_Dot(QuaternionObject * self, QuaternionObject * value)
{
if (!QuaternionObject_Check(value)) {
@@ -257,8 +154,90 @@ static PyObject *Quaternion_Dot(QuaternionObject * self, QuaternionObject * valu
return PyFloat_FromDouble(dot_qtqt(self->quat, value->quat));
}
static char Quaternion_Difference_doc[] =
".. function:: difference(other)\n"
"\n"
" Returns a quaternion representing the rotational difference.\n"
"\n"
" :arg other: second quaternion.\n"
" :type other: :class:`Quaternion`\n"
" :return: the rotational difference between the two quat rotations.\n"
" :rtype: :class:`Quaternion`\n";
static PyObject *Quaternion_Difference(QuaternionObject * self, QuaternionObject * value)
{
float quat[4], tempQuat[4];
double dot = 0.0f;
int x;
if (!QuaternionObject_Check(value)) {
PyErr_SetString( PyExc_TypeError, "quat.difference(value): expected a quaternion argument" );
return NULL;
}
if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value))
return NULL;
tempQuat[0] = self->quat[0];
tempQuat[1] = - self->quat[1];
tempQuat[2] = - self->quat[2];
tempQuat[3] = - self->quat[3];
dot = sqrt(tempQuat[0] * tempQuat[0] + tempQuat[1] * tempQuat[1] +
tempQuat[2] * tempQuat[2] + tempQuat[3] * tempQuat[3]);
for(x = 0; x < 4; x++) {
tempQuat[x] /= (float)(dot * dot);
}
mul_qt_qtqt(quat, tempQuat, value->quat);
return newQuaternionObject(quat, Py_NEW, NULL);
}
static char Quaternion_Slerp_doc[] =
".. function:: slerp(other, factor)\n"
"\n"
" Returns the interpolation of two quaternions.\n"
"\n"
" :arg other: value to interpolate with.\n"
" :type other: :class:`Quaternion`\n"
" :arg factor: The interpolation value in [0.0, 1.0].\n"
" :type factor: float\n"
" :return: The interpolated rotation.\n"
" :rtype: :class:`Quaternion`\n";
static PyObject *Quaternion_Slerp(QuaternionObject *self, PyObject *args)
{
QuaternionObject *value;
float quat[4], fac;
if(!PyArg_ParseTuple(args, "O!f:slerp", &quaternion_Type, &value, &fac)) {
PyErr_SetString(PyExc_TypeError, "quat.slerp(): expected Quaternion types and float");
return NULL;
}
if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value))
return NULL;
if(fac > 1.0f || fac < 0.0f) {
PyErr_SetString(PyExc_AttributeError, "quat.slerp(): interpolation factor must be between 0.0 and 1.0");
return NULL;
}
interp_qt_qtqt(quat, self->quat, value->quat, fac);
return newQuaternionObject(quat, Py_NEW, NULL);
}
//----------------------------Quaternion.normalize()----------------
//normalize the axis of rotation of [theta,vector]
static char Quaternion_Normalize_doc[] =
".. function:: normalize()\n"
"\n"
" Normalize the quaternion.\n"
"\n"
" :return: an instance of itself.\n"
" :rtype: :class:`Quaternion`\n";
static PyObject *Quaternion_Normalize(QuaternionObject * self)
{
if(!BaseMath_ReadCallback(self))
@@ -271,7 +250,14 @@ static PyObject *Quaternion_Normalize(QuaternionObject * self)
return (PyObject*)self;
}
//----------------------------Quaternion.inverse()------------------
//invert the quat
static char Quaternion_Inverse_doc[] =
".. function:: inverse()\n"
"\n"
" Set the quaternion to its inverse.\n"
"\n"
" :return: an instance of itself.\n"
" :rtype: :class:`Quaternion`\n";
static PyObject *Quaternion_Inverse(QuaternionObject * self)
{
if(!BaseMath_ReadCallback(self))
@@ -284,7 +270,14 @@ static PyObject *Quaternion_Inverse(QuaternionObject * self)
return (PyObject*)self;
}
//----------------------------Quaternion.identity()-----------------
//generate the identity quaternion
static char Quaternion_Identity_doc[] =
".. function:: identity()\n"
"\n"
" Set the quaternion to an identity quaternion.\n"
"\n"
" :return: an instance of itself.\n"
" :rtype: :class:`Quaternion`\n";
static PyObject *Quaternion_Identity(QuaternionObject * self)
{
if(!BaseMath_ReadCallback(self))
@@ -297,7 +290,14 @@ static PyObject *Quaternion_Identity(QuaternionObject * self)
return (PyObject*)self;
}
//----------------------------Quaternion.negate()-------------------
//negate the quat
static char Quaternion_Negate_doc[] =
".. function:: negate()\n"
"\n"
" Set the quaternion to its negative.\n"
"\n"
" :return: an instance of itself.\n"
" :rtype: :class:`Quaternion`\n";
static PyObject *Quaternion_Negate(QuaternionObject * self)
{
if(!BaseMath_ReadCallback(self))
@@ -310,7 +310,14 @@ static PyObject *Quaternion_Negate(QuaternionObject * self)
return (PyObject*)self;
}
//----------------------------Quaternion.conjugate()----------------
//negate the vector part
static char Quaternion_Conjugate_doc[] =
".. function:: conjugate()\n"
"\n"
" Set the quaternion to its conjugate (negate x, y, z).\n"
"\n"
" :return: an instance of itself.\n"
" :rtype: :class:`Quaternion`\n";
static PyObject *Quaternion_Conjugate(QuaternionObject * self)
{
if(!BaseMath_ReadCallback(self))
@@ -323,7 +330,16 @@ static PyObject *Quaternion_Conjugate(QuaternionObject * self)
return (PyObject*)self;
}
//----------------------------Quaternion.copy()----------------
//return a copy of the quat
static char Quaternion_copy_doc[] =
".. function:: copy()\n"
"\n"
" Returns a copy of this quaternion.\n"
"\n"
" :return: A copy of the quaternion.\n"
" :rtype: :class:`Quaternion`\n"
"\n"
" .. note:: use this to get a copy of a wrapped quaternion with no reference to the original data.\n";
static PyObject *Quaternion_copy(QuaternionObject * self)
{
if(!BaseMath_ReadCallback(self))
@@ -674,12 +690,7 @@ static PyObject *Quaternion_getMagnitude( QuaternionObject * self, void *type )
static PyObject *Quaternion_getAngle( QuaternionObject * self, void *type )
{
double ang = self->quat[0];
ang = 2 * (saacos(ang));
#ifdef USE_MATHUTILS_DEG
ang *= (180 / Py_PI);
#endif
return PyFloat_FromDouble(ang);
return PyFloat_FromDouble(2.0 * (saacos(self->quat[0])));
}
static PyObject *Quaternion_getAxisVec( QuaternionObject * self, void *type )
@@ -702,53 +713,139 @@ static PyObject *Quaternion_getAxisVec( QuaternionObject * self, void *type )
return (PyObject *) newVectorObject(vec, 3, Py_NEW, NULL);
}
//----------------------------------Mathutils.Quaternion() --------------
static PyObject *Quaternion_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyObject *listObject = NULL, *n, *q;
int size, i;
float quat[4];
double 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, NULL);
} 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;
}
quat[i] = PyFloat_AsDouble(q);
Py_DECREF(q);
if (quat[i]==-1 && PyErr_Occurred()) {
PyErr_SetString(PyExc_TypeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
return NULL;
}
}
if(size == 3) //calculate the quat based on axis/angle
axis_angle_to_quat(quat, quat, angle);
return newQuaternionObject(quat, Py_NEW, NULL);
}
//-----------------------METHOD DEFINITIONS ----------------------
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},
{"inverse", (PyCFunction) Quaternion_Inverse, METH_NOARGS, Quaternion_Inverse_doc},
{"normalize", (PyCFunction) Quaternion_Normalize, METH_NOARGS, Quaternion_Normalize_doc},
{"to_euler", (PyCFunction) Quaternion_ToEuler, METH_VARARGS, Quaternion_ToEuler_doc},
{"to_matrix", (PyCFunction) Quaternion_ToMatrix, METH_NOARGS, Quaternion_ToMatrix_doc},
{"cross", (PyCFunction) Quaternion_Cross, METH_O, Quaternion_Cross_doc},
{"dot", (PyCFunction) Quaternion_Dot, METH_O, Quaternion_Dot_doc},
{"difference", (PyCFunction) Quaternion_Difference, METH_O, Quaternion_Difference_doc},
{"slerp", (PyCFunction) Quaternion_Slerp, METH_VARARGS, Quaternion_Slerp_doc},
{"__copy__", (PyCFunction) Quaternion_copy, METH_NOARGS, Quaternion_copy_doc},
{"copy", (PyCFunction) Quaternion_copy, METH_NOARGS, Quaternion_copy_doc},
{NULL, NULL, 0, NULL}
};
/*****************************************************************************/
/* Python attributes get/set structure: */
/*****************************************************************************/
static PyGetSetDef Quaternion_getseters[] = {
{"w",
(getter)Quaternion_getAxis, (setter)Quaternion_setAxis,
"Quaternion W value",
(void *)0},
{"x",
(getter)Quaternion_getAxis, (setter)Quaternion_setAxis,
"Quaternion X axis",
(void *)1},
{"y",
(getter)Quaternion_getAxis, (setter)Quaternion_setAxis,
"Quaternion Y axis",
(void *)2},
{"z",
(getter)Quaternion_getAxis, (setter)Quaternion_setAxis,
"Quaternion Z axis",
(void *)3},
{"magnitude",
(getter)Quaternion_getMagnitude, (setter)NULL,
"Size of the quaternion",
NULL},
{"angle",
(getter)Quaternion_getAngle, (setter)NULL,
"angle of the quaternion",
NULL},
{"axis",
(getter)Quaternion_getAxisVec, (setter)NULL,
"quaternion axis as a vector",
NULL},
{"wrapped",
(getter)BaseMathObject_getWrapped, (setter)NULL,
"True when this wraps blenders internal data",
NULL},
{"_owner",
(getter)BaseMathObject_getOwner, (setter)NULL,
"Read only owner for vectors that depend on another object",
NULL},
{"w", (getter)Quaternion_getAxis, (setter)Quaternion_setAxis, "Quaternion W value. **type** float", (void *)0},
{"x", (getter)Quaternion_getAxis, (setter)Quaternion_setAxis, "Quaternion X axis. **type** float", (void *)1},
{"y", (getter)Quaternion_getAxis, (setter)Quaternion_setAxis, "Quaternion Y axis. **type** float", (void *)2},
{"z", (getter)Quaternion_getAxis, (setter)Quaternion_setAxis, "Quaternion Z axis. **type** float", (void *)3},
{"magnitude", (getter)Quaternion_getMagnitude, (setter)NULL, "Size of the quaternion (readonly). **type** float", NULL},
{"angle", (getter)Quaternion_getAngle, (setter)NULL, "angle of the quaternion (readonly). **type** float", NULL},
{"axis",(getter)Quaternion_getAxisVec, (setter)NULL, "quaternion axis as a vector (readonly). **type** :class:`Vector`", NULL},
{"is_wrapped", (getter)BaseMathObject_getWrapped, (setter)NULL, BaseMathObject_Wrapped_doc, NULL},
{"_owner", (getter)BaseMathObject_getOwner, (setter)NULL, BaseMathObject_Owner_doc, NULL},
{NULL,NULL,NULL,NULL,NULL} /* Sentinel */
};
//------------------PY_OBECT DEFINITION--------------------------
static char quaternion_doc[] =
"This object gives access to Quaternions in Blender.";
PyTypeObject quaternion_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"quaternion", //tp_name
@@ -770,7 +867,7 @@ PyTypeObject quaternion_Type = {
0, //tp_setattro
0, //tp_as_buffer
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, //tp_flags
0, //tp_doc
quaternion_doc, //tp_doc
0, //tp_traverse
0, //tp_clear
(richcmpfunc)Quaternion_richcmpr, //tp_richcompare
@@ -843,3 +940,4 @@ PyObject *newQuaternionObject_cb(PyObject *cb_user, int cb_type, int cb_subtype)
return (PyObject *)self;
}

View File

@@ -15,7 +15,7 @@
*
* 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.
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.

File diff suppressed because it is too large Load Diff

View File

@@ -14,7 +14,7 @@
*
* 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.
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.

View File

@@ -0,0 +1,143 @@
/**
* $Id:
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Campbell Barton
*
* ***** END GPL LICENSE BLOCK *****
*/
/* This file defines the '_bpy' module which is used by python's 'bpy' package.
* a script writer should never directly access this module */
#include <Python.h>
#include "bpy_util.h"
#include "bpy_rna.h"
#include "bpy_app.h"
#include "bpy_props.h"
#include "bpy_operator.h"
#include "BLI_path_util.h"
/* external util modules */
#include "../generic/Mathutils.h"
#include "../generic/Geometry.h"
#include "../generic/bgl.h"
#include "../generic/blf.h"
#include "../generic/IDProp.h"
static char bpy_home_paths_doc[] =
".. function:: home_paths(subfolder)\n"
"\n"
" return 3 paths to blender home directories.\n"
"\n"
" :arg subfolder: The name of a subfolder to find within the blenders home directory.\n"
" :type subfolder: string\n"
" :return: (system, local, user) strings will be empty when not found.\n"
" :rtype: tuple of strigs\n";
PyObject *bpy_home_paths(PyObject *self, PyObject *args)
{
PyObject *ret= PyTuple_New(3);
char *path;
char *subfolder= "";
if (!PyArg_ParseTuple(args, "|s:blender_homes", &subfolder))
return NULL;
path= BLI_gethome_folder(subfolder, BLI_GETHOME_SYSTEM);
PyTuple_SET_ITEM(ret, 0, PyUnicode_FromString(path?path:""));
path= BLI_gethome_folder(subfolder, BLI_GETHOME_LOCAL);
PyTuple_SET_ITEM(ret, 1, PyUnicode_FromString(path?path:""));
path= BLI_gethome_folder(subfolder, BLI_GETHOME_USER);
PyTuple_SET_ITEM(ret, 2, PyUnicode_FromString(path?path:""));
return ret;
}
static PyMethodDef meth_bpy_home_paths[] = {{ "home_paths", (PyCFunction)bpy_home_paths, METH_VARARGS, bpy_home_paths_doc}};
static void bpy_import_test(char *modname)
{
PyObject *mod= PyImport_ImportModuleLevel(modname, NULL, NULL, NULL, 0);
if(mod) {
Py_DECREF(mod);
}
else {
PyErr_Print();
PyErr_Clear();
}
}
/*****************************************************************************
* Description: Creates the bpy module and adds it to sys.modules for importing
*****************************************************************************/
void BPy_init_modules( void )
{
extern BPy_StructRNA *bpy_context_module;
PyObject *mod;
/* Needs to be first since this dir is needed for future modules */
char *modpath= BLI_gethome_folder("scripts/modules", BLI_GETHOME_ALL);
if(modpath) {
PyObject *sys_path= PySys_GetObject("path"); /* borrow */
PyObject *py_modpath= PyUnicode_FromString(modpath);
PyList_Insert(sys_path, 0, py_modpath); /* add first */
Py_DECREF(py_modpath);
}
/* stand alone utility modules not related to blender directly */
Geometry_Init();
Mathutils_Init();
BGL_Init();
BLF_Init();
IDProp_Init_Types();
mod = PyModule_New("_bpy");
/* add the module so we can import it */
PyDict_SetItemString(PySys_GetObject("modules"), "_bpy", mod);
Py_DECREF(mod);
/* run first, initializes rna types */
BPY_rna_init();
PyModule_AddObject( mod, "types", BPY_rna_types() ); /* needs to be first so bpy_types can run */
bpy_import_test("bpy_types");
PyModule_AddObject( mod, "data", BPY_rna_module() ); /* imports bpy_types by running this */
bpy_import_test("bpy_types");
PyModule_AddObject( mod, "props", BPY_rna_props() );
PyModule_AddObject( mod, "ops", BPY_operator_module() ); /* ops is now a python module that does the conversion from SOME_OT_foo -> some.foo */
PyModule_AddObject( mod, "app", BPY_app_struct() );
/* bpy context */
bpy_context_module= ( BPy_StructRNA * ) PyObject_NEW( BPy_StructRNA, &pyrna_struct_Type );
RNA_pointer_create(NULL, &RNA_Context, BPy_GetContext(), &bpy_context_module->ptr);
bpy_context_module->freeptr= 0;
PyModule_AddObject(mod, "context", (PyObject *)bpy_context_module);
/* utility func's that have nowhere else to go */
PyModule_AddObject(mod, meth_bpy_home_paths->ml_name, (PyObject *)PyCFunction_New(meth_bpy_home_paths, NULL));
/* add our own modules dir, this is a python package */
bpy_import_test("bpy");
}

View File

@@ -0,0 +1,25 @@
/**
* $Id:
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Campbell Barton
*
* ***** END GPL LICENSE BLOCK ***** */
void BPy_init_modules( void );

View File

@@ -0,0 +1,146 @@
/**
* $Id:
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Campbell Barton
*
* ***** END GPL LICENSE BLOCK *****
*/
#include "bpy_app.h"
#include "bpy_util.h"
#include "BLI_path_util.h"
#include "BKE_blender.h"
#include "BKE_global.h"
#include "structseq.h"
#ifdef BUILD_DATE
extern const char * build_date;
extern const char * build_time;
extern const char * build_rev;
extern const char * build_platform;
extern const char * build_type;
#endif
static PyTypeObject BlenderAppType;
static PyStructSequence_Field app_info_fields[] = {
{"version", "The Blender version as a tuple of 3 numbers. eg. (2, 50, 11)"},
{"version_string", "The Blender version formatted as a string"},
{"home", "The blender home directory, normally matching $HOME"},
{"binary_path", "The location of blenders executable, useful for utilities that spawn new instances"},
{"debug", "Boolean, set when blender is running in debug mode (started with -d)"},
/* buildinfo */
{"build_date", "The date this blender instance was built"},
{"build_time", "The time this blender instance was built"},
{"build_revision", "The subversion revision this blender instance was built with"},
{"build_platform", "The platform this blender instance was built for"},
{"build_type", "The type of build (Release, Debug)"},
{0}
};
static PyStructSequence_Desc app_info_desc = {
"bpy.app", /* name */
"This module contains application values that remain unchanged during runtime.", /* doc */
app_info_fields, /* fields */
10
};
static char *strip_quotes(char *buf, const char *input)
{
int i;
strcpy(buf, input);
if(buf[0]=='\0') return buf;
while(buf[1] && (buf[0]=='"' || buf[0]=='\'')) buf++;
if(buf[0]=='\0') return buf;
i= strlen(buf) - 1;
while(i>=0 && (buf[i]=='"' || buf[i]=='\'')) i--;
buf[i+1]= '\0';
return buf;
}
static PyObject *make_app_info(void)
{
extern char bprogname[]; /* argv[0] from creator.c */
char buf[256];
PyObject *app_info;
int pos = 0;
app_info = PyStructSequence_New(&BlenderAppType);
if (app_info == NULL) {
return NULL;
}
#define SetIntItem(flag) \
PyStructSequence_SET_ITEM(app_info, pos++, PyLong_FromLong(flag))
#define SetStrItem(str) \
PyStructSequence_SET_ITEM(app_info, pos++, PyUnicode_FromString(str))
#define SetObjItem(obj) \
PyStructSequence_SET_ITEM(app_info, pos++, obj)
SetObjItem(Py_BuildValue("(iii)", BLENDER_VERSION/100, BLENDER_VERSION%100, BLENDER_SUBVERSION));
SetObjItem(PyUnicode_FromFormat("%d.%02d (sub %d)", BLENDER_VERSION/100, BLENDER_VERSION%100, BLENDER_SUBVERSION));
SetStrItem(BLI_gethome());
SetStrItem(bprogname);
SetObjItem(PyBool_FromLong(G.f & G_DEBUG));
/* build info */
#ifdef BUILD_DATE
SetStrItem(strip_quotes(buf, build_date));
SetStrItem(strip_quotes(buf, build_time));
SetStrItem(strip_quotes(buf, build_rev));
SetStrItem(strip_quotes(buf, build_platform));
SetStrItem(strip_quotes(buf, build_type));
#else
SetStrItem(strip_quotes(buf, "Unknown"));
SetStrItem(strip_quotes(buf, "Unknown"));
SetStrItem(strip_quotes(buf, "Unknown"));
SetStrItem(strip_quotes(buf, "Unknown"));
SetStrItem(strip_quotes(buf, "Unknown"));
#endif
#undef SetIntItem
#undef SetStrItem
#undef SetObjItem
if (PyErr_Occurred()) {
Py_CLEAR(app_info);
return NULL;
}
return app_info;
}
PyObject *BPY_app_struct(void)
{
PyObject *ret;
PyStructSequence_InitType(&BlenderAppType, &app_info_desc);
ret= make_app_info();
/* prevent user from creating new instances */
BlenderAppType.tp_init = NULL;
BlenderAppType.tp_new = NULL;
return ret;
}

View File

@@ -0,0 +1,31 @@
/**
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Campbell Barton
*
* ***** END GPL LICENSE BLOCK *****
*/
#ifndef BPY_APP_H__
#define BPY_APP_H__
#include <Python.h>
PyObject *BPY_app_struct( void );
#endif

View File

@@ -1,5 +1,5 @@
/**
*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -15,7 +15,7 @@
*
* 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.
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Arystanbek Dyussenov
*
@@ -242,7 +242,7 @@ static char *copy_values(PyObject *seq, PointerRNA *ptr, PropertyRNA *prop, int
return data;
}
static int py_to_array(PyObject *py, PointerRNA *ptr, PropertyRNA *prop, char *param_data, ItemTypeCheckFunc check_item_type, const char *item_type_str, int item_size, ItemConvertFunc convert_item, RNA_SetArrayFunc rna_set_array, const char *error_prefix)
static int py_to_array(PyObject *py, PointerRNA *ptr, PropertyRNA *prop, ParameterList *parms, char *param_data, ItemTypeCheckFunc check_item_type, const char *item_type_str, int item_size, ItemConvertFunc convert_item, RNA_SetArrayFunc rna_set_array, const char *error_prefix)
{
int totdim, dim_size[MAX_ARRAY_DIMENSION];
int totitem;
@@ -266,6 +266,8 @@ static int py_to_array(PyObject *py, PointerRNA *ptr, PropertyRNA *prop, char *p
if (RNA_property_flag(prop) & PROP_DYNAMIC) {
/* not freeing allocated mem, RNA_parameter_list_free will do this */
*(char**)param_data= data;
RNA_parameter_length_set_data(parms, prop, param_data, totitem);
}
}
else {
@@ -358,18 +360,18 @@ static void bool_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, void *
RNA_property_boolean_set_index(ptr, prop, index, *(int*)value);
}
int pyrna_py_to_array(PointerRNA *ptr, PropertyRNA *prop, char *param_data, PyObject *py, const char *error_prefix)
int pyrna_py_to_array(PointerRNA *ptr, PropertyRNA *prop, ParameterList *parms, char *param_data, PyObject *py, const char *error_prefix)
{
int ret;
switch (RNA_property_type(prop)) {
case PROP_FLOAT:
ret= py_to_array(py, ptr, prop, param_data, py_float_check, "float", sizeof(float), py_to_float, (RNA_SetArrayFunc)RNA_property_float_set_array, error_prefix);
ret= py_to_array(py, ptr, prop, parms, param_data, py_float_check, "float", sizeof(float), py_to_float, (RNA_SetArrayFunc)RNA_property_float_set_array, error_prefix);
break;
case PROP_INT:
ret= py_to_array(py, ptr, prop, param_data, py_int_check, "int", sizeof(int), py_to_int, (RNA_SetArrayFunc)RNA_property_int_set_array, error_prefix);
ret= py_to_array(py, ptr, prop, parms, param_data, py_int_check, "int", sizeof(int), py_to_int, (RNA_SetArrayFunc)RNA_property_int_set_array, error_prefix);
break;
case PROP_BOOLEAN:
ret= py_to_array(py, ptr, prop, param_data, py_bool_check, "boolean", sizeof(int), py_to_bool, (RNA_SetArrayFunc)RNA_property_boolean_set_array, error_prefix);
ret= py_to_array(py, ptr, prop, parms, param_data, py_bool_check, "boolean", sizeof(int), py_to_bool, (RNA_SetArrayFunc)RNA_property_boolean_set_array, error_prefix);
break;
default:
PyErr_SetString(PyExc_TypeError, "not an array type");
@@ -457,14 +459,16 @@ static PyObject *pyrna_py_from_array_internal(PointerRNA *ptr, PropertyRNA *prop
}
#endif
PyObject *pyrna_py_from_array_index(BPy_PropertyRNA *self, int index)
PyObject *pyrna_py_from_array_index(BPy_PropertyRNA *self, PointerRNA *ptr, PropertyRNA *prop, int index)
{
int totdim, i, len;
int dimsize[MAX_ARRAY_DIMENSION];
int totdim, arraydim, arrayoffset, dimsize[MAX_ARRAY_DIMENSION], i, len;
BPy_PropertyRNA *ret= NULL;
arraydim= self ? self->arraydim : 0;
arrayoffset = self ? self->arrayoffset : 0;
/* just in case check */
len= RNA_property_multi_array_length(&self->ptr, self->prop, self->arraydim);
len= RNA_property_multi_array_length(ptr, prop, arraydim);
if (index >= len || index < 0) {
/* this shouldn't happen because higher level funcs must check for invalid index */
if (G.f & G_DEBUG) printf("pyrna_py_from_array_index: invalid index %d for array with length=%d\n", index, len);
@@ -473,11 +477,11 @@ PyObject *pyrna_py_from_array_index(BPy_PropertyRNA *self, int index)
return NULL;
}
totdim= RNA_property_array_dimension(&self->ptr, self->prop, dimsize);
totdim= RNA_property_array_dimension(ptr, prop, dimsize);
if (self->arraydim + 1 < totdim) {
ret= (BPy_PropertyRNA*)pyrna_prop_CreatePyObject(&self->ptr, self->prop);
ret->arraydim= self->arraydim + 1;
if (arraydim + 1 < totdim) {
ret= (BPy_PropertyRNA*)pyrna_prop_CreatePyObject(ptr, prop);
ret->arraydim= arraydim + 1;
/* arr[3][4][5]
@@ -487,14 +491,14 @@ PyObject *pyrna_py_from_array_index(BPy_PropertyRNA *self, int index)
x = arr[2][3]
index = offset + 3 * 5 */
for (i= self->arraydim + 1; i < totdim; i++)
for (i= arraydim + 1; i < totdim; i++)
index *= dimsize[i];
ret->arrayoffset= self->arrayoffset + index;
ret->arrayoffset= arrayoffset + index;
}
else {
index = self->arrayoffset + index;
ret= (BPy_PropertyRNA*)pyrna_array_item(&self->ptr, self->prop, index);
index = arrayoffset + index;
ret= (BPy_PropertyRNA*)pyrna_array_item(ptr, prop, index);
}
return (PyObject*)ret;

View File

@@ -15,7 +15,7 @@
*
* 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.
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Willian P. Germano, Campbell Barton
*
@@ -30,6 +30,7 @@
#include "BPY_extern.h"
#include "BKE_fcurve.h"
#include "BKE_global.h"
#include <Python.h>
@@ -86,7 +87,7 @@ static int bpy_pydriver_create_dict(void)
/* If there's a Blender text called pydrivers.py, import it.
* Users can add their own functions to this module.
*/
if (G.f & G_DOSCRIPTLINKS) {
if (G.f & G_SCRIPT_AUTOEXEC) {
mod = importText("pydrivers"); /* can also use PyImport_Import() */
if (mod) {
PyDict_SetItemString(d, "pydrivers", mod);
@@ -158,14 +159,18 @@ float BPY_pydriver_eval (ChannelDriver *driver)
int i;
/* sanity checks - should driver be executed? */
if ((driver == NULL) /*|| (G.f & G_DOSCRIPTLINKS)==0*/)
return result;
/*if (G.f & G_SCRIPT_AUTOEXEC)==0) return result; */
/* get the py expression to be evaluated */
expr = driver->expression;
if ((expr == NULL) || (expr[0]=='\0'))
return result;
if(!(G.f & G_SCRIPT_AUTOEXEC)) {
printf("skipping driver '%s', automatic scripts are disabled\n", driver->expression);
return result;
}
gilstate = PyGILState_Ensure();
/* init global dictionary for py-driver evaluation settings */
@@ -207,6 +212,8 @@ float BPY_pydriver_eval (ChannelDriver *driver)
for (dvar= driver->variables.first, i=0; dvar; dvar= dvar->next) {
PyTuple_SET_ITEM(expr_vars, i++, PyUnicode_InternFromString(dvar->name));
}
driver->flag &= ~DRIVER_FLAG_RENAMEVAR;
}
else {
expr_vars= PyTuple_GET_ITEM(((PyObject *)driver->expr_comp), 1);
@@ -253,24 +260,20 @@ float BPY_pydriver_eval (ChannelDriver *driver)
/* process the result */
if (retval == NULL) {
result = pydriver_error(driver);
PyGILState_Release(gilstate);
return result;
pydriver_error(driver);
result = 0.0f;
} else if((result= (float)PyFloat_AsDouble(retval)) == -1.0f && PyErr_Occurred()) {
pydriver_error(driver);
Py_DECREF(retval);
result = 0.0f;
}
result = (float)PyFloat_AsDouble(retval);
Py_DECREF(retval);
if ((result == -1) && PyErr_Occurred()) {
result = pydriver_error(driver);
PyGILState_Release(gilstate);
return result;
else {
/* all fine, make sure the "invalid expression" flag is cleared */
driver->flag &= ~DRIVER_FLAG_INVALID;
Py_DECREF(retval);
}
/* all fine, make sure the "invalid expression" flag is cleared */
driver->flag &= ~DRIVER_FLAG_INVALID;
PyGILState_Release(gilstate);
return result;
}

View File

@@ -15,7 +15,7 @@
*
* 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.
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Michel Selten, Willian P. Germano, Stephen Swaney,
* Chris Keith, Chris Want, Ken Hughes, Campbell Barton
@@ -38,9 +38,8 @@
#include "compile.h" /* for the PyCodeObject */
#include "eval.h" /* for PyEval_EvalCode */
#include "bpy.h"
#include "bpy_rna.h"
#include "bpy_operator.h"
#include "bpy_ui.h"
#include "bpy_util.h"
#ifndef WIN32
@@ -54,33 +53,26 @@
#include "MEM_guardedalloc.h"
#include "BLI_path_util.h"
#include "BLI_storage.h"
#include "BLI_fileops.h"
#include "BLI_string.h"
#include "BLI_path_util.h"
#include "BKE_blender.h"
#include "BKE_context.h"
#include "BKE_text.h"
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_global.h" /* only for script checking */
#include "BPY_extern.h"
#include "../generic/bpy_internal_import.h" // our own imports
/* external util modules */
#include "../generic/Mathutils.h"
#include "../generic/Geometry.h"
#include "../generic/BGL.h"
#include "../generic/IDProp.h"
/* for internal use, when starting and ending python scripts */
/* incase a python script triggers another python call, stop bpy_context_clear from invalidating */
static int py_call_level= 0;
BPy_StructRNA *bpy_context_module= NULL; /* for fast access */
// only for tests
#define TIME_PY_RUN
@@ -149,18 +141,6 @@ void bpy_context_clear(bContext *C, PyGILState_STATE *gilstate)
}
}
static void bpy_import_test(char *modname)
{
PyObject *mod= PyImport_ImportModuleLevel(modname, NULL, NULL, NULL, 0);
if(mod) {
Py_DECREF(mod);
}
else {
PyErr_Print();
PyErr_Clear();
}
}
void BPY_free_compiled_text( struct Text *text )
{
if( text->compiled ) {
@@ -169,75 +149,6 @@ void BPY_free_compiled_text( struct Text *text )
}
}
/*****************************************************************************
* Description: Creates the bpy module and adds it to sys.modules for importing
*****************************************************************************/
static BPy_StructRNA *bpy_context_module= NULL; /* for fast access */
static void bpy_init_modules( void )
{
PyObject *mod;
/* Needs to be first since this dir is needed for future modules */
char *modpath= BLI_gethome_folder("scripts/modules", BLI_GETHOME_ALL);
if(modpath) {
PyObject *sys_path= PySys_GetObject("path"); /* borrow */
PyObject *py_modpath= PyUnicode_FromString(modpath);
PyList_Insert(sys_path, 0, py_modpath); /* add first */
Py_DECREF(py_modpath);
}
/* stand alone utility modules not related to blender directly */
Geometry_Init();
Mathutils_Init();
BGL_Init();
IDProp_Init_Types();
mod = PyModule_New("_bpy");
/* add the module so we can import it */
PyDict_SetItemString(PySys_GetObject("modules"), "_bpy", mod);
Py_DECREF(mod);
/* run first, initializes rna types */
BPY_rna_init();
PyModule_AddObject( mod, "types", BPY_rna_types() ); /* needs to be first so bpy_types can run */
bpy_import_test("bpy_types");
PyModule_AddObject( mod, "data", BPY_rna_module() ); /* imports bpy_types by running this */
bpy_import_test("bpy_types");
/* PyModule_AddObject( mod, "doc", BPY_rna_doc() ); */
PyModule_AddObject( mod, "props", BPY_rna_props() );
PyModule_AddObject( mod, "ops", BPY_operator_module() ); /* ops is now a python module that does the conversion from SOME_OT_foo -> some.foo */
PyModule_AddObject( mod, "ui", BPY_ui_module() ); // XXX very experimental, consider this a test, especially PyCObject is not meant to be permanent
/* bpy context */
{
bpy_context_module= ( BPy_StructRNA * ) PyObject_NEW( BPy_StructRNA, &pyrna_struct_Type );
RNA_pointer_create(NULL, &RNA_Context, NULL, &bpy_context_module->ptr);
PyModule_AddObject(mod, "context", (PyObject *)bpy_context_module);
}
/* blender info that wont change at runtime, add into _bpy */
{
extern char bprogname[]; /* argv[0] from creator.c */
PyObject *mod_dict= PyModule_GetDict(mod);
char tmpstr[256];
PyModule_AddStringConstant(mod, "_HOME", BLI_gethome());
PyDict_SetItemString(mod_dict, "_VERSION", Py_BuildValue("(iii)", BLENDER_VERSION/100, BLENDER_VERSION%100, BLENDER_SUBVERSION));
sprintf(tmpstr, "%d.%02d (sub %d)", BLENDER_VERSION/100, BLENDER_VERSION%100, BLENDER_SUBVERSION);
PyModule_AddStringConstant(mod, "_VERSION_STR", tmpstr);
PyModule_AddStringConstant(mod, "_BINPATH", bprogname);
}
/* add our own modules dir, this is a python package */
bpy_import_test("bpy");
}
void BPY_update_modules( void )
{
#if 0 // slow, this runs all the time poll, draw etc 100's of time a sec.
@@ -374,7 +285,7 @@ void BPY_start_python( int argc, char **argv )
/* bpy.* and lets us import it */
bpy_init_modules();
BPy_init_modules();
{ /* our own import and reload functions */
PyObject *item;
@@ -469,11 +380,11 @@ int BPY_run_python_script( bContext *C, const char *fn, struct Text *text, struc
fclose(fp);
pystring= malloc(strlen(fn) + 32);
pystring= MEM_mallocN(strlen(fn) + 32, "pystring");
pystring[0]= '\0';
sprintf(pystring, "exec(open(r'%s').read())", fn);
py_result = PyRun_String( pystring, Py_file_input, py_dict, py_dict );
free(pystring);
MEM_freeN(pystring);
#else
py_result = PyRun_File(fp, fn, Py_file_input, py_dict, py_dict);
fclose(fp);
@@ -649,24 +560,26 @@ int BPY_button_eval(bContext *C, char *expr, double *value)
PyObject *dict, *mod, *retval;
int error_ret = 0;
if (!value || !expr || expr[0]=='\0') return -1;
if (!value || !expr) return -1;
if(expr[0]=='\0') {
*value= 0.0;
return error_ret;
}
bpy_context_set(C, &gilstate);
dict= CreateGlobalDictionary(C, NULL);
/* import some modules: builtins,math*/
PyDict_SetItemString(dict, "__builtins__", PyEval_GetBuiltins());
mod = PyImport_ImportModule("math");
if (mod) {
PyDict_Merge(dict, PyModule_GetDict(mod), 0); /* 0 - dont overwrite existing values */
/* Only keep for backwards compat! - just import all math into root, they are standard */
PyDict_SetItemString(dict, "math", mod);
PyDict_SetItemString(dict, "m", mod);
Py_DECREF(mod);
}
}
else { /* highly unlikely but possibly */
PyErr_Print();
PyErr_Clear();
}
retval = PyRun_String(expr, Py_eval_input, dict, dict);
@@ -723,14 +636,19 @@ void BPY_load_user_modules(bContext *C)
for(text=CTX_data_main(C)->text.first; text; text= text->id.next) {
if(text->flags & TXT_ISSCRIPT && BLI_testextensie(text->id.name+2, ".py")) {
PyObject *module= bpy_text_import(text);
if (module==NULL) {
PyErr_Print();
PyErr_Clear();
if(!(G.f & G_SCRIPT_AUTOEXEC)) {
printf("scripts disabled for \"%s\", skipping '%s'\n", bmain->name, text->id.name+2);
}
else {
Py_DECREF(module);
PyObject *module= bpy_text_import(text);
if (module==NULL) {
PyErr_Print();
PyErr_Clear();
}
else {
Py_DECREF(module);
}
}
}
}
@@ -793,7 +711,7 @@ int BPY_context_get(bContext *C, const char *member, bContextDataResult *result)
if (item) printf("Context '%s' not a valid type\n", member);
else printf("Context '%s' not found\n", member);
}
else if (G.f & G_DEBUG) {
else {
printf("Context '%s' found\n", member);
}

View File

@@ -16,7 +16,7 @@
*
* 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.
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Campbell Barton
*
@@ -32,6 +32,8 @@
#include "bpy_rna.h" /* for setting arg props only - pyrna_py_to_prop() */
#include "bpy_util.h"
#include "RNA_enum_types.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -45,8 +47,10 @@ static PyObject *pyop_call( PyObject * self, PyObject * args)
wmOperatorType *ot;
int error_val = 0;
PointerRNA ptr;
int operator_ret= OPERATOR_CANCELLED;
char *opname;
char *context_str= NULL;
PyObject *kw= NULL; /* optional args */
PyObject *context_dict= NULL; /* optional args */
PyObject *context_dict_back;
@@ -57,16 +61,25 @@ static PyObject *pyop_call( PyObject * self, PyObject * args)
// XXX Todo, work out a better solution for passing on context, could make a tuple from self and pack the name and Context into it...
bContext *C = BPy_GetContext();
if (!PyArg_ParseTuple(args, "sO|O!i:_bpy.ops.call", &opname, &context_dict, &PyDict_Type, &kw, &context))
if (!PyArg_ParseTuple(args, "sO|O!s:_bpy.ops.call", &opname, &context_dict, &PyDict_Type, &kw, &context_str))
return NULL;
ot= WM_operatortype_exists(opname);
if (ot == NULL) {
PyErr_Format( PyExc_SystemError, "_bpy.ops.call: operator \"%s\" could not be found", opname);
PyErr_Format( PyExc_SystemError, "Calling operator \"bpy.ops.%s\" error, could not be found", opname);
return NULL;
}
if(context_str) {
if(RNA_enum_value_from_id(operator_context_items, context_str, &context)==0) {
char *enum_str= BPy_enum_as_string(operator_context_items);
PyErr_Format(PyExc_TypeError, "Calling operator \"bpy.ops.%s\" error, expected a string enum in (%.200s)", opname, enum_str);
MEM_freeN(enum_str);
return NULL;
}
}
if(!PyDict_Check(context_dict))
context_dict= NULL;
@@ -76,59 +89,57 @@ static PyObject *pyop_call( PyObject * self, PyObject * args)
Py_XINCREF(context_dict); /* so we done loose it */
if(WM_operator_poll((bContext*)C, ot) == FALSE) {
PyErr_Format( PyExc_SystemError, "_bpy.ops.call: operator %.200s.poll() function failed, context is incorrect", opname);
PyErr_Format( PyExc_SystemError, "Operator bpy.ops.%.200s.poll() failed, context is incorrect", opname);
error_val= -1;
}
else {
/* WM_operator_properties_create(&ptr, opname); */
/* Save another lookup */
RNA_pointer_create(NULL, ot->srna, NULL, &ptr);
WM_operator_properties_create_ptr(&ptr, ot);
if(kw && PyDict_Size(kw))
error_val= pyrna_pydict_to_props(&ptr, kw, 0, "Converting py args to operator properties: ");
if(kw && PyDict_Size(kw))
error_val= pyrna_pydict_to_props(&ptr, kw, 0, "Converting py args to operator properties: ");
if (error_val==0) {
ReportList *reports;
if (error_val==0) {
ReportList *reports;
reports= MEM_mallocN(sizeof(ReportList), "wmOperatorReportList");
BKE_reports_init(reports, RPT_STORE);
reports= MEM_mallocN(sizeof(ReportList), "wmOperatorReportList");
BKE_reports_init(reports, RPT_STORE);
WM_operator_call_py(C, ot, context, &ptr, reports);
operator_ret= WM_operator_call_py(C, ot, context, &ptr, reports);
if(BPy_reports_to_error(reports))
error_val = -1;
if(BPy_reports_to_error(reports))
error_val = -1;
/* operator output is nice to have in the terminal/console too */
if(reports->list.first) {
char *report_str= BKE_reports_string(reports, 0); /* all reports */
/* operator output is nice to have in the terminal/console too */
if(reports->list.first) {
char *report_str= BKE_reports_string(reports, 0); /* all reports */
if(report_str) {
PySys_WriteStdout("%s\n", report_str);
MEM_freeN(report_str);
if(report_str) {
PySys_WriteStdout("%s\n", report_str);
MEM_freeN(report_str);
}
}
BKE_reports_clear(reports);
if ((reports->flag & RPT_FREE) == 0)
{
MEM_freeN(reports);
}
}
BKE_reports_clear(reports);
if ((reports->flag & RPT_FREE) == 0)
{
MEM_freeN(reports);
}
}
WM_operator_properties_free(&ptr);
WM_operator_properties_free(&ptr);
#if 0
/* if there is some way to know an operator takes args we should use this */
{
/* no props */
if (kw != NULL) {
PyErr_Format(PyExc_AttributeError, "Operator \"%s\" does not take any args", opname);
return NULL;
}
/* if there is some way to know an operator takes args we should use this */
{
/* no props */
if (kw != NULL) {
PyErr_Format(PyExc_AttributeError, "Operator \"%s\" does not take any args", opname);
return NULL;
}
WM_operator_name_call(C, opname, WM_OP_EXEC_DEFAULT, NULL);
}
WM_operator_name_call(C, opname, WM_OP_EXEC_DEFAULT, NULL);
}
#endif
}
@@ -140,7 +151,9 @@ static PyObject *pyop_call( PyObject * self, PyObject * args)
return NULL;
}
Py_RETURN_NONE;
/* return operator_ret as a bpy enum */
return pyrna_enum_bitfield_to_py(operator_return_items, operator_ret);
}
static PyObject *pyop_as_string( PyObject * self, PyObject * args)

View File

@@ -16,7 +16,7 @@
*
* 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.
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Campbell Barton
*

View File

@@ -15,31 +15,46 @@
*
* 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.
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Campbell Barton
*
* ***** END GPL LICENSE BLOCK *****
*/
#include "bpy_operator_wrap.h"
#include "BLI_listbase.h"
#include "BKE_context.h"
#include "BKE_report.h"
#include "DNA_windowmanager_types.h"
#include "MEM_guardedalloc.h"
#include "WM_api.h"
#include "WM_types.h"
#include "UI_interface.h"
#include "ED_screen.h"
#include "RNA_define.h"
#include "bpy_rna.h"
#include "bpy_props.h"
#include "bpy_util.h"
#include "../generic/bpy_internal_import.h" // our own imports
static void operator_properties_init(wmOperatorType *ot)
{
PyObject *py_class = ot->ext.data;
PyObject *item= ((PyTypeObject*)py_class)->tp_dict; /* getattr(..., "__dict__") returns a proxy */
RNA_struct_blender_type_set(ot->ext.srna, ot);
if(item) {
/* only call this so pyrna_deferred_register_props gives a useful error
* WM_operatortype_append_ptr will call RNA_def_struct_identifier
* later */
RNA_def_struct_identifier(ot->srna, ot->idname);
if(pyrna_deferred_register_props(ot->srna, item) != 0) {
PyErr_Print(); /* failed to register operator props */
PyErr_Clear();
}
}
else {
PyErr_Clear();
}
}
void operator_wrapper(wmOperatorType *ot, void *userdata)
{
@@ -49,32 +64,16 @@ void operator_wrapper(wmOperatorType *ot, void *userdata)
*ot= *((wmOperatorType *)userdata);
ot->srna= srna; /* restore */
RNA_struct_blender_type_set(ot->ext.srna, ot);
operator_properties_init(ot);
{ /* XXX - not nice, set the first enum as searchable, should have a way for python to set */
PointerRNA ptr;
PropertyRNA *prop;
/* Can't use this because it returns a dict proxy
*
* item= PyObject_GetAttrString(py_class, "__dict__");
*/
{
PyObject *py_class = ot->ext.data;
PyObject *item= ((PyTypeObject*)py_class)->tp_dict;
if(item) {
/* only call this so pyrna_deferred_register_props gives a useful error
* WM_operatortype_append_ptr will call RNA_def_struct_identifier
* later */
RNA_def_struct_identifier(ot->srna, ot->idname);
if(pyrna_deferred_register_props(ot->srna, item)!=0) {
/* failed to register operator props */
PyErr_Print();
PyErr_Clear();
}
}
else {
PyErr_Clear();
}
RNA_pointer_create(NULL, ot->srna, NULL, &ptr);
prop = RNA_struct_find_property(&ptr, "type");
if(prop)
ot->prop= prop;
}
}
@@ -91,33 +90,7 @@ void macro_wrapper(wmOperatorType *ot, void *userdata)
ot->ui = data->ui;
ot->ext = data->ext;
RNA_struct_blender_type_set(ot->ext.srna, ot);
/* Can't use this because it returns a dict proxy
*
* item= PyObject_GetAttrString(py_class, "__dict__");
*/
{
PyObject *py_class = ot->ext.data;
PyObject *item= ((PyTypeObject*)py_class)->tp_dict;
if(item) {
/* only call this so pyrna_deferred_register_props gives a useful error
* WM_operatortype_append_ptr will call RNA_def_struct_identifier
* later */
RNA_def_struct_identifier(ot->srna, ot->idname);
if(pyrna_deferred_register_props(ot->srna, item)!=0) {
/* failed to register operator props */
PyErr_Print();
PyErr_Clear();
}
}
else {
PyErr_Clear();
}
}
operator_properties_init(ot);
}
PyObject *PYOP_wrap_macro_define(PyObject *self, PyObject *args)

View File

@@ -16,7 +16,7 @@
*
* 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.
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Campbell Barton
*

View File

@@ -0,0 +1,897 @@
/**
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Campbell Barton
*
* ***** END GPL LICENSE BLOCK *****
*/
#include "bpy_props.h"
#include "bpy_rna.h"
#include "bpy_util.h"
#include "RNA_access.h"
#include "RNA_define.h" /* for defining our own rna */
#include "RNA_enum_types.h"
#include "MEM_guardedalloc.h"
#include "float.h" /* FLT_MIN/MAX */
EnumPropertyItem property_flag_items[] = {
{PROP_HIDDEN, "HIDDEN", 0, "Hidden", ""},
{PROP_ANIMATABLE, "ANIMATABLE", 0, "Animateable", ""},
{0, NULL, 0, NULL, NULL}};
/* subtypes */
EnumPropertyItem property_subtype_string_items[] = {
{PROP_FILEPATH, "FILE_PATH", 0, "File Path", ""},
{PROP_DIRPATH, "DIR_PATH", 0, "Directory Path", ""},
{PROP_FILENAME, "FILENAME", 0, "Filename", ""},
{PROP_NONE, "NONE", 0, "None", ""},
{0, NULL, 0, NULL, NULL}};
EnumPropertyItem property_subtype_number_items[] = {
{PROP_UNSIGNED, "UNSIGNED", 0, "Unsigned", ""},
{PROP_PERCENTAGE, "PERCENTAGE", 0, "Percentage", ""},
{PROP_FACTOR, "FACTOR", 0, "Factor", ""},
{PROP_ANGLE, "ANGLE", 0, "Angle", ""},
{PROP_TIME, "TIME", 0, "Time", ""},
{PROP_DISTANCE, "DISTANCE", 0, "Distance", ""},
{PROP_NONE, "NONE", 0, "None", ""},
{0, NULL, 0, NULL, NULL}};
EnumPropertyItem property_subtype_array_items[] = {
{PROP_COLOR, "COLOR", 0, "Color", ""},
{PROP_TRANSLATION, "TRANSLATION", 0, "Translation", ""},
{PROP_DIRECTION, "DIRECTION", 0, "Direction", ""},
{PROP_VELOCITY, "VELOCITY", 0, "Velocity", ""},
{PROP_ACCELERATION, "ACCELERATION", 0, "Acceleration", ""},
{PROP_MATRIX, "MATRIX", 0, "Matrix", ""},
{PROP_EULER, "EULER", 0, "Euler", ""},
{PROP_QUATERNION, "QUATERNION", 0, "Quaternion", ""},
{PROP_AXISANGLE, "AXISANGLE", 0, "Axis Angle", ""},
{PROP_XYZ, "XYZ", 0, "XYZ", ""},
{PROP_COLOR_GAMMA, "COLOR_GAMMA", 0, "Color Gamma", ""},
{PROP_NONE, "NONE", 0, "None", ""},
{0, NULL, 0, NULL, NULL}};
/* operators use this so it can store the args given but defer running
* it until the operator runs where these values are used to setup the
* default args for that operator instance */
static PyObject *bpy_prop_deferred_return(void *func, PyObject *kw)
{
PyObject *ret = PyTuple_New(2);
PyTuple_SET_ITEM(ret, 0, PyCapsule_New(func, NULL, NULL));
if(kw==NULL) kw= PyDict_New();
else Py_INCREF(kw);
PyTuple_SET_ITEM(ret, 1, kw);
return ret;
}
static int bpy_struct_id_used(StructRNA *srna, char *identifier)
{
PointerRNA ptr;
RNA_pointer_create(NULL, srna, NULL, &ptr);
return (RNA_struct_find_property(&ptr, identifier) != NULL);
}
/* Function that sets RNA, NOTE - self is NULL when called from python, but being abused from C so we can pass the srna allong
* This isnt incorrect since its a python object - but be careful */
static char BPy_BoolProperty_doc[] =
".. function:: BoolProperty(name=\"\", description=\"\", default=False, options={'ANIMATABLE'}, subtype='NONE')\n"
"\n"
" Returns a new boolean property definition.\n"
"\n"
" :arg options: Enumerator in ['HIDDEN', 'ANIMATABLE'].\n"
" :type options: set\n"
" :arg subtype: Enumerator in ['UNSIGNED', 'PERCENTAGE', 'FACTOR', 'ANGLE', 'TIME', 'DISTANCE', 'NONE'].\n"
" :type subtype: string";
PyObject *BPy_BoolProperty(PyObject *self, PyObject *args, PyObject *kw)
{
StructRNA *srna;
if (PyTuple_GET_SIZE(args) > 0) {
PyErr_SetString(PyExc_ValueError, "all args must be keywords");
return NULL;
}
srna= srna_from_self(self);
if(srna==NULL && PyErr_Occurred()) {
return NULL; /* self's type was compatible but error getting the srna */
}
else if(srna) {
static char *kwlist[] = {"attr", "name", "description", "default", "options", "subtype", NULL};
char *id=NULL, *name="", *description="";
int def=0;
PropertyRNA *prop;
PyObject *pyopts= NULL;
int opts=0;
char *pysubtype= NULL;
int subtype= PROP_NONE;
if (!PyArg_ParseTupleAndKeywords(args, kw, "s|ssiO!s:BoolProperty", (char **)kwlist, &id, &name, &description, &def, &PySet_Type, &pyopts, &pysubtype))
return NULL;
if(bpy_struct_id_used(srna, id)) {
// PyErr_Format(PyExc_TypeError, "BoolProperty(): '%s' already defined.", id);
// return NULL;
Py_RETURN_NONE;
}
if(pyopts && pyrna_set_to_enum_bitfield(property_flag_items, pyopts, &opts, "BoolProperty(options={...}):"))
return NULL;
if(pysubtype && RNA_enum_value_from_id(property_subtype_number_items, pysubtype, &subtype)==0) {
PyErr_Format(PyExc_TypeError, "BoolProperty(subtype='%s'): invalid subtype.", pysubtype);
return NULL;
}
// prop= RNA_def_boolean(srna, id, def, name, description);
prop= RNA_def_property(srna, id, PROP_BOOLEAN, subtype);
RNA_def_property_boolean_default(prop, def);
RNA_def_property_ui_text(prop, name, description);
if(pyopts) {
if(opts & PROP_HIDDEN) RNA_def_property_flag(prop, PROP_HIDDEN);
if((opts & PROP_ANIMATABLE)==0) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
}
RNA_def_property_duplicate_pointers(prop);
Py_RETURN_NONE;
}
else { /* operators defer running this function */
return bpy_prop_deferred_return((void *)BPy_BoolProperty, kw);
}
}
static char BPy_BoolVectorProperty_doc[] =
".. function:: BoolVectorProperty(name=\"\", description=\"\", default=(False, False, False), options={'ANIMATABLE'}, subtype='NONE', size=3)\n"
"\n"
" Returns a new vector boolean property definition.\n"
"\n"
" :arg options: Enumerator in ['HIDDEN', 'ANIMATABLE'].\n"
" :type options: set\n"
" :arg subtype: Enumerator in ['COLOR', 'TRANSLATION', 'DIRECTION', 'VELOCITY', 'ACCELERATION', 'MATRIX', 'EULER', 'QUATERNION', 'AXISANGLE', 'XYZ', 'COLOR_GAMMA', 'NONE'].\n"
" :type subtype: string";
PyObject *BPy_BoolVectorProperty(PyObject *self, PyObject *args, PyObject *kw)
{
StructRNA *srna;
if (PyTuple_GET_SIZE(args) > 0) {
PyErr_SetString(PyExc_ValueError, "all args must be keywords");
return NULL;
}
srna= srna_from_self(self);
if(srna==NULL && PyErr_Occurred()) {
return NULL; /* self's type was compatible but error getting the srna */
}
else if(srna) {
static const char *kwlist[] = {"attr", "name", "description", "default", "options", "subtype", "size", NULL};
char *id=NULL, *name="", *description="";
int def[PYRNA_STACK_ARRAY]={0};
int size=3;
PropertyRNA *prop;
PyObject *pydef= NULL;
PyObject *pyopts= NULL;
int opts=0;
char *pysubtype= NULL;
int subtype= PROP_NONE;
if (!PyArg_ParseTupleAndKeywords(args, kw, "s|ssOO!si:BoolVectorProperty", (char **)kwlist, &id, &name, &description, &pydef, &PySet_Type, &pyopts, &pysubtype, &size))
return NULL;
if(bpy_struct_id_used(srna, id)) {
// PyErr_Format(PyExc_TypeError, "BoolVectorProperty(): '%s' already defined.", id);
// return NULL;
Py_RETURN_NONE;
}
if(pyopts && pyrna_set_to_enum_bitfield(property_flag_items, pyopts, &opts, "BoolVectorProperty(options={...}):"))
return NULL;
if(pysubtype && RNA_enum_value_from_id(property_subtype_array_items, pysubtype, &subtype)==0) {
PyErr_Format(PyExc_TypeError, "BoolVectorProperty(subtype='%s'): invalid subtype.", pysubtype);
return NULL;
}
if(size < 1 || size > PYRNA_STACK_ARRAY) {
PyErr_Format(PyExc_TypeError, "BoolVectorProperty(size=%d): size must be between 0 and %d.", size, PYRNA_STACK_ARRAY);
return NULL;
}
if(pydef && BPyAsPrimitiveArray(def, pydef, size, &PyBool_Type, "BoolVectorProperty(default=sequence)") < 0)
return NULL;
// prop= RNA_def_boolean_array(srna, id, size, pydef ? def:NULL, name, description);
prop= RNA_def_property(srna, id, PROP_BOOLEAN, subtype);
RNA_def_property_array(prop, size);
if(pydef) RNA_def_property_boolean_array_default(prop, def);
RNA_def_property_ui_text(prop, name, description);
if(pyopts) {
if(opts & PROP_HIDDEN) RNA_def_property_flag(prop, PROP_HIDDEN);
if((opts & PROP_ANIMATABLE)==0) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
}
RNA_def_property_duplicate_pointers(prop);
Py_RETURN_NONE;
}
else { /* operators defer running this function */
return bpy_prop_deferred_return((void *)BPy_BoolVectorProperty, kw);
}
}
static char BPy_IntProperty_doc[] =
".. function:: IntProperty(name=\"\", description=\"\", default=0, min=-sys.maxint, max=sys.maxint, soft_min=-sys.maxint, soft_max=sys.maxint, step=1, options={'ANIMATABLE'}, subtype='NONE')\n"
"\n"
" Returns a new int property definition.\n"
"\n"
" :arg options: Enumerator in ['HIDDEN', 'ANIMATABLE'].\n"
" :type options: set\n"
" :arg subtype: Enumerator in ['UNSIGNED', 'PERCENTAGE', 'FACTOR', 'ANGLE', 'TIME', 'DISTANCE', 'NONE'].\n"
" :type subtype: string";
PyObject *BPy_IntProperty(PyObject *self, PyObject *args, PyObject *kw)
{
StructRNA *srna;
if (PyTuple_GET_SIZE(args) > 0) {
PyErr_SetString(PyExc_ValueError, "all args must be keywords");
return NULL;
}
srna= srna_from_self(self);
if(srna==NULL && PyErr_Occurred()) {
return NULL; /* self's type was compatible but error getting the srna */
}
else if(srna) {
static const char *kwlist[] = {"attr", "name", "description", "default", "min", "max", "soft_min", "soft_max", "step", "options", "subtype", NULL};
char *id=NULL, *name="", *description="";
int min=INT_MIN, max=INT_MAX, soft_min=INT_MIN, soft_max=INT_MAX, step=1, def=0;
PropertyRNA *prop;
PyObject *pyopts= NULL;
int opts=0;
char *pysubtype= NULL;
int subtype= PROP_NONE;
if (!PyArg_ParseTupleAndKeywords(args, kw, "s|ssiiiiiiO!s:IntProperty", (char **)kwlist, &id, &name, &description, &def, &min, &max, &soft_min, &soft_max, &step, &PySet_Type, &pyopts, &pysubtype))
return NULL;
if(bpy_struct_id_used(srna, id)) {
// PyErr_Format(PyExc_TypeError, "IntProperty(): '%s' already defined.", id);
// return NULL;
Py_RETURN_NONE;
}
if(pyopts && pyrna_set_to_enum_bitfield(property_flag_items, pyopts, &opts, "IntProperty(options={...}):"))
return NULL;
if(pysubtype && RNA_enum_value_from_id(property_subtype_number_items, pysubtype, &subtype)==0) {
PyErr_Format(PyExc_TypeError, "IntProperty(subtype='%s'): invalid subtype.", pysubtype);
return NULL;
}
prop= RNA_def_property(srna, id, PROP_INT, subtype);
RNA_def_property_int_default(prop, def);
RNA_def_property_range(prop, min, max);
RNA_def_property_ui_text(prop, name, description);
RNA_def_property_ui_range(prop, soft_min, soft_max, step, 3);
if(pyopts) {
if(opts & PROP_HIDDEN) RNA_def_property_flag(prop, PROP_HIDDEN);
if((opts & PROP_ANIMATABLE)==0) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
}
RNA_def_property_duplicate_pointers(prop);
Py_RETURN_NONE;
}
else { /* operators defer running this function */
return bpy_prop_deferred_return((void *)BPy_IntProperty, kw);
}
}
static char BPy_IntVectorProperty_doc[] =
".. function:: IntVectorProperty(name=\"\", description=\"\", default=(0, 0, 0), min=-sys.maxint, max=sys.maxint, soft_min=-sys.maxint, soft_max=sys.maxint, options={'ANIMATABLE'}, subtype='NONE', size=3)\n"
"\n"
" Returns a new vector int property definition.\n"
"\n"
" :arg options: Enumerator in ['HIDDEN', 'ANIMATABLE'].\n"
" :type options: set\n"
" :arg subtype: Enumerator in ['COLOR', 'TRANSLATION', 'DIRECTION', 'VELOCITY', 'ACCELERATION', 'MATRIX', 'EULER', 'QUATERNION', 'AXISANGLE', 'XYZ', 'COLOR_GAMMA', 'NONE'].\n"
" :type subtype: string";
PyObject *BPy_IntVectorProperty(PyObject *self, PyObject *args, PyObject *kw)
{
StructRNA *srna;
if (PyTuple_GET_SIZE(args) > 0) {
PyErr_SetString(PyExc_ValueError, "all args must be keywords");
return NULL;
}
srna= srna_from_self(self);
if(srna==NULL && PyErr_Occurred()) {
return NULL; /* self's type was compatible but error getting the srna */
}
else if(srna) {
static const char *kwlist[] = {"attr", "name", "description", "default", "min", "max", "soft_min", "soft_max", "step", "options", "subtype", "size", NULL};
char *id=NULL, *name="", *description="";
int min=INT_MIN, max=INT_MAX, soft_min=INT_MIN, soft_max=INT_MAX, step=1, def[PYRNA_STACK_ARRAY]={0};
int size=3;
PropertyRNA *prop;
PyObject *pydef= NULL;
PyObject *pyopts= NULL;
int opts=0;
char *pysubtype= NULL;
int subtype= PROP_NONE;
if (!PyArg_ParseTupleAndKeywords(args, kw, "s|ssOiiiiO!si:IntVectorProperty", (char **)kwlist, &id, &name, &description, &pydef, &min, &max, &soft_min, &soft_max, &PySet_Type, &pyopts, &pysubtype, &size))
return NULL;
if(bpy_struct_id_used(srna, id)) {
// PyErr_Format(PyExc_TypeError, "IntVectorProperty(): '%s' already defined.", id);
// return NULL;
Py_RETURN_NONE;
}
if(pyopts && pyrna_set_to_enum_bitfield(property_flag_items, pyopts, &opts, "IntVectorProperty(options={...}):"))
return NULL;
if(pysubtype && RNA_enum_value_from_id(property_subtype_array_items, pysubtype, &subtype)==0) {
PyErr_Format(PyExc_TypeError, "IntVectorProperty(subtype='%s'): invalid subtype.", pysubtype);
return NULL;
}
if(size < 1 || size > PYRNA_STACK_ARRAY) {
PyErr_Format(PyExc_TypeError, "IntVectorProperty(size=%d): size must be between 0 and %d.", size, PYRNA_STACK_ARRAY);
return NULL;
}
if(pydef && BPyAsPrimitiveArray(def, pydef, size, &PyLong_Type, "IntVectorProperty(default=sequence)") < 0)
return NULL;
prop= RNA_def_property(srna, id, PROP_INT, subtype);
RNA_def_property_array(prop, size);
if(pydef) RNA_def_property_int_array_default(prop, def);
RNA_def_property_range(prop, min, max);
RNA_def_property_ui_text(prop, name, description);
RNA_def_property_ui_range(prop, soft_min, soft_max, step, 3);
if(pyopts) {
if(opts & PROP_HIDDEN) RNA_def_property_flag(prop, PROP_HIDDEN);
if((opts & PROP_ANIMATABLE)==0) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
}
RNA_def_property_duplicate_pointers(prop);
Py_RETURN_NONE;
}
else { /* operators defer running this function */
return bpy_prop_deferred_return((void *)BPy_IntVectorProperty, kw);
}
}
static char BPy_FloatProperty_doc[] =
".. function:: FloatProperty(name=\"\", description=\"\", default=0.0, min=sys.float_info.min, max=sys.float_info.max, soft_min=sys.float_info.min, soft_max=sys.float_info.max, step=3, precision=2, options={'ANIMATABLE'}, subtype='NONE', unit='NONE')\n"
"\n"
" Returns a new float property definition.\n"
"\n"
" :arg options: Enumerator in ['HIDDEN', 'ANIMATABLE'].\n"
" :type options: set\n"
" :arg subtype: Enumerator in ['UNSIGNED', 'PERCENTAGE', 'FACTOR', 'ANGLE', 'TIME', 'DISTANCE', 'NONE'].\n"
" :type subtype: string\n"
" :arg unit: Enumerator in ['NONE', 'LENGTH', 'AREA', 'VOLUME', 'ROTATION', 'TIME', 'VELOCITY', 'ACCELERATION'].\n"
" :type unit: string\n";
PyObject *BPy_FloatProperty(PyObject *self, PyObject *args, PyObject *kw)
{
StructRNA *srna;
if (PyTuple_GET_SIZE(args) > 0) {
PyErr_SetString(PyExc_ValueError, "all args must be keywords");
return NULL;
}
srna= srna_from_self(self);
if(srna==NULL && PyErr_Occurred()) {
return NULL; /* self's type was compatible but error getting the srna */
}
else if(srna) {
static const char *kwlist[] = {"attr", "name", "description", "default", "min", "max", "soft_min", "soft_max", "step", "precision", "options", "subtype", "unit", NULL};
char *id=NULL, *name="", *description="";
float min=-FLT_MAX, max=FLT_MAX, soft_min=-FLT_MAX, soft_max=FLT_MAX, step=3, def=0.0f;
int precision= 2;
PropertyRNA *prop;
PyObject *pyopts= NULL;
int opts=0;
char *pysubtype= NULL;
int subtype= PROP_NONE;
char *pyunit= NULL;
int unit= PROP_UNIT_NONE;
if (!PyArg_ParseTupleAndKeywords(args, kw, "s|ssffffffiO!ss:FloatProperty", (char **)kwlist, &id, &name, &description, &def, &min, &max, &soft_min, &soft_max, &step, &precision, &PySet_Type, &pyopts, &pysubtype, &pyunit))
return NULL;
if(bpy_struct_id_used(srna, id)) {
// PyErr_Format(PyExc_TypeError, "FloatProperty(): '%s' already defined.", id);
// return NULL;
Py_RETURN_NONE;
}
if(pyopts && pyrna_set_to_enum_bitfield(property_flag_items, pyopts, &opts, "FloatProperty(options={...}):"))
return NULL;
if(pysubtype && RNA_enum_value_from_id(property_subtype_number_items, pysubtype, &subtype)==0) {
PyErr_Format(PyExc_TypeError, "FloatProperty(subtype='%s'): invalid subtype.", pysubtype);
return NULL;
}
if(pyunit && RNA_enum_value_from_id(property_unit_items, pyunit, &unit)==0) {
PyErr_Format(PyExc_TypeError, "FloatProperty(unit='%s'): invalid unit.");
return NULL;
}
prop= RNA_def_property(srna, id, PROP_FLOAT, subtype | unit);
RNA_def_property_float_default(prop, def);
RNA_def_property_range(prop, min, max);
RNA_def_property_ui_text(prop, name, description);
RNA_def_property_ui_range(prop, soft_min, soft_max, step, precision);
if(pyopts) {
if(opts & PROP_HIDDEN) RNA_def_property_flag(prop, PROP_HIDDEN);
if((opts & PROP_ANIMATABLE)==0) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
}
RNA_def_property_duplicate_pointers(prop);
Py_RETURN_NONE;
}
else { /* operators defer running this function */
return bpy_prop_deferred_return((void *)BPy_FloatProperty, kw);
}
}
static char BPy_FloatVectorProperty_doc[] =
".. function:: FloatVectorProperty(name=\"\", description=\"\", default=(0.0, 0.0, 0.0), min=sys.float_info.min, max=sys.float_info.max, soft_min=sys.float_info.min, soft_max=sys.float_info.max, step=3, precision=2, options={'ANIMATABLE'}, subtype='NONE', size=3)\n"
"\n"
" Returns a new vector float property definition.\n"
"\n"
" :arg options: Enumerator in ['HIDDEN', 'ANIMATABLE'].\n"
" :type options: set\n"
" :arg subtype: Enumerator in ['COLOR', 'TRANSLATION', 'DIRECTION', 'VELOCITY', 'ACCELERATION', 'MATRIX', 'EULER', 'QUATERNION', 'AXISANGLE', 'XYZ', 'COLOR_GAMMA', 'NONE'].\n"
" :type subtype: string";
PyObject *BPy_FloatVectorProperty(PyObject *self, PyObject *args, PyObject *kw)
{
StructRNA *srna;
if (PyTuple_GET_SIZE(args) > 0) {
PyErr_SetString(PyExc_ValueError, "all args must be keywords");
return NULL;
}
srna= srna_from_self(self);
if(srna==NULL && PyErr_Occurred()) {
return NULL; /* self's type was compatible but error getting the srna */
}
else if(srna) {
static const char *kwlist[] = {"attr", "name", "description", "default", "min", "max", "soft_min", "soft_max", "step", "precision", "options", "subtype", "size", NULL};
char *id=NULL, *name="", *description="";
float min=-FLT_MAX, max=FLT_MAX, soft_min=-FLT_MAX, soft_max=FLT_MAX, step=3, def[PYRNA_STACK_ARRAY]={0.0f};
int precision= 2, size=3;
PropertyRNA *prop;
PyObject *pydef= NULL;
PyObject *pyopts= NULL;
int opts=0;
char *pysubtype= NULL;
int subtype= PROP_NONE;
if (!PyArg_ParseTupleAndKeywords(args, kw, "s|ssOfffffiO!si:FloatVectorProperty", (char **)kwlist, &id, &name, &description, &pydef, &min, &max, &soft_min, &soft_max, &step, &precision, &PySet_Type, &pyopts, &pysubtype, &size))
return NULL;
if(bpy_struct_id_used(srna, id)) {
// PyErr_Format(PyExc_TypeError, "FloatVectorProperty(): '%s' already defined.", id);
// return NULL;
Py_RETURN_NONE;
}
if(pyopts && pyrna_set_to_enum_bitfield(property_flag_items, pyopts, &opts, "FloatVectorProperty(options={...}):"))
return NULL;
if(pysubtype && RNA_enum_value_from_id(property_subtype_array_items, pysubtype, &subtype)==0) {
PyErr_Format(PyExc_TypeError, "FloatVectorProperty(subtype='%s'): invalid subtype.", pysubtype);
return NULL;
}
if(size < 1 || size > PYRNA_STACK_ARRAY) {
PyErr_Format(PyExc_TypeError, "FloatVectorProperty(size=%d): size must be between 0 and %d.", size, PYRNA_STACK_ARRAY);
return NULL;
}
if(pydef && BPyAsPrimitiveArray(def, pydef, size, &PyFloat_Type, "FloatVectorProperty(default=sequence)") < 0)
return NULL;
prop= RNA_def_property(srna, id, PROP_FLOAT, subtype);
RNA_def_property_array(prop, size);
if(pydef) RNA_def_property_float_array_default(prop, def);
RNA_def_property_range(prop, min, max);
RNA_def_property_ui_text(prop, name, description);
RNA_def_property_ui_range(prop, soft_min, soft_max, step, precision);
if(pyopts) {
if(opts & PROP_HIDDEN) RNA_def_property_flag(prop, PROP_HIDDEN);
if((opts & PROP_ANIMATABLE)==0) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
}
RNA_def_property_duplicate_pointers(prop);
Py_RETURN_NONE;
}
else { /* operators defer running this function */
return bpy_prop_deferred_return((void *)BPy_FloatVectorProperty, kw);
}
}
static char BPy_StringProperty_doc[] =
".. function:: StringProperty(name=\"\", description=\"\", default=\"\", maxlen=0, options={'ANIMATABLE'}, subtype='NONE')\n"
"\n"
" Returns a new string property definition.\n"
"\n"
" :arg options: Enumerator in ['HIDDEN', 'ANIMATABLE'].\n"
" :type options: set\n"
" :arg subtype: Enumerator in ['FILE_PATH', 'DIR_PATH', 'FILENAME', 'NONE'].\n"
" :type subtype: string";
PyObject *BPy_StringProperty(PyObject *self, PyObject *args, PyObject *kw)
{
StructRNA *srna;
if (PyTuple_GET_SIZE(args) > 0) {
PyErr_SetString(PyExc_ValueError, "all args must be keywords");
return NULL;
}
srna= srna_from_self(self);
if(srna==NULL && PyErr_Occurred()) {
return NULL; /* self's type was compatible but error getting the srna */
}
else if(srna) {
static const char *kwlist[] = {"attr", "name", "description", "default", "maxlen", "options", "subtype", NULL};
char *id=NULL, *name="", *description="", *def="";
int maxlen=0;
PropertyRNA *prop;
PyObject *pyopts= NULL;
int opts=0;
char *pysubtype= NULL;
int subtype= PROP_NONE;
if (!PyArg_ParseTupleAndKeywords(args, kw, "s|sssiO!s:StringProperty", (char **)kwlist, &id, &name, &description, &def, &maxlen, &PySet_Type, &pyopts, &pysubtype))
return NULL;
if(bpy_struct_id_used(srna, id)) {
// PyErr_Format(PyExc_TypeError, "StringProperty(): '%s' already defined.", id);
// return NULL;
Py_RETURN_NONE;
}
if(pyopts && pyrna_set_to_enum_bitfield(property_flag_items, pyopts, &opts, "StringProperty(options={...}):"))
return NULL;
if(pysubtype && RNA_enum_value_from_id(property_subtype_string_items, pysubtype, &subtype)==0) {
PyErr_Format(PyExc_TypeError, "StringProperty(subtype='%s'): invalid subtype.", pysubtype);
return NULL;
}
prop= RNA_def_property(srna, id, PROP_STRING, subtype);
if(maxlen != 0) RNA_def_property_string_maxlength(prop, maxlen);
if(def) RNA_def_property_string_default(prop, def);
RNA_def_property_ui_text(prop, name, description);
if(pyopts) {
if(opts & PROP_HIDDEN) RNA_def_property_flag(prop, PROP_HIDDEN);
if((opts & PROP_ANIMATABLE)==0) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
}
RNA_def_property_duplicate_pointers(prop);
Py_RETURN_NONE;
}
else { /* operators defer running this function */
return bpy_prop_deferred_return((void *)BPy_StringProperty, kw);
}
}
static EnumPropertyItem *enum_items_from_py(PyObject *value, const char *def, int *defvalue)
{
EnumPropertyItem *items= NULL;
PyObject *item;
int seq_len, i, totitem= 0;
if(!PySequence_Check(value)) {
PyErr_SetString(PyExc_TypeError, "expected a sequence of tuples for the enum items");
return NULL;
}
seq_len = PySequence_Length(value);
for(i=0; i<seq_len; i++) {
EnumPropertyItem tmp= {0, "", 0, "", ""};
item= PySequence_GetItem(value, i);
if(item==NULL || PyTuple_Check(item)==0) {
PyErr_SetString(PyExc_TypeError, "expected a sequence of tuples for the enum items");
if(items) MEM_freeN(items);
Py_XDECREF(item);
return NULL;
}
if(!PyArg_ParseTuple(item, "sss", &tmp.identifier, &tmp.name, &tmp.description)) {
PyErr_SetString(PyExc_TypeError, "expected an identifier, name and description in the tuple");
Py_DECREF(item);
return NULL;
}
tmp.value= i;
RNA_enum_item_add(&items, &totitem, &tmp);
if(def[0] && strcmp(def, tmp.identifier) == 0)
*defvalue= tmp.value;
Py_DECREF(item);
}
if(!def[0])
*defvalue= 0;
RNA_enum_item_end(&items, &totitem);
return items;
}
static char BPy_EnumProperty_doc[] =
".. function:: EnumProperty(items, name=\"\", description=\"\", default=\"\", options={'ANIMATABLE'})\n"
"\n"
" Returns a new enumerator property definition.\n"
"\n"
" :arg options: Enumerator in ['HIDDEN', 'ANIMATABLE'].\n"
" :type options: set\n"
" :arg items: The items that make up this enumerator.\n"
" :type items: sequence of string triplets";
PyObject *BPy_EnumProperty(PyObject *self, PyObject *args, PyObject *kw)
{
StructRNA *srna;
if (PyTuple_GET_SIZE(args) > 0) {
PyErr_SetString(PyExc_ValueError, "all args must be keywords");
return NULL;
}
srna= srna_from_self(self);
if(srna==NULL && PyErr_Occurred()) {
return NULL; /* self's type was compatible but error getting the srna */
}
else if(srna) {
static const char *kwlist[] = {"attr", "items", "name", "description", "default", "options", NULL};
char *id=NULL, *name="", *description="", *def="";
int defvalue=0;
PyObject *items= Py_None;
EnumPropertyItem *eitems;
PropertyRNA *prop;
PyObject *pyopts= NULL;
int opts=0;
if (!PyArg_ParseTupleAndKeywords(args, kw, "sO|sssO!:EnumProperty", (char **)kwlist, &id, &items, &name, &description, &def, &PySet_Type, &pyopts))
return NULL;
if(bpy_struct_id_used(srna, id)) {
// PyErr_Format(PyExc_TypeError, "EnumProperty(): '%s' already defined.", id);
// return NULL;
Py_RETURN_NONE;
}
if(pyopts && pyrna_set_to_enum_bitfield(property_flag_items, pyopts, &opts, "EnumProperty(options={...}):"))
return NULL;
eitems= enum_items_from_py(items, def, &defvalue);
if(!eitems)
return NULL;
prop= RNA_def_enum(srna, id, eitems, defvalue, name, description);
if(pyopts) {
if(opts & PROP_HIDDEN) RNA_def_property_flag(prop, PROP_HIDDEN);
if((opts & PROP_ANIMATABLE)==0) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
}
RNA_def_property_duplicate_pointers(prop);
MEM_freeN(eitems);
Py_RETURN_NONE;
}
else { /* operators defer running this function */
return bpy_prop_deferred_return((void *)BPy_EnumProperty, kw);
}
}
static StructRNA *pointer_type_from_py(PyObject *value)
{
StructRNA *srna;
srna= srna_from_self(value);
if(!srna) {
PyErr_SetString(PyExc_SystemError, "expected an RNA type derived from IDPropertyGroup");
return NULL;
}
if(!RNA_struct_is_a(srna, &RNA_IDPropertyGroup)) {
PyErr_SetString(PyExc_SystemError, "expected an RNA type derived from IDPropertyGroup");
return NULL;
}
return srna;
}
static char BPy_PointerProperty_doc[] =
".. function:: PointerProperty(items, type=\"\", description=\"\", default=\"\", options={'ANIMATABLE'})\n"
"\n"
" Returns a new pointer property definition.\n"
"\n"
" :arg options: Enumerator in ['HIDDEN', 'ANIMATABLE'].\n"
" :type options: set\n"
" :arg type: Dynamic type from :mod:`bpy.types`.\n"
" :type type: class";
PyObject *BPy_PointerProperty(PyObject *self, PyObject *args, PyObject *kw)
{
StructRNA *srna;
if (PyTuple_GET_SIZE(args) > 0) {
PyErr_SetString(PyExc_ValueError, "all args must be keywords");
return NULL;
}
srna= srna_from_self(self);
if(srna==NULL && PyErr_Occurred()) {
return NULL; /* self's type was compatible but error getting the srna */
}
else if(srna) {
static const char *kwlist[] = {"attr", "type", "name", "description", "options", NULL};
char *id=NULL, *name="", *description="";
PropertyRNA *prop;
StructRNA *ptype;
PyObject *type= Py_None;
PyObject *pyopts= NULL;
int opts=0;
if (!PyArg_ParseTupleAndKeywords(args, kw, "sO|ssO!:PointerProperty", (char **)kwlist, &id, &type, &name, &description, &PySet_Type, &pyopts))
return NULL;
if(bpy_struct_id_used(srna, id)) {
// PyErr_Format(PyExc_TypeError, "PointerProperty(): '%s' already defined.", id);
// return NULL;
Py_RETURN_NONE;
}
if(pyopts && pyrna_set_to_enum_bitfield(property_flag_items, pyopts, &opts, "PointerProperty(options={...}):"))
return NULL;
ptype= pointer_type_from_py(type);
if(!ptype)
return NULL;
prop= RNA_def_pointer_runtime(srna, id, ptype, name, description);
if(pyopts) {
if(opts & PROP_HIDDEN) RNA_def_property_flag(prop, PROP_HIDDEN);
if((opts & PROP_ANIMATABLE)==0) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
}
RNA_def_property_duplicate_pointers(prop);
Py_RETURN_NONE;
}
else { /* operators defer running this function */
return bpy_prop_deferred_return((void *)BPy_PointerProperty, kw);
}
return NULL;
}
static char BPy_CollectionProperty_doc[] =
".. function:: CollectionProperty(items, type=\"\", description=\"\", default=\"\", options={'ANIMATABLE'})\n"
"\n"
" Returns a new collection property definition.\n"
"\n"
" :arg options: Enumerator in ['HIDDEN', 'ANIMATABLE'].\n"
" :type options: set\n"
" :arg type: Dynamic type from :mod:`bpy.types`.\n"
" :type type: class";
PyObject *BPy_CollectionProperty(PyObject *self, PyObject *args, PyObject *kw)
{
StructRNA *srna;
if (PyTuple_GET_SIZE(args) > 0) {
PyErr_SetString(PyExc_ValueError, "all args must be keywords");
return NULL;
}
srna= srna_from_self(self);
if(srna==NULL && PyErr_Occurred()) {
return NULL; /* self's type was compatible but error getting the srna */
}
else if(srna) {
static const char *kwlist[] = {"attr", "type", "name", "description", "options", NULL};
char *id=NULL, *name="", *description="";
PropertyRNA *prop;
StructRNA *ptype;
PyObject *type= Py_None;
PyObject *pyopts= NULL;
int opts=0;
if (!PyArg_ParseTupleAndKeywords(args, kw, "sO|ssO!:CollectionProperty", (char **)kwlist, &id, &type, &name, &description, &PySet_Type, &pyopts))
return NULL;
if(bpy_struct_id_used(srna, id)) {
// PyErr_Format(PyExc_TypeError, "CollectionProperty(): '%s' already defined.", id);
// return NULL;
Py_RETURN_NONE;
}
if(pyopts && pyrna_set_to_enum_bitfield(property_flag_items, pyopts, &opts, "CollectionProperty(options={...}):"))
return NULL;
ptype= pointer_type_from_py(type);
if(!ptype)
return NULL;
prop= RNA_def_collection_runtime(srna, id, ptype, name, description);
if(pyopts) {
if(opts & PROP_HIDDEN) RNA_def_property_flag(prop, PROP_HIDDEN);
if((opts & PROP_ANIMATABLE)==0) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
}
RNA_def_property_duplicate_pointers(prop);
Py_RETURN_NONE;
}
else { /* operators defer running this function */
return bpy_prop_deferred_return((void *)BPy_CollectionProperty, kw);
}
return NULL;
}
static struct PyMethodDef props_methods[] = {
{"BoolProperty", (PyCFunction)BPy_BoolProperty, METH_VARARGS|METH_KEYWORDS, BPy_BoolProperty_doc},
{"BoolVectorProperty", (PyCFunction)BPy_BoolVectorProperty, METH_VARARGS|METH_KEYWORDS, BPy_BoolVectorProperty_doc},
{"IntProperty", (PyCFunction)BPy_IntProperty, METH_VARARGS|METH_KEYWORDS, BPy_IntProperty_doc},
{"IntVectorProperty", (PyCFunction)BPy_IntVectorProperty, METH_VARARGS|METH_KEYWORDS, BPy_IntVectorProperty_doc},
{"FloatProperty", (PyCFunction)BPy_FloatProperty, METH_VARARGS|METH_KEYWORDS, BPy_FloatProperty_doc},
{"FloatVectorProperty", (PyCFunction)BPy_FloatVectorProperty, METH_VARARGS|METH_KEYWORDS, BPy_FloatVectorProperty_doc},
{"StringProperty", (PyCFunction)BPy_StringProperty, METH_VARARGS|METH_KEYWORDS, BPy_StringProperty_doc},
{"EnumProperty", (PyCFunction)BPy_EnumProperty, METH_VARARGS|METH_KEYWORDS, BPy_EnumProperty_doc},
{"PointerProperty", (PyCFunction)BPy_PointerProperty, METH_VARARGS|METH_KEYWORDS, BPy_PointerProperty_doc},
{"CollectionProperty", (PyCFunction)BPy_CollectionProperty, METH_VARARGS|METH_KEYWORDS, BPy_CollectionProperty_doc},
{NULL, NULL, 0, NULL}
};
static struct PyModuleDef props_module = {
PyModuleDef_HEAD_INIT,
"bpy.props",
"This module defines properties to extend blenders internal data, the result of these functions"
" is used to assign properties to classes registered with blender and can't be used directly.",
-1,/* multiple "initialization" just copies the module dict. */
props_methods,
NULL, NULL, NULL, NULL
};
PyObject *BPY_rna_props( void )
{
PyObject *submodule;
submodule= PyModule_Create(&props_module);
PyDict_SetItemString(PySys_GetObject("modules"), props_module.m_name, submodule);
/* INCREF since its its assumed that all these functions return the
* module with a new ref like PyDict_New, since they are passed to
* PyModule_AddObject which steals a ref */
Py_INCREF(submodule);
return submodule;
}

View File

@@ -0,0 +1,46 @@
/**
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Campbell Barton
*
* ***** END GPL LICENSE BLOCK *****
*/
#ifndef BPY_PROPS_H
#define BPY_PROPS_H
#include <Python.h>
PyObject *BPY_rna_props( void );
/* functions for setting up new props - experemental */
PyObject *BPy_BoolProperty(PyObject *self, PyObject *args, PyObject *kw);
PyObject *BPy_BoolVectorProperty(PyObject *self, PyObject *args, PyObject *kw);
PyObject *BPy_IntProperty(PyObject *self, PyObject *args, PyObject *kw);
PyObject *BPy_IntVectorProperty(PyObject *self, PyObject *args, PyObject *kw);
PyObject *BPy_FloatProperty(PyObject *self, PyObject *args, PyObject *kw);
PyObject *BPy_FloatVectorProperty(PyObject *self, PyObject *args, PyObject *kw);
PyObject *BPy_StringProperty(PyObject *self, PyObject *args, PyObject *kw);
PyObject *BPy_EnumProperty(PyObject *self, PyObject *args, PyObject *kw);
PyObject *BPy_PointerProperty(PyObject *self, PyObject *args, PyObject *kw);
PyObject *BPy_CollectionProperty(PyObject *self, PyObject *args, PyObject *kw);
#define PYRNA_STACK_ARRAY 32
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -15,7 +15,7 @@
*
* 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.
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Campbell Barton
*
@@ -32,6 +32,8 @@
extern PyTypeObject pyrna_struct_Type;
extern PyTypeObject pyrna_prop_Type;
extern PyTypeObject pyrna_prop_array_Type;
extern PyTypeObject pyrna_prop_collection_Type;
#define BPy_StructRNA_Check(v) (PyObject_TypeCheck(v, &pyrna_struct_Type))
#define BPy_StructRNA_CheckExact(v) (Py_TYPE(v) == &pyrna_struct_Type)
@@ -70,24 +72,19 @@ PyObject *BPY_rna_module( void );
void BPY_update_rna_module( void );
/*PyObject *BPY_rna_doc( void );*/
PyObject *BPY_rna_types( void );
PyObject *BPY_rna_props( void );
PyObject *pyrna_struct_CreatePyObject( PointerRNA *ptr );
PyObject *pyrna_prop_CreatePyObject( PointerRNA *ptr, PropertyRNA *prop );
/* operators also need this to set args */
int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *value, const char *error_prefix);
int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, ParameterList *parms, void *data, PyObject *value, const char *error_prefix);
int pyrna_pydict_to_props(PointerRNA *ptr, PyObject *kw, int all_args, const char *error_prefix);
PyObject * pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop);
/* functions for setting up new props - experemental */
PyObject *BPy_BoolProperty(PyObject *self, PyObject *args, PyObject *kw);
PyObject *BPy_IntProperty(PyObject *self, PyObject *args, PyObject *kw);
PyObject *BPy_FloatProperty(PyObject *self, PyObject *args, PyObject *kw);
PyObject *BPy_StringProperty(PyObject *self, PyObject *args, PyObject *kw);
PyObject *BPy_EnumProperty(PyObject *self, PyObject *args, PyObject *kw);
PyObject *BPy_PointerProperty(PyObject *self, PyObject *args, PyObject *kw);
PyObject *BPy_CollectionProperty(PyObject *self, PyObject *args, PyObject *kw);
PyObject *pyrna_enum_bitfield_to_py(struct EnumPropertyItem *items, int value);
int pyrna_set_to_enum_bitfield(EnumPropertyItem *items, PyObject *value, int *r_value, const char *error_prefix);
int pyrna_enum_value_from_id(EnumPropertyItem *item, const char *identifier, int *value, const char *error_prefix);
/* function for registering types */
PyObject *pyrna_basetype_register(PyObject *self, PyObject *args);
@@ -100,11 +97,11 @@ void pyrna_alloc_types(void);
void pyrna_free_types(void);
/* primitive type conversion */
int pyrna_py_to_array(PointerRNA *ptr, PropertyRNA *prop, char *param_data, PyObject *py, const char *error_prefix);
int pyrna_py_to_array(PointerRNA *ptr, PropertyRNA *prop, ParameterList *parms, char *param_data, PyObject *py, const char *error_prefix);
int pyrna_py_to_array_index(PointerRNA *ptr, PropertyRNA *prop, int arraydim, int arrayoffset, int index, PyObject *py, const char *error_prefix);
PyObject *pyrna_py_from_array(PointerRNA *ptr, PropertyRNA *prop);
PyObject *pyrna_py_from_array_index(BPy_PropertyRNA *self, int index);
PyObject *pyrna_py_from_array_index(BPy_PropertyRNA *self, PointerRNA *ptr, PropertyRNA *prop, int index);
PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop);
int pyrna_array_contains_py(PointerRNA *ptr, PropertyRNA *prop, PyObject *value);

View File

@@ -0,0 +1,121 @@
/**
* $Id:
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Campbell Barton
*
* ***** END GPL LICENSE BLOCK *****
*/
#include "Python.h"
#include "bpy_rna.h"
#include "bpy_util.h"
#include "BLI_path_util.h"
#include "DNA_screen_types.h"
#include "BKE_context.h"
#include "ED_space_api.h"
/* use this to stop other capsules from being mis-used */
#define RNA_CAPSULE_ID "RNA_HANDLE"
#define RNA_CAPSULE_ID_INVALID "RNA_HANDLE_REMOVED"
void cb_region_draw(const bContext *C, ARegion *ar, void *customdata)
{
PyObject *cb_func, *cb_args, *result;
PyGILState_STATE gilstate;
bpy_context_set((bContext *)C, &gilstate);
cb_func= PyTuple_GET_ITEM((PyObject *)customdata, 0);
cb_args= PyTuple_GET_ITEM((PyObject *)customdata, 1);
result = PyObject_CallObject(cb_func, cb_args);
if(result) {
Py_DECREF(result);
}
else {
PyErr_Print();
PyErr_Clear();
}
bpy_context_clear((bContext *)C, &gilstate);
}
PyObject *pyrna_callback_add(BPy_StructRNA *self, PyObject *args)
{
void *handle;
PyObject *cb_func, *cb_args;
char *cb_event_str= NULL;
int cb_event;
if (!PyArg_ParseTuple(args, "OO|s:bpy_struct.callback_add", &cb_func, &cb_args, &cb_event_str))
return NULL;
if(RNA_struct_is_a(self->ptr.type, &RNA_Region)) {
static EnumPropertyItem region_draw_mode_items[] = {
{REGION_DRAW_POST_VIEW, "POST_VIEW", 0, "Pose View", ""},
{REGION_DRAW_POST_PIXEL, "POST_PIXEL", 0, "Post Pixel", ""},
{REGION_DRAW_PRE_VIEW, "PRE_VIEW", 0, "Pre View", ""},
{0, NULL, 0, NULL, NULL}};
if(pyrna_enum_value_from_id(region_draw_mode_items, cb_event_str, &cb_event, "bpy_struct.callback_add()") < 0)
return NULL;
handle= ED_region_draw_cb_activate(((ARegion *)self->ptr.data)->type, cb_region_draw, (void *)args, cb_event);
Py_INCREF(args);
}
else {
PyErr_SetString(PyExc_TypeError, "callback_add(): type does not suppport callbacks");
return NULL;
}
return PyCapsule_New((void *)handle, RNA_CAPSULE_ID, NULL);
}
PyObject *pyrna_callback_remove(BPy_StructRNA *self, PyObject *args)
{
PyObject *py_handle;
void *handle;
void *customdata;
if (!PyArg_ParseTuple(args, "O!:callback_remove", &PyCapsule_Type, &py_handle))
return NULL;
handle= PyCapsule_GetPointer(py_handle, RNA_CAPSULE_ID);
if(handle==NULL) {
PyErr_SetString(PyExc_ValueError, "callback_remove(handle): NULL handle given, invalid or already removed.");
return NULL;
}
if(RNA_struct_is_a(self->ptr.type, &RNA_Region)) {
customdata= ED_region_draw_cb_customdata(handle);
Py_DECREF((PyObject *)customdata);
ED_region_draw_cb_exit(((ARegion *)self->ptr.data)->type, handle);
}
/* dont allow reuse */
PyCapsule_SetName(py_handle, RNA_CAPSULE_ID_INVALID);
Py_RETURN_NONE;
}

View File

@@ -0,0 +1,29 @@
/**
* $Id:
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Campbell Barton
*
* ***** END GPL LICENSE BLOCK *****
*/
struct BPy_StructRNA;
struct PyObject;
struct PyObject *pyrna_callback_add(struct BPy_StructRNA *self, struct PyObject *args);
struct PyObject *pyrna_callback_remove(struct BPy_StructRNA *self, struct PyObject *args);

View File

@@ -15,7 +15,7 @@
*
* 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.
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Campbell Barton
*
@@ -373,3 +373,56 @@ int BPy_errors_to_report(ReportList *reports)
return 1;
}
/* array utility function */
int BPyAsPrimitiveArray(void *array, PyObject *value, int length, PyTypeObject *type, char *error_prefix)
{
PyObject *value_fast;
int value_len;
int i;
if(!(value_fast=PySequence_Fast(value, error_prefix))) {
return -1;
}
value_len= PySequence_Fast_GET_SIZE(value_fast);
if(value_len != length) {
Py_DECREF(value);
PyErr_Format(PyExc_TypeError, "%s: invalid sequence length. expected %d, got %d.", error_prefix, length, value_len);
return -1;
}
/* for each type */
if(type == &PyFloat_Type) {
float *array_float= array;
for(i=0; i<length; i++) {
array_float[i] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value_fast, i));
}
}
else if(type == &PyLong_Type) {
int *array_int= array;
for(i=0; i<length; i++) {
array_int[i] = PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value_fast, i));
}
}
else if(type == &PyBool_Type) {
int *array_bool= array;
for(i=0; i<length; i++) {
array_bool[i] = (PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value_fast, i)) != 0);
}
}
else {
Py_DECREF(value_fast);
PyErr_Format(PyExc_TypeError, "%s: internal error %s is invalid.", error_prefix, type->tp_name);
return -1;
}
Py_DECREF(value_fast);
if(PyErr_Occurred()) {
PyErr_Format(PyExc_TypeError, "%s: one or more items could not be used as a %s.", error_prefix, type->tp_name);
return -1;
}
return 0;
}

View File

@@ -15,7 +15,7 @@
*
* 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.
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Campbell Barton
*
@@ -78,5 +78,5 @@ void BPy_SetContext(struct bContext *C);
extern void bpy_context_set(struct bContext *C, PyGILState_STATE *gilstate);
extern void bpy_context_clear(struct bContext *C, PyGILState_STATE *gilstate);
int BPyAsPrimitiveArray(void *array, PyObject *value, int length, PyTypeObject *type, char *error_prefix);
#endif

View File

@@ -15,7 +15,7 @@
*
* 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.
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2007 Blender Foundation.
* All rights reserved.

View File

@@ -12,7 +12,7 @@
#
# 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.
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# Contributor(s): Campbell Barton
#

View File

@@ -12,7 +12,7 @@
#
# 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.
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# Contributor(s): Campbell Barton
#

View File

@@ -1,282 +0,0 @@
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# Contributor(s): Campbell Barton
#
# #**** END GPL LICENSE BLOCK #****
script_help_msg = '''
Usage,
run this script from blenders root path once you have compiled blender
./blender.bin -b -P /b/source/blender/python/sphinx_doc_gen.py
This will generate python files in "./source/blender/python/doc/sphinx-in"
Generate html docs by running...
sphinx-build source/blender/python/doc/sphinx-in source/blender/python/doc/sphinx-out
'''
# if you dont have graphvis installed ommit the --graph arg.
# GLOBALS['BASEDIR'] = './source/blender/python/doc'
import os
import inspect
import bpy
import rna_info
reload(rna_info)
def range_str(val):
if val < -10000000: return '-inf'
if val > 10000000: return 'inf'
if type(val)==float:
return '%g' % val
else:
return str(val)
def write_indented_lines(ident, fn, text):
if text is None:
return
for l in text.split("\n"):
fn(ident + l.strip() + "\n")
def rna2sphinx(BASEPATH):
structs, funcs, ops, props = rna_info.BuildRNAInfo()
try:
os.mkdir(BASEPATH)
except:
pass
# conf.py - empty for now
filepath = os.path.join(BASEPATH, "conf.py")
file = open(filepath, "w")
fw = file.write
fw("project = 'Blender 3D'\n")
# fw("master_doc = 'index'\n")
fw("copyright = u'Blender Foundation'\n")
fw("version = '2.5'\n")
fw("release = '2.5'\n")
file.close()
filepath = os.path.join(BASEPATH, "contents.rst")
file = open(filepath, "w")
fw = file.write
fw("\n")
fw(".. toctree::\n")
fw(" :glob:\n\n")
fw(" bpy.ops.*\n\n")
fw(" bpy.types.*\n\n")
file.close()
if 0:
filepath = os.path.join(BASEPATH, "bpy.rst")
file = open(filepath, "w")
fw = file.write
fw("\n")
title = ":mod:`bpy` --- Blender Python Module"
fw("%s\n%s\n\n" % (title, "=" * len(title)))
fw(".. module:: bpy.types\n\n")
file.close()
def write_param(ident, fw, prop, is_return=False):
if is_return:
id_name = "return"
id_type = "rtype"
else:
id_name = "arg"
id_type = "type"
type_descr = prop.get_type_description(as_arg=True, class_fmt=":class:`%s`")
if prop.name or prop.description:
fw(ident + " :%s %s: %s\n" % (id_name, prop.identifier, ", ".join([val for val in (prop.name, prop.description) if val])))
fw(ident + " :%s %s: %s\n" % (id_type, prop.identifier, type_descr))
def write_struct(struct):
#if not struct.identifier.startswith("Sc") and not struct.identifier.startswith("I"):
# return
#if not struct.identifier == "Object":
# return
filepath = os.path.join(BASEPATH, "bpy.types.%s.rst" % struct.identifier)
file = open(filepath, "w")
fw = file.write
if struct.base:
title = "%s(%s)" % (struct.identifier, struct.base.identifier)
else:
title = struct.identifier
fw("%s\n%s\n\n" % (title, "=" * len(title)))
fw(".. module:: bpy.types\n\n")
bases = struct.get_bases()
if bases:
if len(bases) > 1:
fw("base classes --- ")
else:
fw("base class --- ")
fw(", ".join([(":class:`%s`" % base.identifier) for base in reversed(bases)]))
fw("\n\n")
subclasses = [s for s in structs.values() if s.base is struct]
if subclasses:
fw("subclasses --- \n")
fw(", ".join([(":class:`%s`" % s.identifier) for s in subclasses]))
fw("\n\n")
if struct.base:
fw(".. class:: %s(%s)\n\n" % (struct.identifier, struct.base.identifier))
else:
fw(".. class:: %s\n\n" % struct.identifier)
fw(" %s\n\n" % struct.description)
for prop in struct.properties:
fw(" .. attribute:: %s\n\n" % prop.identifier)
if prop.description:
fw(" %s\n\n" % prop.description)
type_descr = prop.get_type_description(as_arg=False, class_fmt=":class:`%s`")
fw(" *type* %s\n\n" % type_descr)
# python attributes
py_properties = struct.get_py_properties()
py_prop = None
for identifier, py_prop in py_properties:
fw(" .. attribute:: %s\n\n" % identifier)
write_indented_lines(" ", fw, py_prop.__doc__)
if py_prop.fset is None:
fw(" (readonly)\n\n")
del py_properties, py_prop
for func in struct.functions:
args_str = ", ".join([prop.get_arg_default(force=False) for prop in func.args])
fw(" .. method:: %s(%s)\n\n" % (func.identifier, args_str))
fw(" %s\n\n" % func.description)
for prop in func.args:
write_param(" ", fw, prop)
if len(func.return_values) == 1:
write_param(" ", fw, func.return_values[0], is_return=True)
else: # multiple return values
fw(" :return (%s):\n" % ", ".join([prop.identifier for prop in func.return_values]))
for prop in func.return_values:
type_descr = prop.get_type_description(as_arg=True, class_fmt=":class:`%s`")
descr = prop.description
if not descr:
descr = prop.name
fw(" `%s`, %s, %s\n\n" % (prop.identifier, descr, type_descr))
fw("\n")
# python methods
py_funcs = struct.get_py_functions()
py_func = None
for identifier, py_func in py_funcs:
arg_str = inspect.formatargspec(*inspect.getargspec(py_func))
if arg_str.startswith("(self, "):
arg_str = "(" + arg_str[7:]
func_type = "method"
elif arg_str.startswith("(cls, "):
arg_str = "(" + arg_str[6:]
func_type = "classmethod"
else:
func_type = "staticmethod"
fw(" .. %s:: %s%s\n\n" % (func_type, identifier, arg_str))
if py_func.__doc__:
write_indented_lines(" ", fw, py_func.__doc__)
fw("\n")
del py_funcs, py_func
if struct.references:
# use this otherwise it gets in the index for a normal heading.
fw(".. rubric:: References\n\n")
for ref in struct.references:
ref_split = ref.split(".")
if len(ref_split) > 2:
ref = ref_split[-2] + "." + ref_split[-1]
fw("* :class:`%s`\n" % ref)
fw("\n")
for struct in structs.values():
write_struct(struct)
# oeprators
def write_ops():
fw = None
last_mod = ''
for op_key in sorted(ops.keys()):
op = ops[op_key]
if last_mod != op.module_name:
filepath = os.path.join(BASEPATH, "bpy.ops.%s.rst" % op.module_name)
file = open(filepath, "w")
fw = file.write
title = "%s Operators" % (op.module_name[0].upper() + op.module_name[1:])
fw("%s\n%s\n\n" % (title, "=" * len(title)))
fw(".. module:: bpy.ops.%s\n\n" % op.module_name)
last_mod = op.module_name
args_str = ", ".join([prop.get_arg_default(force=True) for prop in op.args])
fw(".. function:: %s(%s)\n\n" % (op.func_name, args_str))
if op.description:
fw(" %s\n\n" % op.description)
for prop in op.args:
write_param(" ", fw, prop)
if op.args:
fw("\n")
location = op.get_location()
if location != (None, None):
fw(" *python operator source --- `%s:%d`* \n\n" % location)
write_ops()
file.close()
if __name__ == '__main__':
if 'bpy' not in dir():
print("\nError, this script must run from inside blender2.5")
print(script_help_msg)
else:
# os.system("rm source/blender/python/doc/sphinx-in/*.rst")
# os.system("rm -rf source/blender/python/doc/sphinx-out/*")
rna2sphinx('source/blender/python/doc/sphinx-in')
import sys
sys.exit()