Merged changes in the trunk up to revision 26260.
This commit is contained in:
1779
source/blender/python/doc/epy/BGL.py
Normal file
1779
source/blender/python/doc/epy/BGL.py
Normal file
@@ -0,0 +1,1779 @@
|
||||
# Blender.BGL module (OpenGL wrapper)
|
||||
|
||||
"""
|
||||
The Blender.BGL submodule (the OpenGL wrapper).
|
||||
|
||||
B{New}: some GLU functions: L{gluLookAt}, etc.
|
||||
|
||||
The Blender.BGL submodule
|
||||
=========================
|
||||
(when accessing it from the Game Engine use BGL instead of Blender.BGL)
|
||||
|
||||
This module wraps OpenGL constants and functions, making them available from
|
||||
within Blender Python.
|
||||
|
||||
The complete list can be retrieved from the module itself, by listing its
|
||||
contents: dir(Blender.BGL). A simple search on the net can point to more
|
||||
than enough material to teach OpenGL programming, from books to many
|
||||
collections of tutorials.
|
||||
|
||||
The "red book": "I{OpenGL Programming Guide: The Official Guide to Learning
|
||||
OpenGL}" and the online NeHe tutorials are two of the best resources.
|
||||
|
||||
Example::
|
||||
import Blender
|
||||
from Blender.BGL import *
|
||||
from Blender import Draw
|
||||
R = G = B = 0
|
||||
A = 1
|
||||
title = "Testing BGL + Draw"
|
||||
instructions = "Use mouse buttons or wheel to change the background color."
|
||||
quitting = " Press ESC or q to quit."
|
||||
len1 = Draw.GetStringWidth(title)
|
||||
len2 = Draw.GetStringWidth(instructions + quitting)
|
||||
#
|
||||
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(0.35,0.18,0.92) # define default color
|
||||
glBegin(GL_POLYGON) # begin a vertex data list
|
||||
glVertex2i(165, 158)
|
||||
glVertex2i(252, 55)
|
||||
glVertex2i(104, 128)
|
||||
glEnd()
|
||||
glColor3f(0.4,0.4,0.4) # change default color
|
||||
glRecti(40, 96, 60+len1, 113)
|
||||
glColor3f(1,1,1)
|
||||
glRasterPos2i(50,100) # move cursor to x = 50, y = 100
|
||||
Draw.Text(title) # draw this text there
|
||||
glRasterPos2i(350,40) # 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
|
||||
#
|
||||
def ev(evt, val): # event 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 not val: return
|
||||
elif evt == Draw.LEFTMOUSE: R = 1 - R
|
||||
elif evt == Draw.MIDDLEMOUSE: G = 1 - G
|
||||
elif evt == Draw.RIGHTMOUSE: B = 1 - B
|
||||
elif evt == Draw.WHEELUPMOUSE:
|
||||
R += 0.1
|
||||
if R > 1: R = 1
|
||||
elif evt == Draw.WHEELDOWNMOUSE:
|
||||
R -= 0.1
|
||||
if R < 0: R = 0
|
||||
else:
|
||||
return # don't redraw if nothing changed
|
||||
Draw.Redraw(1) # make changes visible.
|
||||
#
|
||||
Draw.Register(show_win, ev, None) # start the main loop
|
||||
|
||||
@note: you can use the L{Image} module and L{Image.Image} BPy object to load
|
||||
and set textures. See L{Image.Image.glLoad} and L{Image.Image.glFree},
|
||||
for example.
|
||||
@see: U{www.opengl.org}
|
||||
@see: U{nehe.gamedev.net}
|
||||
"""
|
||||
|
||||
def glAccum(op, value):
|
||||
"""
|
||||
Operate on the accumulation buffer
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/accum.html}
|
||||
|
||||
@type op: Enumerated constant
|
||||
@param op: The accumulation buffer operation.
|
||||
@type value: float
|
||||
@param value: a value used in the accumulation buffer operation.
|
||||
"""
|
||||
|
||||
def glAlphaFunc(func, ref):
|
||||
"""
|
||||
Specify the alpha test function
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/alphafunc.html}
|
||||
|
||||
@type func: Enumerated constant
|
||||
@param func: Specifies the alpha comparison function.
|
||||
@type ref: float
|
||||
@param ref: The reference value that incoming alpha values are compared to.
|
||||
Clamped between 0 and 1.
|
||||
"""
|
||||
|
||||
def glAreTexturesResident(n, textures, residences):
|
||||
"""
|
||||
Determine if textures are loaded in texture memory
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/aretexturesresident.html}
|
||||
|
||||
@type n: int
|
||||
@param n: Specifies the number of textures to be queried.
|
||||
@type textures: Buffer object I{type GL_INT}
|
||||
@param textures: Specifies an array containing the names of the textures to be queried
|
||||
@type residences: Buffer object I{type GL_INT}(boolean)
|
||||
@param residences: An array in which the texture residence status in returned.The residence status of a
|
||||
texture named by an element of textures is returned in the corresponding element of residences.
|
||||
"""
|
||||
|
||||
def glBegin(mode):
|
||||
"""
|
||||
Delimit the vertices of a primitive or a group of like primatives
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/begin.html}
|
||||
|
||||
@type mode: Enumerated constant
|
||||
@param mode: Specifies the primitive that will be create from vertices between glBegin and
|
||||
glEnd.
|
||||
"""
|
||||
|
||||
def glBindTexture(target, texture):
|
||||
"""
|
||||
Bind a named texture to a texturing target
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/bindtexture.html}
|
||||
|
||||
@type target: Enumerated constant
|
||||
@param target: Specifies the target to which the texture is bound.
|
||||
@type texture: unsigned int
|
||||
@param texture: Specifies the name of a texture.
|
||||
"""
|
||||
|
||||
def glBitmap(width, height, xorig, yorig, xmove, ymove, bitmap):
|
||||
"""
|
||||
Draw a bitmap
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/bitmap.html}
|
||||
|
||||
@type width, height: int
|
||||
@param width, height: Specify the pixel width and height of the bitmap image.
|
||||
@type xorig, yorig: float
|
||||
@param xorig, yorig: Specify the location of the origin in the bitmap image. The origin is measured
|
||||
from the lower left corner of the bitmap, with right and up being the positive axes.
|
||||
@type xmove, ymove: float
|
||||
@param xmove, ymove: Specify the x and y offsets to be added to the current raster position after
|
||||
the bitmap is drawn.
|
||||
@type bitmap: Buffer object I{type GL_BYTE}
|
||||
@param bitmap: Specifies the address of the bitmap image.
|
||||
"""
|
||||
|
||||
def glBlendFunc(sfactor, dfactor):
|
||||
"""
|
||||
Specify pixel arithmetic
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/blendfunc.html}
|
||||
|
||||
@type sfactor: Enumerated constant
|
||||
@param sfactor: Specifies how the red, green, blue, and alpha source blending factors are
|
||||
computed.
|
||||
@type dfactor: Enumerated constant
|
||||
@param dfactor: Specifies how the red, green, blue, and alpha destination blending factors are
|
||||
computed.
|
||||
"""
|
||||
|
||||
def glCallList(list):
|
||||
"""
|
||||
Execute a display list
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/calllist.html}
|
||||
|
||||
@type list: unsigned int
|
||||
@param list: Specifies the integer name of the display list to be executed.
|
||||
"""
|
||||
|
||||
def glCallLists(n, type, lists):
|
||||
"""
|
||||
Execute a list of display lists
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/calllists.html}
|
||||
|
||||
@type n: int
|
||||
@param n: Specifies the number of display lists to be executed.
|
||||
@type type: Enumerated constant
|
||||
@param type: Specifies the type of values in lists.
|
||||
@type lists: Buffer object
|
||||
@param lists: Specifies the address of an array of name offsets in the display list.
|
||||
The pointer type is void because the offsets can be bytes, shorts, ints, or floats,
|
||||
depending on the value of type.
|
||||
"""
|
||||
|
||||
def glClear(mask):
|
||||
"""
|
||||
Clear buffers to preset values
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/clear.html}
|
||||
|
||||
@type mask: Enumerated constant(s)
|
||||
@param mask: Bitwise OR of masks that indicate the buffers to be cleared.
|
||||
"""
|
||||
|
||||
def glClearAccum(red, green, blue, alpha):
|
||||
"""
|
||||
Specify clear values for the accumulation buffer
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/clearaccum.html}
|
||||
|
||||
@type red, green, blue, alpha: float
|
||||
@param red, green, blue, alpha: Specify the red, green, blue, and alpha values used when the
|
||||
accumulation buffer is cleared. The initial values are all 0.
|
||||
"""
|
||||
|
||||
def glClearColor(red, green, blue, alpha):
|
||||
"""
|
||||
Specify clear values for the color buffers
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/clearcolor.html}
|
||||
|
||||
@type red, green, blue, alpha: float
|
||||
@param red, green, blue, alpha: Specify the red, green, blue, and alpha values used when the
|
||||
color buffers are cleared. The initial values are all 0.
|
||||
"""
|
||||
|
||||
def glClearDepth(depth):
|
||||
"""
|
||||
Specify the clear value for the depth buffer
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/cleardepth.html}
|
||||
|
||||
@type depth: int
|
||||
@param depth: Specifies the depth value used when the depth buffer is cleared.
|
||||
The initial value is 1.
|
||||
"""
|
||||
|
||||
def glClearIndex(c):
|
||||
"""
|
||||
Specify the clear value for the color index buffers
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/clearindex.html}
|
||||
|
||||
@type c: float
|
||||
@param c: Specifies the index used when the color index buffers are cleared.
|
||||
The initial value is 0.
|
||||
"""
|
||||
|
||||
def glClearStencil(s):
|
||||
"""
|
||||
Specify the clear value for the stencil buffer
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/clearstencil.html}
|
||||
|
||||
@type s: int
|
||||
@param s: Specifies the index used when the stencil buffer is cleared. The initial value is 0.
|
||||
"""
|
||||
|
||||
def glClipPlane (plane, equation):
|
||||
"""
|
||||
Specify a plane against which all geometry is clipped
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/clipplane.html}
|
||||
|
||||
@type plane: Enumerated constant
|
||||
@param plane: Specifies which clipping plane is being positioned.
|
||||
@type equation: Buffer object I{type GL_FLOAT}(double)
|
||||
@param equation: Specifies the address of an array of four double- precision floating-point
|
||||
values. These values are interpreted as a plane equation.
|
||||
"""
|
||||
|
||||
def glColor (red, green, blue, alpha):
|
||||
"""
|
||||
B{glColor3b, glColor3d, glColor3f, glColor3i, glColor3s, glColor3ub, glColor3ui, glColor3us,
|
||||
glColor4b, glColor4d, glColor4f, glColor4i, glColor4s, glColor4ub, glColor4ui, glColor4us,
|
||||
glColor3bv, glColor3dv, glColor3fv, glColor3iv, glColor3sv, glColor3ubv, glColor3uiv,
|
||||
glColor3usv, glColor4bv, glColor4dv, glColor4fv, glColor4iv, glColor4sv, glColor4ubv,
|
||||
glColor4uiv, glColor4usv}
|
||||
|
||||
Set a new color.
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/color.html}
|
||||
|
||||
@type red, green, blue, alpha: Depends on function prototype.
|
||||
@param red, green, blue: Specify new red, green, and blue values for the current color.
|
||||
@param alpha: Specifies a new alpha value for the current color. Included only in the
|
||||
four-argument glColor4 commands. (With '4' colors only)
|
||||
"""
|
||||
|
||||
def glColorMask(red, green, blue, alpha):
|
||||
"""
|
||||
Enable and disable writing of frame buffer color components
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/colormask.html}
|
||||
|
||||
@type red, green, blue, alpha: int (boolean)
|
||||
@param red, green, blue, alpha: Specify whether red, green, blue, and alpha can or cannot be
|
||||
written into the frame buffer. The initial values are all GL_TRUE, indicating that the
|
||||
color components can be written.
|
||||
"""
|
||||
|
||||
def glColorMaterial(face, mode):
|
||||
"""
|
||||
Cause a material color to track the current color
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/colormaterial.html}
|
||||
|
||||
@type face: Enumerated constant
|
||||
@param face: Specifies whether front, back, or both front and back material parameters should
|
||||
track the current color.
|
||||
@type mode: Enumerated constant
|
||||
@param mode: Specifies which of several material parameters track the current color.
|
||||
"""
|
||||
|
||||
def glCopyPixels(x, y, width, height, type):
|
||||
"""
|
||||
Copy pixels in the frame buffer
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/copypixels.html}
|
||||
|
||||
@type x, y: int
|
||||
@param x, y: Specify the window coordinates of the lower left corner of the rectangular
|
||||
region of pixels to be copied.
|
||||
@type width, height: int
|
||||
@param width,height: Specify the dimensions of the rectangular region of pixels to be copied.
|
||||
Both must be non-negative.
|
||||
@type type: Enumerated constant
|
||||
@param type: Specifies whether color values, depth values, or stencil values are to be copied.
|
||||
"""
|
||||
|
||||
def glCullFace(mode):
|
||||
"""
|
||||
Specify whether front- or back-facing facets can be culled
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/cullface.html}
|
||||
|
||||
@type mode: Enumerated constant
|
||||
@param mode: Specifies whether front- or back-facing facets are candidates for culling.
|
||||
"""
|
||||
|
||||
def glDeleteLists(list, range):
|
||||
"""
|
||||
Delete a contiguous group of display lists
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/deletelists.html}
|
||||
|
||||
@type list: unsigned int
|
||||
@param list: Specifies the integer name of the first display list to delete
|
||||
@type range: int
|
||||
@param range: Specifies the number of display lists to delete
|
||||
"""
|
||||
|
||||
def glDeleteTextures(n, textures):
|
||||
"""
|
||||
Delete named textures
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/deletetextures.html}
|
||||
|
||||
@type n: int
|
||||
@param n: Specifies the number of textures to be deleted
|
||||
@type textures: Buffer I{GL_INT}
|
||||
@param textures: Specifies an array of textures to be deleted
|
||||
"""
|
||||
|
||||
def glDepthFunc(func):
|
||||
"""
|
||||
Specify the value used for depth buffer comparisons
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/depthfunc.html}
|
||||
|
||||
@type func: Enumerated constant
|
||||
@param func: Specifies the depth comparison function.
|
||||
"""
|
||||
|
||||
def glDepthMask(flag):
|
||||
"""
|
||||
Enable or disable writing into the depth buffer
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/depthmask.html}
|
||||
|
||||
@type flag: int (boolean)
|
||||
@param flag: Specifies whether the depth buffer is enabled for writing. If flag is GL_FALSE,
|
||||
depth buffer writing is disabled. Otherwise, it is enabled. Initially, depth buffer
|
||||
writing is enabled.
|
||||
"""
|
||||
|
||||
def glDepthRange(zNear, zFar):
|
||||
"""
|
||||
Specify mapping of depth values from normalized device coordinates to window coordinates
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/depthrange.html}
|
||||
|
||||
@type zNear: int
|
||||
@param zNear: Specifies the mapping of the near clipping plane to window coordinates.
|
||||
The initial value is 0.
|
||||
@type zFar: int
|
||||
@param zFar: Specifies the mapping of the far clipping plane to window coordinates.
|
||||
The initial value is 1.
|
||||
"""
|
||||
|
||||
def glDisable(cap):
|
||||
"""
|
||||
Disable server-side GL capabilities
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/enable.html}
|
||||
|
||||
@type cap: Enumerated constant
|
||||
@param cap: Specifies a symbolic constant indicating a GL capability.
|
||||
"""
|
||||
|
||||
def glDrawBuffer(mode):
|
||||
"""
|
||||
Specify which color buffers are to be drawn into
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/drawbuffer.html}
|
||||
|
||||
@type mode: Enumerated constant
|
||||
@param mode: Specifies up to four color buffers to be drawn into.
|
||||
"""
|
||||
|
||||
def glDrawPixels(width, height, format, type, pixels):
|
||||
"""
|
||||
Write a block of pixels to the frame buffer
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/drawpixels.html}
|
||||
|
||||
@type width, height: int
|
||||
@param width, height: Specify the dimensions of the pixel rectangle to be
|
||||
written into the frame buffer.
|
||||
@type format: Enumerated constant
|
||||
@param format: Specifies the format of the pixel data.
|
||||
@type type: Enumerated constant
|
||||
@param type: Specifies the data type for pixels.
|
||||
@type pixels: Buffer object
|
||||
@param pixels: Specifies a pointer to the pixel data.
|
||||
"""
|
||||
|
||||
def glEdgeFlag (flag):
|
||||
"""
|
||||
B{glEdgeFlag, glEdgeFlagv}
|
||||
|
||||
Flag edges as either boundary or non-boundary
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/edgeflag.html}
|
||||
|
||||
@type flag: Depends of function prototype
|
||||
@param flag: Specifies the current edge flag value.The initial value is GL_TRUE.
|
||||
"""
|
||||
|
||||
def glEnable(cap):
|
||||
"""
|
||||
Enable server-side GL capabilities
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/enable.html}
|
||||
|
||||
@type cap: Enumerated constant
|
||||
@param cap: Specifies a symbolic constant indicating a GL capability.
|
||||
"""
|
||||
|
||||
def glEnd():
|
||||
"""
|
||||
Delimit the vertices of a primitive or group of like primitives
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/begin.html}
|
||||
"""
|
||||
|
||||
def glEndList():
|
||||
"""
|
||||
Create or replace a display list
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/newlist.html}
|
||||
"""
|
||||
|
||||
def glEvalCoord (u,v):
|
||||
"""
|
||||
B{glEvalCoord1d, glEvalCoord1f, glEvalCoord2d, glEvalCoord2f, glEvalCoord1dv, glEvalCoord1fv,
|
||||
glEvalCoord2dv, glEvalCoord2fv}
|
||||
|
||||
Evaluate enabled one- and two-dimensional maps
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/evalcoord.html}
|
||||
|
||||
@type u: Depends on function prototype.
|
||||
@param u: Specifies a value that is the domain coordinate u to the basis function defined
|
||||
in a previous glMap1 or glMap2 command. If the function prototype ends in 'v' then
|
||||
u specifies a pointer to an array containing either one or two domain coordinates. The first
|
||||
coordinate is u. The second coordinate is v, which is present only in glEvalCoord2 versions.
|
||||
@type v: Depends on function prototype. (only with '2' prototypes)
|
||||
@param v: Specifies a value that is the domain coordinate v to the basis function defined
|
||||
in a previous glMap2 command. This argument is not present in a glEvalCoord1 command.
|
||||
"""
|
||||
|
||||
def glEvalMesh (mode, i1, i2):
|
||||
"""
|
||||
B{glEvalMesh1 or glEvalMesh2}
|
||||
|
||||
Compute a one- or two-dimensional grid of points or lines
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/evalmesh.html}
|
||||
|
||||
@type mode: Enumerated constant
|
||||
@param mode: In glEvalMesh1, specifies whether to compute a one-dimensional
|
||||
mesh of points or lines.
|
||||
@type i1, i2: int
|
||||
@param i1, i2: Specify the first and last integer values for the grid domain variable i.
|
||||
"""
|
||||
|
||||
def glEvalPoint (i, j):
|
||||
"""
|
||||
B{glEvalPoint1 and glEvalPoint2}
|
||||
|
||||
Generate and evaluate a single point in a mesh
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/evalpoint.html}
|
||||
|
||||
@type i: int
|
||||
@param i: Specifies the integer value for grid domain variable i.
|
||||
@type j: int (only with '2' prototypes)
|
||||
@param j: Specifies the integer value for grid domain variable j (glEvalPoint2 only).
|
||||
"""
|
||||
|
||||
def glFeedbackBuffer (size, type, buffer):
|
||||
"""
|
||||
Controls feedback mode
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/feedbackbuffer.html}
|
||||
|
||||
@type size: int
|
||||
@param size:Specifies the maximum number of values that can be written into buffer.
|
||||
@type type: Enumerated constant
|
||||
@param type:Specifies a symbolic constant that describes the information that
|
||||
will be returned for each vertex.
|
||||
@type buffer: Buffer object I{GL_FLOAT}
|
||||
@param buffer: Returns the feedback data.
|
||||
"""
|
||||
|
||||
def glFinish():
|
||||
"""
|
||||
Block until all GL execution is complete
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/finish.html}
|
||||
"""
|
||||
|
||||
def glFlush():
|
||||
"""
|
||||
Force Execution of GL commands in finite time
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/flush.html}
|
||||
"""
|
||||
|
||||
def glFog (pname, param):
|
||||
"""
|
||||
B{glFogf, glFogi, glFogfv, glFogiv}
|
||||
|
||||
Specify fog parameters
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/fog.html}
|
||||
|
||||
@type pname: Enumerated constant
|
||||
@param pname: Specifies a single-valued fog parameter. If the function prototype
|
||||
ends in 'v' specifies a fog parameter.
|
||||
@type param: Depends on function prototype.
|
||||
@param param: Specifies the value or values to be assigned to pname. GL_FOG_COLOR
|
||||
requires an array of four values. All other parameters accept an array containing
|
||||
only a single value.
|
||||
"""
|
||||
|
||||
def glFrontFace(mode):
|
||||
"""
|
||||
Define front- and back-facing polygons
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/frontface.html}
|
||||
|
||||
@type mode: Enumerated constant
|
||||
@param mode: Specifies the orientation of front-facing polygons.
|
||||
"""
|
||||
|
||||
def glFrustum(left, right, bottom, top, zNear, zFar):
|
||||
"""
|
||||
Multiply the current matrix by a perspective matrix
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/frustum.html}
|
||||
|
||||
@type left, right: double (float)
|
||||
@param left, right: Specify the coordinates for the left and right vertical
|
||||
clipping planes.
|
||||
@type top, bottom: double (float)
|
||||
@param top, bottom: Specify the coordinates for the bottom and top horizontal
|
||||
clipping planes.
|
||||
@type zNear, zFar: double (float)
|
||||
@param zNear, zFar: Specify the distances to the near and far depth clipping planes.
|
||||
Both distances must be positive.
|
||||
"""
|
||||
|
||||
def glGenLists(range):
|
||||
"""
|
||||
Generate a contiguous set of empty display lists
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/genlists.html}
|
||||
|
||||
@type range: int
|
||||
@param range: Specifies the number of contiguous empty display lists to be generated.
|
||||
"""
|
||||
|
||||
def glGenTextures(n, textures):
|
||||
"""
|
||||
Generate texture names
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/gentextures.html}
|
||||
|
||||
@type n: int
|
||||
@param n: Specifies the number of textures name to be generated.
|
||||
@type textures: Buffer object I{type GL_INT}
|
||||
@param textures: Specifies an array in which the generated textures names are stored.
|
||||
"""
|
||||
|
||||
def glGet (pname, param):
|
||||
"""
|
||||
B{glGetBooleanv, glGetfloatv, glGetFloatv, glGetIntegerv}
|
||||
|
||||
Return the value or values of a selected parameter
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/get.html}
|
||||
|
||||
@type pname: Enumerated constant
|
||||
@param pname: Specifies the parameter value to be returned.
|
||||
@type param: Depends on function prototype.
|
||||
@param param: Returns the value or values of the specified parameter.
|
||||
"""
|
||||
|
||||
def glGetClipPlane(plane, equation):
|
||||
"""
|
||||
Return the coefficients of the specified clipping plane
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/getclipplane.html}
|
||||
|
||||
@type plane: Enumerated constant
|
||||
@param plane: Specifies a clipping plane. The number of clipping planes depends on the
|
||||
implementation, but at least six clipping planes are supported. They are identified by
|
||||
symbolic names of the form GL_CLIP_PLANEi where 0 < i < GL_MAX_CLIP_PLANES.
|
||||
@type equation: Buffer object I{type GL_FLOAT}
|
||||
@param equation: Returns four float (double)-precision values that are the coefficients of the
|
||||
plane equation of plane in eye coordinates. The initial value is (0, 0, 0, 0).
|
||||
"""
|
||||
|
||||
def glGetError():
|
||||
"""
|
||||
Return error information
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/geterror.html}
|
||||
"""
|
||||
|
||||
def glGetLight (light, pname, params):
|
||||
"""
|
||||
B{glGetLightfv and glGetLightiv}
|
||||
|
||||
Return light source parameter values
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/getlight.html}
|
||||
|
||||
@type light: Enumerated constant
|
||||
@param light: Specifies a light source. The number of possible lights depends on the
|
||||
implementation, but at least eight lights are supported. They are identified by symbolic
|
||||
names of the form GL_LIGHTi where 0 < i < GL_MAX_LIGHTS.
|
||||
@type pname: Enumerated constant
|
||||
@param pname: Specifies a light source parameter for light.
|
||||
@type params: Buffer object. Depends on function prototype.
|
||||
@param params: Returns the requested data.
|
||||
"""
|
||||
|
||||
def glGetMap (target, query, v):
|
||||
"""
|
||||
B{glGetMapdv, glGetMapfv, glGetMapiv}
|
||||
|
||||
Return evaluator parameters
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/getmap.html}
|
||||
|
||||
@type target: Enumerated constant
|
||||
@param target: Specifies the symbolic name of a map.
|
||||
@type query: Enumerated constant
|
||||
@param query: Specifies which parameter to return.
|
||||
@type v: Buffer object. Depends on function prototype.
|
||||
@param v: Returns the requested data.
|
||||
"""
|
||||
|
||||
def glGetMaterial (face, pname, params):
|
||||
"""
|
||||
B{glGetMaterialfv, glGetMaterialiv}
|
||||
|
||||
Return material parameters
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/getmaterial.html}
|
||||
|
||||
@type face: Enumerated constant
|
||||
@param face: Specifies which of the two materials is being queried.
|
||||
representing the front and back materials, respectively.
|
||||
@type pname: Enumerated constant
|
||||
@param pname: Specifies the material parameter to return.
|
||||
@type params: Buffer object. Depends on function prototype.
|
||||
@param params: Returns the requested data.
|
||||
"""
|
||||
|
||||
def glGetPixelMap (map, values):
|
||||
"""
|
||||
B{glGetPixelMapfv, glGetPixelMapuiv, glGetPixelMapusv}
|
||||
|
||||
Return the specified pixel map
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/getpixelmap.html}
|
||||
|
||||
@type map: Enumerated constant
|
||||
@param map: Specifies the name of the pixel map to return.
|
||||
@type values: Buffer object. Depends on function prototype.
|
||||
@param values: Returns the pixel map contents.
|
||||
"""
|
||||
|
||||
def glGetPolygonStipple(mask):
|
||||
"""
|
||||
Return the polygon stipple pattern
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/getpolygonstipple.html}
|
||||
|
||||
@type mask: Buffer object I{type GL_BYTE}
|
||||
@param mask: Returns the stipple pattern. The initial value is all 1's.
|
||||
"""
|
||||
|
||||
def glGetString(name):
|
||||
"""
|
||||
Return a string describing the current GL connection
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/getstring.html}
|
||||
|
||||
@type name: Enumerated constant
|
||||
@param name: Specifies a symbolic constant.
|
||||
|
||||
"""
|
||||
|
||||
def glGetTexEnv (target, pname, params):
|
||||
"""
|
||||
B{glGetTexEnvfv, glGetTexEnviv}
|
||||
|
||||
Return texture environment parameters
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/gettexenv.html}
|
||||
|
||||
@type target: Enumerated constant
|
||||
@param target: Specifies a texture environment. Must be GL_TEXTURE_ENV.
|
||||
@type pname: Enumerated constant
|
||||
@param pname: Specifies the symbolic name of a texture environment parameter.
|
||||
@type params: Buffer object. Depends on function prototype.
|
||||
@param params: Returns the requested data.
|
||||
"""
|
||||
|
||||
def glGetTexGen (coord, pname, params):
|
||||
"""
|
||||
B{glGetTexGendv, glGetTexGenfv, glGetTexGeniv}
|
||||
|
||||
Return texture coordinate generation parameters
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/gettexgen.html}
|
||||
|
||||
@type coord: Enumerated constant
|
||||
@param coord: Specifies a texture coordinate.
|
||||
@type pname: Enumerated constant
|
||||
@param pname: Specifies the symbolic name of the value(s) to be returned.
|
||||
@type params: Buffer object. Depends on function prototype.
|
||||
@param params: Returns the requested data.
|
||||
"""
|
||||
|
||||
def glGetTexImage(target, level, format, type, pixels):
|
||||
"""
|
||||
Return a texture image
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/getteximage.html}
|
||||
|
||||
@type target: Enumerated constant
|
||||
@param target: Specifies which texture is to be obtained.
|
||||
@type level: int
|
||||
@param level: Specifies the level-of-detail number of the desired image.
|
||||
Level 0 is the base image level. Level n is the nth mipmap reduction image.
|
||||
@type format: Enumerated constant
|
||||
@param format: Specifies a pixel format for the returned data.
|
||||
@type type: Enumerated constant
|
||||
@param type: Specifies a pixel type for the returned data.
|
||||
@type pixels: Buffer object.
|
||||
@param pixels: Returns the texture image. Should be a pointer to an array of the
|
||||
type specified by type
|
||||
"""
|
||||
|
||||
def glGetTexLevelParameter (target, level, pname, params):
|
||||
"""
|
||||
B{glGetTexLevelParameterfv, glGetTexLevelParameteriv}
|
||||
|
||||
return texture parameter values for a specific level of detail
|
||||
@see: U{opengl.org/developers/documentation/man_pages/hardcopy/GL/html/gl/gettexlevelparameter.html}
|
||||
|
||||
@type target: Enumerated constant
|
||||
@param target: Specifies the symbolic name of the target texture.
|
||||
@type level: int
|
||||
@param level: Specifies the level-of-detail number of the desired image.
|
||||
Level 0 is the base image level. Level n is the nth mipmap reduction image.
|
||||
@type pname: Enumerated constant
|
||||
@param pname: Specifies the symbolic name of a texture parameter.
|
||||
@type params: Buffer object. Depends on function prototype.
|
||||
@param params: Returns the requested data.
|
||||
"""
|
||||
|
||||
def glGetTexParameter (target, pname, params):
|
||||
"""
|
||||
B{glGetTexParameterfv, glGetTexParameteriv}
|
||||
|
||||
Return texture parameter values
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/gettexparameter.html}
|
||||
|
||||
@type target: Enumerated constant
|
||||
@param target: Specifies the symbolic name of the target texture.
|
||||
@type pname: Enumerated constant
|
||||
@param pname: Specifies the symbolic name the target texture.
|
||||
@type params: Buffer object. Depends on function prototype.
|
||||
@param params: Returns the texture parameters.
|
||||
"""
|
||||
|
||||
def glHint(target, mode):
|
||||
"""
|
||||
Specify implementation-specific hints
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/hint.html}
|
||||
|
||||
@type target: Enumerated constant
|
||||
@param target: Specifies a symbolic constant indicating the behavior to be
|
||||
controlled.
|
||||
@type mode: Enumerated constant
|
||||
@param mode: Specifies a symbolic constant indicating the desired behavior.
|
||||
"""
|
||||
|
||||
def glIndex (c):
|
||||
"""
|
||||
B{glIndexd, glIndexf, glIndexi, glIndexs, glIndexdv, glIndexfv, glIndexiv, glIndexsv}
|
||||
|
||||
Set the current color index
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/index_.html}
|
||||
|
||||
@type c: Buffer object. Depends on function prototype.
|
||||
@param c: Specifies a pointer to a one element array that contains the new value for
|
||||
the current color index.
|
||||
"""
|
||||
|
||||
def glInitNames():
|
||||
"""
|
||||
Initialize the name stack
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/initnames.html}
|
||||
"""
|
||||
|
||||
def glIsEnabled(cap):
|
||||
"""
|
||||
Test whether a capability is enabled
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/isenabled.html}
|
||||
|
||||
@type cap: Enumerated constant
|
||||
@param cap: Specifies a constant representing a GL capability.
|
||||
"""
|
||||
|
||||
def glIsList(list):
|
||||
"""
|
||||
Determine if a name corresponds to a display-list
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/islist.html}
|
||||
|
||||
@type list: unsigned int
|
||||
@param list: Specifies a potential display-list name.
|
||||
"""
|
||||
|
||||
def glIsTexture(texture):
|
||||
"""
|
||||
Determine if a name corresponds to a texture
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/istexture.html}
|
||||
|
||||
@type texture: unsigned int
|
||||
@param texture: Specifies a value that may be the name of a texture.
|
||||
"""
|
||||
|
||||
def glLight (light, pname, param):
|
||||
"""
|
||||
B{glLightf,glLighti, glLightfv, glLightiv}
|
||||
|
||||
Set the light source parameters
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/light.html}
|
||||
|
||||
@type light: Enumerated constant
|
||||
@param light: Specifies a light. The number of lights depends on the implementation,
|
||||
but at least eight lights are supported. They are identified by symbolic names of the
|
||||
form GL_LIGHTi where 0 < i < GL_MAX_LIGHTS.
|
||||
@type pname: Enumerated constant
|
||||
@param pname: Specifies a single-valued light source parameter for light.
|
||||
@type param: Depends on function prototype.
|
||||
@param param: Specifies the value that parameter pname of light source light will be set to.
|
||||
If function prototype ends in 'v' specifies a pointer to the value or values that
|
||||
parameter pname of light source light will be set to.
|
||||
"""
|
||||
|
||||
def glLightModel (pname, param):
|
||||
"""
|
||||
B{glLightModelf, glLightModeli, glLightModelfv, glLightModeliv}
|
||||
|
||||
Set the lighting model parameters
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/lightmodel.html}
|
||||
|
||||
@type pname: Enumerated constant
|
||||
@param pname: Specifies a single-value light model parameter.
|
||||
@type param: Depends on function prototype.
|
||||
@param param: Specifies the value that param will be set to. If function prototype ends in 'v'
|
||||
specifies a pointer to the value or values that param will be set to.
|
||||
"""
|
||||
|
||||
def glLineStipple(factor, pattern):
|
||||
"""
|
||||
Specify the line stipple pattern
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/linestipple.html}
|
||||
|
||||
@type factor: int
|
||||
@param factor: Specifies a multiplier for each bit in the line stipple pattern.
|
||||
If factor is 3, for example, each bit in the pattern is used three times before
|
||||
the next bit in the pattern is used. factor is clamped to the range [1, 256] and
|
||||
defaults to 1.
|
||||
@type pattern: unsigned short int
|
||||
@param pattern: Specifies a 16-bit integer whose bit pattern determines which fragments
|
||||
of a line will be drawn when the line is rasterized. Bit zero is used first; the default
|
||||
pattern is all 1's.
|
||||
"""
|
||||
|
||||
def glLineWidth(width):
|
||||
"""
|
||||
Specify the width of rasterized lines.
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/linewidth.html}
|
||||
|
||||
@type width: float
|
||||
@param width: Specifies the width of rasterized lines. The initial value is 1.
|
||||
"""
|
||||
|
||||
def glListBase(base):
|
||||
"""
|
||||
Set the display-list base for glCallLists
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/listbase.html}
|
||||
|
||||
@type base: unsigned int
|
||||
@param base: Specifies an integer offset that will be added to glCallLists
|
||||
offsets to generate display-list names. The initial value is 0.
|
||||
"""
|
||||
|
||||
def glLoadIdentity():
|
||||
"""
|
||||
Replace the current matrix with the identity matrix
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/loadidentity.html}
|
||||
"""
|
||||
|
||||
def glLoadMatrix (m):
|
||||
"""
|
||||
B{glLoadMatrixd, glLoadMatixf}
|
||||
|
||||
Replace the current matrix with the specified matrix
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/loadmatrix.html}
|
||||
|
||||
@type m: Buffer object. Depends on function prototype.
|
||||
@param m: Specifies a pointer to 16 consecutive values, which are used as the elements
|
||||
of a 4x4 column-major matrix.
|
||||
"""
|
||||
|
||||
def glLoadName(name):
|
||||
"""
|
||||
Load a name onto the name stack.
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/loadname.html}
|
||||
|
||||
@type name: unsigned int
|
||||
@param name: Specifies a name that will replace the top value on the name stack.
|
||||
"""
|
||||
|
||||
def glLogicOp(opcode):
|
||||
"""
|
||||
Specify a logical pixel operation for color index rendering
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/logicop.html}
|
||||
|
||||
@type opcode: Enumerated constant
|
||||
@param opcode: Specifies a symbolic constant that selects a logical operation.
|
||||
"""
|
||||
|
||||
def glMap1 (target, u1, u2, stride, order, points):
|
||||
"""
|
||||
B{glMap1d, glMap1f}
|
||||
|
||||
Define a one-dimensional evaluator
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/map1.html}
|
||||
|
||||
@type target: Enumerated constant
|
||||
@param target: Specifies the kind of values that are generated by the evaluator.
|
||||
@type u1, u2: Depends on function prototype.
|
||||
@param u1,u2: Specify a linear mapping of u, as presented to glEvalCoord1, to ^, t
|
||||
he variable that is evaluated by the equations specified by this command.
|
||||
@type stride: int
|
||||
@param stride: Specifies the number of floats or float (double)s between the beginning
|
||||
of one control point and the beginning of the next one in the data structure
|
||||
referenced in points. This allows control points to be embedded in arbitrary data
|
||||
structures. The only constraint is that the values for a particular control point must
|
||||
occupy contiguous memory locations.
|
||||
@type order: int
|
||||
@param order: Specifies the number of control points. Must be positive.
|
||||
@type points: Buffer object. Depends on function prototype.
|
||||
@param points: Specifies a pointer to the array of control points.
|
||||
"""
|
||||
|
||||
def glMap2 (target, u1, u2, ustride, uorder, v1, v2, vstride, vorder, points):
|
||||
"""
|
||||
B{glMap2d, glMap2f}
|
||||
|
||||
Define a two-dimensional evaluator
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/map2.html}
|
||||
|
||||
@type target: Enumerated constant
|
||||
@param target: Specifies the kind of values that are generated by the evaluator.
|
||||
@type u1, u2: Depends on function prototype.
|
||||
@param u1,u2: Specify a linear mapping of u, as presented to glEvalCoord2, to ^, t
|
||||
he variable that is evaluated by the equations specified by this command. Initially
|
||||
u1 is 0 and u2 is 1.
|
||||
@type ustride: int
|
||||
@param ustride: Specifies the number of floats or float (double)s between the beginning
|
||||
of control point R and the beginning of control point R ij, where i and j are the u
|
||||
and v control point indices, respectively. This allows control points to be embedded
|
||||
in arbitrary data structures. The only constraint is that the values for a particular
|
||||
control point must occupy contiguous memory locations. The initial value of ustride is 0.
|
||||
@type uorder: int
|
||||
@param uorder: Specifies the dimension of the control point array in the u axis.
|
||||
Must be positive. The initial value is 1.
|
||||
@type v1, v2: Depends on function prototype.
|
||||
@param v1, v2: Specify a linear mapping of v, as presented to glEvalCoord2, to ^,
|
||||
one of the two variables that are evaluated by the equations specified by this command.
|
||||
Initially, v1 is 0 and v2 is 1.
|
||||
@type vstride: int
|
||||
@param vstride: Specifies the number of floats or float (double)s between the beginning of control
|
||||
point R and the beginning of control point R ij, where i and j are the u and v control
|
||||
point(indices, respectively. This allows control points to be embedded in arbitrary data
|
||||
structures. The only constraint is that the values for a particular control point must
|
||||
occupy contiguous memory locations. The initial value of vstride is 0.
|
||||
@type vorder: int
|
||||
@param vorder: Specifies the dimension of the control point array in the v axis.
|
||||
Must be positive. The initial value is 1.
|
||||
@type points: Buffer object. Depends on function prototype.
|
||||
@param points: Specifies a pointer to the array of control points.
|
||||
"""
|
||||
|
||||
def glMapGrid (un, u1,u2 ,vn, v1, v2):
|
||||
"""
|
||||
B{glMapGrid1d, glMapGrid1f, glMapGrid2d, glMapGrid2f}
|
||||
|
||||
Define a one- or two-dimensional mesh
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/mapgrid.html}
|
||||
|
||||
@type un: int
|
||||
@param un: Specifies the number of partitions in the grid range interval
|
||||
[u1, u2]. Must be positive.
|
||||
@type u1, u2: Depends on function prototype.
|
||||
@param u1, u2: Specify the mappings for integer grid domain values i=0 and i=un.
|
||||
@type vn: int
|
||||
@param vn: Specifies the number of partitions in the grid range interval [v1, v2]
|
||||
(glMapGrid2 only).
|
||||
@type v1, v2: Depends on function prototype.
|
||||
@param v1, v2: Specify the mappings for integer grid domain values j=0 and j=vn
|
||||
(glMapGrid2 only).
|
||||
"""
|
||||
|
||||
def glMaterial (face, pname, params):
|
||||
"""
|
||||
Specify material parameters for the lighting model.
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/material.html}
|
||||
|
||||
@type face: Enumerated constant
|
||||
@param face: Specifies which face or faces are being updated. Must be one of:
|
||||
@type pname: Enumerated constant
|
||||
@param pname: Specifies the single-valued material parameter of the face
|
||||
or faces that is being updated. Must be GL_SHININESS.
|
||||
@type params: int
|
||||
@param params: Specifies the value that parameter GL_SHININESS will be set to.
|
||||
If function prototype ends in 'v' specifies a pointer to the value or values that
|
||||
pname will be set to.
|
||||
"""
|
||||
|
||||
def glMatrixMode(mode):
|
||||
"""
|
||||
Specify which matrix is the current matrix.
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/matrixmode.html}
|
||||
|
||||
@type mode: Enumerated constant
|
||||
@param mode: Specifies which matrix stack is the target for subsequent matrix operations.
|
||||
"""
|
||||
|
||||
def glMultMatrix (m):
|
||||
"""
|
||||
B{glMultMatrixd, glMultMatrixf}
|
||||
|
||||
Multiply the current matrix with the specified matrix
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/multmatrix.html}
|
||||
|
||||
@type m: Buffer object. Depends on function prototype.
|
||||
@param m: Points to 16 consecutive values that are used as the elements of a 4x4 column
|
||||
major matrix.
|
||||
"""
|
||||
|
||||
def glNewList(list, mode):
|
||||
"""
|
||||
Create or replace a display list
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/newlist.html}
|
||||
|
||||
@type list: unsigned int
|
||||
@param list: Specifies the display list name
|
||||
@type mode: Enumerated constant
|
||||
@param mode: Specifies the compilation mode.
|
||||
"""
|
||||
|
||||
def glNormal3 (nx, ny, nz, v):
|
||||
"""
|
||||
B{Normal3b, Normal3bv, Normal3d, Normal3dv, Normal3f, Normal3fv, Normal3i, Normal3iv,
|
||||
Normal3s, Normal3sv}
|
||||
|
||||
Set the current normal vector
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/normal.html}
|
||||
|
||||
@type nx, ny, nz: Depends on function prototype. (non - 'v' prototypes only)
|
||||
@param nx, ny, nz: Specify the x, y, and z coordinates of the new current normal.
|
||||
The initial value of the current normal is the unit vector, (0, 0, 1).
|
||||
@type v: Buffer object. Depends on function prototype. ('v' prototypes)
|
||||
@param v: Specifies a pointer to an array of three elements: the x, y, and z coordinates
|
||||
of the new current normal.
|
||||
"""
|
||||
|
||||
def glOrtho(left, right, bottom, top, zNear, zFar):
|
||||
"""
|
||||
Multiply the current matrix with an orthographic matrix
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/ortho.html}
|
||||
|
||||
@type left, right: double (float)
|
||||
@param left, right: Specify the coordinates for the left and
|
||||
right vertical clipping planes.
|
||||
@type bottom, top: double (float)
|
||||
@param bottom, top: Specify the coordinates for the bottom and top
|
||||
horizontal clipping planes.
|
||||
@type zNear, zFar: double (float)
|
||||
@param zNear, zFar: Specify the distances to the nearer and farther
|
||||
depth clipping planes. These values are negative if the plane is to be behind the viewer.
|
||||
"""
|
||||
|
||||
def glPassThrough(token):
|
||||
"""
|
||||
Place a marker in the feedback buffer
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/passthrough.html}
|
||||
|
||||
@type token: float
|
||||
@param token: Specifies a marker value to be placed in the feedback
|
||||
buffer following a GL_PASS_THROUGH_TOKEN.
|
||||
"""
|
||||
|
||||
def glPixelMap (map, mapsize, values):
|
||||
"""
|
||||
B{glPixelMapfv, glPixelMapuiv, glPixelMapusv}
|
||||
|
||||
Set up pixel transfer maps
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/pixelmap.html}
|
||||
|
||||
@type map: Enumerated constant
|
||||
@param map: Specifies a symbolic map name.
|
||||
@type mapsize: int
|
||||
@param mapsize: Specifies the size of the map being defined.
|
||||
@type values: Buffer object. Depends on function prototype.
|
||||
@param values: Specifies an array of mapsize values.
|
||||
"""
|
||||
|
||||
def glPixelStore (pname, param):
|
||||
"""
|
||||
B{glPixelStoref, glPixelStorei}
|
||||
|
||||
Set pixel storage modes
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/pixelstore.html}
|
||||
|
||||
@type pname: Enumerated constant
|
||||
@param pname: Specifies the symbolic name of the parameter to be set.
|
||||
Six values affect the packing of pixel data into memory.
|
||||
Six more affect the unpacking of pixel data from memory.
|
||||
@type param: Depends on function prototype.
|
||||
@param param: Specifies the value that pname is set to.
|
||||
"""
|
||||
|
||||
def glPixelTransfer (pname, param):
|
||||
"""
|
||||
B{glPixelTransferf, glPixelTransferi}
|
||||
|
||||
Set pixel transfer modes
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/pixeltransfer.html}
|
||||
|
||||
@type pname: Enumerated constant
|
||||
@param pname: Specifies the symbolic name of the pixel transfer parameter to be set.
|
||||
@type param: Depends on function prototype.
|
||||
@param param: Specifies the value that pname is set to.
|
||||
"""
|
||||
|
||||
def glPixelZoom(xfactor, yfactor):
|
||||
"""
|
||||
Specify the pixel zoom factors
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/pixelzoom.html}
|
||||
|
||||
@type xfactor, yfactor: float
|
||||
@param xfactor, yfactor: Specify the x and y zoom factors for pixel write operations.
|
||||
"""
|
||||
|
||||
def glPointSize(size):
|
||||
"""
|
||||
Specify the diameter of rasterized points
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/pointsize.html}
|
||||
|
||||
@type size: float
|
||||
@param size: Specifies the diameter of rasterized points. The initial value is 1.
|
||||
"""
|
||||
|
||||
def glPolygonMode(face, mode):
|
||||
"""
|
||||
Select a polygon rasterization mode
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/polygonmode.html}
|
||||
|
||||
@type face: Enumerated constant
|
||||
@param face: Specifies the polygons that mode applies to.
|
||||
Must be GL_FRONT for front-facing polygons, GL_BACK for back- facing polygons,
|
||||
or GL_FRONT_AND_BACK for front- and back-facing polygons.
|
||||
@type mode: Enumerated constant
|
||||
@param mode: Specifies how polygons will be rasterized.
|
||||
The initial value is GL_FILL for both front- and back- facing polygons.
|
||||
"""
|
||||
|
||||
def glPolygonOffset(factor, units):
|
||||
"""
|
||||
Set the scale and units used to calculate depth values
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/polygonoffset.html}
|
||||
|
||||
@type factor: float
|
||||
@param factor: Specifies a scale factor that is used to create a variable depth
|
||||
offset for each polygon. The initial value is 0.
|
||||
@type units: float
|
||||
@param units: Is multiplied by an implementation-specific value to create a constant
|
||||
depth offset. The initial value is 0.
|
||||
"""
|
||||
|
||||
def glPolygonStipple(mask):
|
||||
"""
|
||||
Set the polygon stippling pattern
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/polygonstipple.html}
|
||||
|
||||
@type mask: Buffer object I{type GL_BYTE}
|
||||
@param mask: Specifies a pointer to a 32x32 stipple pattern that will be unpacked
|
||||
from memory in the same way that glDrawPixels unpacks pixels.
|
||||
"""
|
||||
|
||||
def glPopAttrib():
|
||||
"""
|
||||
Pop the server attribute stack
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/pushattrib.html}
|
||||
"""
|
||||
|
||||
def glPopClientAttrib():
|
||||
"""
|
||||
Pop the client attribute stack
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/pushclientattrib.html}
|
||||
"""
|
||||
|
||||
def glPopMatrix():
|
||||
"""
|
||||
Pop the current matrix stack
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/pushmatrix.html}
|
||||
"""
|
||||
|
||||
def glPopName():
|
||||
"""
|
||||
Pop the name stack
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/pushname.html}
|
||||
"""
|
||||
|
||||
def glPrioritizeTextures(n, textures, priorities):
|
||||
"""
|
||||
Set texture residence priority
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/prioritizetextures.html}
|
||||
|
||||
@type n: int
|
||||
@param n:Specifies the number of textures to be prioritized.
|
||||
@type textures: Buffer I{type GL_INT}
|
||||
@param textures: Specifies an array containing the names of the textures to be prioritized.
|
||||
@type priorities: Buffer I{type GL_FLOAT}
|
||||
@param priorities: Specifies an array containing the texture priorities. A priority given
|
||||
in an element of priorities applies to the texture named by the corresponding element of textures.
|
||||
"""
|
||||
|
||||
def glPushAttrib(mask):
|
||||
"""
|
||||
Push the server attribute stack
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/pushattrib.html}
|
||||
|
||||
@type mask: Enumerated constant(s)
|
||||
@param mask: Specifies a mask that indicates which attributes to save.
|
||||
"""
|
||||
|
||||
def glPushClientAttrib(mask):
|
||||
"""
|
||||
Push the client attribute stack
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/pushclientattrib.html}
|
||||
|
||||
@type mask: Enumerated constant(s)
|
||||
@param mask: Specifies a mask that indicates which attributes to save.
|
||||
"""
|
||||
|
||||
def glPushMatrix():
|
||||
"""
|
||||
Push the current matrix stack
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/pushmatrix.html}
|
||||
"""
|
||||
|
||||
def glPushName(name):
|
||||
"""
|
||||
Push the name stack
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/pushname.html}
|
||||
|
||||
@type name: unsigned int
|
||||
@param name: Specifies a name that will be pushed onto the name stack.
|
||||
"""
|
||||
|
||||
def glRasterPos (x,y,z,w):
|
||||
"""
|
||||
B{glRasterPos2d, glRasterPos2f, glRasterPos2i, glRasterPos2s, glRasterPos3d,
|
||||
glRasterPos3f, glRasterPos3i, glRasterPos3s, glRasterPos4d, glRasterPos4f,
|
||||
glRasterPos4i, glRasterPos4s, glRasterPos2dv, glRasterPos2fv, glRasterPos2iv,
|
||||
glRasterPos2sv, glRasterPos3dv, glRasterPos3fv, glRasterPos3iv, glRasterPos3sv,
|
||||
glRasterPos4dv, glRasterPos4fv, glRasterPos4iv, glRasterPos4sv}
|
||||
|
||||
Specify the raster position for pixel operations
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/rasterpos.html}
|
||||
|
||||
@type x, y, z, w: Depends on function prototype. (z and w for '3' and '4' prototypes only)
|
||||
@param x, y, z, w: Specify the x,y,z, and w object coordinates (if present) for the
|
||||
raster position. If function prototype ends in 'v' specifies a pointer to an array of two,
|
||||
three, or four elements, specifying x, y, z, and w coordinates, respectively.
|
||||
@note:
|
||||
If you are drawing to the 3d view with a Scriptlink of a space handler
|
||||
the zoom level of the panels will scale the glRasterPos by the view matrix.
|
||||
so a X of 10 will not always offset 10 pixels as you would expect.
|
||||
|
||||
To work around this get the scale value of the view matrix and use it to scale your pixel values.
|
||||
|
||||
Workaround::
|
||||
|
||||
import Blender
|
||||
from Blender.BGL import *
|
||||
xval, yval= 100, 40
|
||||
# Get the scale of the view matrix
|
||||
viewMatrix = Buffer(GL_FLOAT, 16)
|
||||
glGetFloatv(GL_MODELVIEW_MATRIX, viewMatrix)
|
||||
f = 1/viewMatrix[0]
|
||||
glRasterPos2f(xval*f, yval*f) # Instead of the usual glRasterPos2i(xval, yval)
|
||||
"""
|
||||
|
||||
def glReadBuffer(mode):
|
||||
"""
|
||||
Select a color buffer source for pixels.
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/readbuffer.html}
|
||||
|
||||
@type mode: Enumerated constant
|
||||
@param mode: Specifies a color buffer.
|
||||
"""
|
||||
|
||||
def glReadPixels(x, y, width, height, format, type, pixels):
|
||||
"""
|
||||
Read a block of pixels from the frame buffer
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/readpixels.html}
|
||||
|
||||
@type x, y: int
|
||||
@param x, y:Specify the window coordinates of the first pixel that is read
|
||||
from the frame buffer. This location is the lower left corner of a rectangular
|
||||
block of pixels.
|
||||
@type width, height: int
|
||||
@param width, height: Specify the dimensions of the pixel rectangle. width and
|
||||
height of one correspond to a single pixel.
|
||||
@type format: Enumerated constant
|
||||
@param format: Specifies the format of the pixel data.
|
||||
@type type: Enumerated constant
|
||||
@param type: Specifies the data type of the pixel data.
|
||||
@type pixels: Buffer object
|
||||
@param pixels: Returns the pixel data.
|
||||
"""
|
||||
|
||||
def glRect (x1,y1,x2,y2,v1,v2):
|
||||
"""
|
||||
B{glRectd, glRectf, glRecti, glRects, glRectdv, glRectfv, glRectiv, glRectsv}
|
||||
|
||||
Draw a rectangle
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/rect.html}
|
||||
|
||||
@type x1, y1: Depends on function prototype. (for non 'v' prototypes only)
|
||||
@param x1, y1: Specify one vertex of a rectangle
|
||||
@type x2, y2: Depends on function prototype. (for non 'v' prototypes only)
|
||||
@param x2, y2: Specify the opposite vertex of the rectangle
|
||||
@type v1, v2: Depends on function prototype. (for 'v' prototypes only)
|
||||
@param v1, v2: Specifies a pointer to one vertex of a rectangle and the pointer
|
||||
to the opposite vertex of the rectangle
|
||||
"""
|
||||
|
||||
def glRenderMode(mode):
|
||||
"""
|
||||
Set rasterization mode
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/rendermode.html}
|
||||
|
||||
@type mode: Enumerated constant
|
||||
@param mode: Specifies the rasterization mode.
|
||||
"""
|
||||
|
||||
def glRotate (angle, x, y, z):
|
||||
"""
|
||||
B{glRotated, glRotatef}
|
||||
|
||||
Multiply the current matrix by a rotation matrix
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/rotate.html}
|
||||
|
||||
@type angle: Depends on function prototype.
|
||||
@param angle: Specifies the angle of rotation in degrees.
|
||||
@type x, y, z: Depends on function prototype.
|
||||
@param x, y, z: Specify the x, y, and z coordinates of a vector respectively.
|
||||
"""
|
||||
|
||||
def glScale (x,y,z):
|
||||
"""
|
||||
B{glScaled, glScalef}
|
||||
|
||||
Multiply the current matrix by a general scaling matrix
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/scale.html}
|
||||
|
||||
@type x, y, z: Depends on function prototype.
|
||||
@param x, y, z: Specify scale factors along the x, y, and z axes, respectively.
|
||||
"""
|
||||
|
||||
def glScissor(x,y,width,height):
|
||||
"""
|
||||
Define the scissor box
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/scissor.html}
|
||||
|
||||
@type x, y: int
|
||||
@param x, y: Specify the lower left corner of the scissor box. Initially (0, 0).
|
||||
@type width, height: int
|
||||
@param width height: Specify the width and height of the scissor box. When a
|
||||
GL context is first attached to a window, width and height are set to the
|
||||
dimensions of that window.
|
||||
"""
|
||||
|
||||
def glSelectBuffer(size, buffer):
|
||||
"""
|
||||
Establish a buffer for selection mode values
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/selectbuffer.html}
|
||||
|
||||
@type size: int
|
||||
@param size: Specifies the size of buffer
|
||||
@type buffer: Buffer I{type GL_INT}
|
||||
@param buffer: Returns the selection data
|
||||
"""
|
||||
|
||||
def glShadeModel(mode):
|
||||
"""
|
||||
Select flat or smooth shading
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/shademodel.html}
|
||||
|
||||
@type mode: Enumerated constant
|
||||
@param mode: Specifies a symbolic value representing a shading technique.
|
||||
"""
|
||||
|
||||
def glStencilFuc(func, ref, mask):
|
||||
"""
|
||||
Set function and reference value for stencil testing
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/stencilfunc.html}
|
||||
|
||||
@type func: Enumerated constant
|
||||
@param func:Specifies the test function.
|
||||
@type ref: int
|
||||
@param ref:Specifies the reference value for the stencil test. ref is clamped to
|
||||
the range [0,2n-1], where n is the number of bitplanes in the stencil buffer.
|
||||
The initial value is 0.
|
||||
@type mask: unsigned int
|
||||
@param mask:Specifies a mask that is ANDed with both the reference value and
|
||||
the stored stencil value when the test is done. The initial value is all 1's.
|
||||
"""
|
||||
|
||||
def glStencilMask(mask):
|
||||
"""
|
||||
Control the writing of individual bits in the stencil planes
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/stencilmask.html}
|
||||
|
||||
@type mask: unsigned int
|
||||
@param mask: Specifies a bit mask to enable and disable writing of individual bits
|
||||
in the stencil planes. Initially, the mask is all 1's.
|
||||
"""
|
||||
|
||||
def glStencilOp(fail, zfail, zpass):
|
||||
"""
|
||||
Set stencil test actions
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/stencilop.html}
|
||||
|
||||
@type fail: Enumerated constant
|
||||
@param fail: Specifies the action to take when the stencil test fails.
|
||||
The initial value is GL_KEEP.
|
||||
@type zfail: Enumerated constant
|
||||
@param zfail: Specifies the stencil action when the stencil test passes, but the
|
||||
depth test fails. zfail accepts the same symbolic constants as fail.
|
||||
The initial value is GL_KEEP.
|
||||
@type zpass: Enumerated constant
|
||||
@param zpass: Specifies the stencil action when both the stencil test and the
|
||||
depth test pass, or when the stencil test passes and either there is no depth
|
||||
buffer or depth testing is not enabled. zpass accepts the same symbolic constants
|
||||
as fail. The initial value is GL_KEEP.
|
||||
"""
|
||||
|
||||
def glTexCoord (s,t,r,q,v):
|
||||
"""
|
||||
B{glTexCoord1d, glTexCoord1f, glTexCoord1i, glTexCoord1s, glTexCoord2d, glTexCoord2f,
|
||||
glTexCoord2i, glTexCoord2s, glTexCoord3d, glTexCoord3f, glTexCoord3i, glTexCoord3s,
|
||||
glTexCoord4d, glTexCoord4f, glTexCoord4i, glTexCoord4s, glTexCoord1dv, glTexCoord1fv,
|
||||
glTexCoord1iv, glTexCoord1sv, glTexCoord2dv, glTexCoord2fv, glTexCoord2iv,
|
||||
glTexCoord2sv, glTexCoord3dv, glTexCoord3fv, glTexCoord3iv, glTexCoord3sv,
|
||||
glTexCoord4dv, glTexCoord4fv, glTexCoord4iv, glTexCoord4sv}
|
||||
|
||||
Set the current texture coordinates
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/texcoord.html}
|
||||
|
||||
@type s, t, r, q: Depends on function prototype. (r and q for '3' and '4' prototypes only)
|
||||
@param s, t, r, q: Specify s, t, r, and q texture coordinates. Not all parameters are
|
||||
present in all forms of the command.
|
||||
@type v: Buffer object. Depends on function prototype. (for 'v' prototypes only)
|
||||
@param v: Specifies a pointer to an array of one, two, three, or four elements,
|
||||
which in turn specify the s, t, r, and q texture coordinates.
|
||||
"""
|
||||
|
||||
def glTexEnv (target, pname, param):
|
||||
"""
|
||||
B{glTextEnvf, glTextEnvi, glTextEnvfv, glTextEnviv}
|
||||
|
||||
Set texture environment parameters
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/texenv.html}
|
||||
|
||||
@type target: Enumerated constant
|
||||
@param target: Specifies a texture environment. Must be GL_TEXTURE_ENV.
|
||||
@type pname: Enumerated constant
|
||||
@param pname: Specifies the symbolic name of a single-valued texture environment
|
||||
parameter. Must be GL_TEXTURE_ENV_MODE.
|
||||
@type param: Depends on function prototype.
|
||||
@param param: Specifies a single symbolic constant. If function prototype ends in 'v'
|
||||
specifies a pointer to a parameter array that contains either a single symbolic
|
||||
constant or an RGBA color
|
||||
"""
|
||||
|
||||
def glTexGen (coord, pname, param):
|
||||
"""
|
||||
B{glTexGend, glTexGenf, glTexGeni, glTexGendv, glTexGenfv, glTexGeniv}
|
||||
|
||||
Control the generation of texture coordinates
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/texgen.html}
|
||||
|
||||
@type coord: Enumerated constant
|
||||
@param coord: Specifies a texture coordinate.
|
||||
@type pname: Enumerated constant
|
||||
@param pname: Specifies the symbolic name of the texture- coordinate generation function.
|
||||
@type param: Depends on function prototype.
|
||||
@param param: Specifies a single-valued texture generation parameter.
|
||||
If function prototype ends in 'v' specifies a pointer to an array of texture
|
||||
generation parameters. If pname is GL_TEXTURE_GEN_MODE, then the array must
|
||||
contain a single symbolic constant. Otherwise, params holds the coefficients
|
||||
for the texture-coordinate generation function specified by pname.
|
||||
"""
|
||||
|
||||
def glTexImage1D(target, level, internalformat, width, border, format, type, pixels):
|
||||
"""
|
||||
Specify a one-dimensional texture image
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/teximage1d.html}
|
||||
|
||||
@type target: Enumerated constant
|
||||
@param target: Specifies the target texture.
|
||||
@type level: int
|
||||
@param level: Specifies the level-of-detail number. Level 0 is the base image level.
|
||||
Level n is the nth mipmap reduction image.
|
||||
@type internalformat: int
|
||||
@param internalformat: Specifies the number of color components in the texture.
|
||||
@type width: int
|
||||
@param width: Specifies the width of the texture image. Must be 2n+2(border) for
|
||||
some integer n. All implementations support texture images that are at least 64
|
||||
texels wide. The height of the 1D texture image is 1.
|
||||
@type border: int
|
||||
@param border: Specifies the width of the border. Must be either 0 or 1.
|
||||
@type format: Enumerated constant
|
||||
@param format: Specifies the format of the pixel data.
|
||||
@type type: Enumerated constant
|
||||
@param type: Specifies the data type of the pixel data.
|
||||
@type pixels: Buffer object.
|
||||
@param pixels: Specifies a pointer to the image data in memory.
|
||||
"""
|
||||
|
||||
def glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels):
|
||||
"""
|
||||
Specify a two-dimensional texture image
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/teximage2d.html}
|
||||
|
||||
@type target: Enumerated constant
|
||||
@param target: Specifies the target texture.
|
||||
@type level: int
|
||||
@param level: Specifies the level-of-detail number. Level 0 is the base image level.
|
||||
Level n is the nth mipmap reduction image.
|
||||
@type internalformat: int
|
||||
@param internalformat: Specifies the number of color components in the texture.
|
||||
@type width: int
|
||||
@param width: Specifies the width of the texture image. Must be 2n+2(border) for
|
||||
some integer n. All implementations support texture images that are at least 64
|
||||
texels wide.
|
||||
@type height: int
|
||||
@param height: Specifies the height of the texture image. Must be 2m+2(border) for
|
||||
some integer m. All implementations support texture images that are at least 64
|
||||
texels high.
|
||||
@type border: int
|
||||
@param border: Specifies the width of the border. Must be either 0 or 1.
|
||||
@type format: Enumerated constant
|
||||
@param format: Specifies the format of the pixel data.
|
||||
@type type: Enumerated constant
|
||||
@param type: Specifies the data type of the pixel data.
|
||||
@type pixels: Buffer object.
|
||||
@param pixels: Specifies a pointer to the image data in memory.
|
||||
"""
|
||||
|
||||
def glTexParameter (target, pname, param):
|
||||
"""
|
||||
B{glTexParameterf, glTexParameteri, glTexParameterfv, glTexParameteriv}
|
||||
|
||||
Set texture parameters
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/texparameter.html}
|
||||
|
||||
@type target: Enumerated constant
|
||||
@param target: Specifies the target texture.
|
||||
@type pname: Enumerated constant
|
||||
@param pname: Specifies the symbolic name of a single-valued texture parameter.
|
||||
@type param: Depends on function prototype.
|
||||
@param param: Specifies the value of pname. If function prototype ends in 'v' specifies
|
||||
a pointer to an array where the value or values of pname are stored.
|
||||
"""
|
||||
|
||||
def glTranslate (x, y, z):
|
||||
"""
|
||||
B{glTranslatef, glTranslated}
|
||||
|
||||
Multiply the current matrix by a translation matrix
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/translate.html}
|
||||
|
||||
@type x, y, z: Depends on function prototype.
|
||||
@param x, y, z: Specify the x, y, and z coordinates of a translation vector.
|
||||
"""
|
||||
|
||||
def glVertex (x,y,z,w,v):
|
||||
"""
|
||||
B{glVertex2d, glVertex2f, glVertex2i, glVertex2s, glVertex3d, glVertex3f, glVertex3i,
|
||||
glVertex3s, glVertex4d, glVertex4f, glVertex4i, glVertex4s, glVertex2dv, glVertex2fv,
|
||||
glVertex2iv, glVertex2sv, glVertex3dv, glVertex3fv, glVertex3iv, glVertex3sv, glVertex4dv,
|
||||
glVertex4fv, glVertex4iv, glVertex4sv}
|
||||
|
||||
Specify a vertex
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/vertex.html}
|
||||
|
||||
@type x, y, z, w: Depends on function prototype (z and w for '3' and '4' prototypes only)
|
||||
@param x, y, z, w: Specify x, y, z, and w coordinates of a vertex. Not all parameters
|
||||
are present in all forms of the command.
|
||||
@type v: Buffer object. Depends of function prototype (for 'v' prototypes only)
|
||||
@param v: Specifies a pointer to an array of two, three, or four elements. The
|
||||
elements of a two-element array are x and y; of a three-element array, x, y, and z;
|
||||
and of a four-element array, x, y, z, and w.
|
||||
"""
|
||||
|
||||
def glViewport(x,y,width,height):
|
||||
"""
|
||||
Set the viewport
|
||||
@see: U{www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/viewport.html}
|
||||
|
||||
@type x, y: int
|
||||
@param x, y: Specify the lower left corner of the viewport rectangle,
|
||||
in pixels. The initial value is (0,0).
|
||||
@type width, height: int
|
||||
@param width, height: Specify the width and height of the viewport. When a GL context
|
||||
is first attached to a window, width and height are set to the dimensions of that window.
|
||||
"""
|
||||
|
||||
def gluPerspective(fovY, aspect, zNear, zFar):
|
||||
"""
|
||||
Set up a perspective projection matrix.
|
||||
@see: U{http://biology.ncsa.uiuc.edu/cgi-bin/infosrch.cgi?cmd=getdoc&coll=0650&db=bks&fname=/SGI_Developer/OpenGL_RM/ch06.html#id5577288}
|
||||
|
||||
@type fovY: double
|
||||
@param fovY: Specifies the field of view angle, in degrees, in the y direction.
|
||||
@type aspect: double
|
||||
@param aspect: Specifies the aspect ratio that determines the field of view in the x direction.
|
||||
The aspect ratio is the ratio of x (width) to y (height).
|
||||
@type zNear: double
|
||||
@param zNear: Specifies the distance from the viewer to the near clipping plane (always positive).
|
||||
@type zFar: double
|
||||
@param zFar: Specifies the distance from the viewer to the far clipping plane (always positive).
|
||||
"""
|
||||
|
||||
def gluLookAt(eyex, eyey, eyez, centerx, centery, centerz, upx, upy, upz):
|
||||
"""
|
||||
Define a viewing transformation
|
||||
@see: U{http://biology.ncsa.uiuc.edu/cgi-bin/infosrch.cgi?cmd=getdoc&coll=0650&db=bks&fname=/SGI_Developer/OpenGL_RM/ch06.html#id5573042}
|
||||
|
||||
@type eyex, eyey, eyez: double
|
||||
@param eyex, eyey, eyez: Specifies the position of the eye point.
|
||||
@type centerx, centery, centerz: double
|
||||
@param centerx, centery, centerz: Specifies the position of the reference point.
|
||||
@type upx, upy, upz: double
|
||||
@param upx, upy, upz: Specifies the direction of the up vector.
|
||||
"""
|
||||
|
||||
def gluOrtho2D(left, right, bottom, top):
|
||||
"""
|
||||
Define a 2-D orthographic projection matrix
|
||||
@see: U{http://biology.ncsa.uiuc.edu/cgi-bin/infosrch.cgi?cmd=getdoc&coll=0650&db=bks&fname=/SGI_Developer/OpenGL_RM/ch06.html#id5578074}
|
||||
|
||||
@type left, right: double
|
||||
@param left, right: Specify the coordinates for the left and right vertical clipping planes.
|
||||
@type bottom, top: double
|
||||
@param bottom, top: Specify the coordinates for the bottom and top horizontal clipping planes.
|
||||
"""
|
||||
|
||||
def gluPickMatrix(x, y, width, height, viewport):
|
||||
"""
|
||||
Define a picking region
|
||||
@see: U{http://biology.ncsa.uiuc.edu/cgi-bin/infosrch.cgi?cmd=getdoc&coll=0650&db=bks&fname=/SGI_Developer/OpenGL_RM/ch06.html#id5578074}
|
||||
|
||||
@type x, y: double
|
||||
@param x, y: Specify the center of a picking region in window coordinates.
|
||||
@type width, height: double
|
||||
@param width, height: Specify the width and height, respectively, of the picking region in window coordinates.
|
||||
@type viewport: Buffer object. [int]
|
||||
@param viewport: Specifies the current viewport.
|
||||
"""
|
||||
|
||||
def gluProject(objx, objy, objz, modelMatrix, projMatrix, viewport, winx, winy, winz):
|
||||
"""
|
||||
Map object coordinates to window coordinates.
|
||||
@see: U{http://biology.ncsa.uiuc.edu/cgi-bin/infosrch.cgi?cmd=getdoc&coll=0650&db=bks&fname=/SGI_Developer/OpenGL_RM/ch06.html#id5578074}
|
||||
|
||||
@type objx, objy, objz: double
|
||||
@param objx, objy, objz: Specify the object coordinates.
|
||||
@type modelMatrix: Buffer object. [double]
|
||||
@param modelMatrix: Specifies the current modelview matrix (as from a glGetDoublev call).
|
||||
@type projMatrix: Buffer object. [double]
|
||||
@param projMatrix: Specifies the current projection matrix (as from a glGetDoublev call).
|
||||
@type viewport: Buffer object. [int]
|
||||
@param viewport: Specifies the current viewport (as from a glGetIntegerv call).
|
||||
@type winx, winy, winz: Buffer object. [double]
|
||||
@param winx, winy, winz: Return the computed window coordinates.
|
||||
"""
|
||||
|
||||
def gluUnProject(winx, winy, winz, modelMatrix, projMatrix, viewport, objx, objy, objz):
|
||||
"""
|
||||
Map object coordinates to window
|
||||
coordinates.
|
||||
@see: U{http://biology.ncsa.uiuc.edu/cgi-bin/infosrch.cgi?cmd=getdoc&coll=0650&db=bks&fname=/SGI_Developer/OpenGL_RM/ch06.html#id5582204}
|
||||
|
||||
@type winx, winy, winz: double
|
||||
@param winx, winy, winz: Specify the window coordinates to be mapped.
|
||||
@type modelMatrix: Buffer object. [double]
|
||||
@param modelMatrix: Specifies the current modelview matrix (as from a glGetDoublev call).
|
||||
@type projMatrix: Buffer object. [double]
|
||||
@param projMatrix: Specifies the current projection matrix (as from a glGetDoublev call).
|
||||
@type viewport: Buffer object. [int]
|
||||
@param viewport: Specifies the current viewport (as from a glGetIntegerv call).
|
||||
@type objx, objy, objz: Buffer object. [double]
|
||||
@param objx, objy, objz: Return the computed object coordinates.
|
||||
"""
|
||||
|
||||
class Buffer:
|
||||
"""
|
||||
The Buffer object is simply a block of memory that is delineated and initialized by the
|
||||
user. Many OpenGL functions return data to a C-style pointer, however, because this
|
||||
is not possible in python the Buffer object can be used to this end. Wherever pointer
|
||||
notation is used in the OpenGL functions the Buffer object can be used in it's BGL
|
||||
wrapper. In some instances the Buffer object will need to be initialized with the template
|
||||
parameter, while in other instances the user will want to create just a blank buffer
|
||||
which will be zeroed by default.
|
||||
|
||||
Example with Buffer::
|
||||
import Blender
|
||||
from Blender import BGL
|
||||
myByteBuffer = BGL.Buffer(BGL.GL_BYTE, [32,32])
|
||||
BGL.glGetPolygonStipple(myByteBuffer)
|
||||
print myByteBuffer.dimensions
|
||||
print myByteBuffer.list
|
||||
sliceBuffer = myByteBuffer[0:16]
|
||||
print sliceBuffer
|
||||
|
||||
@ivar list: The contents of the Buffer.
|
||||
@ivar dimensions: The size of the Buffer.
|
||||
"""
|
||||
|
||||
def __init__(type, dimensions, template = None):
|
||||
"""
|
||||
This will create a new Buffer object for use with other BGL OpenGL commands.
|
||||
Only the type of argument to store in the buffer and the dimensions of the buffer
|
||||
are necessary. Buffers are zeroed by default unless a template is supplied, in
|
||||
which case the buffer is initialized to the template.
|
||||
|
||||
@type type: int
|
||||
@param type: The format to store data in. The type should be one of
|
||||
GL_BYTE, GL_SHORT, GL_INT, or GL_FLOAT.
|
||||
@type dimensions: An int or sequence object specifying the dimensions of the buffer.
|
||||
@param dimensions: If the dimensions are specified as an int a linear array will
|
||||
be created for the buffer. If a sequence is passed for the dimensions, the buffer
|
||||
becomes n-Dimensional, where n is equal to the number of parameters passed in the
|
||||
sequence. Example: [256,2] is a two- dimensional buffer while [256,256,4] creates
|
||||
a three- dimensional buffer. You can think of each additional dimension as a sub-item
|
||||
of the dimension to the left. i.e. [10,2] is a 10 element array each with 2 sub-items.
|
||||
[(0,0), (0,1), (1,0), (1,1), (2,0), ...] etc.
|
||||
@type template: A python sequence object (optional)
|
||||
@param template: A sequence of matching dimensions which will be used to initialize
|
||||
the Buffer. If a template is not passed in all fields will be initialized to 0.
|
||||
@rtype: Buffer object
|
||||
@return: The newly created buffer as a PyObject.
|
||||
"""
|
||||
189
source/blender/python/doc/epy/Geometry.py
Normal file
189
source/blender/python/doc/epy/Geometry.py
Normal 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)
|
||||
"""
|
||||
132
source/blender/python/doc/epy/IDProp.py
Normal file
132
source/blender/python/doc/epy/IDProp.py
Normal 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
|
||||
|
||||
271
source/blender/python/doc/epy/Mathutils.py
Normal file
271
source/blender/python/doc/epy/Mathutils.py
Normal file
@@ -0,0 +1,271 @@
|
||||
# Blender.Mathutils module and its subtypes
|
||||
|
||||
"""
|
||||
The Blender.Mathutils submodule.
|
||||
|
||||
Mathutils
|
||||
=========
|
||||
(when accessing it from the Game Engine use Mathutils instead of Blender.Mathutils)
|
||||
|
||||
This module provides access to matrices, eulers, quaternions and vectors.
|
||||
|
||||
Example::
|
||||
import Blender
|
||||
from Blender import Mathutils
|
||||
from Blender.Mathutils import *
|
||||
|
||||
vec = Vector([1,2,3])
|
||||
mat = RotationMatrix(90, 4, 'x')
|
||||
matT = TranslationMatrix(vec)
|
||||
|
||||
matTotal = mat * matT
|
||||
matTotal.invert()
|
||||
|
||||
mat3 = matTotal.rotationPart
|
||||
quat1 = mat.to_quat()
|
||||
quat2 = mat3.to_quat()
|
||||
|
||||
angle = DifferenceQuats(quat1, quat2)
|
||||
print angle
|
||||
"""
|
||||
|
||||
class Vector:
|
||||
"""
|
||||
The Vector object
|
||||
=================
|
||||
This object gives access to Vectors in Blender.
|
||||
@group Axises: x, y, z, w
|
||||
@ivar x: The x value.
|
||||
@ivar y: The y value.
|
||||
@ivar z: The z value (if any).
|
||||
@ivar w: The w value (if any).
|
||||
@ivar length: The magnitude of the vector.
|
||||
@ivar magnitude: This is a synonym for length.
|
||||
@ivar wrapped: Whether or not this item is wrapped data
|
||||
@note: Comparison operators can be done on Vector classes:
|
||||
- >, >=, <, <= test the vector magnitude
|
||||
- ==, != test vector values e.g. 1,2,3 != 1,2,4 even if they are the same length
|
||||
@note: Math can be performed on Vector classes
|
||||
- vec + vec
|
||||
- vec - vec
|
||||
- vec * float/int
|
||||
- vec * matrix
|
||||
- vec * vec
|
||||
- vec * quat
|
||||
- -vec
|
||||
@note: You can access a vector object like a sequence
|
||||
- x = vector[0]
|
||||
- vec_a[:] vec_b
|
||||
- vec2d[:] vec3d[:2]
|
||||
@note: Vectors support 'swizzle' operations
|
||||
- vec.xyz = vec.zyx
|
||||
- vec.xy = vec.zw
|
||||
- vec.xxy = vec.wzz
|
||||
- vec.yzyz = vec.yxyx
|
||||
|
||||
See U{http://en.wikipedia.org/wiki/Swizzling_(computer_graphics)}
|
||||
|
||||
@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.
|
||||
Example::
|
||||
wrappedObject = Object.getAttribute() #this is wrapped data
|
||||
print wrappedObject.wrapped #prints 'True'
|
||||
copyOfObject = wrappedObject.copy() #creates a copy of the object
|
||||
secondPointer = wrappedObject #creates a second pointer to the same data
|
||||
print wrappedObject.attribute #prints '5'
|
||||
secondPointer.attribute = 10
|
||||
print wrappedObject.attribute #prints '10'
|
||||
print copyOfObject.attribute #prints '5'
|
||||
"""
|
||||
|
||||
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.
|
||||
@group Axises: x, y, z
|
||||
@ivar x: The heading value in degrees.
|
||||
@ivar y: The pitch value in degrees.
|
||||
@ivar z: The roll value in degrees.
|
||||
@ivar wrapped: Whether or not this object is wrapping data directly
|
||||
@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.
|
||||
Example::
|
||||
wrappedObject = Object.getAttribute() #this is wrapped data
|
||||
print wrappedObject.wrapped #prints 'True'
|
||||
copyOfObject = wrappedObject.copy() #creates a copy of the object
|
||||
secondPointer = wrappedObject #creates a second pointer to the same data
|
||||
print wrappedObject.attribute #prints '5'
|
||||
secondPointer.attribute = 10
|
||||
print wrappedObject.attribute #prints '10'
|
||||
print copyOfObject.attribute #prints '5'
|
||||
"""
|
||||
|
||||
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.
|
||||
@group Axises: x, y, z, w
|
||||
@ivar w: The w value.
|
||||
@ivar x: The x value.
|
||||
@ivar y: The y value.
|
||||
@ivar z: The z value.
|
||||
@ivar wrapped: Wether or not this object wraps data directly
|
||||
@ivar magnitude: The magnitude of the quaternion.
|
||||
@ivar axis: Vector representing the axis of rotation.
|
||||
@ivar angle: A scalar representing the amount of rotation
|
||||
in degrees.
|
||||
@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.
|
||||
Example::
|
||||
wrappedObject = Object.getAttribute() #this is wrapped data
|
||||
print wrappedObject.wrapped #prints 'True'
|
||||
copyOfObject = wrappedObject.copy() #creates a copy of the object
|
||||
secondPointer = wrappedObject #creates a second pointer to the same data
|
||||
print wrappedObject.attribute #prints '5'
|
||||
secondPointer.attribute = 10
|
||||
print wrappedObject.attribute #prints '10'
|
||||
print copyOfObject.attribute #prints '5'
|
||||
"""
|
||||
|
||||
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
|
||||
=================
|
||||
This object gives access to Matrices in Blender.
|
||||
@ivar rowSize: The row size of the matrix.
|
||||
@ivar colSize: The column size of the matrix.
|
||||
@ivar wrapped: Whether or not this object wrapps internal data
|
||||
@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.
|
||||
Example::
|
||||
wrappedObject = Object.getAttribute() #this is wrapped data
|
||||
print wrappedObject.wrapped #prints 'True'
|
||||
copyOfObject = wrappedObject.copy() #creates a copy of the object
|
||||
secondPointer = wrappedObject #creates a second pointer to the same data
|
||||
print wrappedObject.attribute #prints '5'
|
||||
secondPointer.attribute = 10
|
||||
print wrappedObject.attribute #prints '10'
|
||||
print copyOfObject.attribute #prints '5'
|
||||
"""
|
||||
|
||||
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.
|
||||
"""
|
||||
45
source/blender/python/doc/epy/testbgl.py
Normal file
45
source/blender/python/doc/epy/testbgl.py
Normal 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
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -27,114 +27,34 @@
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/* Note: Changes to Mathutils since 2.4x
|
||||
* use radians rather then degrees
|
||||
* - Mathutils.MidpointVecs --> vector.lerp(other, fac)
|
||||
* - Mathutils.AngleBetweenVecs --> vector.angle(other)
|
||||
* - Mathutils.ProjectVecs --> vector.project(other)
|
||||
* - Mathutils.DifferenceQuats --> quat.difference(other)
|
||||
* - Mathutils.Slerp --> quat.slerp(other, fac)
|
||||
* - Mathutils.Rand: removed, use pythons random module
|
||||
* - Mathutils.RotationMatrix(angle, size, axis_flag, axis) --> Mathutils.RotationMatrix(angle, size, axis); merge axis & axis_flag args
|
||||
* - Matrix.scalePart --> Matrix.scale_part
|
||||
* - Matrix.translationPart --> Matrix.translation_part
|
||||
* - Matrix.rotationPart --> Matrix.rotation_part
|
||||
* - toMatrix --> to_matrix
|
||||
* - toEuler --> to_euler
|
||||
* - toQuat --> to_quat
|
||||
* - Vector.toTrackQuat --> Vector.to_track_quat
|
||||
*
|
||||
* Moved to Geometry module: Intersect, TriangleArea, TriangleNormal, QuadNormal, LineIntersect
|
||||
*/
|
||||
|
||||
#include "Mathutils.h"
|
||||
|
||||
#include "BLI_math.h"
|
||||
#include "PIL_time.h"
|
||||
#include "BLI_rand.h"
|
||||
#include "BKE_utildefines.h"
|
||||
|
||||
//-------------------------DOC STRINGS ---------------------------
|
||||
static char M_Mathutils_doc[] = "The Blender Mathutils module\n\n";
|
||||
static char M_Mathutils_Rand_doc[] = "() - return a random number";
|
||||
static char M_Mathutils_AngleBetweenVecs_doc[] = "() - returns the angle between two vectors in degrees";
|
||||
static char M_Mathutils_MidpointVecs_doc[] = "() - return the vector to the midpoint between two vectors";
|
||||
static char M_Mathutils_ProjectVecs_doc[] = "() - returns the projection vector from the projection of vecA onto vecB";
|
||||
static char M_Mathutils_RotationMatrix_doc[] = "() - construct a rotation matrix from an angle and axis of rotation";
|
||||
static char M_Mathutils_ScaleMatrix_doc[] = "() - construct a scaling matrix from a scaling factor";
|
||||
static char M_Mathutils_OrthoProjectionMatrix_doc[] = "() - construct a orthographic projection matrix from a selected plane";
|
||||
static char M_Mathutils_ShearMatrix_doc[] = "() - construct a shearing matrix from a plane of shear and a shear factor";
|
||||
static char M_Mathutils_TranslationMatrix_doc[] = "(vec) - create a translation matrix from a vector";
|
||||
static char M_Mathutils_Slerp_doc[] = "() - returns the interpolation between two quaternions";
|
||||
static char M_Mathutils_DifferenceQuats_doc[] = "() - return the angular displacment difference between two quats";
|
||||
static char M_Mathutils_Intersect_doc[] = "(v1, v2, v3, ray, orig, clip=1) - returns the intersection between a ray and a triangle, if possible, returns None otherwise";
|
||||
static char M_Mathutils_TriangleArea_doc[] = "(v1, v2, v3) - returns the area size of the 2D or 3D triangle defined";
|
||||
static char M_Mathutils_TriangleNormal_doc[] = "(v1, v2, v3) - returns the normal of the 3D triangle defined";
|
||||
static char M_Mathutils_QuadNormal_doc[] = "(v1, v2, v3, v4) - returns the normal of the 3D quad defined";
|
||||
static char M_Mathutils_LineIntersect_doc[] = "(v1, v2, v3, v4) - returns a tuple with the points on each line respectively closest to the other";
|
||||
//-----------------------METHOD DEFINITIONS ----------------------
|
||||
|
||||
static PyObject *M_Mathutils_Rand(PyObject * self, PyObject * args);
|
||||
static PyObject *M_Mathutils_AngleBetweenVecs(PyObject * self, PyObject * args);
|
||||
static PyObject *M_Mathutils_MidpointVecs(PyObject * self, PyObject * args);
|
||||
static PyObject *M_Mathutils_ProjectVecs(PyObject * self, PyObject * args);
|
||||
static PyObject *M_Mathutils_RotationMatrix(PyObject * self, PyObject * args);
|
||||
static PyObject *M_Mathutils_TranslationMatrix(PyObject * self, VectorObject * value);
|
||||
static PyObject *M_Mathutils_ScaleMatrix(PyObject * self, PyObject * args);
|
||||
static PyObject *M_Mathutils_OrthoProjectionMatrix(PyObject * self, PyObject * args);
|
||||
static PyObject *M_Mathutils_ShearMatrix(PyObject * self, PyObject * args);
|
||||
static PyObject *M_Mathutils_DifferenceQuats(PyObject * self, PyObject * args);
|
||||
static PyObject *M_Mathutils_Slerp(PyObject * self, PyObject * args);
|
||||
static PyObject *M_Mathutils_Intersect( PyObject * self, PyObject * args );
|
||||
static PyObject *M_Mathutils_TriangleArea( PyObject * self, PyObject * args );
|
||||
static PyObject *M_Mathutils_TriangleNormal( PyObject * self, PyObject * args );
|
||||
static PyObject *M_Mathutils_QuadNormal( PyObject * self, PyObject * args );
|
||||
static PyObject *M_Mathutils_LineIntersect( PyObject * self, PyObject * args );
|
||||
|
||||
struct PyMethodDef M_Mathutils_methods[] = {
|
||||
{"Rand", (PyCFunction) M_Mathutils_Rand, METH_VARARGS, M_Mathutils_Rand_doc},
|
||||
{"AngleBetweenVecs", (PyCFunction) M_Mathutils_AngleBetweenVecs, METH_VARARGS, M_Mathutils_AngleBetweenVecs_doc},
|
||||
{"MidpointVecs", (PyCFunction) M_Mathutils_MidpointVecs, METH_VARARGS, M_Mathutils_MidpointVecs_doc},
|
||||
{"ProjectVecs", (PyCFunction) M_Mathutils_ProjectVecs, METH_VARARGS, M_Mathutils_ProjectVecs_doc},
|
||||
{"RotationMatrix", (PyCFunction) M_Mathutils_RotationMatrix, METH_VARARGS, M_Mathutils_RotationMatrix_doc},
|
||||
{"ScaleMatrix", (PyCFunction) M_Mathutils_ScaleMatrix, METH_VARARGS, M_Mathutils_ScaleMatrix_doc},
|
||||
{"ShearMatrix", (PyCFunction) M_Mathutils_ShearMatrix, METH_VARARGS, M_Mathutils_ShearMatrix_doc},
|
||||
{"TranslationMatrix", (PyCFunction) M_Mathutils_TranslationMatrix, METH_O, M_Mathutils_TranslationMatrix_doc},
|
||||
{"OrthoProjectionMatrix", (PyCFunction) M_Mathutils_OrthoProjectionMatrix, METH_VARARGS, M_Mathutils_OrthoProjectionMatrix_doc},
|
||||
{"DifferenceQuats", (PyCFunction) M_Mathutils_DifferenceQuats, METH_VARARGS,M_Mathutils_DifferenceQuats_doc},
|
||||
{"Slerp", (PyCFunction) M_Mathutils_Slerp, METH_VARARGS, M_Mathutils_Slerp_doc},
|
||||
{"Intersect", ( PyCFunction ) M_Mathutils_Intersect, METH_VARARGS, M_Mathutils_Intersect_doc},
|
||||
{"TriangleArea", ( PyCFunction ) M_Mathutils_TriangleArea, METH_VARARGS, M_Mathutils_TriangleArea_doc},
|
||||
{"TriangleNormal", ( PyCFunction ) M_Mathutils_TriangleNormal, METH_VARARGS, M_Mathutils_TriangleNormal_doc},
|
||||
{"QuadNormal", ( PyCFunction ) M_Mathutils_QuadNormal, METH_VARARGS, M_Mathutils_QuadNormal_doc},
|
||||
{"LineIntersect", ( PyCFunction ) M_Mathutils_LineIntersect, METH_VARARGS, M_Mathutils_LineIntersect_doc},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
/*----------------------------MODULE INIT-------------------------*/
|
||||
/* from can be Blender.Mathutils or GameLogic.Mathutils for the BGE */
|
||||
|
||||
static struct PyModuleDef M_Mathutils_module_def = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"Mathutils", /* m_name */
|
||||
M_Mathutils_doc, /* m_doc */
|
||||
0, /* m_size */
|
||||
M_Mathutils_methods, /* m_methods */
|
||||
0, /* m_reload */
|
||||
0, /* m_traverse */
|
||||
0, /* m_clear */
|
||||
0, /* m_free */
|
||||
};
|
||||
|
||||
PyObject *Mathutils_Init(void)
|
||||
{
|
||||
PyObject *submodule;
|
||||
|
||||
//seed the generator for the rand function
|
||||
BLI_srand((unsigned int) (PIL_check_seconds_timer() * 0x7FFFFFFF));
|
||||
|
||||
if( PyType_Ready( &vector_Type ) < 0 )
|
||||
return NULL;
|
||||
if( PyType_Ready( &matrix_Type ) < 0 )
|
||||
return NULL;
|
||||
if( PyType_Ready( &euler_Type ) < 0 )
|
||||
return NULL;
|
||||
if( PyType_Ready( &quaternion_Type ) < 0 )
|
||||
return NULL;
|
||||
|
||||
submodule = PyModule_Create(&M_Mathutils_module_def);
|
||||
PyDict_SetItemString(PySys_GetObject("modules"), M_Mathutils_module_def.m_name, submodule);
|
||||
|
||||
/* each type has its own new() function */
|
||||
PyModule_AddObject( submodule, "Vector", (PyObject *)&vector_Type );
|
||||
PyModule_AddObject( submodule, "Matrix", (PyObject *)&matrix_Type );
|
||||
PyModule_AddObject( submodule, "Euler", (PyObject *)&euler_Type );
|
||||
PyModule_AddObject( submodule, "Quaternion", (PyObject *)&quaternion_Type );
|
||||
|
||||
mathutils_matrix_vector_cb_index= Mathutils_RegisterCallback(&mathutils_matrix_vector_cb);
|
||||
|
||||
return (submodule);
|
||||
}
|
||||
static char M_Mathutils_doc[] = "This module provides access to matrices, eulers, quaternions and vectors.";
|
||||
|
||||
//-----------------------------METHODS----------------------------
|
||||
//-----------------quat_rotation (internal)-----------
|
||||
@@ -204,164 +124,49 @@ PyObject *quat_rotation(PyObject *arg1, PyObject *arg2)
|
||||
|
||||
}
|
||||
|
||||
//----------------------------------Mathutils.Rand() --------------------
|
||||
//returns a random number between a high and low value
|
||||
static PyObject *M_Mathutils_Rand(PyObject * self, PyObject * args)
|
||||
{
|
||||
float high, low, range;
|
||||
double drand;
|
||||
//initializers
|
||||
high = 1.0;
|
||||
low = 0.0;
|
||||
|
||||
if(!PyArg_ParseTuple(args, "|ff", &low, &high)) {
|
||||
PyErr_SetString(PyExc_TypeError, "Mathutils.Rand(): expected nothing or optional (float, float)\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if((high < low) || (high < 0 && low > 0)) {
|
||||
PyErr_SetString(PyExc_ValueError, "Mathutils.Rand(): high value should be larger than low value\n");
|
||||
return NULL;
|
||||
}
|
||||
//get the random number 0 - 1
|
||||
drand = BLI_drand();
|
||||
|
||||
//set it to range
|
||||
range = high - low;
|
||||
drand = drand * range;
|
||||
drand = drand + low;
|
||||
|
||||
return PyFloat_FromDouble(drand);
|
||||
}
|
||||
//----------------------------------VECTOR FUNCTIONS---------------------
|
||||
//----------------------------------Mathutils.AngleBetweenVecs() ---------
|
||||
//calculates the angle between 2 vectors
|
||||
static PyObject *M_Mathutils_AngleBetweenVecs(PyObject * self, PyObject * args)
|
||||
{
|
||||
VectorObject *vec1 = NULL, *vec2 = NULL;
|
||||
double dot = 0.0f, angleRads, test_v1 = 0.0f, test_v2 = 0.0f;
|
||||
int x, size;
|
||||
|
||||
if(!PyArg_ParseTuple(args, "O!O!", &vector_Type, &vec1, &vector_Type, &vec2))
|
||||
goto AttributeError1; //not vectors
|
||||
if(vec1->size != vec2->size)
|
||||
goto AttributeError1; //bad sizes
|
||||
|
||||
if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2))
|
||||
return NULL;
|
||||
|
||||
//since size is the same....
|
||||
size = vec1->size;
|
||||
|
||||
for(x = 0; x < size; x++) {
|
||||
test_v1 += vec1->vec[x] * vec1->vec[x];
|
||||
test_v2 += vec2->vec[x] * vec2->vec[x];
|
||||
}
|
||||
if (!test_v1 || !test_v2){
|
||||
goto AttributeError2; //zero-length vector
|
||||
}
|
||||
|
||||
//dot product
|
||||
for(x = 0; x < size; x++) {
|
||||
dot += vec1->vec[x] * vec2->vec[x];
|
||||
}
|
||||
dot /= (sqrt(test_v1) * sqrt(test_v2));
|
||||
|
||||
angleRads = (double)saacos(dot);
|
||||
|
||||
#ifdef USE_MATHUTILS_DEG
|
||||
return PyFloat_FromDouble(angleRads * (180/ Py_PI));
|
||||
#else
|
||||
return PyFloat_FromDouble(angleRads);
|
||||
#endif
|
||||
AttributeError1:
|
||||
PyErr_SetString(PyExc_AttributeError, "Mathutils.AngleBetweenVecs(): expects (2) VECTOR objects of the same size\n");
|
||||
return NULL;
|
||||
|
||||
AttributeError2:
|
||||
PyErr_SetString(PyExc_AttributeError, "Mathutils.AngleBetweenVecs(): zero length vectors are not acceptable arguments\n");
|
||||
return NULL;
|
||||
}
|
||||
//----------------------------------Mathutils.MidpointVecs() -------------
|
||||
//calculates the midpoint between 2 vectors
|
||||
static PyObject *M_Mathutils_MidpointVecs(PyObject * self, PyObject * args)
|
||||
{
|
||||
VectorObject *vec1 = NULL, *vec2 = NULL;
|
||||
float vec[4];
|
||||
int x;
|
||||
|
||||
if(!PyArg_ParseTuple(args, "O!O!", &vector_Type, &vec1, &vector_Type, &vec2)) {
|
||||
PyErr_SetString(PyExc_TypeError, "Mathutils.MidpointVecs(): expects (2) vector objects of the same size\n");
|
||||
return NULL;
|
||||
}
|
||||
if(vec1->size != vec2->size) {
|
||||
PyErr_SetString(PyExc_AttributeError, "Mathutils.MidpointVecs(): expects (2) vector objects of the same size\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2))
|
||||
return NULL;
|
||||
|
||||
for(x = 0; x < vec1->size; x++) {
|
||||
vec[x] = 0.5f * (vec1->vec[x] + vec2->vec[x]);
|
||||
}
|
||||
return newVectorObject(vec, vec1->size, Py_NEW, NULL);
|
||||
}
|
||||
//----------------------------------Mathutils.ProjectVecs() -------------
|
||||
//projects vector 1 onto vector 2
|
||||
static PyObject *M_Mathutils_ProjectVecs(PyObject * self, PyObject * args)
|
||||
{
|
||||
VectorObject *vec1 = NULL, *vec2 = NULL;
|
||||
float vec[4];
|
||||
double dot = 0.0f, dot2 = 0.0f;
|
||||
int x, size;
|
||||
|
||||
if(!PyArg_ParseTuple(args, "O!O!", &vector_Type, &vec1, &vector_Type, &vec2)) {
|
||||
PyErr_SetString(PyExc_TypeError, "Mathutils.ProjectVecs(): expects (2) vector objects of the same size\n");
|
||||
return NULL;
|
||||
}
|
||||
if(vec1->size != vec2->size) {
|
||||
PyErr_SetString(PyExc_AttributeError, "Mathutils.ProjectVecs(): expects (2) vector objects of the same size\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2))
|
||||
return NULL;
|
||||
|
||||
|
||||
//since they are the same size...
|
||||
size = vec1->size;
|
||||
|
||||
//get dot products
|
||||
for(x = 0; x < size; x++) {
|
||||
dot += vec1->vec[x] * vec2->vec[x];
|
||||
dot2 += vec2->vec[x] * vec2->vec[x];
|
||||
}
|
||||
//projection
|
||||
dot /= dot2;
|
||||
for(x = 0; x < size; x++) {
|
||||
vec[x] = (float)(dot * vec2->vec[x]);
|
||||
}
|
||||
return newVectorObject(vec, size, Py_NEW, NULL);
|
||||
}
|
||||
//----------------------------------MATRIX FUNCTIONS--------------------
|
||||
//----------------------------------Mathutils.RotationMatrix() ----------
|
||||
//mat is a 1D array of floats - row[0][0],row[0][1], row[1][0], etc.
|
||||
//creates a rotation matrix
|
||||
static char M_Mathutils_RotationMatrix_doc[] =
|
||||
".. function:: RotationMatrix(angle, size, axis)\n"
|
||||
"\n"
|
||||
" Create a matrix representing a rotation.\n"
|
||||
"\n"
|
||||
" :arg angle: The angle of rotation desired.\n"
|
||||
" :type angle: float\n"
|
||||
" :arg size: The size of the rotation matrix to construct [2, 4].\n"
|
||||
" :type size: int\n"
|
||||
" :arg axis: a string in ['X', 'Y', 'Z'] or a 3D Vector Object (optional when size is 2).\n"
|
||||
" :type axis: string or vector\n"
|
||||
" :return: A new rotation matrix.\n"
|
||||
" :rtype: Matrix\n";
|
||||
|
||||
static PyObject *M_Mathutils_RotationMatrix(PyObject * self, PyObject * args)
|
||||
{
|
||||
VectorObject *vec = NULL;
|
||||
char *axis = NULL;
|
||||
VectorObject *vec= NULL;
|
||||
char *axis= NULL;
|
||||
int matSize;
|
||||
float angle = 0.0f;
|
||||
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};
|
||||
|
||||
if(!PyArg_ParseTuple(args, "fi|sO!", &angle, &matSize, &axis, &vector_Type, &vec)) {
|
||||
PyErr_SetString(PyExc_TypeError, "Mathutils.RotationMatrix(): expected float int and optional string and vector\n");
|
||||
if(!PyArg_ParseTuple(args, "fi|O", &angle, &matSize, &vec)) {
|
||||
PyErr_SetString(PyExc_TypeError, "Mathutils.RotationMatrix(angle, size, axis): expected float int and a string or vector\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(vec && !VectorObject_Check(vec)) {
|
||||
axis= _PyUnicode_AsString((PyObject *)vec);
|
||||
if(axis==NULL || axis[0]=='\0' || axis[1]!='\0' || axis[0] < 'X' || axis[0] > 'Z') {
|
||||
PyErr_SetString(PyExc_TypeError, "Mathutils.RotationMatrix(): 3rd argument axis value must be a 3D vector or a string in 'X', 'Y', 'Z'\n");
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
/* use the string */
|
||||
vec= NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_MATHUTILS_DEG
|
||||
/* Clamp to -360:360 */
|
||||
while (angle<-360.0f)
|
||||
@@ -379,23 +184,17 @@ static PyObject *M_Mathutils_RotationMatrix(PyObject * self, PyObject * args)
|
||||
PyErr_SetString(PyExc_AttributeError, "Mathutils.RotationMatrix(): can only return a 2x2 3x3 or 4x4 matrix\n");
|
||||
return NULL;
|
||||
}
|
||||
if(matSize == 2 && (axis != NULL || vec != NULL)) {
|
||||
if(matSize == 2 && (vec != NULL)) {
|
||||
PyErr_SetString(PyExc_AttributeError, "Mathutils.RotationMatrix(): cannot create a 2x2 rotation matrix around arbitrary axis\n");
|
||||
return NULL;
|
||||
}
|
||||
if((matSize == 3 || matSize == 4) && axis == NULL) {
|
||||
if((matSize == 3 || matSize == 4) && (axis == NULL) && (vec == NULL)) {
|
||||
PyErr_SetString(PyExc_AttributeError, "Mathutils.RotationMatrix(): please choose an axis of rotation for 3d and 4d matrices\n");
|
||||
return NULL;
|
||||
}
|
||||
if(axis) {
|
||||
if(((strcmp(axis, "r") == 0) || (strcmp(axis, "R") == 0)) && vec == NULL) {
|
||||
PyErr_SetString(PyExc_AttributeError, "Mathutils.RotationMatrix(): please define the arbitrary axis of rotation\n");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if(vec) {
|
||||
if(vec->size != 3) {
|
||||
PyErr_SetString(PyExc_AttributeError, "Mathutils.RotationMatrix(): the arbitrary axis must be a 3D vector\n");
|
||||
PyErr_SetString(PyExc_AttributeError, "Mathutils.RotationMatrix(): the vector axis must be a 3D vector\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -414,35 +213,32 @@ static PyObject *M_Mathutils_RotationMatrix(PyObject * self, PyObject * args)
|
||||
mat[1] = (float) sin (angle);
|
||||
mat[2] = -((float) sin(angle));
|
||||
mat[3] = (float) cos(angle);
|
||||
} else if((strcmp(axis, "x") == 0) || (strcmp(axis, "X") == 0)) {
|
||||
} else if(strcmp(axis, "X") == 0) {
|
||||
//rotation around X
|
||||
mat[0] = 1.0f;
|
||||
mat[4] = (float) cos(angle);
|
||||
mat[5] = (float) sin(angle);
|
||||
mat[7] = -((float) sin(angle));
|
||||
mat[8] = (float) cos(angle);
|
||||
} else if((strcmp(axis, "y") == 0) || (strcmp(axis, "Y") == 0)) {
|
||||
} else if(strcmp(axis, "Y") == 0) {
|
||||
//rotation around Y
|
||||
mat[0] = (float) cos(angle);
|
||||
mat[2] = -((float) sin(angle));
|
||||
mat[4] = 1.0f;
|
||||
mat[6] = (float) sin(angle);
|
||||
mat[8] = (float) cos(angle);
|
||||
} else if((strcmp(axis, "z") == 0) || (strcmp(axis, "Z") == 0)) {
|
||||
} else if(strcmp(axis, "Z") == 0) {
|
||||
//rotation around Z
|
||||
mat[0] = (float) cos(angle);
|
||||
mat[1] = (float) sin(angle);
|
||||
mat[3] = -((float) sin(angle));
|
||||
mat[4] = (float) cos(angle);
|
||||
mat[8] = 1.0f;
|
||||
} else if((strcmp(axis, "r") == 0) || (strcmp(axis, "R") == 0)) {
|
||||
//arbitrary rotation
|
||||
axis_angle_to_mat3( (float (*)[3])mat,vec->vec, angle);
|
||||
|
||||
} else {
|
||||
PyErr_SetString(PyExc_AttributeError, "Mathutils.RotationMatrix(): unrecognizable axis of rotation type - expected x,y,z or r\n");
|
||||
return NULL;
|
||||
/* check for valid vector/axis above */
|
||||
axis_angle_to_mat3( (float (*)[3])mat,vec->vec, angle);
|
||||
}
|
||||
|
||||
if(matSize == 4) {
|
||||
//resize matrix
|
||||
mat[10] = mat[8];
|
||||
@@ -457,8 +253,17 @@ static PyObject *M_Mathutils_RotationMatrix(PyObject * self, PyObject * args)
|
||||
//pass to matrix creation
|
||||
return newMatrixObject(mat, matSize, matSize, Py_NEW, NULL);
|
||||
}
|
||||
//----------------------------------Mathutils.TranslationMatrix() -------
|
||||
//creates a translation matrix
|
||||
|
||||
static char M_Mathutils_TranslationMatrix_doc[] =
|
||||
".. function:: TranslationMatrix(vector)\n"
|
||||
"\n"
|
||||
" Create a matrix representing a translation.\n"
|
||||
"\n"
|
||||
" :arg vector: The translation vector.\n"
|
||||
" :type vector: Vector\n"
|
||||
" :return: An identity matrix with a translation.\n"
|
||||
" :rtype: Matrix\n";
|
||||
|
||||
static PyObject *M_Mathutils_TranslationMatrix(PyObject * self, VectorObject * vec)
|
||||
{
|
||||
float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
|
||||
@@ -486,7 +291,20 @@ static PyObject *M_Mathutils_TranslationMatrix(PyObject * self, VectorObject * v
|
||||
}
|
||||
//----------------------------------Mathutils.ScaleMatrix() -------------
|
||||
//mat is a 1D array of floats - row[0][0],row[0][1], row[1][0], etc.
|
||||
//creates a scaling matrix
|
||||
static char M_Mathutils_ScaleMatrix_doc[] =
|
||||
".. function:: ScaleMatrix(factor, size, axis)\n"
|
||||
"\n"
|
||||
" Create a matrix representing a scaling.\n"
|
||||
"\n"
|
||||
" :arg factor: The factor of scaling to apply.\n"
|
||||
" :type factor: float\n"
|
||||
" :arg size: The size of the scale matrix to construct [2, 4].\n"
|
||||
" :type size: int\n"
|
||||
" :arg axis: Direction to influence scale. (optional).\n"
|
||||
" :type axis: Vector\n"
|
||||
" :return: A new scale matrix.\n"
|
||||
" :rtype: Matrix\n";
|
||||
|
||||
static PyObject *M_Mathutils_ScaleMatrix(PyObject * self, PyObject * args)
|
||||
{
|
||||
VectorObject *vec = NULL;
|
||||
@@ -564,7 +382,19 @@ static PyObject *M_Mathutils_ScaleMatrix(PyObject * self, PyObject * args)
|
||||
}
|
||||
//----------------------------------Mathutils.OrthoProjectionMatrix() ---
|
||||
//mat is a 1D array of floats - row[0][0],row[0][1], row[1][0], etc.
|
||||
//creates an ortho projection matrix
|
||||
static char M_Mathutils_OrthoProjectionMatrix_doc[] =
|
||||
".. function:: OrthoProjectionMatrix(plane, size, axis)\n"
|
||||
"\n"
|
||||
" Create a matrix to represent an orthographic projection.\n"
|
||||
"\n"
|
||||
" :arg plane: Can be any of the following: ['X', 'Y', 'XY', 'XZ', 'YZ', 'R'], where a single axis is for a 2D matrix and 'R' requires axis is given.\n"
|
||||
" :type plane: string\n"
|
||||
" :arg size: The size of the projection matrix to construct [2, 4].\n"
|
||||
" :type size: int\n"
|
||||
" :arg axis: Arbitrary perpendicular plane vector.\n"
|
||||
" :type axis: vector (optional)\n"
|
||||
" :return: A new projection matrix.\n"
|
||||
" :rtype: Matrix\n";
|
||||
static PyObject *M_Mathutils_OrthoProjectionMatrix(PyObject * self, PyObject * args)
|
||||
{
|
||||
VectorObject *vec = NULL;
|
||||
@@ -593,30 +423,21 @@ static PyObject *M_Mathutils_OrthoProjectionMatrix(PyObject * self, PyObject * a
|
||||
|
||||
}
|
||||
if(vec == NULL) { //ortho projection onto cardinal plane
|
||||
if(((strcmp(plane, "x") == 0)
|
||||
|| (strcmp(plane, "X") == 0)) && matSize == 2) {
|
||||
if((strcmp(plane, "X") == 0) && matSize == 2) {
|
||||
mat[0] = 1.0f;
|
||||
} else if(((strcmp(plane, "y") == 0)
|
||||
|| (strcmp(plane, "Y") == 0))
|
||||
&& matSize == 2) {
|
||||
} else if((strcmp(plane, "Y") == 0) && matSize == 2) {
|
||||
mat[3] = 1.0f;
|
||||
} else if(((strcmp(plane, "xy") == 0)
|
||||
|| (strcmp(plane, "XY") == 0))
|
||||
&& matSize > 2) {
|
||||
} else if((strcmp(plane, "XY") == 0) && matSize > 2) {
|
||||
mat[0] = 1.0f;
|
||||
mat[4] = 1.0f;
|
||||
} else if(((strcmp(plane, "xz") == 0)
|
||||
|| (strcmp(plane, "XZ") == 0))
|
||||
&& matSize > 2) {
|
||||
} else if((strcmp(plane, "XZ") == 0) && matSize > 2) {
|
||||
mat[0] = 1.0f;
|
||||
mat[8] = 1.0f;
|
||||
} else if(((strcmp(plane, "yz") == 0)
|
||||
|| (strcmp(plane, "YZ") == 0))
|
||||
&& matSize > 2) {
|
||||
} else if((strcmp(plane, "YZ") == 0) && matSize > 2) {
|
||||
mat[4] = 1.0f;
|
||||
mat[8] = 1.0f;
|
||||
} else {
|
||||
PyErr_SetString(PyExc_AttributeError, "Mathutils.OrthoProjectionMatrix(): unknown plane - expected: x, y, xy, xz, yz\n");
|
||||
PyErr_SetString(PyExc_AttributeError, "Mathutils.OrthoProjectionMatrix(): unknown plane - expected: X, Y, XY, XZ, YZ\n");
|
||||
return NULL;
|
||||
}
|
||||
} else { //arbitrary plane
|
||||
@@ -628,15 +449,12 @@ static PyObject *M_Mathutils_OrthoProjectionMatrix(PyObject * self, PyObject * a
|
||||
for(x = 0; x < vec->size; x++) {
|
||||
vec->vec[x] /= norm;
|
||||
}
|
||||
if(((strcmp(plane, "r") == 0)
|
||||
|| (strcmp(plane, "R") == 0)) && matSize == 2) {
|
||||
if((strcmp(plane, "R") == 0) && matSize == 2) {
|
||||
mat[0] = 1 - (vec->vec[0] * vec->vec[0]);
|
||||
mat[1] = -(vec->vec[0] * vec->vec[1]);
|
||||
mat[2] = -(vec->vec[0] * vec->vec[1]);
|
||||
mat[3] = 1 - (vec->vec[1] * vec->vec[1]);
|
||||
} else if(((strcmp(plane, "r") == 0)
|
||||
|| (strcmp(plane, "R") == 0))
|
||||
&& matSize > 2) {
|
||||
} else if((strcmp(plane, "R") == 0) && matSize > 2) {
|
||||
mat[0] = 1 - (vec->vec[0] * vec->vec[0]);
|
||||
mat[1] = -(vec->vec[0] * vec->vec[1]);
|
||||
mat[2] = -(vec->vec[0] * vec->vec[2]);
|
||||
@@ -665,8 +483,21 @@ static PyObject *M_Mathutils_OrthoProjectionMatrix(PyObject * self, PyObject * a
|
||||
//pass to matrix creation
|
||||
return newMatrixObject(mat, matSize, matSize, Py_NEW, NULL);
|
||||
}
|
||||
//----------------------------------Mathutils.ShearMatrix() -------------
|
||||
//creates a shear matrix
|
||||
|
||||
static char M_Mathutils_ShearMatrix_doc[] =
|
||||
".. function:: ShearMatrix(plane, factor, size)\n"
|
||||
"\n"
|
||||
" Create a matrix to represent an shear transformation.\n"
|
||||
"\n"
|
||||
" :arg plane: Can be any of the following: ['X', 'Y', 'XY', 'XZ', 'YZ'], where a single axis is for a 2D matrix.\n"
|
||||
" :type plane: string\n"
|
||||
" :arg factor: The factor of shear to apply.\n"
|
||||
" :type factor: float\n"
|
||||
" :arg size: The size of the shear matrix to construct [2, 4].\n"
|
||||
" :type size: int\n"
|
||||
" :return: A new shear matrix.\n"
|
||||
" :rtype: Matrix\n";
|
||||
|
||||
static PyObject *M_Mathutils_ShearMatrix(PyObject * self, PyObject * args)
|
||||
{
|
||||
int matSize;
|
||||
@@ -684,31 +515,27 @@ static PyObject *M_Mathutils_ShearMatrix(PyObject * self, PyObject * args)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(((strcmp(plane, "x") == 0) || (strcmp(plane, "X") == 0))
|
||||
if((strcmp(plane, "X") == 0)
|
||||
&& matSize == 2) {
|
||||
mat[0] = 1.0f;
|
||||
mat[2] = factor;
|
||||
mat[3] = 1.0f;
|
||||
} else if(((strcmp(plane, "y") == 0)
|
||||
|| (strcmp(plane, "Y") == 0)) && matSize == 2) {
|
||||
} else if((strcmp(plane, "Y") == 0) && matSize == 2) {
|
||||
mat[0] = 1.0f;
|
||||
mat[1] = factor;
|
||||
mat[3] = 1.0f;
|
||||
} else if(((strcmp(plane, "xy") == 0)
|
||||
|| (strcmp(plane, "XY") == 0)) && matSize > 2) {
|
||||
} else if((strcmp(plane, "XY") == 0) && matSize > 2) {
|
||||
mat[0] = 1.0f;
|
||||
mat[4] = 1.0f;
|
||||
mat[6] = factor;
|
||||
mat[7] = factor;
|
||||
} else if(((strcmp(plane, "xz") == 0)
|
||||
|| (strcmp(plane, "XZ") == 0)) && matSize > 2) {
|
||||
} else if((strcmp(plane, "XZ") == 0) && matSize > 2) {
|
||||
mat[0] = 1.0f;
|
||||
mat[3] = factor;
|
||||
mat[4] = 1.0f;
|
||||
mat[5] = factor;
|
||||
mat[8] = 1.0f;
|
||||
} else if(((strcmp(plane, "yz") == 0)
|
||||
|| (strcmp(plane, "YZ") == 0)) && matSize > 2) {
|
||||
} else if((strcmp(plane, "YZ") == 0) && matSize > 2) {
|
||||
mat[0] = 1.0f;
|
||||
mat[1] = factor;
|
||||
mat[2] = factor;
|
||||
@@ -732,375 +559,6 @@ static PyObject *M_Mathutils_ShearMatrix(PyObject * self, PyObject * args)
|
||||
//pass to matrix creation
|
||||
return newMatrixObject(mat, matSize, matSize, Py_NEW, NULL);
|
||||
}
|
||||
//----------------------------------QUATERNION FUNCTIONS-----------------
|
||||
|
||||
//----------------------------------Mathutils.DifferenceQuats() ---------
|
||||
//returns the difference between 2 quaternions
|
||||
static PyObject *M_Mathutils_DifferenceQuats(PyObject * self, PyObject * args)
|
||||
{
|
||||
QuaternionObject *quatU = NULL, *quatV = NULL;
|
||||
float quat[4], tempQuat[4];
|
||||
double dot = 0.0f;
|
||||
int x;
|
||||
|
||||
if(!PyArg_ParseTuple(args, "O!O!", &quaternion_Type, &quatU, &quaternion_Type, &quatV)) {
|
||||
PyErr_SetString(PyExc_TypeError, "Mathutils.DifferenceQuats(): expected Quaternion types");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!BaseMath_ReadCallback(quatU) || !BaseMath_ReadCallback(quatV))
|
||||
return NULL;
|
||||
|
||||
tempQuat[0] = quatU->quat[0];
|
||||
tempQuat[1] = -quatU->quat[1];
|
||||
tempQuat[2] = -quatU->quat[2];
|
||||
tempQuat[3] = -quatU->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, quatV->quat);
|
||||
return newQuaternionObject(quat, Py_NEW, NULL);
|
||||
}
|
||||
//----------------------------------Mathutils.Slerp() ------------------
|
||||
//attemps to interpolate 2 quaternions and return the result
|
||||
static PyObject *M_Mathutils_Slerp(PyObject * self, PyObject * args)
|
||||
{
|
||||
QuaternionObject *quatU = NULL, *quatV = NULL;
|
||||
float quat[4], quat_u[4], quat_v[4], param;
|
||||
double x, y, dot, sinT, angle, IsinT;
|
||||
int z;
|
||||
|
||||
if(!PyArg_ParseTuple(args, "O!O!f", &quaternion_Type, &quatU, &quaternion_Type, &quatV, ¶m)) {
|
||||
PyErr_SetString(PyExc_TypeError, "Mathutils.Slerp(): expected Quaternion types and float");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!BaseMath_ReadCallback(quatU) || !BaseMath_ReadCallback(quatV))
|
||||
return NULL;
|
||||
|
||||
if(param > 1.0f || param < 0.0f) {
|
||||
PyErr_SetString(PyExc_AttributeError, "Mathutils.Slerp(): interpolation factor must be between 0.0 and 1.0");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//copy quats
|
||||
for(z = 0; z < 4; z++){
|
||||
quat_u[z] = quatU->quat[z];
|
||||
quat_v[z] = quatV->quat[z];
|
||||
}
|
||||
|
||||
//dot product
|
||||
dot = quat_u[0] * quat_v[0] + quat_u[1] * quat_v[1] +
|
||||
quat_u[2] * quat_v[2] + quat_u[3] * quat_v[3];
|
||||
|
||||
//if negative negate a quat (shortest arc)
|
||||
if(dot < 0.0f) {
|
||||
quat_v[0] = -quat_v[0];
|
||||
quat_v[1] = -quat_v[1];
|
||||
quat_v[2] = -quat_v[2];
|
||||
quat_v[3] = -quat_v[3];
|
||||
dot = -dot;
|
||||
}
|
||||
if(dot > .99999f) { //very close
|
||||
x = 1.0f - param;
|
||||
y = param;
|
||||
} else {
|
||||
//calculate sin of angle
|
||||
sinT = sqrt(1.0f - (dot * dot));
|
||||
//calculate angle
|
||||
angle = atan2(sinT, dot);
|
||||
//caluculate inverse of sin(theta)
|
||||
IsinT = 1.0f / sinT;
|
||||
x = sin((1.0f - param) * angle) * IsinT;
|
||||
y = sin(param * angle) * IsinT;
|
||||
}
|
||||
//interpolate
|
||||
quat[0] = (float)(quat_u[0] * x + quat_v[0] * y);
|
||||
quat[1] = (float)(quat_u[1] * x + quat_v[1] * y);
|
||||
quat[2] = (float)(quat_u[2] * x + quat_v[2] * y);
|
||||
quat[3] = (float)(quat_u[3] * x + quat_v[3] * y);
|
||||
|
||||
return newQuaternionObject(quat, Py_NEW, NULL);
|
||||
}
|
||||
//----------------------------------EULER FUNCTIONS----------------------
|
||||
//---------------------------------INTERSECTION FUNCTIONS--------------------
|
||||
//----------------------------------Mathutils.Intersect() -------------------
|
||||
static PyObject *M_Mathutils_Intersect( PyObject * self, PyObject * args )
|
||||
{
|
||||
VectorObject *ray, *ray_off, *vec1, *vec2, *vec3;
|
||||
float dir[3], orig[3], v1[3], v2[3], v3[3], e1[3], e2[3], pvec[3], tvec[3], qvec[3];
|
||||
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_Mathutils_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_Mathutils_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_Mathutils_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_Mathutils_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;
|
||||
}
|
||||
}
|
||||
|
||||
/* Utility functions */
|
||||
|
||||
@@ -1219,3 +677,51 @@ void BaseMathObject_dealloc(BaseMathObject * self)
|
||||
Py_TYPE(self)->tp_free(self); // PyObject_DEL(self); // breaks subtypes
|
||||
}
|
||||
|
||||
/*----------------------------MODULE INIT-------------------------*/
|
||||
struct PyMethodDef M_Mathutils_methods[] = {
|
||||
{"RotationMatrix", (PyCFunction) M_Mathutils_RotationMatrix, METH_VARARGS, M_Mathutils_RotationMatrix_doc},
|
||||
{"ScaleMatrix", (PyCFunction) M_Mathutils_ScaleMatrix, METH_VARARGS, M_Mathutils_ScaleMatrix_doc},
|
||||
{"ShearMatrix", (PyCFunction) M_Mathutils_ShearMatrix, METH_VARARGS, M_Mathutils_ShearMatrix_doc},
|
||||
{"TranslationMatrix", (PyCFunction) M_Mathutils_TranslationMatrix, METH_O, M_Mathutils_TranslationMatrix_doc},
|
||||
{"OrthoProjectionMatrix", (PyCFunction) M_Mathutils_OrthoProjectionMatrix, METH_VARARGS, M_Mathutils_OrthoProjectionMatrix_doc},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
static struct PyModuleDef M_Mathutils_module_def = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"Mathutils", /* m_name */
|
||||
M_Mathutils_doc, /* m_doc */
|
||||
0, /* m_size */
|
||||
M_Mathutils_methods, /* m_methods */
|
||||
0, /* m_reload */
|
||||
0, /* m_traverse */
|
||||
0, /* m_clear */
|
||||
0, /* m_free */
|
||||
};
|
||||
|
||||
PyObject *Mathutils_Init(void)
|
||||
{
|
||||
PyObject *submodule;
|
||||
|
||||
if( PyType_Ready( &vector_Type ) < 0 )
|
||||
return NULL;
|
||||
if( PyType_Ready( &matrix_Type ) < 0 )
|
||||
return NULL;
|
||||
if( PyType_Ready( &euler_Type ) < 0 )
|
||||
return NULL;
|
||||
if( PyType_Ready( &quaternion_Type ) < 0 )
|
||||
return NULL;
|
||||
|
||||
submodule = PyModule_Create(&M_Mathutils_module_def);
|
||||
PyDict_SetItemString(PySys_GetObject("modules"), M_Mathutils_module_def.m_name, submodule);
|
||||
|
||||
/* each type has its own new() function */
|
||||
PyModule_AddObject( submodule, "Vector", (PyObject *)&vector_Type );
|
||||
PyModule_AddObject( submodule, "Matrix", (PyObject *)&matrix_Type );
|
||||
PyModule_AddObject( submodule, "Euler", (PyObject *)&euler_Type );
|
||||
PyModule_AddObject( submodule, "Quaternion", (PyObject *)&quaternion_Type );
|
||||
|
||||
mathutils_matrix_vector_cb_index= Mathutils_RegisterCallback(&mathutils_matrix_vector_cb);
|
||||
|
||||
return (submodule);
|
||||
}
|
||||
|
||||
@@ -33,29 +33,6 @@
|
||||
#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}
|
||||
};
|
||||
|
||||
//----------------------------------Mathutils.Euler() -------------------
|
||||
//makes a new euler for you to play with
|
||||
static PyObject *Euler_new(PyTypeObject * type, PyObject * args, PyObject * kwargs)
|
||||
@@ -108,6 +85,15 @@ static PyObject *Euler_new(PyTypeObject * type, PyObject * args, PyObject * kwar
|
||||
//-----------------------------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: Quaternion\n";
|
||||
|
||||
static PyObject *Euler_ToQuat(EulerObject * self)
|
||||
{
|
||||
float quat[4];
|
||||
@@ -132,6 +118,14 @@ static PyObject *Euler_ToQuat(EulerObject * self)
|
||||
}
|
||||
//----------------------------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: 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};
|
||||
@@ -156,6 +150,14 @@ static PyObject *Euler_ToMatrix(EulerObject * self)
|
||||
}
|
||||
//----------------------------Euler.unique()-----------------------
|
||||
//sets the x,y,z values to a unique euler rotation
|
||||
|
||||
static char Euler_Unique_doc[] =
|
||||
".. method:: unique()\n"
|
||||
"\n"
|
||||
" Calculate a unique rotation for this euler. Avoids gimble lock.\n"
|
||||
" :return: an instance of itself\n"
|
||||
" :rtype: Euler\n";
|
||||
|
||||
static PyObject *Euler_Unique(EulerObject * self)
|
||||
{
|
||||
#define PI_2 (Py_PI * 2.0)
|
||||
@@ -220,6 +222,13 @@ static PyObject *Euler_Unique(EulerObject * 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"
|
||||
" :return: an instance of itself\n"
|
||||
" :rtype: Euler\n";
|
||||
|
||||
static PyObject *Euler_Zero(EulerObject * self)
|
||||
{
|
||||
self->eul[0] = 0.0;
|
||||
@@ -278,6 +287,16 @@ static PyObject *Euler_Rotate(EulerObject * self, PyObject *args)
|
||||
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: Euler\n"
|
||||
" :return: an instance of itself.\n"
|
||||
" :rtype: Euler\n";
|
||||
|
||||
static PyObject *Euler_MakeCompatible(EulerObject * self, EulerObject *value)
|
||||
{
|
||||
#ifdef USE_MATHUTILS_DEG
|
||||
@@ -317,6 +336,17 @@ 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: 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))
|
||||
@@ -545,6 +575,20 @@ static PyGetSetDef Euler_getseters[] = {
|
||||
{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--------------------------
|
||||
PyTypeObject euler_Type = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
|
||||
@@ -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->matrix);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*-----------------------------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: Quaternion\n";
|
||||
|
||||
static PyObject *Matrix_toQuat(MatrixObject * self)
|
||||
{
|
||||
float quat[4];
|
||||
@@ -237,6 +229,16 @@ static PyObject *Matrix_toQuat(MatrixObject * self)
|
||||
return newQuaternionObject(quat, Py_NEW, NULL);
|
||||
}
|
||||
/*---------------------------Matrix.toEuler() --------------------*/
|
||||
static char Matrix_toEuler_doc[] =
|
||||
".. method:: to_euler(euler_compat)\n"
|
||||
"\n"
|
||||
" Return an Euler representation of the rotation matrix (3x3 or 4x4 matrix only).\n"
|
||||
"\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: Euler\n"
|
||||
" :return: Euler representation of the matrix.\n"
|
||||
" :rtype: Euler\n";
|
||||
|
||||
PyObject *Matrix_toEuler(MatrixObject * self, PyObject *args)
|
||||
{
|
||||
float eul[3], eul_compatf[3];
|
||||
@@ -288,6 +290,13 @@ PyObject *Matrix_toEuler(MatrixObject * self, PyObject *args)
|
||||
return newEulerObject(eul, Py_NEW, NULL);
|
||||
}
|
||||
/*---------------------------Matrix.resize4x4() ------------------*/
|
||||
static char Matrix_Resize4x4_doc[] =
|
||||
".. method:: resize4x4()\n"
|
||||
"\n"
|
||||
" Resize the matrix to 4x4.\n"
|
||||
" :return: an instance of itself.\n"
|
||||
" :rtype: Vector\n";
|
||||
|
||||
PyObject *Matrix_Resize4x4(MatrixObject * self)
|
||||
{
|
||||
int x, first_row_elem, curr_pos, new_pos, blank_columns, blank_rows, index;
|
||||
@@ -345,6 +354,15 @@ PyObject *Matrix_Resize4x4(MatrixObject * self)
|
||||
return (PyObject *)self;
|
||||
}
|
||||
/*---------------------------Matrix.translationPart() ------------*/
|
||||
static char Matrix_TranslationPart_doc[] =
|
||||
".. method:: translation_part()\n"
|
||||
"\n"
|
||||
" Return a the translation part of a 4 row matrix.\n"
|
||||
" :return: Return a the translation of a matrix.\n"
|
||||
" :rtype: 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];
|
||||
@@ -364,6 +382,15 @@ PyObject *Matrix_TranslationPart(MatrixObject * self)
|
||||
return newVectorObject(vec, 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"
|
||||
" :return: Return the 3d matrix for rotation and scale.\n"
|
||||
" :rtype: 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,
|
||||
@@ -390,6 +417,15 @@ 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"
|
||||
" :return: Return a the scale of a matrix.\n"
|
||||
" :rtype: 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];
|
||||
@@ -419,12 +455,22 @@ 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"
|
||||
" :return: an instance of itself.\n"
|
||||
" :rtype: 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 +483,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*/
|
||||
@@ -478,10 +522,17 @@ PyObject *Matrix_Invert(MatrixObject * self)
|
||||
|
||||
|
||||
/*---------------------------Matrix.determinant() ----------------*/
|
||||
static char Matrix_Determinant_doc[] =
|
||||
".. method:: determinant()\n"
|
||||
"\n"
|
||||
" Return the determinant of a matrix.\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 +541,18 @@ 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"
|
||||
" :return: an instance of itself\n"
|
||||
" :rtype: Matrix\n"
|
||||
"\n"
|
||||
" .. seealso:: <http://en.wikipedia.org/wiki/Transpose>\n";
|
||||
|
||||
PyObject *Matrix_Transpose(MatrixObject * self)
|
||||
{
|
||||
float t = 0.0f;
|
||||
@@ -535,6 +582,13 @@ PyObject *Matrix_Transpose(MatrixObject * self)
|
||||
|
||||
|
||||
/*---------------------------Matrix.zero() -----------------------*/
|
||||
static char Matrix_Zero_doc[] =
|
||||
".. method:: zero()\n"
|
||||
"\n"
|
||||
" Set all the matrix values to zero.\n"
|
||||
" :return: an instance of itself\n"
|
||||
" :rtype: Matrix\n";
|
||||
|
||||
PyObject *Matrix_Zero(MatrixObject * self)
|
||||
{
|
||||
int row, col;
|
||||
@@ -552,6 +606,17 @@ 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"
|
||||
" :return: an instance of itself\n"
|
||||
" :rtype: 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))
|
||||
@@ -580,7 +645,14 @@ 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"
|
||||
" :return: an instance of itself\n"
|
||||
" :rtype: Matrix\n";
|
||||
|
||||
PyObject *Matrix_copy(MatrixObject * self)
|
||||
{
|
||||
if(!BaseMath_ReadCallback(self))
|
||||
@@ -1162,6 +1234,24 @@ static PyGetSetDef Matrix_getseters[] = {
|
||||
{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_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--------------------------*/
|
||||
PyTypeObject matrix_Type = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
|
||||
@@ -32,137 +32,17 @@
|
||||
#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(euler_compat)\n"
|
||||
"\n"
|
||||
" Return Euler representation of the quaternion.\n"
|
||||
"\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: Euler\n"
|
||||
" :return: Euler representation of the quaternion.\n"
|
||||
" :rtype: Euler\n";
|
||||
|
||||
static PyObject *Quaternion_ToEuler(QuaternionObject * self, PyObject *args)
|
||||
{
|
||||
float eul[3];
|
||||
@@ -212,7 +92,14 @@ static PyObject *Quaternion_ToEuler(QuaternionObject * self, PyObject *args)
|
||||
return newEulerObject(eul, 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: Matrix\n";
|
||||
|
||||
static PyObject *Quaternion_ToMatrix(QuaternionObject * self)
|
||||
{
|
||||
float mat[9]; /* all values are set */
|
||||
@@ -225,7 +112,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: Quaternion\n"
|
||||
" :return: The cross product.\n"
|
||||
" :rtype: Quaternion\n";
|
||||
|
||||
static PyObject *Quaternion_Cross(QuaternionObject * self, QuaternionObject * value)
|
||||
{
|
||||
float quat[4];
|
||||
@@ -243,7 +139,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: Quaternion\n"
|
||||
" :return: The dot product.\n"
|
||||
" :rtype: Quaternion\n";
|
||||
|
||||
static PyObject *Quaternion_Dot(QuaternionObject * self, QuaternionObject * value)
|
||||
{
|
||||
if (!QuaternionObject_Check(value)) {
|
||||
@@ -257,8 +162,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: Quaternion\n"
|
||||
" :return: the rotational difference between the two quat rotations.\n"
|
||||
" :rtype: 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: Quaternion\n"
|
||||
" :arg factor: The interpolation value in [0.0, 1.0].\n"
|
||||
" :type factor: float\n"
|
||||
" :return: The interpolated rotation.\n"
|
||||
" :rtype: Quaternion\n";
|
||||
|
||||
static PyObject *Quaternion_Slerp(QuaternionObject *self, PyObject *args)
|
||||
{
|
||||
QuaternionObject *value;
|
||||
float quat[4], fac;
|
||||
|
||||
if(!PyArg_ParseTuple(args, "O!f", &quaternion_Type, &value, &fac)) {
|
||||
PyErr_SetString(PyExc_TypeError, "Mathutils.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, "Mathutils.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: Quaternion\n";
|
||||
|
||||
static PyObject *Quaternion_Normalize(QuaternionObject * self)
|
||||
{
|
||||
if(!BaseMath_ReadCallback(self))
|
||||
@@ -271,7 +258,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: Quaternion\n";
|
||||
|
||||
static PyObject *Quaternion_Inverse(QuaternionObject * self)
|
||||
{
|
||||
if(!BaseMath_ReadCallback(self))
|
||||
@@ -284,7 +278,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: Quaternion\n";
|
||||
|
||||
static PyObject *Quaternion_Identity(QuaternionObject * self)
|
||||
{
|
||||
if(!BaseMath_ReadCallback(self))
|
||||
@@ -297,7 +298,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: Quaternion\n";
|
||||
|
||||
static PyObject *Quaternion_Negate(QuaternionObject * self)
|
||||
{
|
||||
if(!BaseMath_ReadCallback(self))
|
||||
@@ -310,7 +318,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: Quaternion\n";
|
||||
|
||||
static PyObject *Quaternion_Conjugate(QuaternionObject * self)
|
||||
{
|
||||
if(!BaseMath_ReadCallback(self))
|
||||
@@ -323,7 +338,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: 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))
|
||||
@@ -702,52 +726,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
|
||||
#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);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------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", (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},
|
||||
{NULL,NULL,NULL,NULL,NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
|
||||
//------------------PY_OBECT DEFINITION--------------------------
|
||||
PyTypeObject quaternion_Type = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
@@ -843,3 +954,4 @@ PyObject *newQuaternionObject_cb(PyObject *cb_user, int cb_type, int cb_subtype)
|
||||
|
||||
return (PyObject *)self;
|
||||
}
|
||||
|
||||
|
||||
@@ -41,37 +41,6 @@
|
||||
|
||||
static PyObject *row_vector_multiplication(VectorObject* vec, MatrixObject * mat); /* utility func */
|
||||
|
||||
/*-----------------------METHOD DEFINITIONS ----------------------*/
|
||||
static PyObject *Vector_Zero( VectorObject * self );
|
||||
static PyObject *Vector_Normalize( VectorObject * self );
|
||||
static PyObject *Vector_Negate( VectorObject * self );
|
||||
static PyObject *Vector_Resize2D( VectorObject * self );
|
||||
static PyObject *Vector_Resize3D( VectorObject * self );
|
||||
static PyObject *Vector_Resize4D( VectorObject * self );
|
||||
static PyObject *Vector_ToTuple( VectorObject * self, PyObject *value );
|
||||
static PyObject *Vector_ToTrackQuat( VectorObject * self, PyObject * args );
|
||||
static PyObject *Vector_Reflect( VectorObject *self, VectorObject *value );
|
||||
static PyObject *Vector_Cross( VectorObject * self, VectorObject * value );
|
||||
static PyObject *Vector_Dot( VectorObject * self, VectorObject * value );
|
||||
static PyObject *Vector_copy( VectorObject * self );
|
||||
|
||||
static struct PyMethodDef Vector_methods[] = {
|
||||
{"zero", (PyCFunction) Vector_Zero, METH_NOARGS, NULL},
|
||||
{"normalize", (PyCFunction) Vector_Normalize, METH_NOARGS, NULL},
|
||||
{"negate", (PyCFunction) Vector_Negate, METH_NOARGS, NULL},
|
||||
{"resize2D", (PyCFunction) Vector_Resize2D, METH_NOARGS, NULL},
|
||||
{"resize3D", (PyCFunction) Vector_Resize3D, METH_NOARGS, NULL},
|
||||
{"resize4D", (PyCFunction) Vector_Resize4D, METH_NOARGS, NULL},
|
||||
{"toTuple", (PyCFunction) Vector_ToTuple, METH_O, NULL},
|
||||
{"toTrackQuat", ( PyCFunction ) Vector_ToTrackQuat, METH_VARARGS, NULL},
|
||||
{"reflect", ( PyCFunction ) Vector_Reflect, METH_O, NULL},
|
||||
{"cross", ( PyCFunction ) Vector_Cross, METH_O, NULL},
|
||||
{"dot", ( PyCFunction ) Vector_Dot, METH_O, NULL},
|
||||
{"copy", (PyCFunction) Vector_copy, METH_NOARGS, NULL},
|
||||
{"__copy__", (PyCFunction) Vector_copy, METH_NOARGS, NULL},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
//----------------------------------Mathutils.Vector() ------------------
|
||||
// Supports 2D, 3D, and 4D vector objects both int and float values
|
||||
// accepted. Mixed float and int values accepted. Ints are parsed to float
|
||||
@@ -124,8 +93,13 @@ static PyObject *Vector_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||
}
|
||||
|
||||
/*-----------------------------METHODS---------------------------- */
|
||||
/*----------------------------Vector.zero() ----------------------
|
||||
set the vector data to 0,0,0 */
|
||||
static char Vector_Zero_doc[] =
|
||||
".. method:: zero()\n"
|
||||
"\n"
|
||||
" Set all values to zero.\n"
|
||||
" :return: an instance of itself\n"
|
||||
" :rtype: vector\n";
|
||||
|
||||
static PyObject *Vector_Zero(VectorObject * self)
|
||||
{
|
||||
int i;
|
||||
@@ -137,8 +111,18 @@ static PyObject *Vector_Zero(VectorObject * self)
|
||||
Py_INCREF(self);
|
||||
return (PyObject*)self;
|
||||
}
|
||||
/*----------------------------Vector.normalize() -----------------
|
||||
normalize the vector data to a unit vector */
|
||||
/*----------------------------Vector.normalize() ----------------- */
|
||||
static char Vector_Normalize_doc[] =
|
||||
".. method:: normalize()\n"
|
||||
"\n"
|
||||
" Normalize the vector, making the length of the vector always 1.0.\n"
|
||||
" :return: an instance of itself\n"
|
||||
" :rtype: vector\n"
|
||||
"\n"
|
||||
" .. warning:: Normalizing a vector where all values are zero results in all axis having a nan value (not a number).\n"
|
||||
"\n"
|
||||
" .. note:: Normalize works for vectors of all sizes, however 4D Vectors w axis is left untouched.\n";
|
||||
|
||||
static PyObject *Vector_Normalize(VectorObject * self)
|
||||
{
|
||||
int i;
|
||||
@@ -161,8 +145,14 @@ static PyObject *Vector_Normalize(VectorObject * self)
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------Vector.resize2D() ------------------
|
||||
resize the vector to x,y */
|
||||
/*----------------------------Vector.resize2D() ------------------ */
|
||||
static char Vector_Resize2D_doc[] =
|
||||
".. method:: resize2D()\n"
|
||||
"\n"
|
||||
" Resize the vector to 2D (x, y).\n"
|
||||
" :return: an instance of itself\n"
|
||||
" :rtype: vector\n";
|
||||
|
||||
static PyObject *Vector_Resize2D(VectorObject * self)
|
||||
{
|
||||
if(self->wrapped==Py_WRAP) {
|
||||
@@ -184,8 +174,14 @@ static PyObject *Vector_Resize2D(VectorObject * self)
|
||||
Py_INCREF(self);
|
||||
return (PyObject*)self;
|
||||
}
|
||||
/*----------------------------Vector.resize3D() ------------------
|
||||
resize the vector to x,y,z */
|
||||
/*----------------------------Vector.resize3D() ------------------ */
|
||||
static char Vector_Resize3D_doc[] =
|
||||
".. method:: resize3D()\n"
|
||||
"\n"
|
||||
" Resize the vector to 3D (x, y, z).\n"
|
||||
" :return: an instance of itself\n"
|
||||
" :rtype: vector\n";
|
||||
|
||||
static PyObject *Vector_Resize3D(VectorObject * self)
|
||||
{
|
||||
if (self->wrapped==Py_WRAP) {
|
||||
@@ -210,8 +206,14 @@ static PyObject *Vector_Resize3D(VectorObject * self)
|
||||
Py_INCREF(self);
|
||||
return (PyObject*)self;
|
||||
}
|
||||
/*----------------------------Vector.resize4D() ------------------
|
||||
resize the vector to x,y,z,w */
|
||||
/*----------------------------Vector.resize4D() ------------------ */
|
||||
static char Vector_Resize4D_doc[] =
|
||||
".. method:: resize4D()\n"
|
||||
"\n"
|
||||
" Resize the vector to 4D (x, y, z, w).\n"
|
||||
" :return: an instance of itself\n"
|
||||
" :rtype: vector\n";
|
||||
|
||||
static PyObject *Vector_Resize4D(VectorObject * self)
|
||||
{
|
||||
if(self->wrapped==Py_WRAP) {
|
||||
@@ -239,8 +241,17 @@ static PyObject *Vector_Resize4D(VectorObject * self)
|
||||
return (PyObject*)self;
|
||||
}
|
||||
|
||||
/*----------------------------Vector.resize4D() ------------------
|
||||
resize the vector to x,y,z,w */
|
||||
/*----------------------------Vector.toTuple() ------------------ */
|
||||
static char Vector_ToTuple_doc[] =
|
||||
".. method:: to_tuple(precision)\n"
|
||||
"\n"
|
||||
" Return this vector as a tuple with.\n"
|
||||
"\n"
|
||||
" :arg precision: The number to round the value to in [0, 21].\n"
|
||||
" :type precision: int\n"
|
||||
" :return: the values of the vector rounded by *precision*\n"
|
||||
" :rtype: tuple\n";
|
||||
|
||||
static PyObject *Vector_ToTuple(VectorObject * self, PyObject *value)
|
||||
{
|
||||
int ndigits= PyLong_AsSsize_t(value);
|
||||
@@ -265,8 +276,19 @@ static PyObject *Vector_ToTuple(VectorObject * self, PyObject *value)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*----------------------------Vector.toTrackQuat(track, up) ----------------------
|
||||
extract a quaternion from the vector and the track and up axis */
|
||||
/*----------------------------Vector.toTrackQuat(track, up) ---------------------- */
|
||||
static char Vector_ToTrackQuat_doc[] =
|
||||
".. method:: to_track_quat(track, up)\n"
|
||||
"\n"
|
||||
" Return a quaternion rotation from the vector and the track and up axis.\n"
|
||||
"\n"
|
||||
" :arg track: Track axis in ['X', 'Y', 'Z', '-X', '-Y', '-Z'].\n"
|
||||
" :type track: string\n"
|
||||
" :arg up: Up axis in ['X', 'Y', 'Z'].\n"
|
||||
" :type up: string\n"
|
||||
" :return: rotation from the vector and the track and up axis."
|
||||
" :rtype: Quaternion\n";
|
||||
|
||||
static PyObject *Vector_ToTrackQuat( VectorObject * self, PyObject * args )
|
||||
{
|
||||
float vec[3], quat[4];
|
||||
@@ -290,14 +312,11 @@ static PyObject *Vector_ToTrackQuat( VectorObject * self, PyObject * args )
|
||||
if (strack[0] == '-') {
|
||||
switch(strack[1]) {
|
||||
case 'X':
|
||||
case 'x':
|
||||
track = 3;
|
||||
break;
|
||||
case 'Y':
|
||||
case 'y':
|
||||
track = 4;
|
||||
break;
|
||||
case 'z':
|
||||
case 'Z':
|
||||
track = 5;
|
||||
break;
|
||||
@@ -315,14 +334,11 @@ static PyObject *Vector_ToTrackQuat( VectorObject * self, PyObject * args )
|
||||
switch(strack[0]) {
|
||||
case '-':
|
||||
case 'X':
|
||||
case 'x':
|
||||
track = 0;
|
||||
break;
|
||||
case 'Y':
|
||||
case 'y':
|
||||
track = 1;
|
||||
break;
|
||||
case 'z':
|
||||
case 'Z':
|
||||
track = 2;
|
||||
break;
|
||||
@@ -341,14 +357,11 @@ static PyObject *Vector_ToTrackQuat( VectorObject * self, PyObject * args )
|
||||
if (strlen(sup) == 1) {
|
||||
switch(*sup) {
|
||||
case 'X':
|
||||
case 'x':
|
||||
up = 0;
|
||||
break;
|
||||
case 'Y':
|
||||
case 'y':
|
||||
up = 1;
|
||||
break;
|
||||
case 'z':
|
||||
case 'Z':
|
||||
up = 2;
|
||||
break;
|
||||
@@ -385,6 +398,16 @@ static PyObject *Vector_ToTrackQuat( VectorObject * self, PyObject * args )
|
||||
return a reflected vector on the mirror normal
|
||||
vec - ((2 * DotVecs(vec, mirror)) * mirror)
|
||||
*/
|
||||
static char Vector_Reflect_doc[] =
|
||||
".. method:: reflect(mirror)\n"
|
||||
"\n"
|
||||
" Return the reflection vector from the *mirror* argument.\n"
|
||||
"\n"
|
||||
" :arg mirror: This vector could be a normal from the reflecting surface.\n"
|
||||
" :type mirror: vector\n"
|
||||
" :return: The reflected vector.\n"
|
||||
" :rtype: Vector object matching the size of this vector.\n";
|
||||
|
||||
static PyObject *Vector_Reflect( VectorObject * self, VectorObject * value )
|
||||
{
|
||||
float mirror[3], vec[3];
|
||||
@@ -408,11 +431,24 @@ static PyObject *Vector_Reflect( VectorObject * self, VectorObject * value )
|
||||
if (self->size > 2) vec[2] = self->vec[2];
|
||||
else vec[2] = 0.0;
|
||||
|
||||
normalize_v3(mirror);
|
||||
reflect_v3_v3v3(reflect, vec, mirror);
|
||||
|
||||
return newVectorObject(reflect, self->size, Py_NEW, NULL);
|
||||
}
|
||||
|
||||
static char Vector_Cross_doc[] =
|
||||
".. method:: cross(other)\n"
|
||||
"\n"
|
||||
" Return the cross product of this vector and another.\n"
|
||||
"\n"
|
||||
" :arg other: The other vector to perform the cross product with.\n"
|
||||
" :type other: vector\n"
|
||||
" :return: The cross product.\n"
|
||||
" :rtype: Vector\n"
|
||||
"\n"
|
||||
" .. note:: both vectors must be 3D\n";
|
||||
|
||||
static PyObject *Vector_Cross( VectorObject * self, VectorObject * value )
|
||||
{
|
||||
VectorObject *vecCross = NULL;
|
||||
@@ -435,13 +471,23 @@ static PyObject *Vector_Cross( VectorObject * self, VectorObject * value )
|
||||
return (PyObject *)vecCross;
|
||||
}
|
||||
|
||||
static char Vector_Dot_doc[] =
|
||||
".. method:: dot(other)\n"
|
||||
"\n"
|
||||
" Return the dot product of this vector and another.\n"
|
||||
"\n"
|
||||
" :arg other: The other vector to perform the dot product with.\n"
|
||||
" :type other: vector\n"
|
||||
" :return: The dot product.\n"
|
||||
" :rtype: Vector\n";
|
||||
|
||||
static PyObject *Vector_Dot( VectorObject * self, VectorObject * value )
|
||||
{
|
||||
double dot = 0.0;
|
||||
int x;
|
||||
|
||||
if (!VectorObject_Check(value)) {
|
||||
PyErr_SetString( PyExc_TypeError, "vec.cross(value): expected a vector argument" );
|
||||
PyErr_SetString( PyExc_TypeError, "vec.dot(value): expected a vector argument" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -459,8 +505,156 @@ static PyObject *Vector_Dot( VectorObject * self, VectorObject * value )
|
||||
return PyFloat_FromDouble(dot);
|
||||
}
|
||||
|
||||
/*----------------------------Vector.copy() --------------------------------------
|
||||
return a copy of the vector */
|
||||
static char Vector_Angle_doc[] =
|
||||
".. function:: angle(other)\n"
|
||||
"\n"
|
||||
" Return the angle between two vectors.\n"
|
||||
"\n"
|
||||
" :type other: vector\n"
|
||||
" :return angle: angle in radians\n"
|
||||
" :rtype: float\n"
|
||||
"\n"
|
||||
" .. note:: Zero length vectors raise an :exc:`AttributeError`.\n";
|
||||
static PyObject *Vector_Angle(VectorObject * self, VectorObject * value)
|
||||
{
|
||||
double dot = 0.0f, angleRads, test_v1 = 0.0f, test_v2 = 0.0f;
|
||||
int x, size;
|
||||
|
||||
if (!VectorObject_Check(value)) {
|
||||
PyErr_SetString( PyExc_TypeError, "vec.angle(value): expected a vector argument" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(self->size != value->size) {
|
||||
PyErr_SetString(PyExc_AttributeError, "vec.angle(value): expects both vectors to have the same size\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value))
|
||||
return NULL;
|
||||
|
||||
//since size is the same....
|
||||
size = self->size;
|
||||
|
||||
for(x = 0; x < size; x++) {
|
||||
test_v1 += self->vec[x] * self->vec[x];
|
||||
test_v2 += value->vec[x] * value->vec[x];
|
||||
}
|
||||
if (!test_v1 || !test_v2){
|
||||
PyErr_SetString(PyExc_AttributeError, "vector.angle(other): zero length vectors are not acceptable arguments\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//dot product
|
||||
for(x = 0; x < size; x++) {
|
||||
dot += self->vec[x] * value->vec[x];
|
||||
}
|
||||
dot /= (sqrt(test_v1) * sqrt(test_v2));
|
||||
|
||||
angleRads = (double)saacos(dot);
|
||||
|
||||
#ifdef USE_MATHUTILS_DEG
|
||||
return PyFloat_FromDouble(angleRads * (180/ Py_PI));
|
||||
#else
|
||||
return PyFloat_FromDouble(angleRads);
|
||||
#endif
|
||||
}
|
||||
|
||||
static char Vector_Project_doc[] =
|
||||
".. function:: project(other)\n"
|
||||
"\n"
|
||||
" Return the projection of this vector onto the *other*.\n"
|
||||
"\n"
|
||||
" :type other: vector\n"
|
||||
" :return projection: the parallel projection vector\n"
|
||||
" :rtype: vector\n";
|
||||
|
||||
static PyObject *Vector_Project(VectorObject * self, VectorObject * value)
|
||||
{
|
||||
float vec[4];
|
||||
double dot = 0.0f, dot2 = 0.0f;
|
||||
int x, size;
|
||||
|
||||
if (!VectorObject_Check(value)) {
|
||||
PyErr_SetString( PyExc_TypeError, "vec.project(value): expected a vector argument" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(self->size != value->size) {
|
||||
PyErr_SetString(PyExc_AttributeError, "vec.project(value): expects both vectors to have the same size\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value))
|
||||
return NULL;
|
||||
|
||||
|
||||
//since they are the same size...
|
||||
size = self->size;
|
||||
|
||||
//get dot products
|
||||
for(x = 0; x < size; x++) {
|
||||
dot += self->vec[x] * value->vec[x];
|
||||
dot2 += value->vec[x] * value->vec[x];
|
||||
}
|
||||
//projection
|
||||
dot /= dot2;
|
||||
for(x = 0; x < size; x++) {
|
||||
vec[x] = (float)(dot * value->vec[x]);
|
||||
}
|
||||
return newVectorObject(vec, size, Py_NEW, NULL);
|
||||
}
|
||||
|
||||
//----------------------------------Mathutils.MidpointVecs() -------------
|
||||
static char Vector_Lerp_doc[] =
|
||||
".. function:: lerp(other, factor)\n"
|
||||
"\n"
|
||||
" Returns the interpolation of two vectors.\n"
|
||||
"\n"
|
||||
" :arg other: value to interpolate with.\n"
|
||||
" :type other: Vector\n"
|
||||
" :arg factor: The interpolation value in [0.0, 1.0].\n"
|
||||
" :type factor: float\n"
|
||||
" :return: The interpolated rotation.\n"
|
||||
" :rtype: Vector\n";
|
||||
|
||||
static PyObject *Vector_Lerp(VectorObject * self, PyObject * args)
|
||||
{
|
||||
VectorObject *vec2 = NULL;
|
||||
float fac, ifac, vec[4];
|
||||
int x;
|
||||
|
||||
if(!PyArg_ParseTuple(args, "O!f", &vector_Type, &vec2, &fac)) {
|
||||
PyErr_SetString(PyExc_TypeError, "vector.lerp(): expects a vector of the same size and float");
|
||||
return NULL;
|
||||
}
|
||||
if(self->size != vec2->size) {
|
||||
PyErr_SetString(PyExc_AttributeError, "Mathutils.MidpointVecs(): expects (2) vector objects of the same size");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(vec2))
|
||||
return NULL;
|
||||
|
||||
ifac= 1.0 - fac;
|
||||
|
||||
for(x = 0; x < self->size; x++) {
|
||||
vec[x] = (ifac * self->vec[x]) + (fac * vec2->vec[x]);
|
||||
}
|
||||
return newVectorObject(vec, self->size, Py_NEW, NULL);
|
||||
}
|
||||
|
||||
/*----------------------------Vector.copy() -------------------------------------- */
|
||||
static char Vector_copy_doc[] =
|
||||
".. function:: copy()\n"
|
||||
"\n"
|
||||
" Returns a copy of this vector.\n"
|
||||
"\n"
|
||||
" :return: A copy of the vector.\n"
|
||||
" :rtype: Vector\n"
|
||||
"\n"
|
||||
" .. note:: use this to get a copy of a wrapped vector with no reference to the original data.\n";
|
||||
|
||||
static PyObject *Vector_copy(VectorObject * self)
|
||||
{
|
||||
if(!BaseMath_ReadCallback(self))
|
||||
@@ -1807,7 +2001,87 @@ if len(unique) != len(items):
|
||||
|
||||
*/
|
||||
|
||||
//-----------------row_vector_multiplication (internal)-----------
|
||||
//ROW VECTOR Multiplication - Vector X Matrix
|
||||
//[x][y][z] * [1][4][7]
|
||||
// [2][5][8]
|
||||
// [3][6][9]
|
||||
//vector/matrix multiplication IS NOT COMMUTATIVE!!!!
|
||||
static PyObject *row_vector_multiplication(VectorObject* vec, MatrixObject * mat)
|
||||
{
|
||||
float vecNew[4], vecCopy[4];
|
||||
double dot = 0.0f;
|
||||
int x, y, z = 0, vec_size = vec->size;
|
||||
|
||||
if(mat->colSize != vec_size){
|
||||
if(mat->colSize == 4 && vec_size != 3){
|
||||
PyErr_SetString(PyExc_AttributeError, "vector * matrix: matrix column size and the vector size must be the same");
|
||||
return NULL;
|
||||
}else{
|
||||
vecCopy[3] = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
if(!BaseMath_ReadCallback(vec) || !BaseMath_ReadCallback(mat))
|
||||
return NULL;
|
||||
|
||||
for(x = 0; x < vec_size; x++){
|
||||
vecCopy[x] = vec->vec[x];
|
||||
}
|
||||
vecNew[3] = 1.0f;
|
||||
//muliplication
|
||||
for(x = 0; x < mat->rowSize; x++) {
|
||||
for(y = 0; y < mat->colSize; y++) {
|
||||
dot += mat->matrix[x][y] * vecCopy[y];
|
||||
}
|
||||
vecNew[z++] = (float)dot;
|
||||
dot = 0.0f;
|
||||
}
|
||||
return newVectorObject(vecNew, vec_size, Py_NEW, NULL);
|
||||
}
|
||||
|
||||
/*----------------------------Vector.negate() -------------------- */
|
||||
static char Vector_Negate_doc[] =
|
||||
".. method:: negate()\n"
|
||||
"\n"
|
||||
" Set all values to their negative.\n"
|
||||
" :return: an instance of itself\n"
|
||||
" :rtype: vector\n";
|
||||
|
||||
static PyObject *Vector_Negate(VectorObject * self)
|
||||
{
|
||||
int i;
|
||||
if(!BaseMath_ReadCallback(self))
|
||||
return NULL;
|
||||
|
||||
for(i = 0; i < self->size; i++)
|
||||
self->vec[i] = -(self->vec[i]);
|
||||
|
||||
BaseMath_WriteCallback(self); // alredy checked for error
|
||||
|
||||
Py_INCREF(self);
|
||||
return (PyObject*)self;
|
||||
}
|
||||
|
||||
static struct PyMethodDef Vector_methods[] = {
|
||||
{"zero", (PyCFunction) Vector_Zero, METH_NOARGS, Vector_Zero_doc},
|
||||
{"normalize", (PyCFunction) Vector_Normalize, METH_NOARGS, Vector_Normalize_doc},
|
||||
{"negate", (PyCFunction) Vector_Negate, METH_NOARGS, Vector_Negate_doc},
|
||||
{"resize2D", (PyCFunction) Vector_Resize2D, METH_NOARGS, Vector_Resize2D_doc},
|
||||
{"resize3D", (PyCFunction) Vector_Resize3D, METH_NOARGS, Vector_Resize3D_doc},
|
||||
{"resize4D", (PyCFunction) Vector_Resize4D, METH_NOARGS, Vector_Resize4D_doc},
|
||||
{"to_tuple", (PyCFunction) Vector_ToTuple, METH_O, Vector_ToTuple_doc},
|
||||
{"to_track_quat", ( PyCFunction ) Vector_ToTrackQuat, METH_VARARGS, Vector_ToTrackQuat_doc},
|
||||
{"reflect", ( PyCFunction ) Vector_Reflect, METH_O, Vector_Reflect_doc},
|
||||
{"cross", ( PyCFunction ) Vector_Cross, METH_O, Vector_Cross_doc},
|
||||
{"dot", ( PyCFunction ) Vector_Dot, METH_O, Vector_Dot_doc},
|
||||
{"angle", ( PyCFunction ) Vector_Angle, METH_O, Vector_Angle_doc},
|
||||
{"project", ( PyCFunction ) Vector_Project, METH_O, Vector_Project_doc},
|
||||
{"lerp", ( PyCFunction ) Vector_Lerp, METH_VARARGS, Vector_Lerp_doc},
|
||||
{"copy", (PyCFunction) Vector_copy, METH_NOARGS, Vector_copy_doc},
|
||||
{"__copy__", (PyCFunction) Vector_copy, METH_NOARGS, NULL},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
|
||||
/* Note
|
||||
@@ -1816,6 +2090,8 @@ if len(unique) != len(items):
|
||||
vec*mat and mat*vec both get sent to Vector_mul and it neesd to sort out the order
|
||||
*/
|
||||
|
||||
static char vector_doc[] = "This object gives access to Vectors in Blender.";
|
||||
|
||||
PyTypeObject vector_Type = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
/* For printing, in format "<module>.<name>" */
|
||||
@@ -1851,7 +2127,7 @@ PyTypeObject vector_Type = {
|
||||
|
||||
/*** Flags to define presence of optional/expanded features ***/
|
||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
|
||||
NULL, /* char *tp_doc; Documentation string */
|
||||
vector_doc, /* char *tp_doc; Documentation string */
|
||||
/*** Assigned meaning in release 2.0 ***/
|
||||
/* call function for all accessible objects */
|
||||
NULL, /* traverseproc tp_traverse; */
|
||||
@@ -1896,7 +2172,6 @@ PyTypeObject vector_Type = {
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
/*------------------------newVectorObject (internal)-------------
|
||||
creates a new vector object
|
||||
pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER
|
||||
@@ -1955,59 +2230,3 @@ PyObject *newVectorObject_cb(PyObject *cb_user, int size, int cb_type, int cb_su
|
||||
|
||||
return (PyObject *)self;
|
||||
}
|
||||
|
||||
//-----------------row_vector_multiplication (internal)-----------
|
||||
//ROW VECTOR Multiplication - Vector X Matrix
|
||||
//[x][y][z] * [1][4][7]
|
||||
// [2][5][8]
|
||||
// [3][6][9]
|
||||
//vector/matrix multiplication IS NOT COMMUTATIVE!!!!
|
||||
static PyObject *row_vector_multiplication(VectorObject* vec, MatrixObject * mat)
|
||||
{
|
||||
float vecNew[4], vecCopy[4];
|
||||
double dot = 0.0f;
|
||||
int x, y, z = 0, vec_size = vec->size;
|
||||
|
||||
if(mat->colSize != vec_size){
|
||||
if(mat->colSize == 4 && vec_size != 3){
|
||||
PyErr_SetString(PyExc_AttributeError, "vector * matrix: matrix column size and the vector size must be the same");
|
||||
return NULL;
|
||||
}else{
|
||||
vecCopy[3] = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
if(!BaseMath_ReadCallback(vec) || !BaseMath_ReadCallback(mat))
|
||||
return NULL;
|
||||
|
||||
for(x = 0; x < vec_size; x++){
|
||||
vecCopy[x] = vec->vec[x];
|
||||
}
|
||||
vecNew[3] = 1.0f;
|
||||
//muliplication
|
||||
for(x = 0; x < mat->rowSize; x++) {
|
||||
for(y = 0; y < mat->colSize; y++) {
|
||||
dot += mat->matrix[x][y] * vecCopy[y];
|
||||
}
|
||||
vecNew[z++] = (float)dot;
|
||||
dot = 0.0f;
|
||||
}
|
||||
return newVectorObject(vecNew, vec_size, Py_NEW, NULL);
|
||||
}
|
||||
|
||||
/*----------------------------Vector.negate() --------------------
|
||||
set the vector to it's negative -x, -y, -z */
|
||||
static PyObject *Vector_Negate(VectorObject * self)
|
||||
{
|
||||
int i;
|
||||
if(!BaseMath_ReadCallback(self))
|
||||
return NULL;
|
||||
|
||||
for(i = 0; i < self->size; i++)
|
||||
self->vec[i] = -(self->vec[i]);
|
||||
|
||||
BaseMath_WriteCallback(self); // alredy checked for error
|
||||
|
||||
Py_INCREF(self);
|
||||
return (PyObject*)self;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include "eval.h" /* for PyEval_EvalCode */
|
||||
|
||||
#include "bpy_rna.h"
|
||||
#include "bpy_props.h"
|
||||
#include "bpy_operator.h"
|
||||
#include "bpy_ui.h"
|
||||
#include "bpy_util.h"
|
||||
|
||||
@@ -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,6 +47,7 @@ static PyObject *pyop_call( PyObject * self, PyObject * args)
|
||||
wmOperatorType *ot;
|
||||
int error_val = 0;
|
||||
PointerRNA ptr;
|
||||
int operator_ret= OPERATOR_CANCELLED;
|
||||
|
||||
char *opname;
|
||||
PyObject *kw= NULL; /* optional args */
|
||||
@@ -63,7 +66,7 @@ static PyObject *pyop_call( PyObject * self, PyObject * args)
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -76,7 +79,7 @@ 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 {
|
||||
@@ -94,7 +97,7 @@ static PyObject *pyop_call( PyObject * self, PyObject * args)
|
||||
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;
|
||||
@@ -140,7 +143,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)
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "RNA_define.h"
|
||||
|
||||
#include "bpy_rna.h"
|
||||
#include "bpy_props.h"
|
||||
#include "bpy_util.h"
|
||||
|
||||
static void operator_properties_init(wmOperatorType *ot)
|
||||
|
||||
505
source/blender/python/intern/bpy_props.c
Normal file
505
source/blender/python/intern/bpy_props.c
Normal file
@@ -0,0 +1,505 @@
|
||||
/**
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* Contributor(s): Campbell Barton
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#include "bpy_props.h"
|
||||
#include "bpy_rna.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_define.h" /* for defining our own rna */
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "float.h" /* FLT_MIN/MAX */
|
||||
|
||||
/* 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, PyCObject_FromVoidPtr(func, NULL));
|
||||
PyTuple_SET_ITEM(ret, 1, kw);
|
||||
Py_INCREF(kw);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* 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, hidden=False)\n"
|
||||
"\n"
|
||||
" Returns a new boolean property definition..";
|
||||
|
||||
PyObject *BPy_BoolProperty(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
StructRNA *srna;
|
||||
|
||||
if (PyTuple_Size(args) > 0) {
|
||||
PyErr_SetString(PyExc_ValueError, "all args must be keywors"); // TODO - py3 can enforce this.
|
||||
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", "hidden", NULL};
|
||||
char *id=NULL, *name="", *description="";
|
||||
int def=0, hidden=0;
|
||||
PropertyRNA *prop;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "s|ssii:BoolProperty", kwlist, &id, &name, &description, &def, &hidden))
|
||||
return NULL;
|
||||
|
||||
prop= RNA_def_boolean(srna, id, def, name, description);
|
||||
if(hidden) RNA_def_property_flag(prop, PROP_HIDDEN);
|
||||
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_IntProperty_doc[] =
|
||||
".. function:: IntProperty(name=\"\", description=\"\", default=0, min=-sys.maxint, max=sys.maxint, soft_min=-sys.maxint, soft_max=sys.maxint, step=1, hidden=False)\n"
|
||||
"\n"
|
||||
" Returns a new int property definition.";
|
||||
PyObject *BPy_IntProperty(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
StructRNA *srna;
|
||||
|
||||
if (PyTuple_Size(args) > 0) {
|
||||
PyErr_SetString(PyExc_ValueError, "all args must be keywors"); // TODO - py3 can enforce this.
|
||||
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", "min", "max", "soft_min", "soft_max", "step", "hidden", 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;
|
||||
int hidden=0;
|
||||
PropertyRNA *prop;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "s|ssiiiiiii:IntProperty", kwlist, &id, &name, &description, &def, &min, &max, &soft_min, &soft_max, &step, &hidden))
|
||||
return NULL;
|
||||
|
||||
prop= RNA_def_int(srna, id, def, min, max, name, description, soft_min, soft_max);
|
||||
RNA_def_property_ui_range(prop, min, max, step, 0);
|
||||
if(hidden) RNA_def_property_flag(prop, PROP_HIDDEN);
|
||||
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_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, hidden=False)\n"
|
||||
"\n"
|
||||
" Returns a new float property definition.";
|
||||
PyObject *BPy_FloatProperty(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
StructRNA *srna;
|
||||
|
||||
if (PyTuple_Size(args) > 0) {
|
||||
PyErr_SetString(PyExc_ValueError, "all args must be keywors"); // TODO - py3 can enforce this.
|
||||
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", "min", "max", "soft_min", "soft_max", "step", "precision", "hidden", 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, hidden=0;
|
||||
PropertyRNA *prop;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "s|ssffffffii:FloatProperty", kwlist, &id, &name, &description, &def, &min, &max, &soft_min, &soft_max, &step, &precision, &hidden))
|
||||
return NULL;
|
||||
|
||||
prop= RNA_def_float(srna, id, def, min, max, name, description, soft_min, soft_max);
|
||||
RNA_def_property_ui_range(prop, min, max, step, precision);
|
||||
if(hidden) RNA_def_property_flag(prop, PROP_HIDDEN);
|
||||
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, hidden=False, size=3)\n"
|
||||
"\n"
|
||||
" Returns a new vector float property definition.";
|
||||
PyObject *BPy_FloatVectorProperty(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
StructRNA *srna;
|
||||
|
||||
if (PyTuple_Size(args) > 0) {
|
||||
PyErr_SetString(PyExc_ValueError, "all args must be keywors"); // TODO - py3 can enforce this.
|
||||
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", "min", "max", "soft_min", "soft_max", "step", "precision", "hidden", "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, hidden=0, size=3;
|
||||
PropertyRNA *prop;
|
||||
PyObject *pydef= NULL;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "s|ssOfffffiii:FloatVectorProperty", kwlist, &id, &name, &description, &pydef, &min, &max, &soft_min, &soft_max, &step, &precision, &hidden, &size))
|
||||
return NULL;
|
||||
|
||||
if(size < 0 || size > PYRNA_STACK_ARRAY) {
|
||||
PyErr_Format(PyExc_TypeError, "FloatVectorProperty(): size must be between 0 and %d, given %d.", PYRNA_STACK_ARRAY, size);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(pydef) {
|
||||
int i;
|
||||
|
||||
if(!PySequence_Check(pydef)) {
|
||||
PyErr_Format(PyExc_TypeError, "FloatVectorProperty(): default value is not a sequence of size: %d.", size);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(size != PySequence_Size(pydef)) {
|
||||
PyErr_Format(PyExc_TypeError, "FloatVectorProperty(): size: %d, does not default: %d.", size, PySequence_Size(pydef));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for(i=0; i<size; i++) {
|
||||
PyObject *item= PySequence_GetItem(pydef, i);
|
||||
if(item) {
|
||||
def[i]= PyFloat_AsDouble(item);
|
||||
Py_DECREF(item);
|
||||
}
|
||||
}
|
||||
|
||||
if(PyErr_Occurred()) { /* error set above */
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
prop= RNA_def_float_vector(srna, id, size, pydef ? def:NULL, min, max, name, description, soft_min, soft_max);
|
||||
RNA_def_property_ui_range(prop, min, max, step, precision);
|
||||
if(hidden) RNA_def_property_flag(prop, PROP_HIDDEN);
|
||||
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, hidden=False)\n"
|
||||
"\n"
|
||||
" Returns a new string property definition.";
|
||||
PyObject *BPy_StringProperty(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
StructRNA *srna;
|
||||
|
||||
if (PyTuple_Size(args) > 0) {
|
||||
PyErr_SetString(PyExc_ValueError, "all args must be keywors"); // TODO - py3 can enforce this.
|
||||
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", "maxlen", "hidden", NULL};
|
||||
char *id=NULL, *name="", *description="", *def="";
|
||||
int maxlen=0, hidden=0;
|
||||
PropertyRNA *prop;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "s|sssii:StringProperty", kwlist, &id, &name, &description, &def, &maxlen, &hidden))
|
||||
return NULL;
|
||||
|
||||
prop= RNA_def_string(srna, id, def, maxlen, name, description);
|
||||
if(hidden) RNA_def_property_flag(prop, PROP_HIDDEN);
|
||||
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=\"\", hidden=False)\n"
|
||||
"\n"
|
||||
" Returns a new enumerator property definition.\n"
|
||||
"\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_Size(args) > 0) {
|
||||
PyErr_SetString(PyExc_ValueError, "all args must be keywors"); // TODO - py3 can enforce this.
|
||||
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", "items", "name", "description", "default", "hidden", NULL};
|
||||
char *id=NULL, *name="", *description="", *def="";
|
||||
int defvalue=0, hidden=0;
|
||||
PyObject *items= Py_None;
|
||||
EnumPropertyItem *eitems;
|
||||
PropertyRNA *prop;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "sO|sssi:EnumProperty", kwlist, &id, &items, &name, &description, &def, &hidden))
|
||||
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(hidden) RNA_def_property_flag(prop, PROP_HIDDEN);
|
||||
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=\"\", hidden=False)\n"
|
||||
"\n"
|
||||
" Returns a new pointer property definition.\n"
|
||||
"\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_Size(args) > 0) {
|
||||
PyErr_SetString(PyExc_ValueError, "all args must be keywors"); // TODO - py3 can enforce this.
|
||||
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", "type", "name", "description", "hidden", NULL};
|
||||
char *id=NULL, *name="", *description="";
|
||||
int hidden= 0;
|
||||
PropertyRNA *prop;
|
||||
StructRNA *ptype;
|
||||
PyObject *type= Py_None;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "sO|ssi:PointerProperty", kwlist, &id, &type, &name, &description, &hidden))
|
||||
return NULL;
|
||||
|
||||
ptype= pointer_type_from_py(type);
|
||||
if(!ptype)
|
||||
return NULL;
|
||||
|
||||
prop= RNA_def_pointer_runtime(srna, id, ptype, name, description);
|
||||
if(hidden) RNA_def_property_flag(prop, PROP_HIDDEN);
|
||||
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=\"\", hidden=False)\n"
|
||||
"\n"
|
||||
" Returns a new collection property definition.\n"
|
||||
"\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_Size(args) > 0) {
|
||||
PyErr_SetString(PyExc_ValueError, "all args must be keywors"); // TODO - py3 can enforce this.
|
||||
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", "type", "name", "description", "hidden", NULL};
|
||||
char *id=NULL, *name="", *description="";
|
||||
int hidden= 0;
|
||||
PropertyRNA *prop;
|
||||
StructRNA *ptype;
|
||||
PyObject *type= Py_None;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "sO|ssi:CollectionProperty", kwlist, &id, &type, &name, &description, &hidden))
|
||||
return NULL;
|
||||
|
||||
ptype= pointer_type_from_py(type);
|
||||
if(!ptype)
|
||||
return NULL;
|
||||
|
||||
prop= RNA_def_collection_runtime(srna, id, ptype, name, description);
|
||||
if(hidden) RNA_def_property_flag(prop, PROP_HIDDEN);
|
||||
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},
|
||||
{"IntProperty", (PyCFunction)BPy_IntProperty, METH_VARARGS|METH_KEYWORDS, BPy_IntProperty_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;
|
||||
}
|
||||
44
source/blender/python/intern/bpy_props.h
Normal file
44
source/blender/python/intern/bpy_props.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* 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_IntProperty(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
|
||||
@@ -24,6 +24,7 @@
|
||||
*/
|
||||
|
||||
#include "bpy_rna.h"
|
||||
#include "bpy_props.h"
|
||||
#include "bpy_util.h"
|
||||
//#include "blendef.h"
|
||||
#include "BLI_dynstr.h"
|
||||
@@ -54,7 +55,7 @@
|
||||
#include "../generic/Mathutils.h" /* so we can have mathutils callbacks */
|
||||
#include "../generic/IDProp.h" /* for IDprop lookups */
|
||||
|
||||
static PyObject *prop_subscript_array_slice(PointerRNA *ptr, PropertyRNA *prop, int start, int stop, int length);
|
||||
static PyObject *prop_subscript_array_slice(BPy_PropertyRNA *self, PointerRNA *ptr, PropertyRNA *prop, int start, int stop, int length);
|
||||
|
||||
/* bpyrna vector/euler/quat callbacks */
|
||||
static int mathutils_rna_array_cb_index= -1; /* index for our callbacks */
|
||||
@@ -239,7 +240,7 @@ PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop)
|
||||
if(is_thick) {
|
||||
/* this is an array we cant reference (since its not thin wrappable)
|
||||
* and cannot be coerced into a mathutils type, so return as a list */
|
||||
ret = prop_subscript_array_slice(ptr, prop, 0, len, len);
|
||||
ret = prop_subscript_array_slice(NULL, ptr, prop, 0, len, len);
|
||||
} else {
|
||||
ret = pyrna_prop_CreatePyObject(ptr, prop); /* owned by the Mathutils PyObject */
|
||||
}
|
||||
@@ -423,6 +424,24 @@ static int pyrna_string_to_enum(PyObject *item, PointerRNA *ptr, PropertyRNA *pr
|
||||
return 1;
|
||||
}
|
||||
|
||||
PyObject *pyrna_enum_bitfield_to_py(EnumPropertyItem *items, int value)
|
||||
{
|
||||
PyObject *ret= PySet_New(NULL);
|
||||
const char *identifier[RNA_ENUM_BITFLAG_SIZE + 1];
|
||||
|
||||
if(RNA_enum_bitflag_identifiers(items, value, identifier)) {
|
||||
PyObject *item;
|
||||
int index;
|
||||
for(index=0; identifier[index]; index++) {
|
||||
item= PyUnicode_FromString(identifier[index]);
|
||||
PySet_Add(ret, item);
|
||||
Py_DECREF(item);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static PyObject *pyrna_enum_to_py(PointerRNA *ptr, PropertyRNA *prop, int val)
|
||||
{
|
||||
PyObject *item, *ret= NULL;
|
||||
@@ -574,7 +593,7 @@ int pyrna_pydict_to_props(PointerRNA *ptr, PyObject *kw, int all_args, const cha
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (pyrna_py_to_prop(ptr, prop, NULL, item, error_prefix)) {
|
||||
if (pyrna_py_to_prop(ptr, prop, NULL, NULL, item, error_prefix)) {
|
||||
error_val= -1;
|
||||
break;
|
||||
}
|
||||
@@ -628,7 +647,7 @@ static PyObject *pyrna_func_to_py(BPy_DummyPointerRNA *pyrna, FunctionRNA *func)
|
||||
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
/* XXX hard limits should be checked here */
|
||||
int type = RNA_property_type(prop);
|
||||
@@ -651,7 +670,7 @@ int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *v
|
||||
return -1;
|
||||
}
|
||||
/* done getting the length */
|
||||
ok= pyrna_py_to_array(ptr, prop, data, value, error_prefix);
|
||||
ok= pyrna_py_to_array(ptr, prop, parms, data, value, error_prefix);
|
||||
|
||||
if (!ok) {
|
||||
/* PyErr_Format(PyExc_AttributeError, "%.200s %s", error_prefix, error_str); */
|
||||
@@ -669,7 +688,7 @@ int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *v
|
||||
/* prefer not to have an exception here
|
||||
* however so many poll functions return None or a valid Object.
|
||||
* its a hassle to convert these into a bool before returning, */
|
||||
if(RNA_property_flag(prop) & PROP_RETURN)
|
||||
if(RNA_property_flag(prop) & PROP_OUTPUT)
|
||||
param = PyObject_IsTrue( value );
|
||||
else
|
||||
param = PyLong_AsSsize_t( value );
|
||||
@@ -877,7 +896,7 @@ int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *v
|
||||
|
||||
static PyObject * pyrna_prop_to_py_index(BPy_PropertyRNA *self, int index)
|
||||
{
|
||||
return pyrna_py_from_array_index(self, index);
|
||||
return pyrna_py_from_array_index(self, &self->ptr, self->prop, index);
|
||||
}
|
||||
|
||||
static int pyrna_py_to_prop_index(BPy_PropertyRNA *self, int index, PyObject *value)
|
||||
@@ -1034,66 +1053,74 @@ static PyObject *prop_subscript_collection_slice(PointerRNA *ptr, PropertyRNA *p
|
||||
* note: could also use pyrna_prop_to_py_index(self, count) in a loop but its a lot slower
|
||||
* since at the moment it reads (and even allocates) the entire array for each index.
|
||||
*/
|
||||
#define PYRNA_STACK_ARRAY 32
|
||||
static PyObject *prop_subscript_array_slice(PointerRNA *ptr, PropertyRNA *prop, int start, int stop, int length)
|
||||
static PyObject *prop_subscript_array_slice(BPy_PropertyRNA *self, PointerRNA *ptr, PropertyRNA *prop, int start, int stop, int length)
|
||||
{
|
||||
int count, totdim;
|
||||
|
||||
PyObject *list = PyList_New(stop - start);
|
||||
int count;
|
||||
|
||||
switch (RNA_property_type(prop)) {
|
||||
totdim = RNA_property_array_dimension(ptr, prop, NULL);
|
||||
|
||||
if (totdim > 1) {
|
||||
for (count = start; count < stop; count++)
|
||||
PyList_SET_ITEM(list, count - start, pyrna_prop_to_py_index(self, count));
|
||||
}
|
||||
else {
|
||||
switch (RNA_property_type(prop)) {
|
||||
case PROP_FLOAT:
|
||||
{
|
||||
float values_stack[PYRNA_STACK_ARRAY];
|
||||
float *values;
|
||||
if(length > PYRNA_STACK_ARRAY) { values= PyMem_MALLOC(sizeof(float) * length); }
|
||||
else { values= values_stack; }
|
||||
RNA_property_float_get_array(ptr, prop, values);
|
||||
{
|
||||
float values_stack[PYRNA_STACK_ARRAY];
|
||||
float *values;
|
||||
if(length > PYRNA_STACK_ARRAY) { values= PyMem_MALLOC(sizeof(float) * length); }
|
||||
else { values= values_stack; }
|
||||
RNA_property_float_get_array(ptr, prop, values);
|
||||
|
||||
for(count=start; count<stop; count++)
|
||||
PyList_SET_ITEM(list, count-start, PyFloat_FromDouble(values[count]));
|
||||
for(count=start; count<stop; count++)
|
||||
PyList_SET_ITEM(list, count-start, PyFloat_FromDouble(values[count]));
|
||||
|
||||
if(values != values_stack) {
|
||||
PyMem_FREE(values);
|
||||
if(values != values_stack) {
|
||||
PyMem_FREE(values);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PROP_BOOLEAN:
|
||||
{
|
||||
int values_stack[PYRNA_STACK_ARRAY];
|
||||
int *values;
|
||||
if(length > PYRNA_STACK_ARRAY) { values= PyMem_MALLOC(sizeof(int) * length); }
|
||||
else { values= values_stack; }
|
||||
{
|
||||
int values_stack[PYRNA_STACK_ARRAY];
|
||||
int *values;
|
||||
if(length > PYRNA_STACK_ARRAY) { values= PyMem_MALLOC(sizeof(int) * length); }
|
||||
else { values= values_stack; }
|
||||
|
||||
RNA_property_boolean_get_array(ptr, prop, values);
|
||||
for(count=start; count<stop; count++)
|
||||
PyList_SET_ITEM(list, count-start, PyBool_FromLong(values[count]));
|
||||
RNA_property_boolean_get_array(ptr, prop, values);
|
||||
for(count=start; count<stop; count++)
|
||||
PyList_SET_ITEM(list, count-start, PyBool_FromLong(values[count]));
|
||||
|
||||
if(values != values_stack) {
|
||||
PyMem_FREE(values);
|
||||
if(values != values_stack) {
|
||||
PyMem_FREE(values);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PROP_INT:
|
||||
{
|
||||
int values_stack[PYRNA_STACK_ARRAY];
|
||||
int *values;
|
||||
if(length > PYRNA_STACK_ARRAY) { values= PyMem_MALLOC(sizeof(int) * length); }
|
||||
else { values= values_stack; }
|
||||
{
|
||||
int values_stack[PYRNA_STACK_ARRAY];
|
||||
int *values;
|
||||
if(length > PYRNA_STACK_ARRAY) { values= PyMem_MALLOC(sizeof(int) * length); }
|
||||
else { values= values_stack; }
|
||||
|
||||
RNA_property_int_get_array(ptr, prop, values);
|
||||
for(count=start; count<stop; count++)
|
||||
PyList_SET_ITEM(list, count-start, PyLong_FromSsize_t(values[count]));
|
||||
RNA_property_int_get_array(ptr, prop, values);
|
||||
for(count=start; count<stop; count++)
|
||||
PyList_SET_ITEM(list, count-start, PyLong_FromSsize_t(values[count]));
|
||||
|
||||
if(values != values_stack) {
|
||||
PyMem_FREE(values);
|
||||
if(values != values_stack) {
|
||||
PyMem_FREE(values);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
/* probably will never happen */
|
||||
PyErr_SetString(PyExc_TypeError, "not an array type");
|
||||
Py_DECREF(list);
|
||||
list= NULL;
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
@@ -1156,7 +1183,7 @@ static PyObject *prop_subscript_array(BPy_PropertyRNA *self, PyObject *key)
|
||||
return PyList_New(0);
|
||||
}
|
||||
else if (step == 1) {
|
||||
return prop_subscript_array_slice(&self->ptr, self->prop, start, stop, len);
|
||||
return prop_subscript_array_slice(self, &self->ptr, self->prop, start, stop, len);
|
||||
}
|
||||
else {
|
||||
PyErr_SetString(PyExc_TypeError, "slice steps not supported with rna");
|
||||
@@ -1963,7 +1990,7 @@ static int pyrna_struct_setattro( BPy_StructRNA *self, PyObject *pyname, PyObjec
|
||||
}
|
||||
|
||||
/* pyrna_py_to_prop sets its own exceptions */
|
||||
return pyrna_py_to_prop(&self->ptr, prop, NULL, value, "StructRNA - item.attr = val:");
|
||||
return pyrna_py_to_prop(&self->ptr, prop, NULL, NULL, value, "StructRNA - item.attr = val:");
|
||||
}
|
||||
|
||||
static PyObject *pyrna_prop_dir(BPy_PropertyRNA *self)
|
||||
@@ -2039,7 +2066,7 @@ static int pyrna_prop_setattro( BPy_PropertyRNA *self, PyObject *pyname, PyObjec
|
||||
if(RNA_property_collection_type_get(&self->ptr, self->prop, &r_ptr)) {
|
||||
if ((prop = RNA_struct_find_property(&r_ptr, name))) {
|
||||
/* pyrna_py_to_prop sets its own exceptions */
|
||||
return pyrna_py_to_prop(&r_ptr, prop, NULL, value, "BPy_PropertyRNA - Attribute (setattr):");
|
||||
return pyrna_py_to_prop(&r_ptr, prop, NULL, NULL, value, "BPy_PropertyRNA - Attribute (setattr):");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2511,7 +2538,7 @@ PyObject *pyrna_prop_iter(BPy_PropertyRNA *self)
|
||||
|
||||
if(RNA_property_array_check(&self->ptr, self->prop)) {
|
||||
int len= pyrna_prop_array_length(self);
|
||||
ret = prop_subscript_array_slice(&self->ptr, self->prop, 0, len, len);
|
||||
ret = prop_subscript_array_slice(self, &self->ptr, self->prop, 0, len, len);
|
||||
}
|
||||
else if ((ret = pyrna_prop_values(self))) {
|
||||
/* do nothing */
|
||||
@@ -2607,7 +2634,7 @@ static PyObject * pyrna_prop_new(PyTypeObject *type, PyObject *args, PyObject *k
|
||||
}
|
||||
}
|
||||
|
||||
PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *data)
|
||||
PyObject *pyrna_param_to_py(PointerRNA *ptr, ParameterList *parms, PropertyRNA *prop, void *data)
|
||||
{
|
||||
PyObject *ret;
|
||||
int type = RNA_property_type(prop);
|
||||
@@ -2615,7 +2642,15 @@ PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *data)
|
||||
int a;
|
||||
|
||||
if(RNA_property_array_check(ptr, prop)) {
|
||||
int len = RNA_property_array_length(ptr, prop);
|
||||
int len;
|
||||
|
||||
if (flag & PROP_DYNAMIC) {
|
||||
len= RNA_parameter_length_get_data(parms, prop, data);
|
||||
|
||||
data= *((void **)data);
|
||||
}
|
||||
else
|
||||
len= RNA_property_array_length(ptr, prop);
|
||||
|
||||
/* resolve the array from a new pytype */
|
||||
|
||||
@@ -2792,7 +2827,7 @@ static PyObject * pyrna_func_call(PyObject *self, PyObject *args, PyObject *kw)
|
||||
flag= RNA_property_flag(parm);
|
||||
|
||||
/* only useful for single argument returns, we'll need another list loop for multiple */
|
||||
if (flag & PROP_RETURN) {
|
||||
if (flag & PROP_OUTPUT) {
|
||||
ret_len++;
|
||||
if (pret_single==NULL) {
|
||||
pret_single= parm;
|
||||
@@ -2829,7 +2864,7 @@ static PyObject * pyrna_func_call(PyObject *self, PyObject *args, PyObject *kw)
|
||||
continue;
|
||||
}
|
||||
|
||||
err= pyrna_py_to_prop(&funcptr, parm, iter.data, item, "");
|
||||
err= pyrna_py_to_prop(&funcptr, parm, &parms, iter.data, item, "");
|
||||
|
||||
if(err!=0) {
|
||||
/* the error generated isnt that useful, so generate it again with a useful prefix
|
||||
@@ -2842,7 +2877,7 @@ static PyObject * pyrna_func_call(PyObject *self, PyObject *args, PyObject *kw)
|
||||
else
|
||||
snprintf(error_prefix, sizeof(error_prefix), "%s.%s(): error with argument %d, \"%s\" - ", RNA_struct_identifier(self_ptr->type), RNA_function_identifier(self_func), i, parm_id);
|
||||
|
||||
pyrna_py_to_prop(&funcptr, parm, iter.data, item, error_prefix);
|
||||
pyrna_py_to_prop(&funcptr, parm, &parms, iter.data, item, error_prefix);
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -2900,7 +2935,7 @@ static PyObject * pyrna_func_call(PyObject *self, PyObject *args, PyObject *kw)
|
||||
RNA_parameter_list_begin(&parms, &iter);
|
||||
for(; iter.valid; RNA_parameter_list_next(&iter)) {
|
||||
parm= iter.parm;
|
||||
if(RNA_property_flag(parm) & PROP_RETURN)
|
||||
if(RNA_property_flag(parm) & PROP_OUTPUT)
|
||||
continue;
|
||||
|
||||
BLI_dynstr_appendf(good_args, first ? "%s" : ", %s", RNA_property_identifier(parm));
|
||||
@@ -2947,14 +2982,14 @@ static PyObject * pyrna_func_call(PyObject *self, PyObject *args, PyObject *kw)
|
||||
parm= iter.parm;
|
||||
flag= RNA_property_flag(parm);
|
||||
|
||||
if (flag & PROP_RETURN)
|
||||
PyTuple_SET_ITEM(ret, i++, pyrna_param_to_py(&funcptr, parm, iter.data));
|
||||
if (flag & PROP_OUTPUT)
|
||||
PyTuple_SET_ITEM(ret, i++, pyrna_param_to_py(&funcptr, &parms, parm, iter.data));
|
||||
}
|
||||
|
||||
RNA_parameter_list_end(&iter);
|
||||
}
|
||||
else
|
||||
ret= pyrna_param_to_py(&funcptr, pret_single, retdata_single);
|
||||
ret= pyrna_param_to_py(&funcptr, &parms, pret_single, retdata_single);
|
||||
|
||||
/* possible there is an error in conversion */
|
||||
if(ret==NULL)
|
||||
@@ -3140,6 +3175,7 @@ static struct PyMethodDef pyrna_struct_subtype_methods[] = {
|
||||
{"BoolProperty", (PyCFunction)BPy_BoolProperty, METH_VARARGS|METH_KEYWORDS, ""},
|
||||
{"IntProperty", (PyCFunction)BPy_IntProperty, METH_VARARGS|METH_KEYWORDS, ""},
|
||||
{"FloatProperty", (PyCFunction)BPy_FloatProperty, METH_VARARGS|METH_KEYWORDS, ""},
|
||||
{"FloatVectorProperty", (PyCFunction)BPy_FloatVectorProperty, METH_VARARGS|METH_KEYWORDS, ""},
|
||||
{"StringProperty", (PyCFunction)BPy_StringProperty, METH_VARARGS|METH_KEYWORDS, ""},
|
||||
{"EnumProperty", (PyCFunction)BPy_EnumProperty, METH_VARARGS|METH_KEYWORDS, ""},
|
||||
{"PointerProperty", (PyCFunction)BPy_PointerProperty, METH_VARARGS|METH_KEYWORDS, ""},
|
||||
@@ -3462,8 +3498,13 @@ static PyObject *pyrna_basetype_getattro( BPy_BaseTypeRNA *self, PyObject *pynam
|
||||
{
|
||||
PointerRNA newptr;
|
||||
PyObject *ret;
|
||||
char *name= _PyUnicode_AsString(pyname);
|
||||
|
||||
if (RNA_property_collection_lookup_string(&self->ptr, self->prop, _PyUnicode_AsString(pyname), &newptr)) {
|
||||
if(strcmp(name, "register")==0) {
|
||||
/* this is called so often, make an exception and save a full lookup on all types */
|
||||
ret= PyObject_GenericGetAttr((PyObject *)self, pyname);
|
||||
}
|
||||
else if (RNA_property_collection_lookup_string(&self->ptr, self->prop, name, &newptr)) {
|
||||
ret= pyrna_struct_Subtype(&newptr);
|
||||
if (ret==NULL) {
|
||||
PyErr_Format(PyExc_SystemError, "bpy.types.%.200s subtype could not be generated, this is a bug!", _PyUnicode_AsString(pyname));
|
||||
@@ -3531,40 +3572,6 @@ PyObject *BPY_rna_types(void)
|
||||
return (PyObject *)self;
|
||||
}
|
||||
|
||||
static struct PyMethodDef props_methods[] = {
|
||||
{"BoolProperty", (PyCFunction)BPy_BoolProperty, METH_VARARGS|METH_KEYWORDS, ""},
|
||||
{"IntProperty", (PyCFunction)BPy_IntProperty, METH_VARARGS|METH_KEYWORDS, ""},
|
||||
{"FloatProperty", (PyCFunction)BPy_FloatProperty, METH_VARARGS|METH_KEYWORDS, ""},
|
||||
{"StringProperty", (PyCFunction)BPy_StringProperty, METH_VARARGS|METH_KEYWORDS, ""},
|
||||
{"EnumProperty", (PyCFunction)BPy_EnumProperty, METH_VARARGS|METH_KEYWORDS, ""},
|
||||
{"PointerProperty", (PyCFunction)BPy_PointerProperty, METH_VARARGS|METH_KEYWORDS, ""},
|
||||
{"CollectionProperty", (PyCFunction)BPy_CollectionProperty, METH_VARARGS|METH_KEYWORDS, ""},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
static struct PyModuleDef props_module = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"bpy.props",
|
||||
"",
|
||||
-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;
|
||||
}
|
||||
|
||||
StructRNA *pyrna_struct_as_srna(PyObject *self)
|
||||
{
|
||||
BPy_StructRNA *py_srna = NULL;
|
||||
@@ -3602,7 +3609,6 @@ StructRNA *pyrna_struct_as_srna(PyObject *self)
|
||||
return srna;
|
||||
}
|
||||
|
||||
|
||||
/* Orphan functions, not sure where they should go */
|
||||
/* get the srna for methods attached to types */
|
||||
/* */
|
||||
@@ -3611,7 +3617,7 @@ StructRNA *srna_from_self(PyObject *self)
|
||||
/* a bit sloppy but would cause a very confusing bug if
|
||||
* an error happened to be set here */
|
||||
PyErr_Clear();
|
||||
|
||||
|
||||
if(self==NULL) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -3627,336 +3633,6 @@ StructRNA *srna_from_self(PyObject *self)
|
||||
return pyrna_struct_as_srna(self);
|
||||
}
|
||||
|
||||
/* 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, PyCObject_FromVoidPtr(func, NULL));
|
||||
PyTuple_SET_ITEM(ret, 1, kw);
|
||||
Py_INCREF(kw);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
|
||||
PyObject *BPy_BoolProperty(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
StructRNA *srna;
|
||||
|
||||
if (PyTuple_Size(args) > 0) {
|
||||
PyErr_SetString(PyExc_ValueError, "all args must be keywors"); // TODO - py3 can enforce this.
|
||||
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", "hidden", NULL};
|
||||
char *id=NULL, *name="", *description="";
|
||||
int def=0, hidden=0;
|
||||
PropertyRNA *prop;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "s|ssii:BoolProperty", kwlist, &id, &name, &description, &def, &hidden))
|
||||
return NULL;
|
||||
|
||||
prop= RNA_def_boolean(srna, id, def, name, description);
|
||||
if(hidden) RNA_def_property_flag(prop, PROP_HIDDEN);
|
||||
RNA_def_property_duplicate_pointers(prop);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
else { /* operators defer running this function */
|
||||
return bpy_prop_deferred_return((void *)BPy_BoolProperty, kw);
|
||||
}
|
||||
}
|
||||
|
||||
PyObject *BPy_IntProperty(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
StructRNA *srna;
|
||||
|
||||
if (PyTuple_Size(args) > 0) {
|
||||
PyErr_SetString(PyExc_ValueError, "all args must be keywors"); // TODO - py3 can enforce this.
|
||||
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", "min", "max", "soft_min", "soft_max", "step", "hidden", 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;
|
||||
int hidden=0;
|
||||
PropertyRNA *prop;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "s|ssiiiiiii:IntProperty", kwlist, &id, &name, &description, &def, &min, &max, &soft_min, &soft_max, &step, &hidden))
|
||||
return NULL;
|
||||
|
||||
prop= RNA_def_int(srna, id, def, min, max, name, description, soft_min, soft_max);
|
||||
RNA_def_property_ui_range(prop, min, max, step, 0);
|
||||
if(hidden) RNA_def_property_flag(prop, PROP_HIDDEN);
|
||||
RNA_def_property_duplicate_pointers(prop);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
else { /* operators defer running this function */
|
||||
return bpy_prop_deferred_return((void *)BPy_IntProperty, kw);
|
||||
}
|
||||
}
|
||||
|
||||
PyObject *BPy_FloatProperty(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
StructRNA *srna;
|
||||
|
||||
if (PyTuple_Size(args) > 0) {
|
||||
PyErr_SetString(PyExc_ValueError, "all args must be keywors"); // TODO - py3 can enforce this.
|
||||
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", "min", "max", "soft_min", "soft_max", "step", "precision", "hidden", 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= 1, hidden=0;
|
||||
PropertyRNA *prop;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "s|ssffffffii:FloatProperty", kwlist, &id, &name, &description, &def, &min, &max, &soft_min, &soft_max, &step, &precision, &hidden))
|
||||
return NULL;
|
||||
|
||||
prop= RNA_def_float(srna, id, def, min, max, name, description, soft_min, soft_max);
|
||||
RNA_def_property_ui_range(prop, min, max, step, precision);
|
||||
if(hidden) RNA_def_property_flag(prop, PROP_HIDDEN);
|
||||
RNA_def_property_duplicate_pointers(prop);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
else { /* operators defer running this function */
|
||||
return bpy_prop_deferred_return((void *)BPy_FloatProperty, kw);
|
||||
}
|
||||
}
|
||||
|
||||
PyObject *BPy_StringProperty(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
StructRNA *srna;
|
||||
|
||||
if (PyTuple_Size(args) > 0) {
|
||||
PyErr_SetString(PyExc_ValueError, "all args must be keywors"); // TODO - py3 can enforce this.
|
||||
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", "maxlen", "hidden", NULL};
|
||||
char *id=NULL, *name="", *description="", *def="";
|
||||
int maxlen=0, hidden=0;
|
||||
PropertyRNA *prop;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "s|sssii:StringProperty", kwlist, &id, &name, &description, &def, &maxlen, &hidden))
|
||||
return NULL;
|
||||
|
||||
prop= RNA_def_string(srna, id, def, maxlen, name, description);
|
||||
if(hidden) RNA_def_property_flag(prop, PROP_HIDDEN);
|
||||
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;
|
||||
}
|
||||
|
||||
PyObject *BPy_EnumProperty(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
StructRNA *srna;
|
||||
|
||||
if (PyTuple_Size(args) > 0) {
|
||||
PyErr_SetString(PyExc_ValueError, "all args must be keywors"); // TODO - py3 can enforce this.
|
||||
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", "items", "name", "description", "default", "hidden", NULL};
|
||||
char *id=NULL, *name="", *description="", *def="";
|
||||
int defvalue=0, hidden=0;
|
||||
PyObject *items= Py_None;
|
||||
EnumPropertyItem *eitems;
|
||||
PropertyRNA *prop;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "sO|sssi:EnumProperty", kwlist, &id, &items, &name, &description, &def, &hidden))
|
||||
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(hidden) RNA_def_property_flag(prop, PROP_HIDDEN);
|
||||
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;
|
||||
}
|
||||
|
||||
PyObject *BPy_PointerProperty(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
StructRNA *srna;
|
||||
|
||||
if (PyTuple_Size(args) > 0) {
|
||||
PyErr_SetString(PyExc_ValueError, "all args must be keywors"); // TODO - py3 can enforce this.
|
||||
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", "type", "name", "description", "hidden", NULL};
|
||||
char *id=NULL, *name="", *description="";
|
||||
int hidden= 0;
|
||||
PropertyRNA *prop;
|
||||
StructRNA *ptype;
|
||||
PyObject *type= Py_None;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "sO|ssi:PointerProperty", kwlist, &id, &type, &name, &description, &hidden))
|
||||
return NULL;
|
||||
|
||||
ptype= pointer_type_from_py(type);
|
||||
if(!ptype)
|
||||
return NULL;
|
||||
|
||||
prop= RNA_def_pointer_runtime(srna, id, ptype, name, description);
|
||||
if(hidden) RNA_def_property_flag(prop, PROP_HIDDEN);
|
||||
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;
|
||||
}
|
||||
|
||||
PyObject *BPy_CollectionProperty(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
StructRNA *srna;
|
||||
|
||||
if (PyTuple_Size(args) > 0) {
|
||||
PyErr_SetString(PyExc_ValueError, "all args must be keywors"); // TODO - py3 can enforce this.
|
||||
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", "type", "name", "description", "hidden", NULL};
|
||||
char *id=NULL, *name="", *description="";
|
||||
int hidden= 0;
|
||||
PropertyRNA *prop;
|
||||
StructRNA *ptype;
|
||||
PyObject *type= Py_None;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "sO|ssi:CollectionProperty", kwlist, &id, &type, &name, &description, &hidden))
|
||||
return NULL;
|
||||
|
||||
ptype= pointer_type_from_py(type);
|
||||
if(!ptype)
|
||||
return NULL;
|
||||
|
||||
prop= RNA_def_collection_runtime(srna, id, ptype, name, description);
|
||||
if(hidden) RNA_def_property_flag(prop, PROP_HIDDEN);
|
||||
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 int deferred_register_prop(StructRNA *srna, PyObject *item, PyObject *key, PyObject *dummy_args)
|
||||
{
|
||||
/* We only care about results from C which
|
||||
@@ -4056,7 +3732,7 @@ static int rna_function_arg_count(FunctionRNA *func)
|
||||
|
||||
for(link=lb->first; link; link=link->next) {
|
||||
parm= (PropertyRNA*)link;
|
||||
if(!(RNA_property_flag(parm) & PROP_RETURN))
|
||||
if(!(RNA_property_flag(parm) & PROP_OUTPUT))
|
||||
count++;
|
||||
}
|
||||
|
||||
@@ -4157,7 +3833,7 @@ static int bpy_class_validate(PointerRNA *dummyptr, void *py_data, int *have_fun
|
||||
if(strcmp(identifier, rna_attr) == 0) { \
|
||||
item= PyObject_GetAttrString(py_class, py_attr); \
|
||||
if(item && item != Py_None) { \
|
||||
if(pyrna_py_to_prop(dummyptr, prop, NULL, item, "validating class error:") != 0) { \
|
||||
if(pyrna_py_to_prop(dummyptr, prop, NULL, NULL, item, "validating class error:") != 0) { \
|
||||
Py_DECREF(item); \
|
||||
return -1; \
|
||||
} \
|
||||
@@ -4181,7 +3857,7 @@ static int bpy_class_validate(PointerRNA *dummyptr, void *py_data, int *have_fun
|
||||
else {
|
||||
Py_DECREF(item); /* no need to keep a ref, the class owns it */
|
||||
|
||||
if(pyrna_py_to_prop(dummyptr, prop, NULL, item, "validating class error:") != 0)
|
||||
if(pyrna_py_to_prop(dummyptr, prop, NULL, NULL, item, "validating class error:") != 0)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -4244,7 +3920,7 @@ static int bpy_class_call(PointerRNA *ptr, FunctionRNA *func, ParameterList *par
|
||||
flag= RNA_property_flag(parm);
|
||||
|
||||
/* only useful for single argument returns, we'll need another list loop for multiple */
|
||||
if (flag & PROP_RETURN) {
|
||||
if (flag & PROP_OUTPUT) {
|
||||
ret_len++;
|
||||
if (pret_single==NULL) {
|
||||
pret_single= parm;
|
||||
@@ -4254,7 +3930,7 @@ static int bpy_class_call(PointerRNA *ptr, FunctionRNA *func, ParameterList *par
|
||||
continue;
|
||||
}
|
||||
|
||||
parmitem= pyrna_param_to_py(&funcptr, parm, iter.data);
|
||||
parmitem= pyrna_param_to_py(&funcptr, parms, parm, iter.data);
|
||||
PyTuple_SET_ITEM(args, i, parmitem);
|
||||
i++;
|
||||
}
|
||||
@@ -4282,7 +3958,7 @@ static int bpy_class_call(PointerRNA *ptr, FunctionRNA *func, ParameterList *par
|
||||
}
|
||||
else {
|
||||
if(ret_len==1) {
|
||||
err= pyrna_py_to_prop(&funcptr, pret_single, retdata_single, ret, "calling class function:");
|
||||
err= pyrna_py_to_prop(&funcptr, pret_single, parms, retdata_single, ret, "calling class function:");
|
||||
}
|
||||
else if (ret_len > 1) {
|
||||
|
||||
@@ -4304,8 +3980,8 @@ static int bpy_class_call(PointerRNA *ptr, FunctionRNA *func, ParameterList *par
|
||||
flag= RNA_property_flag(parm);
|
||||
|
||||
/* only useful for single argument returns, we'll need another list loop for multiple */
|
||||
if (flag & PROP_RETURN) {
|
||||
err= pyrna_py_to_prop(&funcptr, parm, iter.data, PyTuple_GET_ITEM(ret, i++), "calling class function:");
|
||||
if (flag & PROP_OUTPUT) {
|
||||
err= pyrna_py_to_prop(&funcptr, parm, parms, iter.data, PyTuple_GET_ITEM(ret, i++), "calling class function:");
|
||||
if(err)
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -70,24 +70,16 @@ 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);
|
||||
|
||||
/* function for registering types */
|
||||
PyObject *pyrna_basetype_register(PyObject *self, PyObject *args);
|
||||
@@ -100,11 +92,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);
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ Generate html docs by running...
|
||||
sphinx-build source/blender/python/doc/sphinx-in source/blender/python/doc/sphinx-out
|
||||
'''
|
||||
|
||||
|
||||
import os
|
||||
import inspect
|
||||
import bpy
|
||||
@@ -49,6 +50,142 @@ def write_indented_lines(ident, fn, text):
|
||||
for l in text.split("\n"):
|
||||
fn(ident + l.strip() + "\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__:
|
||||
for l in py_func.__doc__.split("\n"):
|
||||
fw(ident + l + "\n")
|
||||
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")
|
||||
print(filepath)
|
||||
print(filepath)
|
||||
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")
|
||||
|
||||
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__:
|
||||
for l in value.__doc__.split("\n"):
|
||||
fw(" %s\n" % l)
|
||||
fw("\n")
|
||||
|
||||
for key, descr in value.__dict__.items():
|
||||
if key.startswith("__"):
|
||||
continue
|
||||
|
||||
descr_type = type(descr)
|
||||
if descr_type in (MethodDescriptorType, ): # GetSetDescriptorType, GetSetDescriptorType's are not documented yet
|
||||
if descr.__doc__:
|
||||
for l in descr.__doc__.split("\n"):
|
||||
fw(" %s\n" % l)
|
||||
fw("\n")
|
||||
fw("\n\n")
|
||||
|
||||
file.close()
|
||||
|
||||
|
||||
def rna2sphinx(BASEPATH):
|
||||
|
||||
structs, funcs, ops, props = rna_info.BuildRNAInfo()
|
||||
@@ -78,10 +215,34 @@ def rna2sphinx(BASEPATH):
|
||||
fw("\n")
|
||||
fw(".. toctree::\n")
|
||||
fw(" :glob:\n\n")
|
||||
fw(" bpy.ops.*\n\n")
|
||||
fw(" bpy.types.*\n\n")
|
||||
#fw(" bpy.ops.*\n\n")
|
||||
#fw(" bpy.types.*\n\n")
|
||||
|
||||
# py modules
|
||||
fw(" bpy.utils\n\n")
|
||||
fw(" bpy.app\n\n")
|
||||
|
||||
# C modules
|
||||
fw(" bpy.props\n\n")
|
||||
|
||||
fw(" Mathutils\n\n")
|
||||
|
||||
file.close()
|
||||
|
||||
# python modules
|
||||
from bpy import utils as module
|
||||
pymodule2sphinx(BASEPATH, "bpy.utils", module, "Blender Python Utilities")
|
||||
from bpy import app as module
|
||||
pymodule2sphinx(BASEPATH, "bpy.app", module, "Blender Python Application Constants")
|
||||
|
||||
from bpy import props as module
|
||||
pymodule2sphinx(BASEPATH, "bpy.props", module, "Blender Python Property Definitions")
|
||||
|
||||
import Mathutils as module
|
||||
pymodule2sphinx(BASEPATH, "Mathutils", module, "Module Mathutils")
|
||||
del module
|
||||
|
||||
|
||||
if 0:
|
||||
filepath = os.path.join(BASEPATH, "bpy.rst")
|
||||
file = open(filepath, "w")
|
||||
@@ -167,10 +328,7 @@ def rna2sphinx(BASEPATH):
|
||||
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")
|
||||
pyprop2sphinx(" ", fw, identifier, py_prop)
|
||||
del py_properties, py_prop
|
||||
|
||||
for func in struct.functions:
|
||||
@@ -201,20 +359,7 @@ def rna2sphinx(BASEPATH):
|
||||
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")
|
||||
pyfunc2sphinx(" ", fw, identifier, py_func, is_class=True)
|
||||
del py_funcs, py_func
|
||||
|
||||
if struct.references:
|
||||
|
||||
Reference in New Issue
Block a user