odd, this didn't get committed before

This commit is contained in:
2009-07-16 22:23:01 +00:00
parent 4aa15cd216
commit 479c970375
34 changed files with 11046 additions and 483 deletions

View File

@@ -1,5 +1,5 @@
/*
* $Id: BPY_extern.h 12334 2007-10-21 23:00:29Z aligorith $
* $Id: BPY_extern.h 21462 2009-07-09 15:40:04Z ton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -50,6 +50,8 @@ struct bConstraintTarget; /* DNA_constraint_types.h*/
struct Script; /* DNA_screen_types.h */
struct BPyMenu;
struct bContext;
struct ReportList;
#ifdef __cplusplus
extern "C" {
#endif
@@ -97,8 +99,8 @@ extern "C" {
int BPY_menu_invoke( struct BPyMenu *pym, short menutype );
/* 2.5 UI Scripts */
int BPY_run_python_script( struct bContext *C, const char *filename, struct Text *text ); // 2.5 working
int BPY_run_script_space_draw(struct bContext *C, struct SpaceScript * sc); // 2.5 working
int BPY_run_python_script( struct bContext *C, const char *filename, struct Text *text, struct ReportList *reports ); // 2.5 working
int BPY_run_script_space_draw(const struct bContext *C, struct SpaceScript * sc); // 2.5 working
void BPY_run_ui_scripts(struct bContext *C, int reload);
// int BPY_run_script_space_listener(struct bContext *C, struct SpaceScript * sc, struct ARegion *ar, struct wmNotifier *wmn); // 2.5 working
void BPY_update_modules( void ); // XXX - annoying, need this for pointers that get out of date

View File

@@ -24,10 +24,12 @@
# ***** END GPL LICENSE BLOCK *****
FILE(GLOB SRC intern/*.c)
FILE(GLOB GENSRC generic/*.c)
SET(INC
. ../../../intern/guardedalloc ../blenlib ../makesdna ../makesrna
../blenkernel ../editors/include ../windowmanager ${PYTHON_INC}
../../../extern/glew/include
)
IF(WITH_OPENEXR)
@@ -47,3 +49,5 @@ ENDIF(WITH_FFMPEG)
ADD_DEFINITIONS(-DWITH_CCGSUBSURF)
BLENDERLIB(bf_python "${SRC}" "${INC}")
BLENDERLIB(bf_gen_python "${GENSRC}" "${INC}")

View File

@@ -1,5 +1,5 @@
#
# $Id: Makefile 14444 2008-04-16 22:40:48Z hos $
# $Id: Makefile 21094 2009-06-23 00:09:26Z gsrb3d $
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
@@ -29,6 +29,6 @@
# Bounces make to subdirectories.
SOURCEDIR = source/blender/python
DIRS = intern
DIRS = intern generic
include nan_subdirs.mk

View File

@@ -5,7 +5,7 @@ sources = env.Glob('intern/*.c')
incs = '. ../editors/include ../makesdna ../makesrna ../blenlib ../blenkernel ../nodes'
incs += ' ../imbuf ../blenloader ../render/extern/include ../windowmanager'
incs += ' #intern/guardedalloc #intern/memutil'
incs += ' #intern/guardedalloc #intern/memutil #extern/glew/include'
incs += ' ' + env['BF_PYTHON_INC']
defs = []
@@ -15,3 +15,7 @@ if env['OURPLATFORM'] in ('win32-mingw', 'win32-vc') and env['BF_DEBUG']:
env.BlenderLib( libname = 'bf_python', sources = Split(sources), includes = Split(incs), defines = defs, libtype = ['core'], priority = [140])
# generic
sources = env.Glob('generic/*.c')
env.BlenderLib( libname = 'bf_gen_python', sources = Split(sources), includes = Split(incs), defines = defs, libtype = ['core'], priority = [361]) # ketsji is 360

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,338 @@
/*
* $Id: BGL.h 21094 2009-06-23 00:09:26Z gsrb3d $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* This is a new part of Blender.
*
* Contributor(s): Willian P. Germano
*
* ***** END GPL LICENSE BLOCK *****
*/
/* This is the Blender.BGL part of opy_draw.c, from the old bpython/intern
* dir, with minor changes to adapt it to the new Python implementation.
* The BGL submodule "wraps" OpenGL functions and constants, allowing script
* writers to make OpenGL calls in their Python scripts for Blender. The
* more important original comments are marked with an @ symbol. */
#ifndef EXPP_BGL_H
#define EXPP_BGL_H
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <Python.h>
#include <GL/glew.h>
#include "../intern/bpy_compat.h"
PyObject *BGL_Init( const char *from );
/*@ Buffer Object */
/*@ For Python access to OpenGL functions requiring a pointer. */
typedef struct _Buffer {
PyObject_VAR_HEAD
PyObject * parent;
int type; /* GL_BYTE, GL_SHORT, GL_INT, GL_FLOAT */
int ndimensions;
int *dimensions;
union {
char *asbyte;
short *asshort;
int *asint;
float *asfloat;
double *asdouble;
void *asvoid;
} buf;
} Buffer;
/*@ By golly George! It looks like fancy pants macro time!!! */
/*
#define int_str "i"
#define int_var(number) bgl_int##number
#define int_ref(number) &bgl_int##number
#define int_def(number) int int_var(number)
#define float_str "f"
#define float_var(number) bgl_float##number
#define float_ref(number) &bgl_float##number
#define float_def(number) float float_var(number)
*/
/* TYPE_str is the string to pass to Py_ArgParse (for the format) */
/* TYPE_var is the name to pass to the GL function */
/* TYPE_ref is the pointer to pass to Py_ArgParse (to store in) */
/* TYPE_def is the C initialization of the variable */
#define void_str ""
#define void_var(num)
#define void_ref(num) &bgl_var##num
#define void_def(num) char bgl_var##num
#define buffer_str "O!"
#define buffer_var(number) (bgl_buffer##number)->buf.asvoid
#define buffer_ref(number) &buffer_Type, &bgl_buffer##number
#define buffer_def(number) Buffer *bgl_buffer##number
/* GL Pointer fields, handled by buffer type */
/* GLdoubleP, GLfloatP, GLintP, GLuintP, GLshortP */
#define GLbooleanP_str "O!"
#define GLbooleanP_var(number) (bgl_buffer##number)->buf.asvoid
#define GLbooleanP_ref(number) &buffer_Type, &bgl_buffer##number
#define GLbooleanP_def(number) Buffer *bgl_buffer##number
#define GLbyteP_str "O!"
#define GLbyteP_var(number) (bgl_buffer##number)->buf.asvoid
#define GLbyteP_ref(number) &buffer_Type, &bgl_buffer##number
#define GLbyteP_def(number) Buffer *bgl_buffer##number
#define GLubyteP_str "O!"
#define GLubyteP_var(number) (bgl_buffer##number)->buf.asvoid
#define GLubyteP_ref(number) &buffer_Type, &bgl_buffer##number
#define GLubyteP_def(number) Buffer *bgl_buffer##number
#define GLintP_str "O!"
#define GLintP_var(number) (bgl_buffer##number)->buf.asvoid
#define GLintP_ref(number) &buffer_Type, &bgl_buffer##number
#define GLintP_def(number) Buffer *bgl_buffer##number
#define GLuintP_str "O!"
#define GLuintP_var(number) (bgl_buffer##number)->buf.asvoid
#define GLuintP_ref(number) &buffer_Type, &bgl_buffer##number
#define GLuintP_def(number) Buffer *bgl_buffer##number
#define GLshortP_str "O!"
#define GLshortP_var(number) (bgl_buffer##number)->buf.asvoid
#define GLshortP_ref(number) &buffer_Type, &bgl_buffer##number
#define GLshortP_def(number) Buffer *bgl_buffer##number
#define GLushortP_str "O!"
#define GLushortP_var(number) (bgl_buffer##number)->buf.asvoid
#define GLushortP_ref(number) &buffer_Type, &bgl_buffer##number
#define GLushortP_def(number) Buffer *bgl_buffer##number
#define GLfloatP_str "O!"
#define GLfloatP_var(number) (bgl_buffer##number)->buf.asvoid
#define GLfloatP_ref(number) &buffer_Type, &bgl_buffer##number
#define GLfloatP_def(number) Buffer *bgl_buffer##number
#define GLdoubleP_str "O!"
#define GLdoubleP_var(number) (bgl_buffer##number)->buf.asvoid
#define GLdoubleP_ref(number) &buffer_Type, &bgl_buffer##number
#define GLdoubleP_def(number) Buffer *bgl_buffer##number
#define GLclampfP_str "O!"
#define GLclampfP_var(number) (bgl_buffer##number)->buf.asvoid
#define GLclampfP_ref(number) &buffer_Type, &bgl_buffer##number
#define GLclampfP_def(number) Buffer *bgl_buffer##number
#define GLvoidP_str "O!"
#define GLvoidP_var(number) (bgl_buffer##number)->buf.asvoid
#define GLvoidP_ref(number) &buffer_Type, &bgl_buffer##number
#define GLvoidP_def(number) Buffer *bgl_buffer##number
#define buffer_str "O!"
#define buffer_var(number) (bgl_buffer##number)->buf.asvoid
#define buffer_ref(number) &buffer_Type, &bgl_buffer##number
#define buffer_def(number) Buffer *bgl_buffer##number
/*@The standard GL typedefs are used as prototypes, we can't
* use the GL type directly because Py_ArgParse expects normal
* C types.
*
* Py_ArgParse doesn't grok writing into unsigned variables,
* so we use signed everything (even stuff that should be unsigned.
*/
/* typedef unsigned int GLenum; */
#define GLenum_str "i"
#define GLenum_var(num) bgl_var##num
#define GLenum_ref(num) &bgl_var##num
#define GLenum_def(num) /* unsigned */ int GLenum_var(num)
/* typedef unsigned int GLboolean; */
#define GLboolean_str "b"
#define GLboolean_var(num) bgl_var##num
#define GLboolean_ref(num) &bgl_var##num
#define GLboolean_def(num) /* unsigned */ char GLboolean_var(num)
/* typedef unsigned int GLbitfield; */
#define GLbitfield_str "i"
#define GLbitfield_var(num) bgl_var##num
#define GLbitfield_ref(num) &bgl_var##num
#define GLbitfield_def(num) /* unsigned */ int GLbitfield_var(num)
/* typedef signed char GLbyte; */
#define GLbyte_str "b"
#define GLbyte_var(num) bgl_var##num
#define GLbyte_ref(num) &bgl_var##num
#define GLbyte_def(num) signed char GLbyte_var(num)
/* typedef short GLshort; */
#define GLshort_str "h"
#define GLshort_var(num) bgl_var##num
#define GLshort_ref(num) &bgl_var##num
#define GLshort_def(num) short GLshort_var(num)
/* typedef int GLint; */
#define GLint_str "i"
#define GLint_var(num) bgl_var##num
#define GLint_ref(num) &bgl_var##num
#define GLint_def(num) int GLint_var(num)
/* typedef int GLsizei; */
#define GLsizei_str "i"
#define GLsizei_var(num) bgl_var##num
#define GLsizei_ref(num) &bgl_var##num
#define GLsizei_def(num) int GLsizei_var(num)
/* typedef unsigned char GLubyte; */
#define GLubyte_str "b"
#define GLubyte_var(num) bgl_var##num
#define GLubyte_ref(num) &bgl_var##num
#define GLubyte_def(num) /* unsigned */ char GLubyte_var(num)
/* typedef unsigned short GLushort; */
#define GLushort_str "h"
#define GLushort_var(num) bgl_var##num
#define GLushort_ref(num) &bgl_var##num
#define GLushort_def(num) /* unsigned */ short GLushort_var(num)
/* typedef unsigned int GLuint; */
#define GLuint_str "i"
#define GLuint_var(num) bgl_var##num
#define GLuint_ref(num) &bgl_var##num
#define GLuint_def(num) /* unsigned */ int GLuint_var(num)
/* typedef float GLfloat; */
#define GLfloat_str "f"
#define GLfloat_var(num) bgl_var##num
#define GLfloat_ref(num) &bgl_var##num
#define GLfloat_def(num) float GLfloat_var(num)
/* typedef float GLclampf; */
#define GLclampf_str "f"
#define GLclampf_var(num) bgl_var##num
#define GLclampf_ref(num) &bgl_var##num
#define GLclampf_def(num) float GLclampf_var(num)
/* typedef double GLdouble; */
#define GLdouble_str "d"
#define GLdouble_var(num) bgl_var##num
#define GLdouble_ref(num) &bgl_var##num
#define GLdouble_def(num) double GLdouble_var(num)
/* typedef double GLclampd; */
#define GLclampd_str "d"
#define GLclampd_var(num) bgl_var##num
#define GLclampd_ref(num) &bgl_var##num
#define GLclampd_def(num) double GLclampd_var(num)
/* typedef void GLvoid; */
/* #define GLvoid_str "" */
/* #define GLvoid_var(num) bgl_var##num */
/* #define GLvoid_ref(num) &bgl_var##num */
/* #define GLvoid_def(num) char bgl_var##num */
#define arg_def1(a1) a1##_def(1)
#define arg_def2(a1, a2) arg_def1(a1); a2##_def(2)
#define arg_def3(a1, a2, a3) arg_def2(a1, a2); a3##_def(3)
#define arg_def4(a1, a2, a3, a4) arg_def3(a1, a2, a3); a4##_def(4)
#define arg_def5(a1, a2, a3, a4, a5) arg_def4(a1, a2, a3, a4); a5##_def(5)
#define arg_def6(a1, a2, a3, a4, a5, a6)arg_def5(a1, a2, a3, a4, a5); a6##_def(6)
#define arg_def7(a1, a2, a3, a4, a5, a6, a7)arg_def6(a1, a2, a3, a4, a5, a6); a7##_def(7)
#define arg_def8(a1, a2, a3, a4, a5, a6, a7, a8)arg_def7(a1, a2, a3, a4, a5, a6, a7); a8##_def(8)
#define arg_def9(a1, a2, a3, a4, a5, a6, a7, a8, a9)arg_def8(a1, a2, a3, a4, a5, a6, a7, a8); a9##_def(9)
#define arg_def10(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)arg_def9(a1, a2, a3, a4, a5, a6, a7, a8, a9); a10##_def(10)
#define arg_var1(a1) a1##_var(1)
#define arg_var2(a1, a2) arg_var1(a1), a2##_var(2)
#define arg_var3(a1, a2, a3) arg_var2(a1, a2), a3##_var(3)
#define arg_var4(a1, a2, a3, a4) arg_var3(a1, a2, a3), a4##_var(4)
#define arg_var5(a1, a2, a3, a4, a5) arg_var4(a1, a2, a3, a4), a5##_var(5)
#define arg_var6(a1, a2, a3, a4, a5, a6)arg_var5(a1, a2, a3, a4, a5), a6##_var(6)
#define arg_var7(a1, a2, a3, a4, a5, a6, a7)arg_var6(a1, a2, a3, a4, a5, a6), a7##_var(7)
#define arg_var8(a1, a2, a3, a4, a5, a6, a7, a8)arg_var7(a1, a2, a3, a4, a5, a6, a7), a8##_var(8)
#define arg_var9(a1, a2, a3, a4, a5, a6, a7, a8, a9)arg_var8(a1, a2, a3, a4, a5, a6, a7, a8), a9##_var(9)
#define arg_var10(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)arg_var9(a1, a2, a3, a4, a5, a6, a7, a8, a9), a10##_var(10)
#define arg_ref1(a1) a1##_ref(1)
#define arg_ref2(a1, a2) arg_ref1(a1), a2##_ref(2)
#define arg_ref3(a1, a2, a3) arg_ref2(a1, a2), a3##_ref(3)
#define arg_ref4(a1, a2, a3, a4) arg_ref3(a1, a2, a3), a4##_ref(4)
#define arg_ref5(a1, a2, a3, a4, a5) arg_ref4(a1, a2, a3, a4), a5##_ref(5)
#define arg_ref6(a1, a2, a3, a4, a5, a6)arg_ref5(a1, a2, a3, a4, a5), a6##_ref(6)
#define arg_ref7(a1, a2, a3, a4, a5, a6, a7)arg_ref6(a1, a2, a3, a4, a5, a6), a7##_ref(7)
#define arg_ref8(a1, a2, a3, a4, a5, a6, a7, a8)arg_ref7(a1, a2, a3, a4, a5, a6, a7), a8##_ref(8)
#define arg_ref9(a1, a2, a3, a4, a5, a6, a7, a8, a9)arg_ref8(a1, a2, a3, a4, a5, a6, a7, a8), a9##_ref(9)
#define arg_ref10(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)arg_ref9(a1, a2, a3, a4, a5, a6, a7, a8, a9), a10##_ref(10)
#define arg_str1(a1) a1##_str
#define arg_str2(a1, a2) arg_str1(a1) a2##_str
#define arg_str3(a1, a2, a3) arg_str2(a1, a2) a3##_str
#define arg_str4(a1, a2, a3, a4) arg_str3(a1, a2, a3) a4##_str
#define arg_str5(a1, a2, a3, a4, a5) arg_str4(a1, a2, a3, a4) a5##_str
#define arg_str6(a1, a2, a3, a4, a5, a6)arg_str5(a1, a2, a3, a4, a5) a6##_str
#define arg_str7(a1, a2, a3, a4, a5, a6, a7)arg_str6(a1, a2, a3, a4, a5, a6) a7##_str
#define arg_str8(a1, a2, a3, a4, a5, a6, a7, a8)arg_str7(a1, a2, a3, a4, a5, a6, a7) a8##_str
#define arg_str9(a1, a2, a3, a4, a5, a6, a7, a8, a9)arg_str8(a1, a2, a3, a4, a5, a6, a7, a8) a9##_str
#define arg_str10(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)arg_str9(a1, a2, a3, a4, a5, a6, a7, a8, a9) a10##_str
#define ret_def_void
#define ret_set_void
/* would use Py_RETURN_NONE - except for py 2.3 doesnt have it */
#define ret_ret_void { Py_INCREF(Py_None); return Py_None; }
#define ret_def_GLint int ret_int
#define ret_set_GLint ret_int=
#define ret_ret_GLint return PyLong_FromLong(ret_int);
#define ret_def_GLuint unsigned int ret_uint
#define ret_set_GLuint ret_uint=
#define ret_ret_GLuint return PyLong_FromLong((long) ret_uint);
#define ret_def_GLenum unsigned int ret_uint
#define ret_set_GLenum ret_uint=
#define ret_ret_GLenum return PyLong_FromLong((long) ret_uint);
#define ret_def_GLboolean unsigned char ret_bool
#define ret_set_GLboolean ret_bool=
#define ret_ret_GLboolean return PyLong_FromLong((long) ret_bool);
#define ret_def_GLstring const unsigned char *ret_str;
#define ret_set_GLstring ret_str=
#define ret_ret_GLstring \
if (ret_str) {\
return PyUnicode_FromString(ret_str);\
} else {\
PyErr_SetString(PyExc_AttributeError, "could not get opengl string");\
return NULL;\
}
#endif /* EXPP_BGL_H */

View File

@@ -0,0 +1,542 @@
/*
* $Id: Geometry.c 21254 2009-06-30 00:42:17Z campbellbarton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* This is a new part of Blender.
*
* Contributor(s): Joseph Gilbert, Campbell Barton
*
* ***** END GPL LICENSE BLOCK *****
*/
#include "Geometry.h"
/* - Not needed for now though other geometry functions will probably need them
#include "BLI_arithb.h"
#include "BKE_utildefines.h"
*/
/* Used for PolyFill */
#include "BKE_displist.h"
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
#include "BKE_utildefines.h"
#include "BKE_curve.h"
#include "BLI_boxpack2d.h"
#include "BLI_arithb.h"
#define SWAP_FLOAT(a,b,tmp) tmp=a; a=b; b=tmp
#define eul 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 );
/*-------------------------DOC STRINGS ---------------------------*/
static char M_Geometry_doc[] = "The Blender Geometry module\n\n";
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";
static char M_Geometry_PointInTriangle2D_doc[] = "(pt, tri_p1, tri_p2, tri_p3) - takes 4 vectors, one is the point and the next 3 define the triangle, only the x and y are used from the vectors";
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},
{NULL, NULL, 0, NULL}
};
#if (PY_VERSION_HEX >= 0x03000000)
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 */
};
#endif
/*----------------------------MODULE INIT-------------------------*/
PyObject *Geometry_Init(const char *from)
{
PyObject *submodule;
#if (PY_VERSION_HEX >= 0x03000000)
submodule = PyModule_Create(&M_Geometry_module_def);
PyDict_SetItemString(PySys_GetObject("modules"), M_Geometry_module_def.m_name, submodule);
#else
submodule = Py_InitModule3(from, M_Geometry_methods, M_Geometry_doc);
#endif
return (submodule);
}
/*----------------------------------Geometry.PolyFill() -------------------*/
/* PolyFill function, uses Blenders scanfill to fill multiple poly lines */
static PyObject *M_Geometry_PolyFill( PyObject * self, PyObject * polyLineSeq )
{
PyObject *tri_list; /*return this list of tri's */
PyObject *polyLine, *polyVec;
int i, len_polylines, len_polypoints, ls_error = 0;
/* display listbase */
ListBase dispbase={NULL, NULL};
DispList *dl;
float *fp; /*pointer to the array of malloced dl->verts to set the points from the vectors */
int index, *dl_face, totpoints=0;
dispbase.first= dispbase.last= NULL;
if(!PySequence_Check(polyLineSeq)) {
PyErr_SetString( PyExc_TypeError, "expected a sequence of poly lines" );
return NULL;
}
len_polylines = PySequence_Size( polyLineSeq );
for( i = 0; i < len_polylines; ++i ) {
polyLine= PySequence_GetItem( polyLineSeq, i );
if (!PySequence_Check(polyLine)) {
freedisplist(&dispbase);
Py_XDECREF(polyLine); /* may be null so use Py_XDECREF*/
PyErr_SetString( PyExc_TypeError, "One or more of the polylines is not a sequence of Mathutils.Vector's" );
return NULL;
}
len_polypoints= PySequence_Size( polyLine );
if (len_polypoints>0) { /* dont bother adding edges as polylines */
#if 0
if (EXPP_check_sequence_consistency( polyLine, &vector_Type ) != 1) {
freedisplist(&dispbase);
Py_DECREF(polyLine);
PyErr_SetString( PyExc_TypeError, "A point in one of the polylines is not a Mathutils.Vector type" );
return NULL;
}
#endif
dl= MEM_callocN(sizeof(DispList), "poly disp");
BLI_addtail(&dispbase, dl);
dl->type= DL_INDEX3;
dl->nr= len_polypoints;
dl->type= DL_POLY;
dl->parts= 1; /* no faces, 1 edge loop */
dl->col= 0; /* no material */
dl->verts= fp= MEM_callocN( sizeof(float)*3*len_polypoints, "dl verts");
dl->index= MEM_callocN(sizeof(int)*3*len_polypoints, "dl index");
for( index = 0; index<len_polypoints; ++index, fp+=3) {
polyVec= PySequence_GetItem( polyLine, index );
if(VectorObject_Check(polyVec)) {
if(!BaseMath_ReadCallback((VectorObject *)polyVec))
ls_error= 1;
fp[0] = ((VectorObject *)polyVec)->vec[0];
fp[1] = ((VectorObject *)polyVec)->vec[1];
if( ((VectorObject *)polyVec)->size > 2 )
fp[2] = ((VectorObject *)polyVec)->vec[2];
else
fp[2]= 0.0f; /* if its a 2d vector then set the z to be zero */
}
else {
ls_error= 1;
}
totpoints++;
Py_DECREF(polyVec);
}
}
Py_DECREF(polyLine);
}
if(ls_error) {
freedisplist(&dispbase); /* possible some dl was allocated */
PyErr_SetString( PyExc_TypeError, "A point in one of the polylines is not a Mathutils.Vector type" );
return NULL;
}
else if (totpoints) {
/* now make the list to return */
filldisplist(&dispbase, &dispbase);
/* The faces are stored in a new DisplayList
thats added to the head of the listbase */
dl= dispbase.first;
tri_list= PyList_New(dl->parts);
if( !tri_list ) {
freedisplist(&dispbase);
PyErr_SetString( PyExc_RuntimeError, "Geometry.PolyFill failed to make a new list" );
return NULL;
}
index= 0;
dl_face= dl->index;
while(index < dl->parts) {
PyList_SetItem(tri_list, index, Py_BuildValue("iii", dl_face[0], dl_face[1], dl_face[2]) );
dl_face+= 3;
index++;
}
freedisplist(&dispbase);
} else {
/* no points, do this so scripts dont barf */
freedisplist(&dispbase); /* possible some dl was allocated */
tri_list= PyList_New(0);
}
return tri_list;
}
static PyObject *M_Geometry_LineIntersect2D( PyObject * self, PyObject * args )
{
VectorObject *line_a1, *line_a2, *line_b1, *line_b2;
float a1x, a1y, a2x, a2y, b1x, b1y, b2x, b2y, xi, yi, a1,a2,b1,b2, newvec[2];
if( !PyArg_ParseTuple ( args, "O!O!O!O!",
&vector_Type, &line_a1,
&vector_Type, &line_a2,
&vector_Type, &line_b1,
&vector_Type, &line_b2)
) {
PyErr_SetString( PyExc_TypeError, "expected 4 vector types\n" );
return NULL;
}
if(!BaseMath_ReadCallback(line_a1) || !BaseMath_ReadCallback(line_a2) || !BaseMath_ReadCallback(line_b1) || !BaseMath_ReadCallback(line_b2))
return NULL;
a1x= line_a1->vec[0];
a1y= line_a1->vec[1];
a2x= line_a2->vec[0];
a2y= line_a2->vec[1];
b1x= line_b1->vec[0];
b1y= line_b1->vec[1];
b2x= line_b2->vec[0];
b2y= line_b2->vec[1];
if((MIN2(a1x, a2x) > MAX2(b1x, b2x)) ||
(MAX2(a1x, a2x) < MIN2(b1x, b2x)) ||
(MIN2(a1y, a2y) > MAX2(b1y, b2y)) ||
(MAX2(a1y, a2y) < MIN2(b1y, b2y)) ) {
Py_RETURN_NONE;
}
/* Make sure the hoz/vert line comes first. */
if (fabs(b1x - b2x) < eul || fabs(b1y - b2y) < eul) {
SWAP_FLOAT(a1x, b1x, xi); /*abuse xi*/
SWAP_FLOAT(a1y, b1y, xi);
SWAP_FLOAT(a2x, b2x, xi);
SWAP_FLOAT(a2y, b2y, xi);
}
if (fabs(a1x-a2x) < eul) { /* verticle line */
if (fabs(b1x-b2x) < eul){ /*verticle second line */
Py_RETURN_NONE; /* 2 verticle lines dont intersect. */
}
else if (fabs(b1y-b2y) < eul) {
/*X of vert, Y of hoz. no calculation needed */
newvec[0]= a1x;
newvec[1]= b1y;
return newVectorObject(newvec, 2, Py_NEW, NULL);
}
yi = (float)(((b1y / fabs(b1x - b2x)) * fabs(b2x - a1x)) + ((b2y / fabs(b1x - b2x)) * fabs(b1x - a1x)));
if (yi > MAX2(a1y, a2y)) {/* New point above seg1's vert line */
Py_RETURN_NONE;
} else if (yi < MIN2(a1y, a2y)) { /* New point below seg1's vert line */
Py_RETURN_NONE;
}
newvec[0]= a1x;
newvec[1]= yi;
return newVectorObject(newvec, 2, Py_NEW, NULL);
} else if (fabs(a2y-a1y) < eul) { /* hoz line1 */
if (fabs(b2y-b1y) < eul) { /*hoz line2*/
Py_RETURN_NONE; /*2 hoz lines dont intersect*/
}
/* Can skip vert line check for seg 2 since its covered above. */
xi = (float)(((b1x / fabs(b1y - b2y)) * fabs(b2y - a1y)) + ((b2x / fabs(b1y - b2y)) * fabs(b1y - a1y)));
if (xi > MAX2(a1x, a2x)) { /* New point right of hoz line1's */
Py_RETURN_NONE;
} else if (xi < MIN2(a1x, a2x)) { /*New point left of seg1's hoz line */
Py_RETURN_NONE;
}
newvec[0]= xi;
newvec[1]= a1y;
return newVectorObject(newvec, 2, Py_NEW, NULL);
}
b1 = (a2y-a1y)/(a2x-a1x);
b2 = (b2y-b1y)/(b2x-b1x);
a1 = a1y-b1*a1x;
a2 = b1y-b2*b1x;
if (b1 - b2 == 0.0) {
Py_RETURN_NONE;
}
xi = - (a1-a2)/(b1-b2);
yi = a1+b1*xi;
if ((a1x-xi)*(xi-a2x) >= 0 && (b1x-xi)*(xi-b2x) >= 0 && (a1y-yi)*(yi-a2y) >= 0 && (b1y-yi)*(yi-b2y)>=0) {
newvec[0]= xi;
newvec[1]= yi;
return newVectorObject(newvec, 2, Py_NEW, NULL);
}
Py_RETURN_NONE;
}
static PyObject *M_Geometry_ClosestPointOnLine( PyObject * self, PyObject * args )
{
VectorObject *pt, *line_1, *line_2;
float pt_in[3], pt_out[3], l1[3], l2[3];
float lambda;
PyObject *ret;
if( !PyArg_ParseTuple ( args, "O!O!O!",
&vector_Type, &pt,
&vector_Type, &line_1,
&vector_Type, &line_2)
) {
PyErr_SetString( PyExc_TypeError, "expected 3 vector types\n" );
return NULL;
}
if(!BaseMath_ReadCallback(pt) || !BaseMath_ReadCallback(line_1) || !BaseMath_ReadCallback(line_2))
return NULL;
/* accept 2d verts */
if (pt->size==3) { VECCOPY(pt_in, pt->vec);}
else { pt_in[2]=0.0; VECCOPY2D(pt_in, pt->vec) }
if (line_1->size==3) { VECCOPY(l1, line_1->vec);}
else { l1[2]=0.0; VECCOPY2D(l1, line_1->vec) }
if (line_2->size==3) { VECCOPY(l2, line_2->vec);}
else { l2[2]=0.0; VECCOPY2D(l2, line_2->vec) }
/* do the calculation */
lambda = lambda_cp_line_ex(pt_in, l1, l2, pt_out);
ret = PyTuple_New(2);
PyTuple_SET_ITEM( ret, 0, newVectorObject(pt_out, 3, Py_NEW, NULL) );
PyTuple_SET_ITEM( ret, 1, PyFloat_FromDouble(lambda) );
return ret;
}
static PyObject *M_Geometry_PointInTriangle2D( PyObject * self, PyObject * args )
{
VectorObject *pt_vec, *tri_p1, *tri_p2, *tri_p3;
if( !PyArg_ParseTuple ( args, "O!O!O!O!",
&vector_Type, &pt_vec,
&vector_Type, &tri_p1,
&vector_Type, &tri_p2,
&vector_Type, &tri_p3)
) {
PyErr_SetString( PyExc_TypeError, "expected 4 vector types\n" );
return NULL;
}
if(!BaseMath_ReadCallback(pt_vec) || !BaseMath_ReadCallback(tri_p1) || !BaseMath_ReadCallback(tri_p2) || !BaseMath_ReadCallback(tri_p3))
return NULL;
return PyLong_FromLong(IsectPT2Df(pt_vec->vec, tri_p1->vec, tri_p2->vec, tri_p3->vec));
}
static PyObject *M_Geometry_PointInQuad2D( PyObject * self, PyObject * args )
{
VectorObject *pt_vec, *quad_p1, *quad_p2, *quad_p3, *quad_p4;
if( !PyArg_ParseTuple ( args, "O!O!O!O!O!",
&vector_Type, &pt_vec,
&vector_Type, &quad_p1,
&vector_Type, &quad_p2,
&vector_Type, &quad_p3,
&vector_Type, &quad_p4)
) {
PyErr_SetString( PyExc_TypeError, "expected 5 vector types\n" );
return NULL;
}
if(!BaseMath_ReadCallback(pt_vec) || !BaseMath_ReadCallback(quad_p1) || !BaseMath_ReadCallback(quad_p2) || !BaseMath_ReadCallback(quad_p3) || !BaseMath_ReadCallback(quad_p4))
return NULL;
return PyLong_FromLong(IsectPQ2Df(pt_vec->vec, quad_p1->vec, quad_p2->vec, quad_p3->vec, quad_p4->vec));
}
static int boxPack_FromPyObject(PyObject * value, boxPack **boxarray )
{
int len, i;
PyObject *list_item, *item_1, *item_2;
boxPack *box;
/* Error checking must alredy be done */
if( !PyList_Check( value ) ) {
PyErr_SetString( PyExc_TypeError, "can only back a list of [x,y,x,w]" );
return -1;
}
len = PyList_Size( value );
(*boxarray) = MEM_mallocN( len*sizeof(boxPack), "boxPack box");
for( i = 0; i < len; i++ ) {
list_item = PyList_GET_ITEM( value, i );
if( !PyList_Check( list_item ) || PyList_Size( list_item ) < 4 ) {
MEM_freeN(*boxarray);
PyErr_SetString( PyExc_TypeError, "can only back a list of [x,y,x,w]" );
return -1;
}
box = (*boxarray)+i;
item_1 = PyList_GET_ITEM(list_item, 2);
item_2 = PyList_GET_ITEM(list_item, 3);
if (!PyNumber_Check(item_1) || !PyNumber_Check(item_2)) {
MEM_freeN(*boxarray);
PyErr_SetString( PyExc_TypeError, "can only back a list of 2d boxes [x,y,x,w]" );
return -1;
}
box->w = (float)PyFloat_AsDouble( item_1 );
box->h = (float)PyFloat_AsDouble( item_2 );
box->index = i;
/* verts will be added later */
}
return 0;
}
static void boxPack_ToPyObject(PyObject * value, boxPack **boxarray)
{
int len, i;
PyObject *list_item;
boxPack *box;
len = PyList_Size( value );
for( i = 0; i < len; i++ ) {
box = (*boxarray)+i;
list_item = PyList_GET_ITEM( value, box->index );
PyList_SET_ITEM( list_item, 0, PyFloat_FromDouble( box->x ));
PyList_SET_ITEM( list_item, 1, PyFloat_FromDouble( box->y ));
}
MEM_freeN(*boxarray);
}
static PyObject *M_Geometry_BoxPack2D( PyObject * self, PyObject * boxlist )
{
boxPack *boxarray = NULL;
float tot_width, tot_height;
int len;
int error;
if(!PyList_Check(boxlist)) {
PyErr_SetString( PyExc_TypeError, "expected a sequence of boxes [[x,y,w,h], ... ]" );
return NULL;
}
len = PyList_Size( boxlist );
if (!len)
return Py_BuildValue( "ff", 0.0, 0.0);
error = boxPack_FromPyObject(boxlist, &boxarray);
if (error!=0) return NULL;
/* Non Python function */
boxPack2D(boxarray, len, &tot_width, &tot_height);
boxPack_ToPyObject(boxlist, &boxarray);
return Py_BuildValue( "ff", tot_width, tot_height);
}
static PyObject *M_Geometry_BezierInterp( PyObject * self, PyObject * args )
{
VectorObject *vec_k1, *vec_h1, *vec_k2, *vec_h2;
int resolu;
int dims;
int i;
float *coord_array, *fp;
PyObject *list;
float k1[4] = {0.0, 0.0, 0.0, 0.0};
float h1[4] = {0.0, 0.0, 0.0, 0.0};
float k2[4] = {0.0, 0.0, 0.0, 0.0};
float h2[4] = {0.0, 0.0, 0.0, 0.0};
if( !PyArg_ParseTuple ( args, "O!O!O!O!i",
&vector_Type, &vec_k1,
&vector_Type, &vec_h1,
&vector_Type, &vec_h2,
&vector_Type, &vec_k2, &resolu) || (resolu<=1)
) {
PyErr_SetString( PyExc_TypeError, "expected 4 vector types and an int greater then 1\n" );
return NULL;
}
if(!BaseMath_ReadCallback(vec_k1) || !BaseMath_ReadCallback(vec_h1) || !BaseMath_ReadCallback(vec_k2) || !BaseMath_ReadCallback(vec_h2))
return NULL;
dims= MAX4(vec_k1->size, vec_h1->size, vec_h2->size, vec_k2->size);
for(i=0; i < vec_k1->size; i++) k1[i]= vec_k1->vec[i];
for(i=0; i < vec_h1->size; i++) h1[i]= vec_h1->vec[i];
for(i=0; i < vec_k2->size; i++) k2[i]= vec_k2->vec[i];
for(i=0; i < vec_h2->size; i++) h2[i]= vec_h2->vec[i];
coord_array = MEM_callocN(dims * (resolu) * sizeof(float), "BezierInterp");
for(i=0; i<dims; i++) {
forward_diff_bezier(k1[i], h1[i], h2[i], k2[i], coord_array+i, resolu-1, dims);
}
list= PyList_New(resolu);
fp= coord_array;
for(i=0; i<resolu; i++, fp= fp+dims) {
PyList_SET_ITEM(list, i, newVectorObject(fp, dims, Py_NEW, NULL));
}
MEM_freeN(coord_array);
return list;
}

