odd, this didn't get committed before
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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}")
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
1610
source/blender/python/generic/BGL.c
Normal file
1610
source/blender/python/generic/BGL.c
Normal file
File diff suppressed because it is too large
Load Diff
338
source/blender/python/generic/BGL.h
Normal file
338
source/blender/python/generic/BGL.h
Normal 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 */
|
||||
542
source/blender/python/generic/Geometry.c
Normal file
542
source/blender/python/generic/Geometry.c
Normal 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;
|
||||
}
|
||||
39
source/blender/python/generic/Geometry.h
Normal file
39
source/blender/python/generic/Geometry.h
Normal 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 */
|
||||
66
source/blender/python/generic/Makefile
Normal file
66
source/blender/python/generic/Makefile
Normal 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..
|
||||
1266
source/blender/python/generic/Mathutils.c
Normal file
1266
source/blender/python/generic/Mathutils.c
Normal file
File diff suppressed because it is too large
Load Diff
116
source/blender/python/generic/Mathutils.h
Normal file
116
source/blender/python/generic/Mathutils.h
Normal 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 */
|
||||
341
source/blender/python/generic/bpy_internal_import.c
Normal file
341
source/blender/python/generic/bpy_internal_import.c
Normal 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
|
||||
50
source/blender/python/generic/bpy_internal_import.h
Normal file
50
source/blender/python/generic/bpy_internal_import.h
Normal 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 */
|
||||
651
source/blender/python/generic/euler.c
Normal file
651
source/blender/python/generic/euler.c
Normal 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;
|
||||
}
|
||||
60
source/blender/python/generic/euler.h
Normal file
60
source/blender/python/generic/euler.h
Normal 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 */
|
||||
1358
source/blender/python/generic/matrix.c
Normal file
1358
source/blender/python/generic/matrix.c
Normal file
File diff suppressed because it is too large
Load Diff
66
source/blender/python/generic/matrix.h
Normal file
66
source/blender/python/generic/matrix.h
Normal 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 */
|
||||
879
source/blender/python/generic/quat.c
Normal file
879
source/blender/python/generic/quat.c
Normal 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;
|
||||
}
|
||||
60
source/blender/python/generic/quat.h
Normal file
60
source/blender/python/generic/quat.h
Normal 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 */
|
||||
2078
source/blender/python/generic/vector.c
Normal file
2078
source/blender/python/generic/vector.c
Normal file
File diff suppressed because it is too large
Load Diff
55
source/blender/python/generic/vector.h
Normal file
55
source/blender/python/generic/vector.h
Normal 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 */
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
/**
|
||||
* $Id$
|
||||
* $Id: bpy_operator.h 21094 2009-06-23 00:09:26Z gsrb3d $
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* $Id$
|
||||
* $Id: bpy_ui.h 21094 2009-06-23 00:09:26Z gsrb3d $
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user