View File

@@ -0,0 +1,39 @@
/*
* $Id: Geometry.h 21094 2009-06-23 00:09:26Z gsrb3d $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* This is a new part of Blender.
*
* Contributor(s): Joseph Gilbert
*
* ***** END GPL LICENSE BLOCK *****
*/
/*Include this file for access to vector, quat, matrix, euler, etc...*/
#ifndef EXPP_Geometry_H
#define EXPP_Geometry_H
#include <Python.h>
#include "Mathutils.h"
PyObject *Geometry_Init( const char *from );
#endif /* EXPP_Geometry_H */

View File

@@ -0,0 +1,66 @@
#
# $Id: Makefile 21094 2009-06-23 00:09:26Z gsrb3d $
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
# All rights reserved.
#
# The Original Code is: all of this file.
#
# Contributor(s): none yet.
#
# ***** END GPL LICENSE BLOCK *****
#
#
LIBNAME = gen_python
DIR = $(OCGDIR)/blender/$(LIBNAME)
include nan_compile.mk
CFLAGS += $(LEVEL_1_C_WARNINGS)
# OpenGL and Python
CPPFLAGS += -I$(NAN_GLEW)/include
CPPFLAGS += $(OGL_CPPFLAGS)
CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION)
# PreProcessor stuff
CPPFLAGS += -I$(NAN_GHOST)/include
CPPFLAGS += -I$(NAN_SOUNDSYSTEM)/include $(NAN_SDLCFLAGS)
# modules
CPPFLAGS += -I../../editors/include
CPPFLAGS += -I../../python
CPPFLAGS += -I../../makesdna
CPPFLAGS += -I../../makesrna
CPPFLAGS += -I../../blenlib
CPPFLAGS += -I../../blenkernel
CPPFLAGS += -I../../nodes
CPPFLAGS += -I../../imbuf
CPPFLAGS += -I../../blenloader
CPPFLAGS += -I../../windowmanager
CPPFLAGS += -I../../render/extern/include
# path to the guarded memory allocator
CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
CPPFLAGS += -I$(NAN_MEMUTIL)/include
# path to our own headerfiles
CPPFLAGS += -I..

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,116 @@
/*
* $Id: Mathutils.h 21499 2009-07-10 18:09:53Z campbellbarton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* This is a new part of Blender.
*
* Contributor(s): Joseph Gilbert
*
* ***** END GPL LICENSE BLOCK *****
*/
//Include this file for access to vector, quat, matrix, euler, etc...
#ifndef EXPP_Mathutils_H
#define EXPP_Mathutils_H
#include <Python.h>
#include "../intern/bpy_compat.h"
#include "vector.h"
#include "matrix.h"
#include "quat.h"
#include "euler.h"
/* #define USE_MATHUTILS_DEG - for backwards compat */
/* Can cast different mathutils types to this, use for generic funcs */
typedef struct {
PyObject_VAR_HEAD
float *data; /*array of data (alias), wrapped status depends on wrapped status */
PyObject *cb_user; /* if this vector references another object, otherwise NULL, *Note* this owns its reference */
unsigned char cb_type; /* which user funcs do we adhere to, RNA, GameObject, etc */
unsigned char cb_subtype; /* subtype: location, rotation... to avoid defining many new functions for every attribute of the same type */
unsigned char wrapped; /* wrapped data type? */
} BaseMathObject;
PyObject *BaseMathObject_getOwner( BaseMathObject * self, void * );
PyObject *BaseMathObject_getWrapped( BaseMathObject *self, void * );
void BaseMathObject_dealloc(BaseMathObject * self);
PyObject *Mathutils_Init( const char * from );
PyObject *quat_rotation(PyObject *arg1, PyObject *arg2);
int EXPP_FloatsAreEqual(float A, float B, int floatSteps);
int EXPP_VectorsAreEqual(float *vecA, float *vecB, int size, int floatSteps);
#define Py_PI 3.14159265358979323846
#define Py_NEW 1
#define Py_WRAP 2
/* Mathutils is used by the BGE and Blender so have to define
* some things here for luddite mac users of py2.3 */
#ifndef Py_RETURN_NONE
#define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
#endif
#ifndef Py_RETURN_FALSE
#define Py_RETURN_FALSE return Py_INCREF(Py_False), Py_False
#endif
#ifndef Py_RETURN_TRUE
#define Py_RETURN_TRUE return Py_INCREF(Py_True), Py_True
#endif
typedef struct Mathutils_Callback Mathutils_Callback;
typedef int (*BaseMathCheckFunc)(PyObject *);
typedef int (*BaseMathGetFunc)(PyObject *, int, float *);
typedef int (*BaseMathSetFunc)(PyObject *, int, float *);
typedef int (*BaseMathGetIndexFunc)(PyObject *, int, float *, int);
typedef int (*BaseMathSetIndexFunc)(PyObject *, int, float *, int);
struct Mathutils_Callback {
int (*check)(PyObject *user); /* checks the user is still valid */
int (*get)(PyObject *user, int subtype, float *from); /* gets the vector from the user */
int (*set)(PyObject *user, int subtype, float *to); /* sets the users vector values once the vector is modified */
int (*get_index)(PyObject *user, int subtype, float *from,int index); /* same as above but only for an index */
int (*set_index)(PyObject *user, int subtype, float *to, int index); /* same as above but only for an index */
};
int Mathutils_RegisterCallback(Mathutils_Callback *cb);
int _BaseMathObject_ReadCallback(BaseMathObject *self);
int _BaseMathObject_WriteCallback(BaseMathObject *self);
int _BaseMathObject_ReadIndexCallback(BaseMathObject *self, int index);
int _BaseMathObject_WriteIndexCallback(BaseMathObject *self, int index);
/* since this is called so often avoid where possible */
#define BaseMath_ReadCallback(_self) (((_self)->cb_user ? _BaseMathObject_ReadCallback((BaseMathObject *)_self):1))
#define BaseMath_WriteCallback(_self) (((_self)->cb_user ?_BaseMathObject_WriteCallback((BaseMathObject *)_self):1))
#define BaseMath_ReadIndexCallback(_self, _index) (((_self)->cb_user ? _BaseMathObject_ReadIndexCallback((BaseMathObject *)_self, _index):1))
#define BaseMath_WriteIndexCallback(_self, _index) (((_self)->cb_user ? _BaseMathObject_WriteIndexCallback((BaseMathObject *)_self, _index):1))
#endif /* EXPP_Mathutils_H */

View File

@@ -0,0 +1,341 @@
/*
* $Id: bpy_internal_import.c 21094 2009-06-23 00:09:26Z gsrb3d $
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* This is a new part of Blender.
*
* Contributor(s): Willian P. Germano
*
* ***** END GPL LICENSE BLOCK *****
*/
#include "bpy_internal_import.h"
#include "DNA_text_types.h"
#include "DNA_ID.h"
#include "MEM_guardedalloc.h"
#include "BKE_text.h" /* txt_to_buf */
#include "BKE_main.h"
static Main *bpy_import_main= NULL;
static void free_compiled_text(Text *text)
{
if(text->compiled) {
Py_DECREF(( PyObject * )text->compiled);
}
text->compiled= NULL;
}
struct Main *bpy_import_main_get(void)
{
return bpy_import_main;
}
void bpy_import_main_set(struct Main *maggie)
{
bpy_import_main= maggie;
}
PyObject *bpy_text_import( char *name, int *found )
{
Text *text;
char txtname[22]; /* 21+NULL */
char *buf = NULL;
int namelen = strlen( name );
//XXX Main *maggie= bpy_import_main ? bpy_import_main:G.main;
Main *maggie= bpy_import_main;
*found= 0;
if (namelen>21-3) return NULL; /* we know this cant be importable, the name is too long for blender! */
memcpy( txtname, name, namelen );
memcpy( &txtname[namelen], ".py", 4 );
for(text = maggie->text.first; text; text = text->id.next) {
if( !strcmp( txtname, text->id.name+2 ) )
break;
}
if( !text )
return NULL;
else
*found = 1;
if( !text->compiled ) {
buf = txt_to_buf( text );
text->compiled = Py_CompileString( buf, text->id.name+2, Py_file_input );
MEM_freeN( buf );
if( PyErr_Occurred( ) ) {
PyErr_Print( );
PyErr_Clear( );
PySys_SetObject("last_traceback", NULL);
free_compiled_text( text );
return NULL;
}
}
return PyImport_ExecCodeModule( name, text->compiled );
}
/*
* find in-memory module and recompile
*/
PyObject *bpy_text_reimport( PyObject *module, int *found )
{
Text *text;
char *txtname;
char *name;
char *buf = NULL;
//XXX Main *maggie= bpy_import_main ? bpy_import_main:G.main;
Main *maggie= bpy_import_main;
*found= 0;
/* get name, filename from the module itself */
txtname = PyModule_GetFilename( module );
name = PyModule_GetName( module );
if( !txtname || !name)
return NULL;
/* look up the text object */
text = ( Text * ) & ( maggie->text.first );
while( text ) {
if( !strcmp( txtname, text->id.name+2 ) )
break;
text = text->id.next;
}
/* uh-oh.... didn't find it */
if( !text )
return NULL;
else
*found = 1;
/* if previously compiled, free the object */
/* (can't see how could be NULL, but check just in case) */
if( text->compiled ){
Py_DECREF( (PyObject *)text->compiled );
}
/* compile the buffer */
buf = txt_to_buf( text );
text->compiled = Py_CompileString( buf, text->id.name+2, Py_file_input );
MEM_freeN( buf );
/* if compile failed.... return this error */
if( PyErr_Occurred( ) ) {
PyErr_Print( );
PyErr_Clear( );
PySys_SetObject("last_traceback", NULL);
free_compiled_text( text );
return NULL;
}
/* make into a module */
return PyImport_ExecCodeModule( name, text->compiled );
}
static PyObject *blender_import( PyObject * self, PyObject * args, PyObject * kw)
{
PyObject *exception, *err, *tb;
char *name;
int found= 0;
PyObject *globals = NULL, *locals = NULL, *fromlist = NULL;
PyObject *newmodule;
//PyObject_Print(args, stderr, 0);
#if (PY_VERSION_HEX >= 0x02060000)
int dummy_val; /* what does this do?*/
static char *kwlist[] = {"name", "globals", "locals", "fromlist", "level", 0};
if( !PyArg_ParseTupleAndKeywords( args, kw, "s|OOOi:bpy_import_meth", kwlist,
&name, &globals, &locals, &fromlist, &dummy_val) )
return NULL;
#else
static char *kwlist[] = {"name", "globals", "locals", "fromlist", 0};
if( !PyArg_ParseTupleAndKeywords( args, kw, "s|OOO:bpy_import_meth", kwlist,
&name, &globals, &locals, &fromlist ) )
return NULL;
#endif
/* import existing builtin modules or modules that have been imported alredy */
newmodule = PyImport_ImportModuleEx( name, globals, locals, fromlist );
if(newmodule)
return newmodule;
PyErr_Fetch( &exception, &err, &tb ); /* get the python error incase we cant import as blender text either */
/* importing from existing modules failed, see if we have this module as blender text */
newmodule = bpy_text_import( name, &found );
if( newmodule ) {/* found module as blender text, ignore above exception */
PyErr_Clear( );
Py_XDECREF( exception );
Py_XDECREF( err );
Py_XDECREF( tb );
/* printf( "imported from text buffer...\n" ); */
}
else if (found==1) { /* blender text module failed to execute but was found, use its error message */
Py_XDECREF( exception );
Py_XDECREF( err );
Py_XDECREF( tb );
return NULL;
}
else {
/* no blender text was found that could import the module
* rause the original error from PyImport_ImportModuleEx */
PyErr_Restore( exception, err, tb );
}
return newmodule;
}
/*
* our reload() module, to handle reloading in-memory scripts
*/
static PyObject *blender_reload( PyObject * self, PyObject * args )
{
PyObject *exception, *err, *tb;
PyObject *module = NULL;
PyObject *newmodule = NULL;
int found= 0;
/* check for a module arg */
if( !PyArg_ParseTuple( args, "O:bpy_reload_meth", &module ) )
return NULL;
/* try reimporting from file */
newmodule = PyImport_ReloadModule( module );
if( newmodule )
return newmodule;
/* no file, try importing from memory */
PyErr_Fetch( &exception, &err, &tb ); /*restore for probable later use */
newmodule = bpy_text_reimport( module, &found );
if( newmodule ) {/* found module as blender text, ignore above exception */
PyErr_Clear( );
Py_XDECREF( exception );
Py_XDECREF( err );
Py_XDECREF( tb );
/* printf( "imported from text buffer...\n" ); */
}
else if (found==1) { /* blender text module failed to execute but was found, use its error message */
Py_XDECREF( exception );
Py_XDECREF( err );
Py_XDECREF( tb );
return NULL;
}
else {
/* no blender text was found that could import the module
* rause the original error from PyImport_ImportModuleEx */
PyErr_Restore( exception, err, tb );
}
return newmodule;
}
PyMethodDef bpy_import_meth[] = { {"bpy_import_meth", blender_import, METH_VARARGS | METH_KEYWORDS, "blenders import"} };
PyMethodDef bpy_reload_meth[] = { {"bpy_reload_meth", blender_reload, METH_VARARGS, "blenders reload"} };
/* Clear user modules.
* This is to clear any modules that could be defined from running scripts in blender.
*
* Its also needed for the BGE Python api so imported scripts are not used between levels
*
* This clears every modules that has a __file__ attribute (is not a builtin)
*
* Note that clearing external python modules is important for the BGE otherwise
* it wont reload scripts between loading different blend files or while making the game.
* - use 'clear_all' arg in this case.
*
* Since pythons bultins include a full path even for win32.
* even if we remove a python module a reimport will bring it back again.
*/
#if 0 // not used anymore but may still come in handy later
#if defined(WIN32) || defined(WIN64)
#define SEPSTR "\\"
#else
#define SEPSTR "/"
#endif
void bpy_text_clear_modules(int clear_all)
{
PyObject *modules= PySys_GetObject("modules");
char *fname;
char *file_extension;
/* looping over the dict */
PyObject *key, *value;
int pos = 0;
/* new list */
PyObject *list;
if (modules==NULL)
return; /* should never happen but just incase */
list= PyList_New(0);
/* go over sys.modules and remove anything with a
* sys.modukes[x].__file__ thats ends with a .py and has no path
*/
while (PyDict_Next(modules, &pos, &key, &value)) {
fname= PyModule_GetFilename(value);
if(fname) {
if (clear_all || ((strstr(fname, SEPSTR))==0)) { /* no path ? */
file_extension = strstr(fname, ".py");
if(file_extension && (*(file_extension + 3) == '\0' || *(file_extension + 4) == '\0')) { /* .py or pyc extension? */
/* now we can be fairly sure its a python import from the blendfile */
PyList_Append(list, key); /* free'd with the list */
}
}
}
else {
PyErr_Clear();
}
}
/* remove all our modules */
for(pos=0; pos < PyList_Size(list); pos++) {
/* PyObject_Print(key, stderr, 0); */
key= PyList_GET_ITEM(list, pos);
PyDict_DelItem(modules, key);
}
Py_DECREF(list); /* removes all references from append */
}
#endif

View File

@@ -0,0 +1,50 @@
/*
* $Id: bpy_internal_import.h 21094 2009-06-23 00:09:26Z gsrb3d $
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* This is a new part of Blender.
*
* Contributor(s): Willian P. Germano, Campbell Barton
*
* ***** END GPL LICENSE BLOCK *****
*/
/* Note, the BGE needs to use this too, keep it minimal */
#ifndef EXPP_bpy_import_h
#define EXPP_bpy_import_h
#include <Python.h>
#include "../intern/bpy_compat.h"
#include "compile.h" /* for the PyCodeObject */
#include "eval.h" /* for PyEval_EvalCode */
PyObject* bpy_text_import( char *name, int *found );
PyObject* bpy_text_reimport( PyObject *module, int *found );
/* void bpy_text_clear_modules( int clear_all );*/ /* Clear user modules */
extern PyMethodDef bpy_import_meth[];
extern PyMethodDef bpy_reload_meth[];
/* The game engine has its own Main struct, if this is set search this rather then G.main */
struct Main *bpy_import_main_get(void);
void bpy_import_main_set(struct Main *maggie);
#endif /* EXPP_bpy_import_h */

View File

@@ -0,0 +1,651 @@
/*
* $Id: euler.c 21462 2009-07-09 15:40:04Z ton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
*
* Contributor(s): Joseph Gilbert
*
* ***** END GPL LICENSE BLOCK *****
*/
#include "Mathutils.h"
#include "BLI_arithb.h"
#include "BKE_utildefines.h"
#include "BLI_blenlib.h"
//-------------------------DOC STRINGS ---------------------------
static PyObject *Euler_Zero( EulerObject * self );
static PyObject *Euler_Unique( EulerObject * self );
static PyObject *Euler_ToMatrix( EulerObject * self );
static PyObject *Euler_ToQuat( EulerObject * self );
static PyObject *Euler_Rotate( EulerObject * self, PyObject *args );
static PyObject *Euler_MakeCompatible( EulerObject * self, EulerObject *value );
static PyObject *Euler_copy( EulerObject * self, PyObject *args );
//-----------------------METHOD DEFINITIONS ----------------------
static struct PyMethodDef Euler_methods[] = {
{"zero", (PyCFunction) Euler_Zero, METH_NOARGS, NULL},
{"unique", (PyCFunction) Euler_Unique, METH_NOARGS, NULL},
{"toMatrix", (PyCFunction) Euler_ToMatrix, METH_NOARGS, NULL},
{"toQuat", (PyCFunction) Euler_ToQuat, METH_NOARGS, NULL},
{"rotate", (PyCFunction) Euler_Rotate, METH_VARARGS, NULL},
{"makeCompatible", (PyCFunction) Euler_MakeCompatible, METH_O, NULL},
{"__copy__", (PyCFunction) Euler_copy, METH_VARARGS, NULL},
{"copy", (PyCFunction) Euler_copy, METH_VARARGS, NULL},
{NULL, NULL, 0, NULL}
};
//----------------------------------Mathutils.Euler() -------------------
//makes a new euler for you to play with
static PyObject *Euler_new(PyTypeObject * type, PyObject * args, PyObject * kwargs)
{
PyObject *listObject = NULL;
int size, i;
float eul[3];
PyObject *e;
size = PyTuple_GET_SIZE(args);
if (size == 1) {
listObject = PyTuple_GET_ITEM(args, 0);
if (PySequence_Check(listObject)) {
size = PySequence_Length(listObject);
} else { // Single argument was not a sequence
PyErr_SetString(PyExc_TypeError, "Mathutils.Euler(): 3d numeric sequence expected\n");
return NULL;
}
} else if (size == 0) {
//returns a new empty 3d euler
return newEulerObject(NULL, Py_NEW, NULL);
} else {
listObject = args;
}
if (size != 3) { // Invalid euler size
PyErr_SetString(PyExc_AttributeError, "Mathutils.Euler(): 3d numeric sequence expected\n");
return NULL;
}
for (i=0; i<size; i++) {
e = PySequence_GetItem(listObject, i);
if (e == NULL) { // Failed to read sequence
Py_DECREF(listObject);
PyErr_SetString(PyExc_RuntimeError, "Mathutils.Euler(): 3d numeric sequence expected\n");
return NULL;
}
eul[i]= (float)PyFloat_AsDouble(e);
Py_DECREF(e);
if(eul[i]==-1 && PyErr_Occurred()) { // parsed item is not a number
PyErr_SetString(PyExc_TypeError, "Mathutils.Euler(): 3d numeric sequence expected\n");
return NULL;
}
}
return newEulerObject(eul, Py_NEW, NULL);
}
//-----------------------------METHODS----------------------------
//----------------------------Euler.toQuat()----------------------
//return a quaternion representation of the euler
static PyObject *Euler_ToQuat(EulerObject * self)
{
float quat[4];
#ifdef USE_MATHUTILS_DEG
float eul[3];
int x;
#endif
if(!BaseMath_ReadCallback(self))
return NULL;
#ifdef USE_MATHUTILS_DEG
for(x = 0; x < 3; x++) {
eul[x] = self->eul[x] * ((float)Py_PI / 180);
}
EulToQuat(eul, quat);
#else
EulToQuat(self->eul, quat);
#endif
return newQuaternionObject(quat, Py_NEW, NULL);
}
//----------------------------Euler.toMatrix()---------------------
//return a matrix representation of the euler
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};
if(!BaseMath_ReadCallback(self))
return NULL;
#ifdef USE_MATHUTILS_DEG
{
float eul[3];
int x;
for(x = 0; x < 3; x++) {
eul[x] = self->eul[x] * ((float)Py_PI / 180);
}
EulToMat3(eul, (float (*)[3]) mat);
}
#else
EulToMat3(self->eul, (float (*)[3]) mat);
#endif
return newMatrixObject(mat, 3, 3 , Py_NEW, NULL);
}
//----------------------------Euler.unique()-----------------------
//sets the x,y,z values to a unique euler rotation
static PyObject *Euler_Unique(EulerObject * self)
{
#define PI_2 (Py_PI * 2.0)
#define PI_HALF (Py_PI / 2.0)
#define PI_INV (1.0 / Py_PI)
double heading, pitch, bank;
if(!BaseMath_ReadCallback(self))
return NULL;
#ifdef USE_MATHUTILS_DEG
//radians
heading = self->eul[0] * (float)Py_PI / 180;
pitch = self->eul[1] * (float)Py_PI / 180;
bank = self->eul[2] * (float)Py_PI / 180;
#else
heading = self->eul[0];
pitch = self->eul[1];
bank = self->eul[2];
#endif
//wrap heading in +180 / -180
pitch += Py_PI;
pitch -= floor(pitch * PI_INV) * PI_2;
pitch -= Py_PI;
if(pitch < -PI_HALF) {
pitch = -Py_PI - pitch;
heading += Py_PI;
bank += Py_PI;
} else if(pitch > PI_HALF) {
pitch = Py_PI - pitch;
heading += Py_PI;
bank += Py_PI;
}
//gimbal lock test
if(fabs(pitch) > PI_HALF - 1e-4) {
heading += bank;
bank = 0.0f;
} else {
bank += Py_PI;
bank -= (floor(bank * PI_INV)) * PI_2;
bank -= Py_PI;
}
heading += Py_PI;
heading -= (floor(heading * PI_INV)) * PI_2;
heading -= Py_PI;
#ifdef USE_MATHUTILS_DEG
//back to degrees
self->eul[0] = (float)(heading * 180 / (float)Py_PI);
self->eul[1] = (float)(pitch * 180 / (float)Py_PI);
self->eul[2] = (float)(bank * 180 / (float)Py_PI);
#endif
BaseMath_WriteCallback(self);
Py_INCREF(self);
return (PyObject *)self;
}
//----------------------------Euler.zero()-------------------------
//sets the euler to 0,0,0
static PyObject *Euler_Zero(EulerObject * self)
{
self->eul[0] = 0.0;
self->eul[1] = 0.0;
self->eul[2] = 0.0;
BaseMath_WriteCallback(self);
Py_INCREF(self);
return (PyObject *)self;
}
//----------------------------Euler.rotate()-----------------------
//rotates a euler a certain amount and returns the result
//should return a unique euler rotation (i.e. no 720 degree pitches :)
static PyObject *Euler_Rotate(EulerObject * self, PyObject *args)
{
float angle = 0.0f;
char *axis;
if(!PyArg_ParseTuple(args, "fs", &angle, &axis)){
PyErr_SetString(PyExc_TypeError, "euler.rotate():expected angle (float) and axis (x,y,z)");
return NULL;
}
if(!STREQ3(axis,"x","y","z")){
PyErr_SetString(PyExc_TypeError, "euler.rotate(): expected axis to be 'x', 'y' or 'z'");
return NULL;
}
if(!BaseMath_ReadCallback(self))
return NULL;
#ifdef USE_MATHUTILS_DEG
{
int x;
//covert to radians
angle *= ((float)Py_PI / 180);
for(x = 0; x < 3; x++) {
self->eul[x] *= ((float)Py_PI / 180);
}
}
#endif
euler_rot(self->eul, angle, *axis);
#ifdef USE_MATHUTILS_DEG
{
int x;
//convert back from radians
for(x = 0; x < 3; x++) {
self->eul[x] *= (180 / (float)Py_PI);
}
}
#endif
BaseMath_WriteCallback(self);
Py_INCREF(self);
return (PyObject *)self;
}
static PyObject *Euler_MakeCompatible(EulerObject * self, EulerObject *value)
{
#ifdef USE_MATHUTILS_DEG
float eul_from_rad[3];
int x;
#endif
if(!EulerObject_Check(value)) {
PyErr_SetString(PyExc_TypeError, "euler.makeCompatible(euler):expected a single euler argument.");
return NULL;
}
if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value))
return NULL;
#ifdef USE_MATHUTILS_DEG
//covert to radians
for(x = 0; x < 3; x++) {
self->eul[x] = self->eul[x] * ((float)Py_PI / 180);
eul_from_rad[x] = value->eul[x] * ((float)Py_PI / 180);
}
compatible_eul(self->eul, eul_from_rad);
#else
compatible_eul(self->eul, value->eul);
#endif
#ifdef USE_MATHUTILS_DEG
//convert back from radians
for(x = 0; x < 3; x++) {
self->eul[x] *= (180 / (float)Py_PI);
}
#endif
BaseMath_WriteCallback(self);
Py_INCREF(self);
return (PyObject *)self;
}
//----------------------------Euler.rotate()-----------------------
// return a copy of the euler
static PyObject *Euler_copy(EulerObject * self, PyObject *args)
{
if(!BaseMath_ReadCallback(self))
return NULL;
return newEulerObject(self->eul, Py_NEW, Py_TYPE(self));
}
//----------------------------print object (internal)--------------
//print the object to screen
static PyObject *Euler_repr(EulerObject * self)
{
char str[64];
if(!BaseMath_ReadCallback(self))
return NULL;
sprintf(str, "[%.6f, %.6f, %.6f](euler)", self->eul[0], self->eul[1], self->eul[2]);
return PyUnicode_FromString(str);
}
//------------------------tp_richcmpr
//returns -1 execption, 0 false, 1 true
static PyObject* Euler_richcmpr(PyObject *objectA, PyObject *objectB, int comparison_type)
{
EulerObject *eulA = NULL, *eulB = NULL;
int result = 0;
if(EulerObject_Check(objectA)) {
eulA = (EulerObject*)objectA;
if(!BaseMath_ReadCallback(eulA))
return NULL;
}
if(EulerObject_Check(objectB)) {
eulB = (EulerObject*)objectB;
if(!BaseMath_ReadCallback(eulB))
return NULL;
}
if (!eulA || !eulB){
if (comparison_type == Py_NE){
Py_RETURN_TRUE;
}else{
Py_RETURN_FALSE;
}
}
eulA = (EulerObject*)objectA;
eulB = (EulerObject*)objectB;
switch (comparison_type){
case Py_EQ:
result = EXPP_VectorsAreEqual(eulA->eul, eulB->eul, 3, 1);
break;
case Py_NE:
result = EXPP_VectorsAreEqual(eulA->eul, eulB->eul, 3, 1);
if (result == 0){
result = 1;
}else{
result = 0;
}
break;
default:
printf("The result of the comparison could not be evaluated");
break;
}
if (result == 1){
Py_RETURN_TRUE;
}else{
Py_RETURN_FALSE;
}
}
//---------------------SEQUENCE PROTOCOLS------------------------
//----------------------------len(object)------------------------
//sequence length
static int Euler_len(EulerObject * self)
{
return 3;
}
//----------------------------object[]---------------------------
//sequence accessor (get)
static PyObject *Euler_item(EulerObject * self, int i)
{
if(i<0) i= 3-i;
if(i < 0 || i >= 3) {
PyErr_SetString(PyExc_IndexError, "euler[attribute]: array index out of range");
return NULL;
}
if(!BaseMath_ReadIndexCallback(self, i))
return NULL;
return PyFloat_FromDouble(self->eul[i]);
}
//----------------------------object[]-------------------------
//sequence accessor (set)
static int Euler_ass_item(EulerObject * self, int i, PyObject * value)
{
float f = PyFloat_AsDouble(value);
if(f == -1 && PyErr_Occurred()) { // parsed item not a number
PyErr_SetString(PyExc_TypeError, "euler[attribute] = x: argument not a number");
return -1;
}
if(i<0) i= 3-i;
if(i < 0 || i >= 3){
PyErr_SetString(PyExc_IndexError, "euler[attribute] = x: array assignment index out of range\n");
return -1;
}
self->eul[i] = f;
if(!BaseMath_WriteIndexCallback(self, i))
return -1;
return 0;
}
//----------------------------object[z:y]------------------------
//sequence slice (get)
static PyObject *Euler_slice(EulerObject * self, int begin, int end)
{
PyObject *list = NULL;
int count;
if(!BaseMath_ReadCallback(self))
return NULL;
CLAMP(begin, 0, 3);
if (end<0) end= 4+end;
CLAMP(end, 0, 3);
begin = MIN2(begin,end);
list = PyList_New(end - begin);
for(count = begin; count < end; count++) {
PyList_SetItem(list, count - begin,
PyFloat_FromDouble(self->eul[count]));
}
return list;
}
//----------------------------object[z:y]------------------------
//sequence slice (set)
static int Euler_ass_slice(EulerObject * self, int begin, int end,
PyObject * seq)
{
int i, y, size = 0;
float eul[3];
PyObject *e;
if(!BaseMath_ReadCallback(self))
return -1;
CLAMP(begin, 0, 3);
if (end<0) end= 4+end;
CLAMP(end, 0, 3);
begin = MIN2(begin,end);
size = PySequence_Length(seq);
if(size != (end - begin)){
PyErr_SetString(PyExc_TypeError, "euler[begin:end] = []: size mismatch in slice assignment");
return -1;
}
for (i = 0; i < size; i++) {
e = PySequence_GetItem(seq, i);
if (e == NULL) { // Failed to read sequence
PyErr_SetString(PyExc_RuntimeError, "euler[begin:end] = []: unable to read sequence");
return -1;
}
eul[i] = (float)PyFloat_AsDouble(e);
Py_DECREF(e);
if(eul[i]==-1 && PyErr_Occurred()) { // parsed item not a number
PyErr_SetString(PyExc_TypeError, "euler[begin:end] = []: sequence argument not a number");
return -1;
}
}
//parsed well - now set in vector
for(y = 0; y < 3; y++){
self->eul[begin + y] = eul[y];
}
BaseMath_WriteCallback(self);
return 0;
}
//-----------------PROTCOL DECLARATIONS--------------------------
static PySequenceMethods Euler_SeqMethods = {
(inquiry) Euler_len, /* sq_length */
(binaryfunc) 0, /* sq_concat */
(ssizeargfunc) 0, /* sq_repeat */
(ssizeargfunc) Euler_item, /* sq_item */
(ssizessizeargfunc) Euler_slice, /* sq_slice */
(ssizeobjargproc) Euler_ass_item, /* sq_ass_item */
(ssizessizeobjargproc) Euler_ass_slice, /* sq_ass_slice */
};
/*
* vector axis, vector.x/y/z/w
*/
static PyObject *Euler_getAxis( EulerObject * self, void *type )
{
return Euler_item(self, GET_INT_FROM_POINTER(type));
}
static int Euler_setAxis( EulerObject * self, PyObject * value, void * type )
{
return Euler_ass_item(self, GET_INT_FROM_POINTER(type), value);
}
/*****************************************************************************/
/* Python attributes get/set structure: */
/*****************************************************************************/
static PyGetSetDef Euler_getseters[] = {
{"x", (getter)Euler_getAxis, (setter)Euler_setAxis, "Euler X axis", (void *)0},
{"y", (getter)Euler_getAxis, (setter)Euler_setAxis, "Euler Y axis", (void *)1},
{"z", (getter)Euler_getAxis, (setter)Euler_setAxis, "Euler Z axis", (void *)2},
{"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 euler_Type = {
#if (PY_VERSION_HEX >= 0x02060000)
PyVarObject_HEAD_INIT(NULL, 0)
#else
/* python 2.5 and below */
PyObject_HEAD_INIT( NULL ) /* required py macro */
0, /* ob_size */
#endif
"euler", //tp_name
sizeof(EulerObject), //tp_basicsize
0, //tp_itemsize
(destructor)BaseMathObject_dealloc, //tp_dealloc
0, //tp_print
0, //tp_getattr
0, //tp_setattr
0, //tp_compare
(reprfunc) Euler_repr, //tp_repr
0, //tp_as_number
&Euler_SeqMethods, //tp_as_sequence
0, //tp_as_mapping
0, //tp_hash
0, //tp_call
0, //tp_str
0, //tp_getattro
0, //tp_setattro
0, //tp_as_buffer
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, //tp_flags
0, //tp_doc
0, //tp_traverse
0, //tp_clear
(richcmpfunc)Euler_richcmpr, //tp_richcompare
0, //tp_weaklistoffset
0, //tp_iter
0, //tp_iternext
Euler_methods, //tp_methods
0, //tp_members
Euler_getseters, //tp_getset
0, //tp_base
0, //tp_dict
0, //tp_descr_get
0, //tp_descr_set
0, //tp_dictoffset
0, //tp_init
0, //tp_alloc
Euler_new, //tp_new
0, //tp_free
0, //tp_is_gc
0, //tp_bases
0, //tp_mro
0, //tp_cache
0, //tp_subclasses
0, //tp_weaklist
0 //tp_del
};
//------------------------newEulerObject (internal)-------------
//creates a new euler object
/*pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER
(i.e. it was allocated elsewhere by MEM_mallocN())
pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON
(i.e. it must be created here with PyMEM_malloc())*/
PyObject *newEulerObject(float *eul, int type, PyTypeObject *base_type)
{
EulerObject *self;
int x;
if(base_type) self = (EulerObject *)base_type->tp_alloc(base_type, 0);
else self = PyObject_NEW(EulerObject, &euler_Type);
/* init callbacks as NULL */
self->cb_user= NULL;
self->cb_type= self->cb_subtype= 0;
if(type == Py_WRAP){
self->eul = eul;
self->wrapped = Py_WRAP;
}else if (type == Py_NEW){
self->eul = PyMem_Malloc(3 * sizeof(float));
if(!eul) { //new empty
for(x = 0; x < 3; x++) {
self->eul[x] = 0.0f;
}
}else{
VECCOPY(self->eul, eul);
}
self->wrapped = Py_NEW;
}else{ //bad type
return NULL;
}
return (PyObject *)self;
}
PyObject *newEulerObject_cb(PyObject *cb_user, int cb_type, int cb_subtype)
{
EulerObject *self= (EulerObject *)newEulerObject(NULL, Py_NEW, NULL);
if(self) {
Py_INCREF(cb_user);
self->cb_user= cb_user;
self->cb_type= (unsigned char)cb_type;
self->cb_subtype= (unsigned char)cb_subtype;
}
return (PyObject *)self;
}

View File

@@ -0,0 +1,60 @@
/*
* $Id: euler.h 21254 2009-06-30 00:42:17Z campbellbarton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): Joseph Gilbert
*
* ***** END GPL LICENSE BLOCK *****
*
*/
#ifndef EXPP_euler_h
#define EXPP_euler_h
#include <Python.h>
#include "../intern/bpy_compat.h"
extern PyTypeObject euler_Type;
#define EulerObject_Check(_v) PyObject_TypeCheck((_v), &euler_Type)
typedef struct {
PyObject_VAR_HEAD
float *eul; /*1D array of data */
PyObject *cb_user; /* if this vector references another object, otherwise NULL, *Note* this owns its reference */
unsigned char cb_type; /* which user funcs do we adhere to, RNA, GameObject, etc */
unsigned char cb_subtype; /* subtype: location, rotation... to avoid defining many new functions for every attribute of the same type */
unsigned char wrapped; /* wrapped data type? */
/* end BaseMathObject */
} EulerObject;
/*struct data contains a pointer to the actual data that the
object uses. It can use either PyMem allocated data (which will
be stored in py_data) or be a wrapper for data allocated through
blender (stored in blend_data). This is an either/or struct not both*/
//prototypes
PyObject *newEulerObject( float *eul, int type, PyTypeObject *base_type);
PyObject *newEulerObject_cb(PyObject *cb_user, int cb_type, int cb_subtype);
#endif /* EXPP_euler_h */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,66 @@
/*
* $Id: matrix.h 21254 2009-06-30 00:42:17Z campbellbarton $
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): Joseph Gilbert
*
* ***** END GPL LICENSE BLOCK *****
*
*/
#ifndef EXPP_matrix_h
#define EXPP_matrix_h
#include <Python.h>
extern PyTypeObject matrix_Type;
#define MatrixObject_Check(_v) PyObject_TypeCheck((_v), &matrix_Type)
typedef float **ptRow;
typedef struct _Matrix { /* keep aligned with BaseMathObject in Mathutils.h */
PyObject_VAR_HEAD
float *contigPtr; /*1D array of data (alias)*/
PyObject *cb_user; /* if this vector references another object, otherwise NULL, *Note* this owns its reference */
unsigned char cb_type; /* which user funcs do we adhere to, RNA, GameObject, etc */
unsigned char cb_subtype; /* subtype: location, rotation... to avoid defining many new functions for every attribute of the same type */
unsigned char wrapped; /*is wrapped data?*/
/* end BaseMathObject */
unsigned char rowSize;
unsigned int colSize;
ptRow matrix; /*ptr to the contigPtr (accessor)*/
} MatrixObject;
/*struct data contains a pointer to the actual data that the
object uses. It can use either PyMem allocated data (which will
be stored in py_data) or be a wrapper for data allocated through
blender (stored in blend_data). This is an either/or struct not both*/
/*prototypes*/
PyObject *newMatrixObject(float *mat, int rowSize, int colSize, int type, PyTypeObject *base_type);
PyObject *newMatrixObject_cb(PyObject *user, int rowSize, int colSize, int cb_type, int cb_subtype);
extern int mathutils_matrix_vector_cb_index;
extern struct Mathutils_Callback mathutils_matrix_vector_cb;
#endif /* EXPP_matrix_H */

View File

@@ -0,0 +1,879 @@
/*
* $Id: quat.c 21462 2009-07-09 15:40:04Z ton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
*
* Contributor(s): Joseph Gilbert
*
* ***** END GPL LICENSE BLOCK *****
*/
#include "Mathutils.h"
#include "BLI_arithb.h"
#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
AxisAngleToQuat(quat, quat, angle * (Py_PI / 180));
#else
AxisAngleToQuat(quat, quat, angle);
#endif
return newQuaternionObject(quat, Py_NEW, NULL);
}
//-----------------------------METHODS------------------------------
//----------------------------Quaternion.toEuler()------------------
//return the quat as a euler
static PyObject *Quaternion_ToEuler(QuaternionObject * self, PyObject *args)
{
float eul[3];
EulerObject *eul_compat = NULL;
if(!PyArg_ParseTuple(args, "|O!:toEuler", &euler_Type, &eul_compat))
return NULL;
if(!BaseMath_ReadCallback(self))
return NULL;
if(eul_compat) {
float mat[3][3];
if(!BaseMath_ReadCallback(eul_compat))
return NULL;
QuatToMat3(self->quat, mat);
#ifdef USE_MATHUTILS_DEG
{
float eul_compatf[3];
int x;
for(x = 0; x < 3; x++) {
eul_compatf[x] = eul_compat->eul[x] * ((float)Py_PI / 180);
}
Mat3ToCompatibleEul(mat, eul, eul_compatf);
}
#else
Mat3ToCompatibleEul(mat, eul, eul_compat->eul);
#endif
}
else {
QuatToEul(self->quat, eul);
}
#ifdef USE_MATHUTILS_DEG
{
int x;
for(x = 0; x < 3; x++) {
eul[x] *= (180 / (float)Py_PI);
}
}
#endif
return newEulerObject(eul, Py_NEW, NULL);
}
//----------------------------Quaternion.toMatrix()------------------
//return the quat as a matrix
static PyObject *Quaternion_ToMatrix(QuaternionObject * self)
{
float mat[9]; /* all values are set */
if(!BaseMath_ReadCallback(self))
return NULL;
QuatToMat3(self->quat, (float (*)[3]) mat);
return newMatrixObject(mat, 3, 3, Py_NEW, NULL);
}
//----------------------------Quaternion.cross(other)------------------
//return the cross quat
static PyObject *Quaternion_Cross(QuaternionObject * self, QuaternionObject * value)
{
float quat[4];
if (!QuaternionObject_Check(value)) {
PyErr_SetString( PyExc_TypeError, "quat.cross(value): expected a quaternion argument" );
return NULL;
}
if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value))
return NULL;
QuatMul(quat, self->quat, value->quat);
return newQuaternionObject(quat, Py_NEW, NULL);
}
//----------------------------Quaternion.dot(other)------------------
//return the dot quat
static PyObject *Quaternion_Dot(QuaternionObject * self, QuaternionObject * value)
{
if (!QuaternionObject_Check(value)) {
PyErr_SetString( PyExc_TypeError, "quat.dot(value): expected a quaternion argument" );
return NULL;
}
if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value))
return NULL;
return PyFloat_FromDouble(QuatDot(self->quat, value->quat));
}
//----------------------------Quaternion.normalize()----------------
//normalize the axis of rotation of [theta,vector]
static PyObject *Quaternion_Normalize(QuaternionObject * self)
{
if(!BaseMath_ReadCallback(self))
return NULL;
NormalQuat(self->quat);
BaseMath_WriteCallback(self);
Py_INCREF(self);
return (PyObject*)self;
}
//----------------------------Quaternion.inverse()------------------
//invert the quat
static PyObject *Quaternion_Inverse(QuaternionObject * self)
{
if(!BaseMath_ReadCallback(self))
return NULL;
QuatInv(self->quat);
BaseMath_WriteCallback(self);
Py_INCREF(self);
return (PyObject*)self;
}
//----------------------------Quaternion.identity()-----------------
//generate the identity quaternion
static PyObject *Quaternion_Identity(QuaternionObject * self)
{
if(!BaseMath_ReadCallback(self))
return NULL;
QuatOne(self->quat);
BaseMath_WriteCallback(self);
Py_INCREF(self);
return (PyObject*)self;
}
//----------------------------Quaternion.negate()-------------------
//negate the quat
static PyObject *Quaternion_Negate(QuaternionObject * self)
{
if(!BaseMath_ReadCallback(self))
return NULL;
QuatMulf(self->quat, -1.0f);
BaseMath_WriteCallback(self);
Py_INCREF(self);
return (PyObject*)self;
}
//----------------------------Quaternion.conjugate()----------------
//negate the vector part
static PyObject *Quaternion_Conjugate(QuaternionObject * self)
{
if(!BaseMath_ReadCallback(self))
return NULL;
QuatConj(self->quat);
BaseMath_WriteCallback(self);
Py_INCREF(self);
return (PyObject*)self;
}
//----------------------------Quaternion.copy()----------------
//return a copy of the quat
static PyObject *Quaternion_copy(QuaternionObject * self)
{
if(!BaseMath_ReadCallback(self))
return NULL;
return newQuaternionObject(self->quat, Py_NEW, Py_TYPE(self));
}
//----------------------------print object (internal)--------------
//print the object to screen
static PyObject *Quaternion_repr(QuaternionObject * self)
{
char str[64];
if(!BaseMath_ReadCallback(self))
return NULL;
sprintf(str, "[%.6f, %.6f, %.6f, %.6f](quaternion)", self->quat[0], self->quat[1], self->quat[2], self->quat[3]);
return PyUnicode_FromString(str);
}
//------------------------tp_richcmpr
//returns -1 execption, 0 false, 1 true
static PyObject* Quaternion_richcmpr(PyObject *objectA, PyObject *objectB, int comparison_type)
{
QuaternionObject *quatA = NULL, *quatB = NULL;
int result = 0;
if(QuaternionObject_Check(objectA)) {
quatA = (QuaternionObject*)objectA;
if(!BaseMath_ReadCallback(quatA))
return NULL;
}
if(QuaternionObject_Check(objectB)) {
quatB = (QuaternionObject*)objectB;
if(!BaseMath_ReadCallback(quatB))
return NULL;
}
if (!quatA || !quatB){
if (comparison_type == Py_NE){
Py_RETURN_TRUE;
}else{
Py_RETURN_FALSE;
}
}
switch (comparison_type){
case Py_EQ:
result = EXPP_VectorsAreEqual(quatA->quat, quatB->quat, 4, 1);
break;
case Py_NE:
result = EXPP_VectorsAreEqual(quatA->quat, quatB->quat, 4, 1);
if (result == 0){
result = 1;
}else{
result = 0;
}
break;
default:
printf("The result of the comparison could not be evaluated");
break;
}
if (result == 1){
Py_RETURN_TRUE;
}else{
Py_RETURN_FALSE;
}
}
//---------------------SEQUENCE PROTOCOLS------------------------
//----------------------------len(object)------------------------
//sequence length
static int Quaternion_len(QuaternionObject * self)
{
return 4;
}
//----------------------------object[]---------------------------
//sequence accessor (get)
static PyObject *Quaternion_item(QuaternionObject * self, int i)
{
if(i<0) i= 4-i;
if(i < 0 || i >= 4) {
PyErr_SetString(PyExc_IndexError, "quaternion[attribute]: array index out of range\n");
return NULL;
}
if(!BaseMath_ReadIndexCallback(self, i))
return NULL;
return PyFloat_FromDouble(self->quat[i]);
}
//----------------------------object[]-------------------------
//sequence accessor (set)
static int Quaternion_ass_item(QuaternionObject * self, int i, PyObject * ob)
{
float scalar= (float)PyFloat_AsDouble(ob);
if(scalar==-1.0f && PyErr_Occurred()) { /* parsed item not a number */
PyErr_SetString(PyExc_TypeError, "quaternion[index] = x: index argument not a number\n");
return -1;
}
if(i<0) i= 4-i;
if(i < 0 || i >= 4){
PyErr_SetString(PyExc_IndexError, "quaternion[attribute] = x: array assignment index out of range\n");
return -1;
}
self->quat[i] = scalar;
if(!BaseMath_WriteIndexCallback(self, i))
return -1;
return 0;
}
//----------------------------object[z:y]------------------------
//sequence slice (get)
static PyObject *Quaternion_slice(QuaternionObject * self, int begin, int end)
{
PyObject *list = NULL;
int count;
if(!BaseMath_ReadCallback(self))
return NULL;
CLAMP(begin, 0, 4);
if (end<0) end= 5+end;
CLAMP(end, 0, 4);
begin = MIN2(begin,end);
list = PyList_New(end - begin);
for(count = begin; count < end; count++) {
PyList_SetItem(list, count - begin,
PyFloat_FromDouble(self->quat[count]));
}
return list;
}
//----------------------------object[z:y]------------------------
//sequence slice (set)
static int Quaternion_ass_slice(QuaternionObject * self, int begin, int end, PyObject * seq)
{
int i, y, size = 0;
float quat[4];
PyObject *q;
if(!BaseMath_ReadCallback(self))
return -1;
CLAMP(begin, 0, 4);
if (end<0) end= 5+end;
CLAMP(end, 0, 4);
begin = MIN2(begin,end);
size = PySequence_Length(seq);
if(size != (end - begin)){
PyErr_SetString(PyExc_TypeError, "quaternion[begin:end] = []: size mismatch in slice assignment\n");
return -1;
}
for (i = 0; i < size; i++) {
q = PySequence_GetItem(seq, i);
if (q == NULL) { // Failed to read sequence
PyErr_SetString(PyExc_RuntimeError, "quaternion[begin:end] = []: unable to read sequence\n");
return -1;
}
quat[i]= (float)PyFloat_AsDouble(q);
Py_DECREF(q);
if(quat[i]==-1.0f && PyErr_Occurred()) { /* parsed item not a number */
PyErr_SetString(PyExc_TypeError, "quaternion[begin:end] = []: sequence argument not a number\n");
return -1;
}
}
//parsed well - now set in vector
for(y = 0; y < size; y++)
self->quat[begin + y] = quat[y];
BaseMath_WriteCallback(self);
return 0;
}
//------------------------NUMERIC PROTOCOLS----------------------
//------------------------obj + obj------------------------------
//addition
static PyObject *Quaternion_add(PyObject * q1, PyObject * q2)
{
float quat[4];
QuaternionObject *quat1 = NULL, *quat2 = NULL;
if(!QuaternionObject_Check(q1) || !QuaternionObject_Check(q2)) {
PyErr_SetString(PyExc_AttributeError, "Quaternion addition: arguments not valid for this operation....\n");
return NULL;
}
quat1 = (QuaternionObject*)q1;
quat2 = (QuaternionObject*)q2;
if(!BaseMath_ReadCallback(quat1) || !BaseMath_ReadCallback(quat2))
return NULL;
QuatAdd(quat, quat1->quat, quat2->quat, 1.0f);
return newQuaternionObject(quat, Py_NEW, NULL);
}
//------------------------obj - obj------------------------------
//subtraction
static PyObject *Quaternion_sub(PyObject * q1, PyObject * q2)
{
int x;
float quat[4];
QuaternionObject *quat1 = NULL, *quat2 = NULL;
if(!QuaternionObject_Check(q1) || !QuaternionObject_Check(q2)) {
PyErr_SetString(PyExc_AttributeError, "Quaternion addition: arguments not valid for this operation....\n");
return NULL;
}
quat1 = (QuaternionObject*)q1;
quat2 = (QuaternionObject*)q2;
if(!BaseMath_ReadCallback(quat1) || !BaseMath_ReadCallback(quat2))
return NULL;
for(x = 0; x < 4; x++) {
quat[x] = quat1->quat[x] - quat2->quat[x];
}
return newQuaternionObject(quat, Py_NEW, NULL);
}
//------------------------obj * obj------------------------------
//mulplication
static PyObject *Quaternion_mul(PyObject * q1, PyObject * q2)
{
float quat[4], scalar;
QuaternionObject *quat1 = NULL, *quat2 = NULL;
VectorObject *vec = NULL;
if(QuaternionObject_Check(q1)) {
quat1 = (QuaternionObject*)q1;
if(!BaseMath_ReadCallback(quat1))
return NULL;
}
if(QuaternionObject_Check(q2)) {
quat2 = (QuaternionObject*)q2;
if(!BaseMath_ReadCallback(quat2))
return NULL;
}
if(quat1 && quat2) { /* QUAT*QUAT (dot product) */
return PyFloat_FromDouble(QuatDot(quat1->quat, quat2->quat));
}
/* the only case this can happen (for a supported type is "FLOAT*QUAT" ) */
if(!QuaternionObject_Check(q1)) {
scalar= PyFloat_AsDouble(q1);
if ((scalar == -1.0 && PyErr_Occurred())==0) { /* FLOAT*QUAT */
QUATCOPY(quat, quat2->quat);
QuatMulf(quat, scalar);
return newQuaternionObject(quat, Py_NEW, NULL);
}
PyErr_SetString(PyExc_TypeError, "Quaternion multiplication: val * quat, val is not an acceptable type");
return NULL;
}
else { /* QUAT*SOMETHING */
if(VectorObject_Check(q2)){ /* QUAT*VEC */
vec = (VectorObject*)q2;
if(vec->size != 3){
PyErr_SetString(PyExc_TypeError, "Quaternion multiplication: only 3D vector rotations currently supported\n");
return NULL;
}
return quat_rotation((PyObject*)quat1, (PyObject*)vec); /* vector updating done inside the func */
}
scalar= PyFloat_AsDouble(q2);
if ((scalar == -1.0 && PyErr_Occurred())==0) { /* QUAT*FLOAT */
QUATCOPY(quat, quat1->quat);
QuatMulf(quat, scalar);
return newQuaternionObject(quat, Py_NEW, NULL);
}
}
PyErr_SetString(PyExc_TypeError, "Quaternion multiplication: arguments not acceptable for this operation\n");
return NULL;
}
//-----------------PROTOCOL DECLARATIONS--------------------------
static PySequenceMethods Quaternion_SeqMethods = {
(inquiry) Quaternion_len, /* sq_length */
(binaryfunc) 0, /* sq_concat */
(ssizeargfunc) 0, /* sq_repeat */
(ssizeargfunc) Quaternion_item, /* sq_item */
(ssizessizeargfunc) Quaternion_slice, /* sq_slice */
(ssizeobjargproc) Quaternion_ass_item, /* sq_ass_item */
(ssizessizeobjargproc) Quaternion_ass_slice, /* sq_ass_slice */
};
#if (PY_VERSION_HEX >= 0x03000000)
static PyNumberMethods Quaternion_NumMethods = {
(binaryfunc) Quaternion_add, /*nb_add*/
(binaryfunc) Quaternion_sub, /*nb_subtract*/
(binaryfunc) Quaternion_mul, /*nb_multiply*/
0, /*nb_remainder*/
0, /*nb_divmod*/
0, /*nb_power*/
(unaryfunc) 0, /*nb_negative*/
(unaryfunc) 0, /*tp_positive*/
(unaryfunc) 0, /*tp_absolute*/
(inquiry) 0, /*tp_bool*/
(unaryfunc) 0, /*nb_invert*/
0, /*nb_lshift*/
(binaryfunc)0, /*nb_rshift*/
0, /*nb_and*/
0, /*nb_xor*/
0, /*nb_or*/
0, /*nb_int*/
0, /*nb_reserved*/
0, /*nb_float*/
0, /* nb_inplace_add */
0, /* nb_inplace_subtract */
0, /* nb_inplace_multiply */
0, /* nb_inplace_remainder */
0, /* nb_inplace_power */
0, /* nb_inplace_lshift */
0, /* nb_inplace_rshift */
0, /* nb_inplace_and */
0, /* nb_inplace_xor */
0, /* nb_inplace_or */
0, /* nb_floor_divide */
0, /* nb_true_divide */
0, /* nb_inplace_floor_divide */
0, /* nb_inplace_true_divide */
0, /* nb_index */
};
#else
static PyNumberMethods Quaternion_NumMethods = {
(binaryfunc) Quaternion_add, /* __add__ */
(binaryfunc) Quaternion_sub, /* __sub__ */
(binaryfunc) Quaternion_mul, /* __mul__ */
(binaryfunc) 0, /* __div__ */
(binaryfunc) 0, /* __mod__ */
(binaryfunc) 0, /* __divmod__ */
(ternaryfunc) 0, /* __pow__ */
(unaryfunc) 0, /* __neg__ */
(unaryfunc) 0, /* __pos__ */
(unaryfunc) 0, /* __abs__ */
(inquiry) 0, /* __nonzero__ */
(unaryfunc) 0, /* __invert__ */
(binaryfunc) 0, /* __lshift__ */
(binaryfunc) 0, /* __rshift__ */
(binaryfunc) 0, /* __and__ */
(binaryfunc) 0, /* __xor__ */
(binaryfunc) 0, /* __or__ */
/*(coercion)*/ 0, /* __coerce__ */
(unaryfunc) 0, /* __int__ */
(unaryfunc) 0, /* __long__ */
(unaryfunc) 0, /* __float__ */
(unaryfunc) 0, /* __oct__ */
(unaryfunc) 0, /* __hex__ */
};
#endif
static PyObject *Quaternion_getAxis( QuaternionObject * self, void *type )
{
return Quaternion_item(self, GET_INT_FROM_POINTER(type));
}
static int Quaternion_setAxis( QuaternionObject * self, PyObject * value, void * type )
{
return Quaternion_ass_item(self, GET_INT_FROM_POINTER(type), value);
}
static PyObject *Quaternion_getMagnitude( QuaternionObject * self, void *type )
{
return PyFloat_FromDouble(sqrt(QuatDot(self->quat, self->quat)));
}
static PyObject *Quaternion_getAngle( QuaternionObject * self, void *type )
{
double ang = self->quat[0];
ang = 2 * (saacos(ang));
#ifdef USE_MATHUTILS_DEG
ang *= (180 / Py_PI);
#endif
return PyFloat_FromDouble(ang);
}
static PyObject *Quaternion_getAxisVec( QuaternionObject * self, void *type )
{
int i;
float vec[3];
double mag = self->quat[0] * (Py_PI / 180);
mag = 2 * (saacos(mag));
mag = sin(mag / 2);
for(i = 0; i < 3; i++)
vec[i] = (float)(self->quat[i + 1] / mag);
Normalize(vec);
//If the axis of rotation is 0,0,0 set it to 1,0,0 - for zero-degree rotations
if( EXPP_FloatsAreEqual(vec[0], 0.0f, 10) &&
EXPP_FloatsAreEqual(vec[1], 0.0f, 10) &&
EXPP_FloatsAreEqual(vec[2], 0.0f, 10) ){
vec[0] = 1.0f;
}
return (PyObject *) newVectorObject(vec, 3, Py_NEW, 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},
{NULL,NULL,NULL,NULL,NULL} /* Sentinel */
};
//------------------PY_OBECT DEFINITION--------------------------
PyTypeObject quaternion_Type = {
#if (PY_VERSION_HEX >= 0x02060000)
PyVarObject_HEAD_INIT(NULL, 0)
#else
/* python 2.5 and below */
PyObject_HEAD_INIT( NULL ) /* required py macro */
0, /* ob_size */
#endif
"quaternion", //tp_name
sizeof(QuaternionObject), //tp_basicsize
0, //tp_itemsize
(destructor)BaseMathObject_dealloc, //tp_dealloc
0, //tp_print
0, //tp_getattr
0, //tp_setattr
0, //tp_compare
(reprfunc) Quaternion_repr, //tp_repr
&Quaternion_NumMethods, //tp_as_number
&Quaternion_SeqMethods, //tp_as_sequence
0, //tp_as_mapping
0, //tp_hash
0, //tp_call
0, //tp_str
0, //tp_getattro
0, //tp_setattro
0, //tp_as_buffer
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, //tp_flags
0, //tp_doc
0, //tp_traverse
0, //tp_clear
(richcmpfunc)Quaternion_richcmpr, //tp_richcompare
0, //tp_weaklistoffset
0, //tp_iter
0, //tp_iternext
Quaternion_methods, //tp_methods
0, //tp_members
Quaternion_getseters, //tp_getset
0, //tp_base
0, //tp_dict
0, //tp_descr_get
0, //tp_descr_set
0, //tp_dictoffset
0, //tp_init
0, //tp_alloc
Quaternion_new, //tp_new
0, //tp_free
0, //tp_is_gc
0, //tp_bases
0, //tp_mro
0, //tp_cache
0, //tp_subclasses
0, //tp_weaklist
0 //tp_del
};
//------------------------newQuaternionObject (internal)-------------
//creates a new quaternion object
/*pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER
(i.e. it was allocated elsewhere by MEM_mallocN())
pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON
(i.e. it must be created here with PyMEM_malloc())*/
PyObject *newQuaternionObject(float *quat, int type, PyTypeObject *base_type)
{
QuaternionObject *self;
if(base_type) self = (QuaternionObject *)base_type->tp_alloc(base_type, 0);
else self = PyObject_NEW(QuaternionObject, &quaternion_Type);
/* init callbacks as NULL */
self->cb_user= NULL;
self->cb_type= self->cb_subtype= 0;
if(type == Py_WRAP){
self->quat = quat;
self->wrapped = Py_WRAP;
}else if (type == Py_NEW){
self->quat = PyMem_Malloc(4 * sizeof(float));
if(!quat) { //new empty
QuatOne(self->quat);
}else{
QUATCOPY(self->quat, quat);
}
self->wrapped = Py_NEW;
}else{ //bad type
return NULL;
}
return (PyObject *) self;
}
PyObject *newQuaternionObject_cb(PyObject *cb_user, int cb_type, int cb_subtype)
{
QuaternionObject *self= (QuaternionObject *)newQuaternionObject(NULL, Py_NEW, NULL);
if(self) {
Py_INCREF(cb_user);
self->cb_user= cb_user;
self->cb_type= (unsigned char)cb_type;
self->cb_subtype= (unsigned char)cb_subtype;
}
return (PyObject *)self;
}

View File

@@ -0,0 +1,60 @@
/*
* $Id: quat.h 21254 2009-06-30 00:42:17Z campbellbarton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): Joseph Gilbert
*
* ***** END GPL LICENSE BLOCK *****
*
*/
#ifndef EXPP_quat_h
#define EXPP_quat_h
#include <Python.h>
#include "../intern/bpy_compat.h"
extern PyTypeObject quaternion_Type;
#define QuaternionObject_Check(_v) PyObject_TypeCheck((_v), &quaternion_Type)
typedef struct { /* keep aligned with BaseMathObject in Mathutils.h */
PyObject_VAR_HEAD
float *quat; /* 1D array of data (alias) */
PyObject *cb_user; /* if this vector references another object, otherwise NULL, *Note* this owns its reference */
unsigned char cb_type; /* which user funcs do we adhere to, RNA, GameObject, etc */
unsigned char cb_subtype; /* subtype: location, rotation... to avoid defining many new functions for every attribute of the same type */
unsigned char wrapped; /* wrapped data type? */
/* end BaseMathObject */
} QuaternionObject;
/*struct data contains a pointer to the actual data that the
object uses. It can use either PyMem allocated data (which will
be stored in py_data) or be a wrapper for data allocated through
blender (stored in blend_data). This is an either/or struct not both*/
//prototypes
PyObject *newQuaternionObject( float *quat, int type, PyTypeObject *base_type);
PyObject *newQuaternionObject_cb(PyObject *cb_user, int cb_type, int cb_subtype);
#endif /* EXPP_quat_h */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,55 @@
/* $Id: vector.h 21254 2009-06-30 00:42:17Z campbellbarton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): Willian P. Germano & Joseph Gilbert
*
* ***** END GPL LICENSE BLOCK *****
*
*/
#ifndef EXPP_vector_h
#define EXPP_vector_h
#include <Python.h>
#include "../intern/bpy_compat.h"
extern PyTypeObject vector_Type;
#define VectorObject_Check(_v) PyObject_TypeCheck((_v), &vector_Type)
typedef struct { /* keep aligned with BaseMathObject in Mathutils.h */
PyObject_VAR_HEAD
float *vec; /*1D array of data (alias), wrapped status depends on wrapped status */
PyObject *cb_user; /* if this vector references another object, otherwise NULL, *Note* this owns its reference */
unsigned char cb_type; /* which user funcs do we adhere to, RNA, GameObject, etc */
unsigned char cb_subtype; /* subtype: location, rotation... to avoid defining many new functions for every attribute of the same type */
unsigned char wrapped; /* wrapped data type? */
/* end BaseMathObject */
unsigned char size; /* vec size 2,3 or 4 */
} VectorObject;
/*prototypes*/
PyObject *newVectorObject(float *vec, int size, int type, PyTypeObject *base_type);
PyObject *newVectorObject_cb(PyObject *user, int size, int callback_type, int subtype);
#endif /* EXPP_vector_h */

View File

@@ -1,5 +1,5 @@
#
# $Id: Makefile 11904 2007-08-31 16:16:33Z sirdude $
# $Id: Makefile 21094 2009-06-23 00:09:26Z gsrb3d $
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
@@ -37,6 +37,7 @@ CFLAGS += $(LEVEL_1_C_WARNINGS)
# OpenGL and Python
CPPFLAGS += $(OGL_CPPFLAGS)
CPPFLAGS += -I$(NAN_GLEW)/include
CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION)
# PreProcessor stuff

View File

@@ -1,5 +1,5 @@
/**
* $Id$
* $Id: bpy_compat.h 21427 2009-07-08 14:26:43Z ton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -85,9 +85,35 @@ typedef Py_ssize_t (*lenfunc)(PyObject *);
#ifndef Py_RETURN_TRUE
#define Py_RETURN_TRUE return PyBool_FromLong(1)
#endif
#define PyInt_FromSsize_t PyInt_FromLong
#define PyNumber_AsSsize_t(ob, exc) PyInt_AsLong(ob)
#define PyIndex_Check(ob) PyInt_Check(ob)
#endif
#if PY_VERSION_HEX < 0x03000000
#ifndef ssizeargfunc
#define ssizeargfunc intargfunc
#endif
#ifndef ssizessizeargfunc
#define ssizessizeargfunc intintargfunc
#endif
#ifndef ssizeobjargproc
#define ssizeobjargproc intobjargproc
#endif
#ifndef ssizessizeobjargproc
#define ssizessizeobjargproc intintobjargproc
#endif
#endif
/* defined in bpy_util.c */
#if PY_VERSION_HEX < 0x03000000
PyObject *Py_CmpToRich(int op, int cmp);

View File

@@ -36,6 +36,14 @@
#include "BPY_extern.h"
#include "../generic/bpy_internal_import.h" // our own imports
/* external util modules */
#include "../generic/Mathutils.h"
#include "../generic/Geometry.h"
#include "../generic/BGL.h"
void BPY_free_compiled_text( struct Text *text )
{
if( text->compiled ) {
@@ -56,12 +64,19 @@ static void bpy_init_modules( void )
PyModule_AddObject( mod, "data", BPY_rna_module() );
/* PyModule_AddObject( mod, "doc", BPY_rna_doc() ); */
PyModule_AddObject( mod, "types", BPY_rna_types() );
PyModule_AddObject( mod, "props", BPY_rna_props() );
PyModule_AddObject( mod, "ops", BPY_operator_module() );
PyModule_AddObject( mod, "ui", BPY_ui_module() ); // XXX very experemental, consider this a test, especially PyCObject is not meant to be perminant
PyModule_AddObject( mod, "ui", BPY_ui_module() ); // XXX very experimental, consider this a test, especially PyCObject is not meant to be permanent
/* add the module so we can import it */
PyDict_SetItemString(PySys_GetObject("modules"), "bpy", mod);
Py_DECREF(mod);
/* stand alone utility modules not related to blender directly */
Geometry_Init("Geometry");
Mathutils_Init("Mathutils");
BGL_Init("BGL");
}
#if (PY_VERSION_HEX < 0x02050000)
@@ -100,6 +115,7 @@ static PyObject *CreateGlobalDictionary( bContext *C )
{"FloatProperty", (PyCFunction)BPy_FloatProperty, METH_VARARGS|METH_KEYWORDS, ""},
{"IntProperty", (PyCFunction)BPy_IntProperty, METH_VARARGS|METH_KEYWORDS, ""},
{"BoolProperty", (PyCFunction)BPy_BoolProperty, METH_VARARGS|METH_KEYWORDS, ""},
{"StringProperty", (PyCFunction)BPy_StringProperty, METH_VARARGS|METH_KEYWORDS, ""},
{NULL, NULL, 0, NULL}
};
@@ -116,13 +132,81 @@ static PyObject *CreateGlobalDictionary( bContext *C )
return dict;
}
/* Use this so we can include our own python bundle */
#if 0
wchar_t* Py_GetPath(void)
{
int i;
static wchar_t py_path[FILE_MAXDIR] = L"";
char *dirname= BLI_gethome_folder("python");
if(dirname) {
i= mbstowcs(py_path, dirname, FILE_MAXDIR);
printf("py path %s, %d\n", dirname, i);
}
return py_path;
}
#endif
/* must be called before Py_Initialize */
void BPY_start_python_path(void)
{
char *py_path_bundle= BLI_gethome_folder("python");
if(py_path_bundle==NULL)
return;
/* set the environment path */
printf("found bundled python: %s\n", py_path_bundle);
#if (defined(WIN32) || defined(WIN64))
#if defined(FREE_WINDOWS)
{
char py_path[FILE_MAXDIR + 11] = "";
sprintf(py_path, "PYTHONPATH=%s", py_path_bundle);
putenv(py_path);
}
#else
_putenv_s("PYTHONPATH", py_path_bundle);
#endif
#else
#ifdef __sgi
{
char py_path[FILE_MAXDIR + 11] = "";
sprintf(py_path, "PYTHONPATH=%s", py_path_bundle);
putenv(py_path);
}
#else
setenv("PYTHONPATH", py_path_bundle, 1);
#endif
#endif
}
void BPY_start_python( int argc, char **argv )
{
PyThreadState *py_tstate = NULL;
BPY_start_python_path(); /* allow to use our own included python */
Py_Initialize( );
//PySys_SetArgv( argc_copy, argv_copy );
#if (PY_VERSION_HEX < 0x03000000)
PySys_SetArgv( argc, argv);
#else
/* sigh, why do python guys not have a char** version anymore? :( */
{
int i;
PyObject *py_argv= PyList_New(argc);
for (i=0; i<argc; i++)
PyList_SET_ITEM(py_argv, i, PyUnicode_FromString(argv[i]));
PySys_SetObject("argv", py_argv);
Py_DECREF(py_argv);
}
#endif
/* Initialize thread support (also acquires lock) */
PyEval_InitThreads();
@@ -131,10 +215,17 @@ void BPY_start_python( int argc, char **argv )
/* bpy.* and lets us import it */
bpy_init_modules();
{ /* our own import and reload functions */
PyObject *item;
//PyObject *m = PyImport_AddModule("__builtin__");
//PyObject *d = PyModule_GetDict(m);
PyObject *d = PyEval_GetBuiltins( );
PyDict_SetItemString(d, "reload", item=PyCFunction_New(bpy_reload_meth, NULL)); Py_DECREF(item);
PyDict_SetItemString(d, "__import__", item=PyCFunction_New(bpy_import_meth, NULL)); Py_DECREF(item);
}
py_tstate = PyGILState_GetThisThreadState();
PyEval_ReleaseThread(py_tstate);
}
void BPY_end_python( void )
@@ -150,7 +241,7 @@ void BPY_end_python( void )
}
/* Can run a file or text block */
int BPY_run_python_script( bContext *C, const char *fn, struct Text *text )
int BPY_run_python_script( bContext *C, const char *fn, struct Text *text, struct ReportList *reports)
{
PyObject *py_dict, *py_result;
PyGILState_STATE gilstate;
@@ -164,6 +255,7 @@ int BPY_run_python_script( bContext *C, const char *fn, struct Text *text )
gilstate = PyGILState_Ensure();
BPY_update_modules(); /* can give really bad results if this isnt here */
bpy_import_main_set(CTX_data_main(C));
py_dict = CreateGlobalDictionary(C);
@@ -178,7 +270,7 @@ int BPY_run_python_script( bContext *C, const char *fn, struct Text *text )
MEM_freeN( buf );
if( PyErr_Occurred( ) ) {
PyErr_Print(); PyErr_Clear();
BPy_errors_to_report(reports);
BPY_free_compiled_text( text );
PyGILState_Release(gilstate);
return 0;
@@ -194,13 +286,14 @@ int BPY_run_python_script( bContext *C, const char *fn, struct Text *text )
}
if (!py_result) {
PyErr_Print(); PyErr_Clear();
BPy_errors_to_report(reports);
} else {
Py_DECREF( py_result );
}
Py_DECREF(py_dict);
PyGILState_Release(gilstate);
bpy_import_main_set(NULL);
//BPY_end_python();
return py_result ? 1:0;
@@ -221,7 +314,7 @@ static void exit_pydraw( SpaceScript * sc, short err )
script = sc->script;
if( err ) {
PyErr_Print(); PyErr_Clear();
BPy_errors_to_report(NULL); // TODO, reports
script->flags = 0; /* mark script struct for deletion */
SCRIPT_SET_NULL(script);
script->scriptname[0] = '\0';
@@ -250,7 +343,7 @@ static int bpy_run_script_init(bContext *C, SpaceScript * sc)
return 0;
if (sc->script->py_draw==NULL && sc->script->scriptname[0] != '\0')
BPY_run_python_script(C, sc->script->scriptname, NULL);
BPY_run_python_script(C, sc->script->scriptname, NULL, NULL);
if (sc->script->py_draw==NULL)
return 0;
@@ -258,9 +351,9 @@ static int bpy_run_script_init(bContext *C, SpaceScript * sc)
return 1;
}
int BPY_run_script_space_draw(struct bContext *C, SpaceScript * sc)
int BPY_run_script_space_draw(const struct bContext *C, SpaceScript * sc)
{
if (bpy_run_script_init(C, sc)) {
if (bpy_run_script_init( (bContext *)C, sc)) {
PyGILState_STATE gilstate = PyGILState_Ensure();
PyObject *result = PyObject_CallObject( sc->script->py_draw, NULL );
@@ -329,7 +422,7 @@ int BPY_run_python_script_space(const char *modulename, const char *func)
}
if (!py_result) {
PyErr_Print(); PyErr_Clear();
BPy_errors_to_report(NULL); // TODO - reports
} else
Py_DECREF( py_result );
@@ -357,69 +450,72 @@ void BPY_run_ui_scripts(bContext *C, int reload)
DIR *dir;
struct dirent *de;
char *file_extension;
char *dirname;
char path[FILE_MAX];
char *dirname= BLI_gethome_folder("ui");
int filelen; /* filename length */
char *dirs[] = {"io", "ui", NULL};
int a;
PyGILState_STATE gilstate;
PyObject *mod;
PyObject *sys_path_orig;
PyObject *sys_path_new;
if(!dirname)
return;
dir = opendir(dirname);
PyObject *sys_path;
if(!dir)
return;
gilstate = PyGILState_Ensure();
/* backup sys.path */
sys_path_orig= PySys_GetObject("path");
Py_INCREF(sys_path_orig); /* dont free it */
sys_path_new= PyList_New(1);
PyList_SET_ITEM(sys_path_new, 0, PyUnicode_FromString(dirname));
PySys_SetObject("path", sys_path_new);
Py_DECREF(sys_path_new);
// XXX - evil, need to access context
BPy_SetContext(C);
while((de = readdir(dir)) != NULL) {
/* We could stat the file but easier just to let python
* import it and complain if theres a problem */
bpy_import_main_set(CTX_data_main(C));
sys_path= PySys_GetObject("path"); /* borrow */
PyList_Insert(sys_path, 0, Py_None); /* place holder, resizes the list */
for(a=0; dirs[a]; a++) {
dirname= BLI_gethome_folder(dirs[a]);
if(!dirname)
continue;
dir = opendir(dirname);
if(!dir)
continue;
file_extension = strstr(de->d_name, ".py");
if(file_extension && *(file_extension + 3) == '\0') {
filelen = strlen(de->d_name);
BLI_strncpy(path, de->d_name, filelen-2); /* cut off the .py on copy */
/* set the first dir in the sys.path for fast importing of modules */
PyList_SetItem(sys_path, 0, PyUnicode_FromString(dirname)); /* steals the ref */
mod= PyImport_ImportModuleLevel(path, NULL, NULL, NULL, 0);
if (mod) {
if (reload) {
PyObject *mod_orig= mod;
mod= PyImport_ReloadModule(mod);
Py_DECREF(mod_orig);
while((de = readdir(dir)) != NULL) {
/* We could stat the file but easier just to let python
* import it and complain if theres a problem */
file_extension = strstr(de->d_name, ".py");
if(file_extension && file_extension[3] == '\0') {
BLI_strncpy(path, de->d_name, (file_extension - de->d_name) + 1); /* cut off the .py on copy */
mod= PyImport_ImportModuleLevel(path, NULL, NULL, NULL, 0);
if (mod) {
if (reload) {
PyObject *mod_orig= mod;
mod= PyImport_ReloadModule(mod);
Py_DECREF(mod_orig);
}
}
}
if(mod) {
Py_DECREF(mod); /* could be NULL from reloading */
} else {
PyErr_Print(); PyErr_Clear();
fprintf(stderr, "unable to import \"%s\" %s/%s\n", path, dirname, de->d_name);
if(mod) {
Py_DECREF(mod); /* could be NULL from reloading */
} else {
BPy_errors_to_report(NULL);
fprintf(stderr, "unable to import \"%s\" %s/%s\n", path, dirname, de->d_name);
}
}
}
}
closedir(dir);
closedir(dir);
}
PySys_SetObject("path", sys_path_orig);
Py_DECREF(sys_path_orig);
PyList_SetSlice(sys_path, 0, 1, NULL); /* remove the first item */
bpy_import_main_set(NULL);
PyGILState_Release(gilstate);
#ifdef TIME_REGISTRATION
@@ -530,7 +626,7 @@ static float pydriver_error(ChannelDriver *driver)
driver->flag |= DRIVER_FLAG_INVALID; /* py expression failed */
fprintf(stderr, "\nError in Driver: The following Python expression failed:\n\t'%s'\n\n", driver->expression);
PyErr_Print(); PyErr_Clear();
BPy_errors_to_report(NULL); // TODO - reports
return 0.0f;
}
@@ -589,7 +685,7 @@ float BPY_pydriver_eval (ChannelDriver *driver)
}
fprintf(stderr, "\tBPY_pydriver_eval() - couldn't add variable '%s' to namespace \n", dtar->name);
PyErr_Print(); PyErr_Clear();
BPy_errors_to_report(NULL); // TODO - reports
}
}

View File

@@ -1,6 +1,6 @@
/**
* $Id$
* $Id: bpy_operator.c 21554 2009-07-13 08:33:51Z campbellbarton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -68,7 +68,7 @@ static PyObject *pyop_base_call( PyObject * self, PyObject * args, PyObject * k
return NULL;
}
ot= WM_operatortype_find(opname);
ot= WM_operatortype_find(opname, 1);
if (ot == NULL) {
PyErr_Format( PyExc_SystemError, "Operator \"%s\"could not be found", opname);
return NULL;
@@ -130,11 +130,18 @@ static PyObject *pyop_base_getattro( BPy_OperatorBase * self, PyObject *pyname )
PyObject *ret;
wmOperatorType *ot;
if ((ot= WM_operatortype_find(name))) {
/* First look for the operator, then our own methods if that fails.
* when methods are searched first, PyObject_GenericGetAttr will raise an error
* each time we want to call an operator, we could clear the error but I prefer
* not to since calling operators is a lot more common then adding and removing. - Campbell */
if ((ot= WM_operatortype_find(name, 1))) {
ret = PyCFunction_New( pyop_base_call_meth, pyname); /* set the name string as self, PyCFunction_New incref's self */
}
else if ((ret = PyObject_GenericGetAttr((PyObject *)self, pyname))) {
/* do nothing, this accounts for methoddef's add and remove */
/* do nothing, this accounts for methoddef's add and remove
* An exception is raised when PyObject_GenericGetAttr fails
* but its ok because its overwritten below */
}
else {
PyErr_Format( PyExc_AttributeError, "Operator \"%s\" not found", name);
@@ -170,7 +177,7 @@ static PyObject *pyop_base_rna(PyObject *self, PyObject *pyname)
char *name = _PyUnicode_AsString(pyname);
wmOperatorType *ot;
if ((ot= WM_operatortype_find(name))) {
if ((ot= WM_operatortype_find(name, 1))) {
BPy_StructRNA *pyrna;
PointerRNA ptr;
@@ -191,6 +198,8 @@ PyTypeObject pyop_base_Type = {NULL};
PyObject *BPY_operator_module( void )
{
PyObject *ob;
pyop_base_Type.tp_name = "OperatorBase";
pyop_base_Type.tp_basicsize = sizeof( BPy_OperatorBase );
pyop_base_Type.tp_getattro = ( getattrofunc )pyop_base_getattro;
@@ -201,6 +210,9 @@ PyObject *BPY_operator_module( void )
return NULL;
//submodule = Py_InitModule3( "operator", M_rna_methods, "rna module" );
return (PyObject *)PyObject_NEW( BPy_OperatorBase, &pyop_base_Type );
ob = PyObject_NEW( BPy_OperatorBase, &pyop_base_Type );
Py_INCREF(ob);
return ob;
}

View File

@@ -1,6 +1,6 @@
/**
* $Id$
* $Id: bpy_operator.h 21094 2009-06-23 00:09:26Z gsrb3d $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*

View File

@@ -1,6 +1,6 @@
/**
* $Id$
* $Id: bpy_operator_wrap.c 21440 2009-07-08 21:31:28Z blendix $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -40,116 +40,13 @@
#include "bpy_compat.h"
#include "bpy_util.h"
#include "../generic/bpy_internal_import.h" // our own imports
#define PYOP_ATTR_PROP "__props__"
#define PYOP_ATTR_UINAME "__label__"
#define PYOP_ATTR_IDNAME "__name__" /* use pythons class name */
#define PYOP_ATTR_DESCRIPTION "__doc__" /* use pythons docstring */
static PyObject *pyop_dict_from_event(wmEvent *event)
{
PyObject *dict= PyDict_New();
PyObject *item;
char *cstring, ascii[2];
/* type */
item= PyUnicode_FromString(WM_key_event_string(event->type));
PyDict_SetItemString(dict, "type", item); Py_DECREF(item);
/* val */
switch(event->val) {
case KM_ANY:
cstring = "ANY";
break;
case KM_RELEASE:
cstring = "RELEASE";
break;
case KM_PRESS:
cstring = "PRESS";
break;
default:
cstring = "UNKNOWN";
break;
}
item= PyUnicode_FromString(cstring);
PyDict_SetItemString(dict, "val", item); Py_DECREF(item);
/* x, y (mouse) */
item= PyLong_FromLong(event->x);
PyDict_SetItemString(dict, "x", item); Py_DECREF(item);
item= PyLong_FromLong(event->y);
PyDict_SetItemString(dict, "y", item); Py_DECREF(item);
item= PyLong_FromLong(event->prevx);
PyDict_SetItemString(dict, "prevx", item); Py_DECREF(item);
item= PyLong_FromLong(event->prevy);
PyDict_SetItemString(dict, "prevy", item); Py_DECREF(item);
/* ascii */
ascii[0]= event->ascii;
ascii[1]= '\0';
item= PyUnicode_FromString(ascii);
PyDict_SetItemString(dict, "ascii", item); Py_DECREF(item);
/* modifier keys */
item= PyLong_FromLong(event->shift);
PyDict_SetItemString(dict, "shift", item); Py_DECREF(item);
item= PyLong_FromLong(event->ctrl);
PyDict_SetItemString(dict, "ctrl", item); Py_DECREF(item);
item= PyLong_FromLong(event->alt);
PyDict_SetItemString(dict, "alt", item); Py_DECREF(item);
item= PyLong_FromLong(event->oskey);
PyDict_SetItemString(dict, "oskey", item); Py_DECREF(item);
/* modifier */
#if 0
item= PyTuple_New(0);
if(event->keymodifier & KM_SHIFT) {
_PyTuple_Resize(&item, size+1);
PyTuple_SET_ITEM(item, size, _PyUnicode_AsString("SHIFT"));
size++;
}
if(event->keymodifier & KM_CTRL) {
_PyTuple_Resize(&item, size+1);
PyTuple_SET_ITEM(item, size, _PyUnicode_AsString("CTRL"));
size++;
}
if(event->keymodifier & KM_ALT) {
_PyTuple_Resize(&item, size+1);
PyTuple_SET_ITEM(item, size, _PyUnicode_AsString("ALT"));
size++;
}
if(event->keymodifier & KM_OSKEY) {
_PyTuple_Resize(&item, size+1);
PyTuple_SET_ITEM(item, size, _PyUnicode_AsString("OSKEY"));
size++;
}
PyDict_SetItemString(dict, "keymodifier", item); Py_DECREF(item);
#endif
return dict;
}
/* TODO - a whole traceback would be ideal */
static void pyop_error_report(ReportList *reports)
{
PyObject *exception, *v, *tb;
PyErr_Fetch(&exception, &v, &tb);
if (exception == NULL)
return;
/* Now we know v != NULL too */
BKE_report(reports, RPT_ERROR, _PyUnicode_AsString(v));
PyErr_Print();
}
static struct BPY_flag_def pyop_ret_flags[] = {
{"RUNNING_MODAL", OPERATOR_RUNNING_MODAL},
{"CANCELLED", OPERATOR_CANCELLED},
@@ -190,9 +87,13 @@ static int PYTHON_OT_generic(int mode, bContext *C, wmOperator *op, wmEvent *eve
PyObject *ret= NULL, *py_class_instance, *item= NULL;
int ret_flag= (mode==PYOP_POLL ? 0:OPERATOR_CANCELLED);
PointerRNA ptr_context;
PyObject *py_context;
PointerRNA ptr_operator;
PointerRNA ptr_event;
PyObject *py_operator;
PyGILState_STATE gilstate = PyGILState_Ensure();
bpy_import_main_set(CTX_data_main(C));
BPY_update_modules(); // XXX - the RNA pointers can change so update before running, would like a nicer solutuon for this.
@@ -206,15 +107,9 @@ static int PYTHON_OT_generic(int mode, bContext *C, wmOperator *op, wmEvent *eve
/* Assign instance attributes from operator properties */
{
PropertyRNA *prop, *iterprop;
CollectionPropertyIterator iter;
const char *arg_name;
iterprop= RNA_struct_iterator_property(op->ptr->type);
RNA_property_collection_begin(op->ptr, iterprop, &iter);
for(; iter.valid; RNA_property_collection_next(&iter)) {
prop= iter.ptr.data;
RNA_STRUCT_BEGIN(op->ptr, prop) {
arg_name= RNA_property_identifier(prop);
if (strcmp(arg_name, "rna_type")==0) continue;
@@ -223,23 +118,33 @@ static int PYTHON_OT_generic(int mode, bContext *C, wmOperator *op, wmEvent *eve
PyObject_SetAttrString(py_class_instance, arg_name, item);
Py_DECREF(item);
}
RNA_property_collection_end(&iter);
RNA_STRUCT_END;
}
/* set operator pointer RNA as instance "__operator__" attribute */
RNA_pointer_create(NULL, &RNA_Operator, op, &ptr_operator);
py_operator= pyrna_struct_CreatePyObject(&ptr_operator);
PyObject_SetAttrString(py_class_instance, "__operator__", py_operator);
Py_DECREF(py_operator);
RNA_pointer_create(NULL, &RNA_Context, C, &ptr_context);
if (mode==PYOP_INVOKE) {
item= PyObject_GetAttrString(py_class, "invoke");
args = PyTuple_New(2);
PyTuple_SET_ITEM(args, 1, pyop_dict_from_event(event));
args = PyTuple_New(3);
RNA_pointer_create(NULL, &RNA_Event, event, &ptr_event);
// PyTuple_SET_ITEM "steals" object reference, it is
// an object passed shouldn't be DECREF'ed
PyTuple_SET_ITEM(args, 1, pyrna_struct_CreatePyObject(&ptr_context));
PyTuple_SET_ITEM(args, 2, pyrna_struct_CreatePyObject(&ptr_event));
}
else if (mode==PYOP_EXEC) {
item= PyObject_GetAttrString(py_class, "exec");
item= PyObject_GetAttrString(py_class, "execute");
args = PyTuple_New(2);
RNA_pointer_create(NULL, &RNA_Context, C, &ptr_context);
py_context = pyrna_struct_CreatePyObject(&ptr_context);
PyTuple_SET_ITEM(args, 1, py_context);
PyTuple_SET_ITEM(args, 1, pyrna_struct_CreatePyObject(&ptr_context));
}
else if (mode==PYOP_POLL) {
item= PyObject_GetAttrString(py_class, "poll");
@@ -256,13 +161,13 @@ static int PYTHON_OT_generic(int mode, bContext *C, wmOperator *op, wmEvent *eve
}
if (ret == NULL) { /* covers py_class_instance failing too */
pyop_error_report(op->reports);
BPy_errors_to_report(op->reports);
}
else {
if (mode==PYOP_POLL) {
if (PyBool_Check(ret) == 0) {
PyErr_SetString(PyExc_ValueError, "Python poll function return value ");
pyop_error_report(op->reports);
BPy_errors_to_report(op->reports);
}
else {
ret_flag= ret==Py_True ? 1:0;
@@ -270,8 +175,9 @@ static int PYTHON_OT_generic(int mode, bContext *C, wmOperator *op, wmEvent *eve
} else if (BPY_flag_from_seq(pyop_ret_flags, ret, &ret_flag) == -1) {
/* the returned value could not be converted into a flag */
pyop_error_report(op->reports);
BPy_errors_to_report(op->reports);
ret_flag = OPERATOR_CANCELLED;
}
/* there is no need to copy the py keyword dict modified by
* pyot->py_invoke(), back to the operator props since they are just
@@ -284,7 +190,34 @@ static int PYTHON_OT_generic(int mode, bContext *C, wmOperator *op, wmEvent *eve
Py_DECREF(ret);
}
/* print operator return value */
if (mode != PYOP_POLL) {
char flag_str[100];
char class_name[100];
BPY_flag_def *flag_def = pyop_ret_flags;
strcpy(flag_str, "");
while(flag_def->name) {
if (ret_flag & flag_def->flag) {
if(flag_str[1])
sprintf(flag_str, "%s | %s", flag_str, flag_def->name);
else
strcpy(flag_str, flag_def->name);
}
flag_def++;
}
/* get class name */
item= PyObject_GetAttrString(py_class, PYOP_ATTR_IDNAME);
Py_DECREF(item);
strcpy(class_name, _PyUnicode_AsString(item));
fprintf(stderr, "%s's %s returned %s\n", class_name, mode == PYOP_EXEC ? "execute" : "invoke", flag_str);
}
PyGILState_Release(gilstate);
bpy_import_main_set(NULL);
return ret_flag;
}
@@ -334,7 +267,7 @@ void PYTHON_OT_wrapper(wmOperatorType *ot, void *userdata)
/* api callbacks, detailed checks dont on adding */
if (PyObject_HasAttrString(py_class, "invoke"))
ot->invoke= PYTHON_OT_invoke;
if (PyObject_HasAttrString(py_class, "exec"))
if (PyObject_HasAttrString(py_class, "execute"))
ot->exec= PYTHON_OT_exec;
if (PyObject_HasAttrString(py_class, "poll"))
ot->poll= PYTHON_OT_poll;
@@ -387,6 +320,7 @@ void PYTHON_OT_wrapper(wmOperatorType *ot, void *userdata)
PyObject *PYOP_wrap_add(PyObject *self, PyObject *py_class)
{
PyObject *base_class, *item;
wmOperatorType *ot;
char *idname= NULL;
@@ -397,8 +331,8 @@ PyObject *PYOP_wrap_add(PyObject *self, PyObject *py_class)
{PYOP_ATTR_UINAME, 's', 0, BPY_CLASS_ATTR_OPTIONAL},
{PYOP_ATTR_PROP, 'l', 0, BPY_CLASS_ATTR_OPTIONAL},
{PYOP_ATTR_DESCRIPTION, 's', 0, BPY_CLASS_ATTR_NONE_OK},
{"exec", 'f', 2, BPY_CLASS_ATTR_OPTIONAL},
{"invoke", 'f', 2, BPY_CLASS_ATTR_OPTIONAL},
{"execute", 'f', 2, BPY_CLASS_ATTR_OPTIONAL},
{"invoke", 'f', 3, BPY_CLASS_ATTR_OPTIONAL},
{"poll", 'f', 2, BPY_CLASS_ATTR_OPTIONAL},
{NULL, 0, 0, 0}
};
@@ -417,9 +351,12 @@ PyObject *PYOP_wrap_add(PyObject *self, PyObject *py_class)
Py_DECREF(item);
idname = _PyUnicode_AsString(item);
if (WM_operatortype_find(idname)) {
PyErr_Format( PyExc_AttributeError, "Operator alredy exists with this name \"%s\"", idname);
return NULL;
/* remove if it already exists */
if ((ot=WM_operatortype_exists(idname))) {
if(ot->pyop_data) {
Py_XDECREF((PyObject*)ot->pyop_data);
}
WM_operatortype_remove(idname);
}
/* If we have properties set, check its a list of dicts */
@@ -466,7 +403,7 @@ PyObject *PYOP_wrap_remove(PyObject *self, PyObject *value)
return NULL;
}
if (!(ot= WM_operatortype_find(idname))) {
if (!(ot= WM_operatortype_exists(idname))) {
PyErr_Format( PyExc_AttributeError, "Operator \"%s\" does not exists, cant remove", idname);
return NULL;
}

View File

@@ -1,6 +1,6 @@
/**
* $Id$
* $Id: bpy_operator_wrap.h 21094 2009-06-23 00:09:26Z gsrb3d $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
/**
* $Id$
* $Id: bpy_rna.h 21094 2009-06-23 00:09:26Z gsrb3d $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -63,6 +63,7 @@ typedef struct {
PyObject *BPY_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 );
@@ -76,6 +77,7 @@ PyObject * pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop);
PyObject *BPy_FloatProperty(PyObject *self, PyObject *args, PyObject *kw);
PyObject *BPy_IntProperty(PyObject *self, PyObject *args, PyObject *kw);
PyObject *BPy_BoolProperty(PyObject *self, PyObject *args, PyObject *kw);
PyObject *BPy_StringProperty(PyObject *self, PyObject *args, PyObject *kw);
/* function for registering types */
PyObject *pyrna_basetype_register(PyObject *self, PyObject *args);

View File

@@ -1,5 +1,5 @@
/**
* $Id$
* $Id: bpy_ui.c 21611 2009-07-16 00:50:27Z campbellbarton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -373,7 +373,7 @@ static struct PyMethodDef ui_methods[] = {
#if PY_VERSION_HEX >= 0x03000000
static struct PyModuleDef ui_module = {
PyModuleDef_HEAD_INIT,
"bpyui",
"bpy.ui",
"",
-1,/* multiple "initialization" just copies the module dict. */
ui_methods,
@@ -557,6 +557,7 @@ PyObject *BPY_ui_module( void )
PyModule_AddObject( mod, "SCRIPT", PyLong_FromSsize_t(SPACE_SCRIPT) );
PyModule_AddObject( mod, "TIME", PyLong_FromSsize_t(SPACE_TIME) );
PyModule_AddObject( mod, "NODE", PyLong_FromSsize_t(SPACE_NODE) );
//PyModule_AddObject( mod, "CONSOLE", PyLong_FromSsize_t(SPACE_CONSOLE) );
/* INCREF since its its assumed that all these functions return the
* module with a new ref like PyDict_New, since they are passed to

View File

@@ -1,5 +1,5 @@
/**
* $Id$
* $Id: bpy_ui.h 21094 2009-06-23 00:09:26Z gsrb3d $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*

View File

@@ -1,5 +1,5 @@
/**
* $Id$
* $Id: bpy_util.c 21526 2009-07-11 13:57:56Z campbellbarton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -81,6 +81,7 @@ int BPY_flag_from_seq(BPY_flag_def *flagdef, PyObject *seq, int *flag)
char *cstring;
PyObject *item;
BPY_flag_def *fd;
*flag = 0;
if (PySequence_Check(seq)) {
i= PySequence_Length(seq);
@@ -108,6 +109,9 @@ int BPY_flag_from_seq(BPY_flag_def *flagdef, PyObject *seq, int *flag)
error_val= 1;
}
if (*flag == 0)
error_val = 1;
if (error_val) {
char *buf = bpy_flag_error_str(flagdef);
PyErr_SetString(PyExc_AttributeError, buf);
@@ -167,7 +171,13 @@ void PyObSpit(char *name, PyObject *var) {
else {
PyObject_Print(var, stderr, 0);
fprintf(stderr, " ref:%d ", var->ob_refcnt);
fprintf(stderr, " ptr:%ld", (long)var);
fprintf(stderr, " ptr:%p", (void *)var);
fprintf(stderr, " type:");
if(Py_TYPE(var))
fprintf(stderr, "%s", Py_TYPE(var)->tp_name);
else
fprintf(stderr, "<NIL>");
}
fprintf(stderr, "\n");
}
@@ -329,6 +339,81 @@ int BPY_class_validate(const char *class_type, PyObject *class, PyObject *base_c
return 0;
}
/* returns the exception string as a new PyUnicode object, depends on external StringIO module */
PyObject *BPY_exception_buffer(void)
{
PyObject *stdout_backup = PySys_GetObject("stdout"); /* borrowed */
PyObject *stderr_backup = PySys_GetObject("stderr"); /* borrowed */
PyObject *string_io = NULL;
PyObject *string_io_buf = NULL;
PyObject *string_io_mod= NULL;
PyObject *string_io_getvalue= NULL;
PyObject *error_type, *error_value, *error_traceback;
if (!PyErr_Occurred())
return NULL;
PyErr_Fetch(&error_type, &error_value, &error_traceback);
PyErr_Clear();
/* import StringIO / io
* string_io = StringIO.StringIO()
*/
#if PY_VERSION_HEX < 0x03000000
if(! (string_io_mod= PyImport_ImportModule("StringIO")) ) {
#else
if(! (string_io_mod= PyImport_ImportModule("io")) ) {
#endif
goto error_cleanup;
} else if (! (string_io = PyObject_CallMethod(string_io_mod, "StringIO", NULL))) {
goto error_cleanup;
} else if (! (string_io_getvalue= PyObject_GetAttrString(string_io, "getvalue"))) {
goto error_cleanup;
}
Py_INCREF(stdout_backup); // since these were borrowed we dont want them freed when replaced.
Py_INCREF(stderr_backup);
PySys_SetObject("stdout", string_io); // both of these are free'd when restoring
PySys_SetObject("stderr", string_io);
PyErr_Restore(error_type, error_value, error_traceback);
PyErr_Print(); /* print the error */
PyErr_Clear();
string_io_buf = PyObject_CallObject(string_io_getvalue, NULL);
PySys_SetObject("stdout", stdout_backup);
PySys_SetObject("stderr", stderr_backup);
Py_DECREF(stdout_backup); /* now sys owns the ref again */
Py_DECREF(stderr_backup);
Py_DECREF(string_io_mod);
Py_DECREF(string_io_getvalue);
Py_DECREF(string_io); /* free the original reference */
PyErr_Clear();
return string_io_buf;
error_cleanup:
/* could not import the module so print the error and close */
Py_XDECREF(string_io_mod);
Py_XDECREF(string_io);
PyErr_Restore(error_type, error_value, error_traceback);
PyErr_Print(); /* print the error */
PyErr_Clear();
return NULL;
}
char *BPy_enum_as_string(EnumPropertyItem *item)
{
DynStr *dynstr= BLI_dynstr_new();
@@ -336,7 +421,8 @@ char *BPy_enum_as_string(EnumPropertyItem *item)
char *cstring;
for (e= item; item->identifier; item++) {
BLI_dynstr_appendf(dynstr, (e==item)?"'%s'":", '%s'", item->identifier);
if(item->identifier[0])
BLI_dynstr_appendf(dynstr, (e==item)?"'%s'":", '%s'", item->identifier);
}
cstring = BLI_dynstr_get_cstring(dynstr);
@@ -358,3 +444,33 @@ int BPy_reports_to_error(ReportList *reports)
return (report_str != NULL);
}
int BPy_errors_to_report(ReportList *reports)
{
PyObject *pystring;
char *cstring;
if (!PyErr_Occurred())
return 1;
/* less hassle if we allow NULL */
if(reports==NULL) {
PyErr_Print();
PyErr_Clear();
return 1;
}
pystring= BPY_exception_buffer();
if(pystring==NULL) {
BKE_report(reports, RPT_ERROR, "unknown py-exception, could not convert");
return 0;
}
cstring= _PyUnicode_AsString(pystring);
BKE_report(reports, RPT_ERROR, cstring);
fprintf(stderr, "%s\n", cstring); // not exactly needed. just for testing
Py_DECREF(pystring);
return 1;
}

View File

@@ -1,5 +1,5 @@
/**
* $Id$
* $Id: bpy_util.h 21094 2009-06-23 00:09:26Z gsrb3d $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -47,6 +47,8 @@ void PyObSpit(char *name, PyObject *var);
void PyLineSpit(void);
void BPY_getFileAndNum(char **filename, int *lineno);
PyObject *BPY_exception_buffer(void);
/* own python like utility function */
PyObject *PyObject_GetAttrStringArgs(PyObject *o, Py_ssize_t n, ...);
@@ -73,6 +75,7 @@ char *BPy_enum_as_string(struct EnumPropertyItem *item);
/* error reporting */
int BPy_reports_to_error(struct ReportList *reports);
int BPy_errors_to_report(struct ReportList *reports);
/* TODO - find a better solution! */
struct bContext *BPy_GetContext(void);