diff options
author | Tamito Kajiyama <rd6t-kjym@asahi-net.or.jp> | 2011-12-05 06:12:49 +0400 |
---|---|---|
committer | Tamito Kajiyama <rd6t-kjym@asahi-net.or.jp> | 2011-12-05 06:12:49 +0400 |
commit | 3197796cf7aa4f1c34f2e68a2eca9d6a412a51d0 (patch) | |
tree | 5a0a119149b1079f888178bc2df3d15950c2f9b9 /source/blender/python | |
parent | 43c5e1b58030322096770b1aa4d91077793cd2c4 (diff) | |
parent | eb233d933223a3795f3ff5204c4412f7a0fd6782 (diff) |
Merged changes in the trunk up to revision 42425.
Conflicts resolved:
doc/python_api/sphinx_doc_gen.py
source/blender/blenkernel/intern/DerivedMesh.c
source/blender/blenloader/intern/readfile.c
source/blender/editors/mesh/editmesh.c
source/blender/editors/space_view3d/drawobject.c
Diffstat (limited to 'source/blender/python')
29 files changed, 1316 insertions, 989 deletions
diff --git a/source/blender/python/generic/CMakeLists.txt b/source/blender/python/generic/CMakeLists.txt index bd9731a277a..9a73911d697 100644 --- a/source/blender/python/generic/CMakeLists.txt +++ b/source/blender/python/generic/CMakeLists.txt @@ -37,14 +37,12 @@ set(SRC blf_py_api.c bpy_internal_import.c idprop_py_api.c - noise_py_api.c py_capi_utils.c bgl.h blf_py_api.h bpy_internal_import.h idprop_py_api.h - noise_py_api.h py_capi_utils.h ) diff --git a/source/blender/python/generic/idprop_py_api.c b/source/blender/python/generic/idprop_py_api.c index 73d954057c9..c31dadff3e1 100644 --- a/source/blender/python/generic/idprop_py_api.c +++ b/source/blender/python/generic/idprop_py_api.c @@ -151,9 +151,9 @@ PyObject *BPy_IDGroup_WrapData(ID *id, IDProperty *prop, IDProperty *parent) case IDP_GROUP: return idprop_py_from_idp_group(id, prop, parent); case IDP_ARRAY: - return idprop_py_from_idp_idparray(id, prop); + return idprop_py_from_idp_array(id, prop); case IDP_IDPARRAY: /* this could be better a internal type */ - idprop_py_from_idp_array(id, prop); + return idprop_py_from_idp_idparray(id, prop); default: Py_RETURN_NONE; } diff --git a/source/blender/python/generic/noise_py_api.c b/source/blender/python/generic/noise_py_api.c deleted file mode 100644 index 902e64eb7c1..00000000000 --- a/source/blender/python/generic/noise_py_api.c +++ /dev/null @@ -1,792 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * This is a new part of Blender. - * - * Contributor(s): eeshlo, Campbell Barton - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/python/generic/noise_py_api.c - * \ingroup pygen - * - * This file defines the 'noise' module, a general purpose module to access - * blenders noise functions. - */ - - -/************************/ -/* Blender Noise Module */ -/************************/ - -#include <Python.h> - -#include "structseq.h" - -#include "BLI_blenlib.h" -#include "BLI_utildefines.h" - -#include "DNA_texture_types.h" - -#include "noise_py_api.h" - -/*-----------------------------------------*/ -/* 'mersenne twister' random number generator */ - -/* - A C-program for MT19937, with initialization improved 2002/2/10. - Coded by Takuji Nishimura and Makoto Matsumoto. - This is a faster version by taking Shawn Cokus's optimization, - Matthe Bellew's simplification, Isaku Wada's real version. - - Before using, initialize the state by using init_genrand(seed) - or init_by_array(init_key, key_length). - - Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - 3. The names of its contributors may not be used to endorse or promote - products derived from this software without specific prior written - permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - - Any feedback is very welcome. - http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html - email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space) -*/ - -/* 2.5 update - * Noise.setRandomSeed --> seed_set - * Noise.randuvec --> random_unit_vector - * Noise.vNoise --> noise_vector - * Noise.vTurbulence --> turbulence_vector - * Noise.multiFractal --> multi_fractal - * Noise.cellNoise --> cell - * Noise.cellNoiseV --> cell_vector - * Noise.vlNoise --> vl_vector - * Noise.heteroTerrain --> hetero_terrain - * Noise.hybridMFractal --> hybrid_multi_fractal - * Noise.fBm --> fractal - * Noise.ridgedMFractal --> ridged_multi_fractal - * - * Const's * - * Noise.NoiseTypes --> types - * Noise.DistanceMetrics --> distance_metrics - */ - -/* Period parameters */ -#define N 624 -#define M 397 -#define MATRIX_A 0x9908b0dfUL /* constant vector a */ -#define UMASK 0x80000000UL /* most significant w-r bits */ -#define LMASK 0x7fffffffUL /* least significant r bits */ -#define MIXBITS(u,v) (((u) & UMASK) | ((v) & LMASK)) -#define TWIST(u,v) ((MIXBITS(u,v) >> 1) ^ ((v)&1UL ? MATRIX_A : 0UL)) - -static unsigned long state[N]; /* the array for the state vector */ -static int left = 1; -static int initf = 0; -static unsigned long *next; - -/* initializes state[N] with a seed */ -static void init_genrand(unsigned long s) -{ - int j; - state[0] = s & 0xffffffffUL; - for (j = 1; j < N; j++) { - state[j] = - (1812433253UL * - (state[j - 1] ^ (state[j - 1] >> 30)) + j); - /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ - /* In the previous versions, MSBs of the seed affect */ - /* only MSBs of the array state[]. */ - /* 2002/01/09 modified by Makoto Matsumoto */ - state[j] &= 0xffffffffUL; /* for >32 bit machines */ - } - left = 1; - initf = 1; -} - -static void next_state(void) -{ - unsigned long *p = state; - int j; - - /* if init_genrand() has not been called, */ - /* a default initial seed is used */ - if (initf == 0) - init_genrand(5489UL); - - left = N; - next = state; - - for (j = N - M + 1; --j; p++) - *p = p[M] ^ TWIST(p[0], p[1]); - - for (j = M; --j; p++) - *p = p[M - N] ^ TWIST(p[0], p[1]); - - *p = p[M - N] ^ TWIST(p[0], state[0]); -} - -/*------------------------------------------------------------*/ - -static void setRndSeed(int seed) -{ - if (seed == 0) - init_genrand(time(NULL)); - else - init_genrand(seed); -} - -/* float number in range [0, 1) using the mersenne twister rng */ -static float frand(void) -{ - unsigned long y; - - if (--left == 0) - next_state(); - y = *next++; - - /* Tempering */ - y ^= (y >> 11); - y ^= (y << 7) & 0x9d2c5680UL; - y ^= (y << 15) & 0xefc60000UL; - y ^= (y >> 18); - - return (float) y / 4294967296.f; -} - -/*------------------------------------------------------------*/ - -/* returns random unit vector */ -static void randuvec(float v[3]) -{ - float r; - v[2] = 2.f * frand() - 1.f; - if ((r = 1.f - v[2] * v[2]) > 0.f) { - float a = (float)(6.283185307f * frand()); - r = (float)sqrt(r); - v[0] = (float)(r * cosf(a)); - v[1] = (float)(r * sinf(a)); - } - else { - v[2] = 1.f; - } -} - -static PyObject *Noise_random(PyObject *UNUSED(self)) -{ - return PyFloat_FromDouble(frand()); -} - -static PyObject *Noise_random_unit_vector(PyObject *UNUSED(self)) -{ - float v[3] = {0.0f, 0.0f, 0.0f}; - randuvec(v); - return Py_BuildValue("[fff]", v[0], v[1], v[2]); -} - -/*---------------------------------------------------------------------*/ - -/* Random seed init. Only used for MT random() & randuvec() */ - -static PyObject *Noise_seed_set(PyObject *UNUSED(self), PyObject *args) -{ - int s; - if (!PyArg_ParseTuple(args, "i:seed_set", &s)) - return NULL; - setRndSeed(s); - Py_RETURN_NONE; -} - -/*-------------------------------------------------------------------------*/ - -/* General noise */ - -static PyObject *Noise_noise(PyObject *UNUSED(self), PyObject *args) -{ - float x, y, z; - int nb = 1; - if (!PyArg_ParseTuple(args, "(fff)|i:noise", &x, &y, &z, &nb)) - return NULL; - - return PyFloat_FromDouble((2.0f * BLI_gNoise(1.0f, x, y, z, 0, nb) - 1.0f)); -} - -/*-------------------------------------------------------------------------*/ - -/* General Vector noise */ - -static void noise_vector(float x, float y, float z, int nb, float v[3]) -{ - /* Simply evaluate noise at 3 different positions */ - v[0]= (float)(2.0f * BLI_gNoise(1.f, x + 9.321f, y - 1.531f, z - 7.951f, 0, - nb) - 1.0f); - v[1]= (float)(2.0f * BLI_gNoise(1.f, x, y, z, 0, nb) - 1.0f); - v[2]= (float)(2.0f * BLI_gNoise(1.f, x + 6.327f, y + 0.1671f, z - 2.672f, 0, - nb) - 1.0f); -} - -static PyObject *Noise_vector(PyObject *UNUSED(self), PyObject *args) -{ - float x, y, z, v[3]; - int nb = 1; - if (!PyArg_ParseTuple(args, "(fff)|i:vector", &x, &y, &z, &nb)) - return NULL; - noise_vector(x, y, z, nb, v); - return Py_BuildValue("[fff]", v[0], v[1], v[2]); -} - -/*---------------------------------------------------------------------------*/ - -/* General turbulence */ - -static float turb(float x, float y, float z, int oct, int hard, int nb, - float ampscale, float freqscale) -{ - float amp, out, t; - int i; - amp = 1.f; - out = (float)(2.0f * BLI_gNoise(1.f, x, y, z, 0, nb) - 1.0f); - if (hard) - out = fabsf(out); - for (i = 1; i < oct; i++) { - amp *= ampscale; - x *= freqscale; - y *= freqscale; - z *= freqscale; - t = (float)(amp * (2.0f * BLI_gNoise(1.f, x, y, z, 0, nb) - 1.0f)); - if (hard) - t = fabsf(t); - out += t; - } - return out; -} - -static PyObject *Noise_turbulence(PyObject *UNUSED(self), PyObject *args) -{ - float x, y, z; - int oct, hd, nb = 1; - float as = 0.5, fs = 2.0; - if (!PyArg_ParseTuple(args, "(fff)ii|iff:turbulence", &x, &y, &z, &oct, &hd, &nb, &as, &fs)) - return NULL; - - return PyFloat_FromDouble(turb(x, y, z, oct, hd, nb, as, fs)); -} - -/*--------------------------------------------------------------------------*/ - -/* Turbulence Vector */ - -static void vTurb(float x, float y, float z, int oct, int hard, int nb, - float ampscale, float freqscale, float v[3]) -{ - float amp, t[3]; - int i; - amp = 1.f; - noise_vector(x, y, z, nb, v); - if (hard) { - v[0] = fabsf(v[0]); - v[1] = fabsf(v[1]); - v[2] = fabsf(v[2]); - } - for (i = 1; i < oct; i++) { - amp *= ampscale; - x *= freqscale; - y *= freqscale; - z *= freqscale; - noise_vector(x, y, z, nb, t); - if (hard) { - t[0] = fabsf(t[0]); - t[1] = fabsf(t[1]); - t[2] = fabsf(t[2]); - } - v[0] += amp * t[0]; - v[1] += amp * t[1]; - v[2] += amp * t[2]; - } -} - -static PyObject *Noise_turbulence_vector(PyObject *UNUSED(self), PyObject *args) -{ - float x, y, z, v[3]; - int oct, hd, nb = 1; - float as = 0.5, fs = 2.0; - if (!PyArg_ParseTuple(args, "(fff)ii|iff:turbulence_vector", &x, &y, &z, &oct, &hd, &nb, &as, &fs)) - return NULL; - vTurb(x, y, z, oct, hd, nb, as, fs, v); - return Py_BuildValue("[fff]", v[0], v[1], v[2]); -} - -/*---------------------------------------------------------------------*/ - -/* F. Kenton Musgrave's fractal functions */ - -static PyObject *Noise_fractal(PyObject *UNUSED(self), PyObject *args) -{ - float x, y, z, H, lac, oct; - int nb = 1; - if (!PyArg_ParseTuple(args, "(fff)fff|i:fractal", &x, &y, &z, &H, &lac, &oct, &nb)) - return NULL; - return PyFloat_FromDouble(mg_fBm(x, y, z, H, lac, oct, nb)); -} - -/*------------------------------------------------------------------------*/ - -static PyObject *Noise_multi_fractal(PyObject *UNUSED(self), PyObject *args) -{ - float x, y, z, H, lac, oct; - int nb = 1; - if (!PyArg_ParseTuple(args, "(fff)fff|i:multi_fractal", &x, &y, &z, &H, &lac, &oct, &nb)) - return NULL; - - return PyFloat_FromDouble(mg_MultiFractal(x, y, z, H, lac, oct, nb)); -} - -/*------------------------------------------------------------------------*/ - -static PyObject *Noise_vl_vector(PyObject *UNUSED(self), PyObject *args) -{ - float x, y, z, d; - int nt1 = 1, nt2 = 1; - if (!PyArg_ParseTuple(args, "(fff)f|ii:vl_vector", &x, &y, &z, &d, &nt1, &nt2)) - return NULL; - return PyFloat_FromDouble(mg_VLNoise(x, y, z, d, nt1, nt2)); -} - -/*-------------------------------------------------------------------------*/ - -static PyObject *Noise_hetero_terrain(PyObject *UNUSED(self), PyObject *args) -{ - float x, y, z, H, lac, oct, ofs; - int nb = 1; - if (!PyArg_ParseTuple(args, "(fff)ffff|i:hetero_terrain", &x, &y, &z, &H, &lac, &oct, &ofs, &nb)) - return NULL; - - return PyFloat_FromDouble(mg_HeteroTerrain(x, y, z, H, lac, oct, ofs, nb)); -} - -/*-------------------------------------------------------------------------*/ - -static PyObject *Noise_hybrid_multi_fractal(PyObject *UNUSED(self), PyObject *args) -{ - float x, y, z, H, lac, oct, ofs, gn; - int nb = 1; - if (!PyArg_ParseTuple(args, "(fff)fffff|i:hybrid_multi_fractal", &x, &y, &z, &H, &lac, &oct, &ofs, &gn, &nb)) - return NULL; - - return PyFloat_FromDouble(mg_HybridMultiFractal(x, y, z, H, lac, oct, ofs, gn, nb)); -} - -/*------------------------------------------------------------------------*/ - -static PyObject *Noise_ridged_multi_fractal(PyObject *UNUSED(self), PyObject *args) -{ - float x, y, z, H, lac, oct, ofs, gn; - int nb = 1; - if (!PyArg_ParseTuple(args, "(fff)fffff|i:ridged_multi_fractal", &x, &y, &z, &H, &lac, &oct, &ofs, &gn, &nb)) - return NULL; - return PyFloat_FromDouble(mg_RidgedMultiFractal(x, y, z, H, lac, oct, ofs, gn, nb)); -} - -/*-------------------------------------------------------------------------*/ - -static PyObject *Noise_voronoi(PyObject *UNUSED(self), PyObject *args) -{ - float x, y, z, da[4], pa[12]; - int dtype = 0; - float me = 2.5; /* default minkovsky exponent */ - if (!PyArg_ParseTuple(args, "(fff)|if:voronoi", &x, &y, &z, &dtype, &me)) - return NULL; - voronoi(x, y, z, da, pa, me, dtype); - return Py_BuildValue("[[ffff][[fff][fff][fff][fff]]]", - da[0], da[1], da[2], da[3], - pa[0], pa[1], pa[2], - pa[3], pa[4], pa[5], - pa[6], pa[7], pa[8], pa[9], pa[10], pa[11]); -} - -/*-------------------------------------------------------------------------*/ - -static PyObject *Noise_cell(PyObject *UNUSED(self), PyObject *args) -{ - float x, y, z; - if (!PyArg_ParseTuple(args, "(fff):cell", &x, &y, &z)) - return NULL; - - return PyFloat_FromDouble(cellNoise(x, y, z)); -} - -/*--------------------------------------------------------------------------*/ - -static PyObject *Noise_cell_vector(PyObject *UNUSED(self), PyObject *args) -{ - float x, y, z, ca[3]; - if (!PyArg_ParseTuple(args, "(fff):cell_vector", &x, &y, &z)) - return NULL; - cellNoiseV(x, y, z, ca); - return Py_BuildValue("[fff]", ca[0], ca[1], ca[2]); -} - -/*--------------------------------------------------------------------------*/ -/* For all other Blender modules, this stuff seems to be put in a header file. - This doesn't seem really appropriate to me, so I just put it here, feel free to change it. - In the original module I actually kept the docs stings with the functions themselves, - but I grouped them here so that it can easily be moved to a header if anyone thinks that is necessary. */ - -PyDoc_STRVAR(random__doc__, -"() No arguments.\n\n\ -Returns a random floating point number in the range [0, 1)" -); - -PyDoc_STRVAR(random_unit_vector__doc__, -"() No arguments.\n\nReturns a random unit vector (3-float list)." -); - -PyDoc_STRVAR(seed_set__doc__, -"(seed value)\n\n\ -Initializes random number generator.\n\ -if seed is zero, the current time will be used instead." -); - -PyDoc_STRVAR(noise__doc__, -"((x,y,z) tuple, [noisetype])\n\n\ -Returns general noise of the optional specified type.\n\ -Optional argument noisetype determines the type of noise, STDPERLIN by default, see NoiseTypes." -); - -PyDoc_STRVAR(noise_vector__doc__, -"((x,y,z) tuple, [noisetype])\n\n\ -Returns noise vector (3-float list) of the optional specified type.\ -Optional argument noisetype determines the type of noise, STDPERLIN by default, see NoiseTypes." -); - -PyDoc_STRVAR(turbulence__doc__, -"((x,y,z) tuple, octaves, hard, [noisebasis], [ampscale], [freqscale])\n\n\ -Returns general turbulence value using the optional specified noisebasis function.\n\ -octaves (integer) is the number of noise values added.\n\ -hard (bool), when false (0) returns 'soft' noise, when true (1) returns 'hard' noise (returned value always positive).\n\ -Optional arguments:\n\ -noisebasis determines the type of noise used for the turbulence, STDPERLIN by default, see NoiseTypes.\n\ -ampscale sets the amplitude scale value of the noise frequencies added, 0.5 by default.\n\ -freqscale sets the frequency scale factor, 2.0 by default." -); - -PyDoc_STRVAR(turbulence_vector__doc__, -"((x,y,z) tuple, octaves, hard, [noisebasis], [ampscale], [freqscale])\n\n\ -Returns general turbulence vector (3-float list) using the optional specified noisebasis function.\n\ -octaves (integer) is the number of noise values added.\n\ -hard (bool), when false (0) returns 'soft' noise, when true (1) returns 'hard' noise (returned vector always positive).\n\ -Optional arguments:\n\ -noisebasis determines the type of noise used for the turbulence, STDPERLIN by default, see NoiseTypes.\n\ -ampscale sets the amplitude scale value of the noise frequencies added, 0.5 by default.\n\ -freqscale sets the frequency scale factor, 2.0 by default." -); - -PyDoc_STRVAR(fractal__doc__, -"((x,y,z) tuple, H, lacunarity, octaves, [noisebasis])\n\n\ -Returns Fractal Brownian Motion noise value(fBm).\n\ -H is the fractal increment parameter.\n\ -lacunarity is the gap between successive frequencies.\n\ -octaves is the number of frequencies in the fBm.\n\ -Optional argument noisebasis determines the type of noise used for the turbulence, STDPERLIN by default, see NoiseTypes." -); - -PyDoc_STRVAR(multi_fractal__doc__, -"((x,y,z) tuple, H, lacunarity, octaves, [noisebasis])\n\n\ -Returns Multifractal noise value.\n\ -H determines the highest fractal dimension.\n\ -lacunarity is gap between successive frequencies.\n\ -octaves is the number of frequencies in the fBm.\n\ -Optional argument noisebasis determines the type of noise used for the turbulence, STDPERLIN by default, see NoiseTypes." -); - -PyDoc_STRVAR(vl_vector__doc__, -"((x,y,z) tuple, distortion, [noisetype1], [noisetype2])\n\n\ -Returns Variable Lacunarity Noise value, a distorted variety of noise.\n\ -distortion sets the amount of distortion.\n\ -Optional arguments noisetype1 and noisetype2 set the noisetype to distort and the noisetype used for the distortion respectively.\n\ -See NoiseTypes, both are STDPERLIN by default." -); - -PyDoc_STRVAR(hetero_terrain__doc__, -"((x,y,z) tuple, H, lacunarity, octaves, offset, [noisebasis])\n\n\ -returns Heterogeneous Terrain value\n\ -H determines the fractal dimension of the roughest areas.\n\ -lacunarity is the gap between successive frequencies.\n\ -octaves is the number of frequencies in the fBm.\n\ -offset raises the terrain from 'sea level'.\n\ -Optional argument noisebasis determines the type of noise used for the turbulence, STDPERLIN by default, see NoiseTypes." -); - -PyDoc_STRVAR(hybrid_multi_fractal__doc__, -"((x,y,z) tuple, H, lacunarity, octaves, offset, gain, [noisebasis])\n\n\ -returns Hybrid Multifractal value.\n\ -H determines the fractal dimension of the roughest areas.\n\ -lacunarity is the gap between successive frequencies.\n\ -octaves is the number of frequencies in the fBm.\n\ -offset raises the terrain from 'sea level'.\n\ -gain scales the values.\n\ -Optional argument noisebasis determines the type of noise used for the turbulence, STDPERLIN by default, see NoiseTypes." -); - -PyDoc_STRVAR(ridged_multi_fractal__doc__, -"((x,y,z) tuple, H, lacunarity, octaves, offset, gain [noisebasis])\n\n\ -returns Ridged Multifractal value.\n\ -H determines the fractal dimension of the roughest areas.\n\ -lacunarity is the gap between successive frequencies.\n\ -octaves is the number of frequencies in the fBm.\n\ -offset raises the terrain from 'sea level'.\n\ -gain scales the values.\n\ -Optional argument noisebasis determines the type of noise used for the turbulence, STDPERLIN by default, see NoiseTypes." -); - -PyDoc_STRVAR(voronoi__doc__, -"((x,y,z) tuple, distance_metric, [exponent])\n\n\ -returns a list, containing a list of distances in order of closest feature,\n\ -and a list containing the positions of the four closest features\n\ -Optional arguments:\n\ -distance_metric: see DistanceMetrics, default is DISTANCE\n\ -exponent is only used with MINKOVSKY, default is 2.5." -); - -PyDoc_STRVAR(cell__doc__, -"((x,y,z) tuple)\n\n\ -returns cellnoise float value." -); - -PyDoc_STRVAR(cell_vector__doc__, -"((x,y,z) tuple)\n\n\ -returns cellnoise vector/point/color (3-float list)." -); - -PyDoc_STRVAR(Noise__doc__, -"Blender Noise and Turbulence Module\n\n\ -This module can be used to generate noise of various types.\n\ -This can be used for terrain generation, to create textures,\n\ -make animations more 'animated', object deformation, etc.\n\ -As an example, this code segment when scriptlinked to a framechanged event,\n\ -will make the camera sway randomly about, by changing parameters this can\n\ -look like anything from an earthquake to a very nervous or maybe even drunk cameraman...\n\ -(the camera needs an ipo with at least one Loc & Rot key for this to work!):\n\ -\n\ -\tfrom Blender import Get, Scene, Noise\n\ -\n\ -\t####################################################\n\ -\t# This controls jitter speed\n\ -\tsl = 0.025\n\ -\t# This controls the amount of position jitter\n\ -\tsp = 0.1\n\ -\t# This controls the amount of rotation jitter\n\ -\tsr = 0.25\n\ -\t####################################################\n\ -\n\ -\ttime = Get('curtime')\n\ -\tob = Scene.GetCurrent().getCurrentCamera()\n\ -\tps = (sl*time, sl*time, sl*time)\n\ -\t# To add jitter only when the camera moves, use this next line instead\n\ -\t#ps = (sl*ob.LocX, sl*ob.LocY, sl*ob.LocZ)\n\ -\trv = Noise.turbulence_vector(ps, 3, 0, Noise.NoiseTypes.NEWPERLIN)\n\ -\tob.dloc = (sp*rv[0], sp*rv[1], sp*rv[2])\n\ -\tob.drot = (sr*rv[0], sr*rv[1], sr*rv[2])\n\ -\n" -); - -/* Just in case, declarations for a header file */ -/* -static PyObject *Noise_random(PyObject *UNUSED(self)); -static PyObject *Noise_random_unit_vector(PyObject *UNUSED(self)); -static PyObject *Noise_seed_set(PyObject *UNUSED(self), PyObject *args); -static PyObject *Noise_noise(PyObject *UNUSED(self), PyObject *args); -static PyObject *Noise_vector(PyObject *UNUSED(self), PyObject *args); -static PyObject *Noise_turbulence(PyObject *UNUSED(self), PyObject *args); -static PyObject *Noise_turbulence_vector(PyObject *UNUSED(self), PyObject *args); -static PyObject *Noise_fractal(PyObject *UNUSED(self), PyObject *args); -static PyObject *Noise_multi_fractal(PyObject *UNUSED(self), PyObject *args); -static PyObject *Noise_vl_vector(PyObject *UNUSED(self), PyObject *args); -static PyObject *Noise_hetero_terrain(PyObject *UNUSED(self), PyObject *args); -static PyObject *Noise_hybrid_multi_fractal(PyObject *UNUSED(self), PyObject *args); -static PyObject *Noise_ridged_multi_fractal(PyObject *UNUSED(self), PyObject *args); -static PyObject *Noise_voronoi(PyObject *UNUSED(self), PyObject *args); -static PyObject *Noise_cell(PyObject *UNUSED(self), PyObject *args); -static PyObject *Noise_cell_vector(PyObject *UNUSED(self), PyObject *args); -*/ - -static PyMethodDef NoiseMethods[] = { - {"seed_set", (PyCFunction) Noise_seed_set, METH_VARARGS, seed_set__doc__}, - {"random", (PyCFunction) Noise_random, METH_NOARGS, random__doc__}, - {"random_unit_vector", (PyCFunction) Noise_random_unit_vector, METH_NOARGS, random_unit_vector__doc__}, - {"noise", (PyCFunction) Noise_noise, METH_VARARGS, noise__doc__}, - {"vector", (PyCFunction) Noise_vector, METH_VARARGS, noise_vector__doc__}, - {"turbulence", (PyCFunction) Noise_turbulence, METH_VARARGS, turbulence__doc__}, - {"turbulence_vector", (PyCFunction) Noise_turbulence_vector, METH_VARARGS, turbulence_vector__doc__}, - {"fractal", (PyCFunction) Noise_fractal, METH_VARARGS, fractal__doc__}, - {"multi_fractal", (PyCFunction) Noise_multi_fractal, METH_VARARGS, multi_fractal__doc__}, - {"vl_vector", (PyCFunction) Noise_vl_vector, METH_VARARGS, vl_vector__doc__}, - {"hetero_terrain", (PyCFunction) Noise_hetero_terrain, METH_VARARGS, hetero_terrain__doc__}, - {"hybrid_multi_fractal", (PyCFunction) Noise_hybrid_multi_fractal, METH_VARARGS, hybrid_multi_fractal__doc__}, - {"ridged_multi_fractal", (PyCFunction) Noise_ridged_multi_fractal, METH_VARARGS, ridged_multi_fractal__doc__}, - {"voronoi", (PyCFunction) Noise_voronoi, METH_VARARGS, voronoi__doc__}, - {"cell", (PyCFunction) Noise_cell, METH_VARARGS, cell__doc__}, - {"cell_vector", (PyCFunction) Noise_cell_vector, METH_VARARGS, cell_vector__doc__}, - {NULL, NULL, 0, NULL} -}; - -/*----------------------------------------------------------------------*/ - -static struct PyModuleDef noise_module_def = { - PyModuleDef_HEAD_INIT, - "noise", /* m_name */ - Noise__doc__, /* m_doc */ - 0, /* m_size */ - NoiseMethods, /* m_methods */ - NULL, /* m_reload */ - NULL, /* m_traverse */ - NULL, /* m_clear */ - NULL, /* m_free */ -}; - -PyObject *BPyInit_noise(void) -{ - PyObject *submodule = PyModule_Create(&noise_module_def); - - /* use current time as seed for random number generator by default */ - setRndSeed(0); - - /* Constant noisetype dictionary */ - if (submodule) { - static PyStructSequence_Field noise_types_fields[] = { - {(char *)"BLENDER", NULL}, - {(char *)"STDPERLIN", NULL}, - {(char *)"NEWPERLIN", NULL}, - {(char *)"VORONOI_F1", NULL}, - {(char *)"VORONOI_F2", NULL}, - {(char *)"VORONOI_F3", NULL}, - {(char *)"VORONOI_F4", NULL}, - {(char *)"VORONOI_F2F1", NULL}, - {(char *)"VORONOI_CRACKLE", NULL}, - {(char *)"CELLNOISE", NULL}, - {NULL} - }; - - static PyStructSequence_Desc noise_types_info_desc = { - (char *)"noise.types", /* name */ - (char *)"Noise type", /* doc */ - noise_types_fields, /* fields */ - (sizeof(noise_types_fields)/sizeof(PyStructSequence_Field)) - 1 - }; - - static PyTypeObject NoiseType; - - PyObject *noise_types; - - int pos = 0; - - PyStructSequence_InitType(&NoiseType, &noise_types_info_desc); - - noise_types = PyStructSequence_New(&NoiseType); - if (noise_types == NULL) { - return NULL; - } - - PyStructSequence_SET_ITEM(noise_types, pos++, PyLong_FromLong(TEX_BLENDER)); - PyStructSequence_SET_ITEM(noise_types, pos++, PyLong_FromLong(TEX_STDPERLIN)); - PyStructSequence_SET_ITEM(noise_types, pos++, PyLong_FromLong(TEX_NEWPERLIN)); - PyStructSequence_SET_ITEM(noise_types, pos++, PyLong_FromLong(TEX_VORONOI_F1)); - PyStructSequence_SET_ITEM(noise_types, pos++, PyLong_FromLong(TEX_VORONOI_F2)); - PyStructSequence_SET_ITEM(noise_types, pos++, PyLong_FromLong(TEX_VORONOI_F3)); - PyStructSequence_SET_ITEM(noise_types, pos++, PyLong_FromLong(TEX_VORONOI_F4)); - PyStructSequence_SET_ITEM(noise_types, pos++, PyLong_FromLong(TEX_VORONOI_F2F1)); - PyStructSequence_SET_ITEM(noise_types, pos++, PyLong_FromLong(TEX_VORONOI_CRACKLE)); - PyStructSequence_SET_ITEM(noise_types, pos++, PyLong_FromLong(TEX_CELLNOISE)); - - PyModule_AddObject(submodule, "types", noise_types); - } - - if (submodule) { - static PyStructSequence_Field distance_metrics_fields[] = { - {(char *)"DISTANCE", NULL}, - {(char *)"DISTANCE_SQUARED", NULL}, - {(char *)"MANHATTAN", NULL}, - {(char *)"CHEBYCHEV", NULL}, - {(char *)"MINKOVSKY_HALF", NULL}, - {(char *)"MINKOVSKY_FOUR", NULL}, - {(char *)"MINKOVSKY", NULL}, - {NULL} - }; - - static PyStructSequence_Desc noise_types_info_desc = { - (char *)"noise.distance_metrics", /* name */ - (char *)"Distance Metrics for noise module.", /* doc */ - distance_metrics_fields, /* fields */ - (sizeof(distance_metrics_fields)/sizeof(PyStructSequence_Field)) - 1 - }; - - static PyTypeObject DistanceMetrics; - - PyObject *distance_metrics; - - int pos = 0; - - PyStructSequence_InitType(&DistanceMetrics, &noise_types_info_desc); - - distance_metrics = PyStructSequence_New(&DistanceMetrics); - if (distance_metrics == NULL) { - return NULL; - } - - PyStructSequence_SET_ITEM(distance_metrics, pos++, PyLong_FromLong(TEX_DISTANCE)); - PyStructSequence_SET_ITEM(distance_metrics, pos++, PyLong_FromLong(TEX_DISTANCE_SQUARED)); - PyStructSequence_SET_ITEM(distance_metrics, pos++, PyLong_FromLong(TEX_MANHATTAN)); - PyStructSequence_SET_ITEM(distance_metrics, pos++, PyLong_FromLong(TEX_CHEBYCHEV)); - PyStructSequence_SET_ITEM(distance_metrics, pos++, PyLong_FromLong(TEX_MINKOVSKY_HALF)); - PyStructSequence_SET_ITEM(distance_metrics, pos++, PyLong_FromLong(TEX_MINKOVSKY_FOUR)); - PyStructSequence_SET_ITEM(distance_metrics, pos++, PyLong_FromLong(TEX_MINKOVSKY)); - - PyModule_AddObject(submodule, "distance_metrics", distance_metrics); - } - - return submodule; -} diff --git a/source/blender/python/intern/bpy.c b/source/blender/python/intern/bpy.c index d2d9c51643f..81882317244 100644 --- a/source/blender/python/intern/bpy.c +++ b/source/blender/python/intern/bpy.c @@ -205,10 +205,14 @@ static PyObject *bpy_resource_path(PyObject *UNUSED(self), PyObject *args, PyObj return PyUnicode_DecodeFSDefault(path); } -static PyMethodDef meth_bpy_script_paths= {"script_paths", (PyCFunction)bpy_script_paths, METH_NOARGS, bpy_script_paths_doc}; -static PyMethodDef meth_bpy_blend_paths= {"blend_paths", (PyCFunction)bpy_blend_paths, METH_VARARGS|METH_KEYWORDS, bpy_blend_paths_doc}; -static PyMethodDef meth_bpy_user_resource= {"user_resource", (PyCFunction)bpy_user_resource, METH_VARARGS|METH_KEYWORDS, NULL}; -static PyMethodDef meth_bpy_resource_path= {"resource_path", (PyCFunction)bpy_resource_path, METH_VARARGS|METH_KEYWORDS, bpy_resource_path_doc}; +static PyMethodDef meth_bpy_script_paths= + {"script_paths", (PyCFunction)bpy_script_paths, METH_NOARGS, bpy_script_paths_doc}; +static PyMethodDef meth_bpy_blend_paths= + {"blend_paths", (PyCFunction)bpy_blend_paths, METH_VARARGS|METH_KEYWORDS, bpy_blend_paths_doc}; +static PyMethodDef meth_bpy_user_resource= + {"user_resource", (PyCFunction)bpy_user_resource, METH_VARARGS|METH_KEYWORDS, NULL}; +static PyMethodDef meth_bpy_resource_path= + {"resource_path", (PyCFunction)bpy_resource_path, METH_VARARGS|METH_KEYWORDS, bpy_resource_path_doc}; static PyObject *bpy_import_test(const char *modname) @@ -260,16 +264,21 @@ void BPy_init_modules(void) /* run first, initializes rna types */ BPY_rna_init(); - PyModule_AddObject(mod, "types", BPY_rna_types()); /* needs to be first so bpy_types can run */ - PyModule_AddObject(mod, "StructMetaPropGroup", (PyObject *)&pyrna_struct_meta_idprop_Type); /* metaclass for idprop types, bpy_types.py needs access */ + /* needs to be first so bpy_types can run */ + PyModule_AddObject(mod, "types", BPY_rna_types()); - bpy_lib_init(mod); /* adds '_bpy._library_load', must be called before 'bpy_types' which uses it */ + /* metaclass for idprop types, bpy_types.py needs access */ + PyModule_AddObject(mod, "StructMetaPropGroup", (PyObject *)&pyrna_struct_meta_idprop_Type); + + /* needs to be first so bpy_types can run */ + bpy_lib_init(mod); bpy_import_test("bpy_types"); PyModule_AddObject(mod, "data", BPY_rna_module()); /* imports bpy_types by running this */ bpy_import_test("bpy_types"); - PyModule_AddObject(mod, "props", BPY_rna_props()); - PyModule_AddObject(mod, "ops", BPY_operator_module()); /* ops is now a python module that does the conversion from SOME_OT_foo -> some.foo */ + PyModule_AddObject(mod, "props", BPY_rna_props()); + /* ops is now a python module that does the conversion from SOME_OT_foo -> some.foo */ + PyModule_AddObject(mod, "ops", BPY_operator_module()); PyModule_AddObject(mod, "app", BPY_app_struct()); /* bpy context */ diff --git a/source/blender/python/intern/bpy_app.c b/source/blender/python/intern/bpy_app.c index b5ae225fda7..1f99503202a 100644 --- a/source/blender/python/intern/bpy_app.c +++ b/source/blender/python/intern/bpy_app.c @@ -159,6 +159,10 @@ static PyObject *make_app_info(void) /* a few getsets because it makes sense for them to be in bpy.app even though * they are not static */ + +PyDoc_STRVAR(bpy_app_debug_doc, +"Boolean, set when blender is running in debug mode (started with --debug)" +); static PyObject *bpy_app_debug_get(PyObject *UNUSED(self), void *UNUSED(closure)) { return PyBool_FromLong(G.f & G_DEBUG); @@ -179,6 +183,9 @@ static int bpy_app_debug_set(PyObject *UNUSED(self), PyObject *value, void *UNUS return 0; } +PyDoc_STRVAR(bpy_app_debug_value_doc, +"Int, number which can be set to non-zero values for testing purposes" +); static PyObject *bpy_app_debug_value_get(PyObject *UNUSED(self), void *UNUSED(closure)) { return PyLong_FromSsize_t(G.rt); @@ -198,11 +205,17 @@ static int bpy_app_debug_value_set(PyObject *UNUSED(self), PyObject *value, void return 0; } +PyDoc_STRVAR(bpy_app_tempdir_doc, +"String, the temp directory used by blender (read-only)" +); static PyObject *bpy_app_tempdir_get(PyObject *UNUSED(self), void *UNUSED(closure)) { return PyC_UnicodeFromByte(BLI_temporary_dir()); } +PyDoc_STRVAR(bpy_app_driver_dict_doc, +"Dictionary for drivers namespace, editable in-place, reset on file load (read-only)" +); static PyObject *bpy_app_driver_dict_get(PyObject *UNUSED(self), void *UNUSED(closure)) { if (bpy_pydriver_Dict == NULL) @@ -217,10 +230,10 @@ static PyObject *bpy_app_driver_dict_get(PyObject *UNUSED(self), void *UNUSED(cl static PyGetSetDef bpy_app_getsets[]= { - {(char *)"debug", bpy_app_debug_get, bpy_app_debug_set, (char *)"Boolean, set when blender is running in debug mode (started with -d)", NULL}, - {(char *)"debug_value", bpy_app_debug_value_get, bpy_app_debug_value_set, (char *)"Int, number which can be set to non-zero values for testing purposes.", NULL}, - {(char *)"tempdir", bpy_app_tempdir_get, NULL, (char *)"String, the temp directory used by blender (read-only)", NULL}, - {(char *)"driver_namespace", bpy_app_driver_dict_get, NULL, (char *)"Dictionary for drivers namespace, editable in-place, reset on file load (read-only)", NULL}, + {(char *)"debug", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, NULL}, + {(char *)"debug_value", bpy_app_debug_value_get, bpy_app_debug_value_set, (char *)bpy_app_debug_value_doc, NULL}, + {(char *)"tempdir", bpy_app_tempdir_get, NULL, (char *)bpy_app_tempdir_doc, NULL}, + {(char *)"driver_namespace", bpy_app_driver_dict_get, NULL, (char *)bpy_app_driver_dict_doc, NULL}, {NULL, NULL, NULL, NULL, NULL} }; @@ -253,4 +266,3 @@ PyObject *BPY_app_struct(void) return ret; } - diff --git a/source/blender/python/intern/bpy_driver.c b/source/blender/python/intern/bpy_driver.c index 2aad4d8f2fe..34270c832ea 100644 --- a/source/blender/python/intern/bpy_driver.c +++ b/source/blender/python/intern/bpy_driver.c @@ -82,7 +82,7 @@ int bpy_pydriver_create_dict(void) } /* add noise to global namespace */ - mod= PyImport_ImportModuleLevel((char *)"noise", NULL, NULL, NULL, 0); + mod= PyImport_ImportModuleLevel((char *)"mathutils.noise", NULL, NULL, NULL, 0); if (mod) { PyDict_SetItemString(bpy_pydriver_Dict, "noise", mod); Py_DECREF(mod); diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c index b7ead49633c..14d74bcf5d0 100644 --- a/source/blender/python/intern/bpy_interface.c +++ b/source/blender/python/intern/bpy_interface.c @@ -71,7 +71,6 @@ /* inittab initialization functions */ #include "../generic/bgl.h" #include "../generic/blf_py_api.h" -#include "../generic/noise_py_api.h" #include "../mathutils/mathutils.h" /* for internal use, when starting and ending python scripts */ @@ -134,9 +133,12 @@ void bpy_context_clear(bContext *UNUSED(C), PyGILState_STATE *gilstate) fprintf(stderr, "ERROR: Python context internal state bug. this should not happen!\n"); } else if (py_call_level==0) { - // XXX - Calling classes currently wont store the context :\, cant set NULL because of this. but this is very flakey still. - //BPy_SetContext(NULL); - //bpy_import_main_set(NULL); + /* XXX - Calling classes currently wont store the context :\, + * cant set NULL because of this. but this is very flakey still. */ +#if 0 + BPy_SetContext(NULL); + bpy_import_main_set(NULL); +#endif #ifdef TIME_PY_RUN bpy_timer_run_tot += PIL_check_seconds_timer() - bpy_timer_run; @@ -178,9 +180,9 @@ extern PyObject *AUD_initPython(void); extern PyObject *CYCLES_initPython(void); static struct _inittab bpy_internal_modules[]= { - {(char *)"noise", BPyInit_noise}, {(char *)"mathutils", PyInit_mathutils}, // {(char *)"mathutils.geometry", PyInit_mathutils_geometry}, +// {(char *)"mathutils.noise", PyInit_mathutils_noise}, {(char *)"bgl", BPyInit_bgl}, {(char *)"blf", BPyInit_blf}, #ifdef WITH_AUDASPACE @@ -329,7 +331,8 @@ typedef struct { } PyModuleObject; #endif -static int python_script_exec(bContext *C, const char *fn, struct Text *text, struct ReportList *reports, const short do_jump) +static int python_script_exec(bContext *C, const char *fn, struct Text *text, + struct ReportList *reports, const short do_jump) { PyObject *main_mod= NULL; PyObject *py_dict= NULL, *py_result= NULL; @@ -717,7 +720,10 @@ void bpy_module_delay_init(PyObject *bpy_proxy) { const int argc= 1; const char *argv[2]; - PyObject *filename_obj= PyModule_GetFilenameObject(bpy_proxy); /* updating the module dict below will loose the reference to __file__ */ + + /* updating the module dict below will loose the reference to __file__ */ + PyObject *filename_obj= PyModule_GetFilenameObject(bpy_proxy); + const char *filename_rel= _PyUnicode_AsString(filename_obj); /* can be relative */ char filename_abs[1024]; diff --git a/source/blender/python/intern/bpy_library.c b/source/blender/python/intern/bpy_library.c index b91948cc0b8..a6426a02e18 100644 --- a/source/blender/python/intern/bpy_library.c +++ b/source/blender/python/intern/bpy_library.c @@ -265,8 +265,8 @@ static PyObject *bpy_lib_enter(BPy_Library *self, PyObject *UNUSED(args)) /* create a dummy */ self_from= PyObject_New(BPy_Library, &bpy_lib_Type); - BLI_strncpy(self_from->relpath, self->relpath, sizeof(BPy_Library)); - BLI_strncpy(self_from->abspath, self->abspath, sizeof(BPy_Library)); + BLI_strncpy(self_from->relpath, self->relpath, sizeof(self_from->relpath)); + BLI_strncpy(self_from->abspath, self->abspath, sizeof(self_from->abspath)); self_from->blo_handle= NULL; self_from->flag= 0; @@ -396,6 +396,7 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args)) return NULL; } else { + Library *lib= mainl->curlib; /* newly added lib, assign before append end */ BLO_library_append_end(NULL, mainl, &(self->blo_handle), 0, self->flag); BLO_blendhandle_close(self->blo_handle); self->blo_handle= NULL; @@ -406,9 +407,7 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args)) /* append, rather than linking */ if ((self->flag & FILE_LINK)==0) { - Library *lib= BLI_findstring(&G.main->library, self->abspath, offsetof(Library, name)); - if (lib) BKE_library_make_local(bmain, lib, 1); - else BLI_assert(!"cant find name of just added library!"); + BKE_library_make_local(bmain, lib, 1); } } @@ -426,7 +425,10 @@ static PyObject *bpy_lib_dir(BPy_Library *self) int bpy_lib_init(PyObject *mod_par) { - static PyMethodDef load_meth= {"load", (PyCFunction)bpy_lib_load, METH_STATIC|METH_VARARGS|METH_KEYWORDS, bpy_lib_load_doc}; + static PyMethodDef load_meth= {"load", (PyCFunction)bpy_lib_load, + METH_STATIC|METH_VARARGS|METH_KEYWORDS, + bpy_lib_load_doc}; + PyModule_AddObject(mod_par, "_library_load", PyCFunction_New(&load_meth, NULL)); /* some compilers dont like accessing this directly, delay assignment */ diff --git a/source/blender/python/intern/bpy_operator.c b/source/blender/python/intern/bpy_operator.c index 3fd4e8a128b..70346a65bf9 100644 --- a/source/blender/python/intern/bpy_operator.c +++ b/source/blender/python/intern/bpy_operator.c @@ -31,11 +31,6 @@ * which fakes exposing operators as modules/functions using its own classes. */ - -/* Note, this module is not to be used directly by the user. - * Internally its exposed as '_bpy.ops', which provides functions for 'bpy.ops', a python package. - * */ - #include <Python.h> #include "RNA_types.h" @@ -78,7 +73,8 @@ static PyObject *pyop_poll(PyObject *UNUSED(self), PyObject *args) int context= WM_OP_EXEC_DEFAULT; - // XXX Todo, work out a better solution for passing on context, could make a tuple from self and pack the name and Context into it... + /* XXX Todo, work out a better solution for passing on context, + * could make a tuple from self and pack the name and Context into it... */ bContext *C= (bContext *)BPy_GetContext(); if (C==NULL) { @@ -152,7 +148,8 @@ static PyObject *pyop_call(PyObject *UNUSED(self), PyObject *args) /* note that context is an int, python does the conversion in this case */ int context= WM_OP_EXEC_DEFAULT; - // XXX Todo, work out a better solution for passing on context, could make a tuple from self and pack the name and Context into it... + /* XXX Todo, work out a better solution for passing on context, + * could make a tuple from self and pack the name and Context into it... */ bContext *C= (bContext *)BPy_GetContext(); if (C==NULL) { diff --git a/source/blender/python/intern/bpy_props.c b/source/blender/python/intern/bpy_props.c index 950aa9458d5..c0d796669d6 100644 --- a/source/blender/python/intern/bpy_props.c +++ b/source/blender/python/intern/bpy_props.c @@ -233,7 +233,7 @@ static void bpy_prop_update_cb(struct bContext *C, struct PointerRNA *ptr, struc static int bpy_prop_callback_check(PyObject *py_func, int argcount) { - if (py_func) { + if (py_func && py_func != Py_None) { if (!PyFunction_Check(py_func)) { PyErr_Format(PyExc_TypeError, "update keyword: expected a function type, not a %.200s", @@ -301,7 +301,7 @@ static int py_long_as_int(PyObject *py_long, int *r_int) if (srna==NULL) { \ if (PyErr_Occurred()) \ return NULL; \ - return bpy_prop_deferred_return((void *)pymeth_##_func, kw); \ + return bpy_prop_deferred_return(pymeth_##_func, kw); \ } \ /* terse macros for error checks shared between all funcs cant use function @@ -370,7 +370,8 @@ static int bpy_struct_id_used(StructRNA *srna, char *identifier) #endif -/* Function that sets RNA, NOTE - self is NULL when called from python, but being abused from C so we can pass the srna along +/* Function that sets RNA, NOTE - self is NULL when called from python, + * but being abused from C so we can pass the srna along. * This isnt incorrect since its a python object - but be careful */ PyDoc_STRVAR(BPy_BoolProperty_doc, ".. function:: BoolProperty(name=\"\", description=\"\", default=False, options={'ANIMATABLE'}, subtype='NONE', update=None)\n" @@ -392,7 +393,8 @@ static PyObject *BPy_BoolProperty(PyObject *self, PyObject *args, PyObject *kw) BPY_PROPDEF_HEAD(BoolProperty) if (srna) { - static const char *kwlist[]= {"attr", "name", "description", "default", "options", "subtype", "update", NULL}; + static const char *kwlist[]= {"attr", "name", "description", "default", + "options", "subtype", "update", NULL}; const char *id=NULL, *name="", *description=""; int id_len; int def=0; @@ -459,7 +461,8 @@ static PyObject *BPy_BoolVectorProperty(PyObject *self, PyObject *args, PyObject BPY_PROPDEF_HEAD(BoolVectorProperty) if (srna) { - static const char *kwlist[]= {"attr", "name", "description", "default", "options", "subtype", "size", "update", NULL}; + static const char *kwlist[]= {"attr", "name", "description", "default", + "options", "subtype", "size", "update", NULL}; const char *id=NULL, *name="", *description=""; int id_len; int def[PYRNA_STACK_ARRAY]={0}; @@ -485,7 +488,9 @@ static PyObject *BPy_BoolVectorProperty(PyObject *self, PyObject *args, PyObject BPY_PROPDEF_SUBTYPE_CHECK(BoolVectorProperty, property_flag_items, property_subtype_array_items) if (size < 1 || size > PYRNA_STACK_ARRAY) { - PyErr_Format(PyExc_TypeError, "BoolVectorProperty(size=%d): size must be between 0 and " STRINGIFY(PYRNA_STACK_ARRAY), size); + PyErr_Format(PyExc_TypeError, + "BoolVectorProperty(size=%d): size must be between 0 and " + STRINGIFY(PYRNA_STACK_ARRAY), size); return NULL; } @@ -534,7 +539,8 @@ static PyObject *BPy_IntProperty(PyObject *self, PyObject *args, PyObject *kw) BPY_PROPDEF_HEAD(IntProperty) if (srna) { - static const char *kwlist[]= {"attr", "name", "description", "default", "min", "max", "soft_min", "soft_max", "step", "options", "subtype", "update", NULL}; + static const char *kwlist[]= {"attr", "name", "description", "default", + "min", "max", "soft_min", "soft_max", "step", "options", "subtype", "update", NULL}; const char *id=NULL, *name="", *description=""; int id_len; int min=INT_MIN, max=INT_MAX, soft_min=INT_MIN, soft_max=INT_MAX, step=1, def=0; @@ -603,7 +609,9 @@ static PyObject *BPy_IntVectorProperty(PyObject *self, PyObject *args, PyObject BPY_PROPDEF_HEAD(IntVectorProperty) if (srna) { - static const char *kwlist[]= {"attr", "name", "description", "default", "min", "max", "soft_min", "soft_max", "step", "options", "subtype", "size", "update", NULL}; + static const char *kwlist[]= {"attr", "name", "description", "default", + "min", "max", "soft_min", "soft_max", + "step", "options", "subtype", "size", "update", NULL}; const char *id=NULL, *name="", *description=""; int id_len; int min=INT_MIN, max=INT_MAX, soft_min=INT_MIN, soft_max=INT_MAX, step=1, def[PYRNA_STACK_ARRAY]={0}; @@ -631,7 +639,9 @@ static PyObject *BPy_IntVectorProperty(PyObject *self, PyObject *args, PyObject BPY_PROPDEF_SUBTYPE_CHECK(IntVectorProperty, property_flag_items, property_subtype_array_items) if (size < 1 || size > PYRNA_STACK_ARRAY) { - PyErr_Format(PyExc_TypeError, "IntVectorProperty(size=%d): size must be between 0 and " STRINGIFY(PYRNA_STACK_ARRAY), size); + PyErr_Format(PyExc_TypeError, + "IntVectorProperty(size=%d): size must be between 0 and " + STRINGIFY(PYRNA_STACK_ARRAY), size); return NULL; } @@ -682,7 +692,9 @@ static PyObject *BPy_FloatProperty(PyObject *self, PyObject *args, PyObject *kw) BPY_PROPDEF_HEAD(FloatProperty) if (srna) { - static const char *kwlist[]= {"attr", "name", "description", "default", "min", "max", "soft_min", "soft_max", "step", "precision", "options", "subtype", "unit", "update", NULL}; + static const char *kwlist[]= {"attr", "name", "description", "default", + "min", "max", "soft_min", "soft_max", + "step", "precision", "options", "subtype", "unit", "update", NULL}; const char *id=NULL, *name="", *description=""; int id_len; float min=-FLT_MAX, max=FLT_MAX, soft_min=-FLT_MAX, soft_max=FLT_MAX, step=3, def=0.0f; @@ -761,7 +773,9 @@ static PyObject *BPy_FloatVectorProperty(PyObject *self, PyObject *args, PyObjec BPY_PROPDEF_HEAD(FloatVectorProperty) if (srna) { - static const char *kwlist[]= {"attr", "name", "description", "default", "min", "max", "soft_min", "soft_max", "step", "precision", "options", "subtype", "unit", "size", "update", NULL}; + static const char *kwlist[]= {"attr", "name", "description", "default", + "min", "max", "soft_min", "soft_max", + "step", "precision", "options", "subtype", "unit", "size", "update", NULL}; const char *id=NULL, *name="", *description=""; int id_len; float min=-FLT_MAX, max=FLT_MAX, soft_min=-FLT_MAX, soft_max=FLT_MAX, step=3, def[PYRNA_STACK_ARRAY]={0.0f}; @@ -796,7 +810,9 @@ static PyObject *BPy_FloatVectorProperty(PyObject *self, PyObject *args, PyObjec } if (size < 1 || size > PYRNA_STACK_ARRAY) { - PyErr_Format(PyExc_TypeError, "FloatVectorProperty(size=%d): size must be between 0 and " STRINGIFY(PYRNA_STACK_ARRAY), size); + PyErr_Format(PyExc_TypeError, + "FloatVectorProperty(size=%d): size must be between 0 and " + STRINGIFY(PYRNA_STACK_ARRAY), size); return NULL; } @@ -845,7 +861,8 @@ static PyObject *BPy_StringProperty(PyObject *self, PyObject *args, PyObject *kw BPY_PROPDEF_HEAD(StringProperty) if (srna) { - static const char *kwlist[]= {"attr", "name", "description", "default", "maxlen", "options", "subtype", "update", NULL}; + static const char *kwlist[]= {"attr", "name", "description", "default", + "maxlen", "options", "subtype", "update", NULL}; const char *id=NULL, *name="", *description="", *def=""; int id_len; int maxlen=0; @@ -913,7 +930,10 @@ static EnumPropertyItem *enum_items_from_py(PyObject *seq_fast, PyObject *def, i if (is_enum_flag) { if (seq_len > RNA_ENUM_BITFLAG_SIZE) { - PyErr_SetString(PyExc_TypeError, "EnumProperty(...): maximum " STRINGIFY(RNA_ENUM_BITFLAG_SIZE) " members for a ENUM_FLAG type property"); + PyErr_SetString(PyExc_TypeError, + "EnumProperty(...): maximum " + STRINGIFY(RNA_ENUM_BITFLAG_SIZE) + " members for a ENUM_FLAG type property"); return NULL; } if (def && !PySet_Check(def)) { @@ -1026,7 +1046,8 @@ static EnumPropertyItem *enum_items_from_py(PyObject *seq_fast, PyObject *def, i * immediately after use, so we need to duplicate them, ugh. * annoying because it works most of the time without this. */ { - EnumPropertyItem *items_dup= MEM_mallocN((sizeof(EnumPropertyItem) * (seq_len + 1)) + (sizeof(char) * totbuf), "enum_items_from_py2"); + EnumPropertyItem *items_dup= MEM_mallocN((sizeof(EnumPropertyItem) * (seq_len + 1)) + (sizeof(char) * totbuf), + "enum_items_from_py2"); EnumPropertyItem *items_ptr= items_dup; char *buf= ((char *)items_dup) + (sizeof(EnumPropertyItem) * (seq_len + 1)); memcpy(items_dup, items, sizeof(EnumPropertyItem) * (seq_len + 1)); @@ -1077,7 +1098,9 @@ static EnumPropertyItem *bpy_props_enum_itemf(struct bContext *C, PointerRNA *pt PyObject *items_fast; int defvalue_dummy=0; - if (!(items_fast= PySequence_Fast(items, "EnumProperty(...): return value from the callback was not a sequence"))) { + if (!(items_fast= PySequence_Fast(items, "EnumProperty(...): " + "return value from the callback was not a sequence"))) + { err= -1; } else { @@ -1137,7 +1160,8 @@ static PyObject *BPy_EnumProperty(PyObject *self, PyObject *args, PyObject *kw) BPY_PROPDEF_HEAD(EnumProperty) if (srna) { - static const char *kwlist[]= {"attr", "items", "name", "description", "default", "options", "update", NULL}; + static const char *kwlist[]= {"attr", "items", "name", "description", "default", + "options", "update", NULL}; const char *id=NULL, *name="", *description=""; PyObject *def= NULL; int id_len; @@ -1187,7 +1211,9 @@ static PyObject *BPy_EnumProperty(PyObject *self, PyObject *args, PyObject *kw) eitems= DummyRNA_NULL_items; } else { - if (!(items_fast= PySequence_Fast(items, "EnumProperty(...): expected a sequence of tuples for the enum items or a function"))) { + if (!(items_fast= PySequence_Fast(items, "EnumProperty(...): " + "expected a sequence of tuples for the enum items or a function"))) + { return NULL; } @@ -1206,7 +1232,10 @@ static PyObject *BPy_EnumProperty(PyObject *self, PyObject *args, PyObject *kw) if (is_itemf) { RNA_def_enum_funcs(prop, bpy_props_enum_itemf); RNA_def_enum_py_data(prop, (void *)items); - /* Py_INCREF(items); */ /* watch out!, if user is tricky they can probably crash blender if they manage to free the callback, take care! */ + + /* watch out!, if a user is tricky they can probably crash blender + * if they manage to free the callback, take care! */ + /* Py_INCREF(items); */ } if (pyopts) { diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index 9b42335dfe5..f099994fc57 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -367,7 +367,8 @@ static int deferred_register_prop(StructRNA *srna, PyObject *key, PyObject *item #ifdef USE_MATHUTILS #include "../mathutils/mathutils.h" /* so we can have mathutils callbacks */ -static PyObject *pyrna_prop_array_subscript_slice(BPy_PropertyArrayRNA *self, PointerRNA *ptr, PropertyRNA *prop, Py_ssize_t start, Py_ssize_t stop, Py_ssize_t length); +static PyObject *pyrna_prop_array_subscript_slice(BPy_PropertyArrayRNA *self, PointerRNA *ptr, PropertyRNA *prop, + Py_ssize_t start, Py_ssize_t stop, Py_ssize_t length); static short pyrna_rotation_euler_order_get(PointerRNA *ptr, PropertyRNA **prop_eul_order, short order_fallback); /* bpyrna vector/euler/quat callbacks */ @@ -589,7 +590,15 @@ static short pyrna_rotation_euler_order_get(PointerRNA *ptr, PropertyRNA **prop_ /* note that PROP_NONE is included as a vector subtype. this is because its handy to * have x/y access to fcurve keyframes and other fixed size float arrays of length 2-4. */ -#define PROP_ALL_VECTOR_SUBTYPES PROP_COORDS: case PROP_TRANSLATION: case PROP_DIRECTION: case PROP_VELOCITY: case PROP_ACCELERATION: case PROP_XYZ: case PROP_XYZ_LENGTH +#define PROP_ALL_VECTOR_SUBTYPES \ + PROP_COORDS: \ + case PROP_TRANSLATION: \ + case PROP_DIRECTION: \ + case PROP_VELOCITY: \ + case PROP_ACCELERATION: \ + case PROP_XYZ: \ + case PROP_XYZ_LENGTH \ + PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop) { @@ -2098,8 +2107,18 @@ static PyObject *pyrna_prop_collection_subscript_str(BPy_PropertyRNA *self, cons /* static PyObject *pyrna_prop_array_subscript_str(BPy_PropertyRNA *self, char *keyname) */ /* special case: bpy.data.objects["some_id_name", "//some_lib_name.blend"] - * also for: bpy.data.objects.get(("some_id_name", "//some_lib_name.blend"), fallback) */ -static PyObject *pyrna_prop_collection_subscript_str_lib_pair(BPy_PropertyRNA *self, PyObject *key, const char *err_prefix, const short err_not_found) + * also for: bpy.data.objects.get(("some_id_name", "//some_lib_name.blend"), fallback) + * + * note: + * error codes since this is not to be called directly from python, + * this matches pythons __contains__ values capi. + * -1: exception set + * 0: not found + * 1: found */ +int pyrna_prop_collection_subscript_str_lib_pair_ptr(BPy_PropertyRNA *self, PyObject *key, + const char *err_prefix, const short err_not_found, + PointerRNA *r_ptr + ) { char *keyname; @@ -2108,24 +2127,24 @@ static PyObject *pyrna_prop_collection_subscript_str_lib_pair(BPy_PropertyRNA *s PyErr_Format(PyExc_KeyError, "%s: tuple key must be a pair, not size %d", err_prefix, PyTuple_GET_SIZE(key)); - return NULL; + return -1; } else if (self->ptr.type != &RNA_BlendData) { PyErr_Format(PyExc_KeyError, "%s: is only valid for bpy.data collections, not %.200s", err_prefix, RNA_struct_identifier(self->ptr.type)); - return NULL; + return -1; } else if ((keyname= _PyUnicode_AsString(PyTuple_GET_ITEM(key, 0))) == NULL) { PyErr_Format(PyExc_KeyError, "%s: id must be a string, not %.200s", err_prefix, Py_TYPE(PyTuple_GET_ITEM(key, 0))->tp_name); - return NULL; + return -1; } else { PyObject *keylib= PyTuple_GET_ITEM(key, 1); Library *lib; - PyObject *ret= NULL; + int found= FALSE; if (keylib == Py_None) { lib= NULL; @@ -2140,16 +2159,19 @@ static PyObject *pyrna_prop_collection_subscript_str_lib_pair(BPy_PropertyRNA *s "%s: lib name '%.240s' " "does not reference a valid library", err_prefix, keylib_str); + return -1; + } + else { + return 0; } - return NULL; } } else { PyErr_Format(PyExc_KeyError, "%s: lib must be a sting or None, not %.200s", err_prefix, Py_TYPE(keylib)->tp_name); - return NULL; + return -1; } /* lib is either a valid poniter or NULL, @@ -2158,23 +2180,43 @@ static PyObject *pyrna_prop_collection_subscript_str_lib_pair(BPy_PropertyRNA *s RNA_PROP_BEGIN(&self->ptr, itemptr, self->prop) { ID *id= itemptr.data; /* always an ID */ if (id->lib == lib && (strncmp(keyname, id->name+2, sizeof(id->name)-2) == 0)) { - ret= pyrna_struct_CreatePyObject(&itemptr); + found= TRUE; + if (r_ptr) { + *r_ptr= itemptr; + } break; } } RNA_PROP_END; /* we may want to fail silently as with collection.get() */ - if ((ret == NULL) && err_not_found) { + if ((found == FALSE) && err_not_found) { /* only runs for getitem access so use fixed string */ PyErr_SetString(PyExc_KeyError, "bpy_prop_collection[key, lib]: not found"); + return -1; } + else { + return found; /* 1 / 0, no exception */ + } + } +} - return ret; +static PyObject *pyrna_prop_collection_subscript_str_lib_pair(BPy_PropertyRNA *self, PyObject *key, + const char *err_prefix, const short err_not_found) +{ + PointerRNA ptr; + const int contains= pyrna_prop_collection_subscript_str_lib_pair_ptr(self, key, err_prefix, err_not_found, &ptr); + + if (contains == 1) { + return pyrna_struct_CreatePyObject(&ptr); + } + else { + return NULL; } } + static PyObject *pyrna_prop_collection_subscript_slice(BPy_PropertyRNA *self, Py_ssize_t start, Py_ssize_t stop) { CollectionPropertyIterator rna_macro_iter; @@ -2188,7 +2230,10 @@ static PyObject *pyrna_prop_collection_subscript_slice(BPy_PropertyRNA *self, Py list= PyList_New(0); /* first loop up-until the start */ - for (RNA_property_collection_begin(&self->ptr, self->prop, &rna_macro_iter); rna_macro_iter.valid; RNA_property_collection_next(&rna_macro_iter)) { + for (RNA_property_collection_begin(&self->ptr, self->prop, &rna_macro_iter); + rna_macro_iter.valid; + RNA_property_collection_next(&rna_macro_iter)) + { /* PointerRNA itemptr= rna_macro_iter.ptr; */ if (count == start) { break; @@ -2197,7 +2242,9 @@ static PyObject *pyrna_prop_collection_subscript_slice(BPy_PropertyRNA *self, Py } /* add items until stop */ - for (; rna_macro_iter.valid; RNA_property_collection_next(&rna_macro_iter)) { + for (; rna_macro_iter.valid; + RNA_property_collection_next(&rna_macro_iter)) + { item= pyrna_struct_CreatePyObject(&rna_macro_iter.ptr); PyList_Append(list, item); Py_DECREF(item); @@ -2217,7 +2264,8 @@ static PyObject *pyrna_prop_collection_subscript_slice(BPy_PropertyRNA *self, Py * note: could also use pyrna_prop_array_to_py_index(self, count) in a loop but its a lot slower * since at the moment it reads (and even allocates) the entire array for each index. */ -static PyObject *pyrna_prop_array_subscript_slice(BPy_PropertyArrayRNA *self, PointerRNA *ptr, PropertyRNA *prop, Py_ssize_t start, Py_ssize_t stop, Py_ssize_t length) +static PyObject *pyrna_prop_array_subscript_slice(BPy_PropertyArrayRNA *self, PointerRNA *ptr, PropertyRNA *prop, + Py_ssize_t start, Py_ssize_t stop, Py_ssize_t length) { int count, totdim; PyObject *tuple; @@ -2347,7 +2395,8 @@ static PyObject *pyrna_prop_collection_subscript(BPy_PropertyRNA *self, PyObject } else if (PyTuple_Check(key)) { /* special case, for ID datablocks we */ - return pyrna_prop_collection_subscript_str_lib_pair(self, key, "bpy_prop_collection[id, lib]", TRUE); + return pyrna_prop_collection_subscript_str_lib_pair(self, key, + "bpy_prop_collection[id, lib]", TRUE); } else { PyErr_Format(PyExc_TypeError, @@ -2532,7 +2581,8 @@ static PyObject *pyrna_prop_array_subscript(BPy_PropertyArrayRNA *self, PyObject } /* could call (pyrna_py_to_prop_array_index(self, i, value) in a loop but it is slow */ -static int prop_subscript_ass_array_slice(PointerRNA *ptr, PropertyRNA *prop, int start, int stop, int length, PyObject *value_orig) +static int prop_subscript_ass_array_slice(PointerRNA *ptr, PropertyRNA *prop, + int start, int stop, int length, PyObject *value_orig) { PyObject *value; int count; @@ -2540,7 +2590,8 @@ static int prop_subscript_ass_array_slice(PointerRNA *ptr, PropertyRNA *prop, in int ret= 0; if (value_orig == NULL) { - PyErr_SetString(PyExc_TypeError, "bpy_prop_array[slice]= value: deleting with list types is not supported by bpy_struct"); + PyErr_SetString(PyExc_TypeError, + "bpy_prop_array[slice]= value: deleting with list types is not supported by bpy_struct"); return -1; } @@ -2550,7 +2601,8 @@ static int prop_subscript_ass_array_slice(PointerRNA *ptr, PropertyRNA *prop, in if (PySequence_Fast_GET_SIZE(value) != stop-start) { Py_DECREF(value); - PyErr_SetString(PyExc_TypeError, "bpy_prop_array[slice]= value: resizing bpy_struct arrays isn't supported"); + PyErr_SetString(PyExc_TypeError, + "bpy_prop_array[slice]= value: resizing bpy_struct arrays isn't supported"); return -1; } @@ -2751,22 +2803,30 @@ static int pyrna_prop_array_contains(BPy_PropertyRNA *self, PyObject *value) return pyrna_array_contains_py(&self->ptr, self->prop, value); } -static int pyrna_prop_collection_contains(BPy_PropertyRNA *self, PyObject *value) +static int pyrna_prop_collection_contains(BPy_PropertyRNA *self, PyObject *key) { PointerRNA newptr; /* not used, just so RNA_property_collection_lookup_string runs */ - /* key in dict style check */ - const char *keyname= _PyUnicode_AsString(value); - - if (keyname==NULL) { - PyErr_SetString(PyExc_TypeError, "bpy_prop_collection.__contains__: expected a string"); - return -1; + if (PyTuple_Check(key)) { + /* special case, for ID datablocks we */ + return pyrna_prop_collection_subscript_str_lib_pair_ptr(self, key, + "(id, lib) in bpy_prop_collection", FALSE, NULL); } + else { - if (RNA_property_collection_lookup_string(&self->ptr, self->prop, keyname, &newptr)) - return 1; + /* key in dict style check */ + const char *keyname= _PyUnicode_AsString(key); - return 0; + if (keyname==NULL) { + PyErr_SetString(PyExc_TypeError, "bpy_prop_collection.__contains__: expected a string or a typle of strings"); + return -1; + } + + if (RNA_property_collection_lookup_string(&self->ptr, self->prop, keyname, &newptr)) + return 1; + + return 0; + } } static int pyrna_struct_contains(BPy_StructRNA *self, PyObject *value) @@ -3459,9 +3519,12 @@ static int pyrna_struct_pydict_contains(PyObject *self, PyObject *pyname) #endif //--------------- setattr------------------------------------------- -static int pyrna_is_deferred_prop(PyObject *value) +static int pyrna_is_deferred_prop(const PyObject *value) { - return PyTuple_CheckExact(value) && PyTuple_GET_SIZE(value)==2 && PyCallable_Check(PyTuple_GET_ITEM(value, 0)) && PyDict_CheckExact(PyTuple_GET_ITEM(value, 1)); + return PyTuple_CheckExact(value) && + PyTuple_GET_SIZE(value) == 2 && + PyCFunction_Check(PyTuple_GET_ITEM(value, 0)) && + PyDict_CheckExact(PyTuple_GET_ITEM(value, 1)); } #if 0 @@ -3472,7 +3535,7 @@ static PyObject *pyrna_struct_meta_idprop_getattro(PyObject *cls, PyObject *attr /* Allows: * >>> bpy.types.Scene.foo= BoolProperty() * >>> bpy.types.Scene.foo - * <bpy_struct, BooleanProperty("foo")> + * <bpy_struct, BoolProperty("foo")> * ...rather than returning the deferred class register tuple as checked by pyrna_is_deferred_prop() * * Disable for now, this is faking internal behavior in a way thats too tricky to maintain well. */ @@ -3499,8 +3562,9 @@ static int pyrna_struct_meta_idprop_setattro(PyObject *cls, PyObject *attr, PyOb { StructRNA *srna= srna_from_self(cls, "StructRNA.__setattr__"); const int is_deferred_prop= (value && pyrna_is_deferred_prop(value)); + const char *attr_str= _PyUnicode_AsString(attr); - if (srna && !pyrna_write_check() && (is_deferred_prop || RNA_struct_type_find_property(srna, _PyUnicode_AsString(attr)))) { + if (srna && !pyrna_write_check() && (is_deferred_prop || RNA_struct_type_find_property(srna, attr_str))) { PyErr_Format(PyExc_AttributeError, "pyrna_struct_meta_idprop_setattro() " "can't set in readonly state '%.200s.%S'", @@ -3538,14 +3602,12 @@ static int pyrna_struct_meta_idprop_setattro(PyObject *cls, PyObject *attr, PyOb } else { /* remove existing property if its set or we also end up with confusion */ - const char *attr_str= _PyUnicode_AsString(attr); RNA_def_property_free_identifier(srna, attr_str); /* ignore on failure */ } } else { /* __delattr__ */ /* first find if this is a registered property */ - const char *attr_str= _PyUnicode_AsString(attr); - int ret= RNA_def_property_free_identifier(srna, attr_str); + const int ret= RNA_def_property_free_identifier(srna, attr_str); if (ret == -1) { PyErr_Format(PyExc_TypeError, "struct_meta_idprop.detattr(): '%s' not a dynamic property", @@ -3801,6 +3863,10 @@ static PyObject *pyrna_prop_collection_idprop_move(BPy_PropertyRNA *self, PyObje Py_RETURN_NONE; } + +PyDoc_STRVAR(pyrna_struct_get_id_data_doc, +"The :class:`bpy.types.ID` object this datablock is from or None, (not available for all data types)" +); static PyObject *pyrna_struct_get_id_data(BPy_DummyPointerRNA *self) { /* used for struct and pointer since both have a ptr */ @@ -3813,11 +3879,17 @@ static PyObject *pyrna_struct_get_id_data(BPy_DummyPointerRNA *self) Py_RETURN_NONE; } +PyDoc_STRVAR(pyrna_struct_get_data_doc, +"The data this property is using, *type* :class:`bpy.types.bpy_struct`" +); static PyObject *pyrna_struct_get_data(BPy_DummyPointerRNA *self) { return pyrna_struct_CreatePyObject(&self->ptr); } +PyDoc_STRVAR(pyrna_struct_get_rna_type_doc, +"The property type for introspection" +); static PyObject *pyrna_struct_get_rna_type(BPy_PropertyRNA *self) { PointerRNA tptr; @@ -3832,18 +3904,18 @@ static PyObject *pyrna_struct_get_rna_type(BPy_PropertyRNA *self) /*****************************************************************************/ static PyGetSetDef pyrna_prop_getseters[]= { - {(char *)"id_data", (getter)pyrna_struct_get_id_data, (setter)NULL, (char *)"The :class:`bpy.types.ID` object this datablock is from or None, (not available for all data types)", NULL}, - {(char *)"data", (getter)pyrna_struct_get_data, (setter)NULL, (char *)"The data this property is using, *type* :class:`bpy.types.bpy_struct`", NULL}, - {(char *)"rna_type", (getter)pyrna_struct_get_rna_type, (setter)NULL, (char *)"The property type for introspection", NULL}, + {(char *)"id_data", (getter)pyrna_struct_get_id_data, (setter)NULL, (char *)pyrna_struct_get_id_data_doc, NULL}, + {(char *)"data", (getter)pyrna_struct_get_data, (setter)NULL, (char *)pyrna_struct_get_data_doc, NULL}, + {(char *)"rna_type", (getter)pyrna_struct_get_rna_type, (setter)NULL, (char *)pyrna_struct_get_rna_type_doc, NULL}, {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ }; - static PyGetSetDef pyrna_struct_getseters[]= { - {(char *)"id_data", (getter)pyrna_struct_get_id_data, (setter)NULL, (char *)"The :class:`bpy.types.ID` object this datablock is from or None, (not available for all data types)", NULL}, + {(char *)"id_data", (getter)pyrna_struct_get_id_data, (setter)NULL, (char *)pyrna_struct_get_id_data_doc, NULL}, {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ }; + PyDoc_STRVAR(pyrna_prop_collection_keys_doc, ".. method:: keys()\n" "\n" @@ -3908,7 +3980,8 @@ static PyObject *pyrna_prop_collection_items(BPy_PropertyRNA *self) MEM_freeN(nameptr); } else { - PyTuple_SET_ITEM(item, 0, PyLong_FromSsize_t(i)); /* a bit strange but better then returning an empty list */ + /* a bit strange but better then returning an empty list */ + PyTuple_SET_ITEM(item, 0, PyLong_FromSsize_t(i)); } PyTuple_SET_ITEM(item, 1, pyrna_struct_CreatePyObject(&itemptr)); @@ -4030,7 +4103,8 @@ static PyObject *pyrna_prop_collection_get(BPy_PropertyRNA *self, PyObject *args return pyrna_struct_CreatePyObject(&newptr); } else if (PyTuple_Check(key_ob)) { - PyObject *ret= pyrna_prop_collection_subscript_str_lib_pair(self, key_ob, "bpy_prop_collection.get((id, lib))", FALSE); + PyObject *ret= pyrna_prop_collection_subscript_str_lib_pair(self, key_ob, + "bpy_prop_collection.get((id, lib))", FALSE); if (ret) { return ret; } @@ -4066,10 +4140,12 @@ static void foreach_attr_type( BPy_PropertyRNA *self, const char *attr, /* pyrna_prop_collection_foreach_get/set both use this */ static int foreach_parse_args( - BPy_PropertyRNA *self, PyObject *args, + BPy_PropertyRNA *self, PyObject *args, /*values to assign */ - const char **attr, PyObject **seq, int *tot, int *size, RawPropertyType *raw_type, int *attr_tot, int *attr_signed) + const char **attr, PyObject **seq, int *tot, int *size, + RawPropertyType *raw_type, int *attr_tot, int *attr_signed + ) { #if 0 int array_tot; @@ -4748,7 +4824,8 @@ static PyObject *pyrna_func_call(BPy_FunctionRNA *self, PyObject *args, PyObject const char *fn; int lineno; PyC_FileAndNum(&fn, &lineno); - printf("pyrna_func_call > %.200s.%.200s : %.200s:%d\n", RNA_struct_identifier(self_ptr->type), RNA_function_identifier(self_func), fn, lineno); + printf("pyrna_func_call > %.200s.%.200s : %.200s:%d\n", + RNA_struct_identifier(self_ptr->type), RNA_function_identifier(self_func), fn, lineno); } */ @@ -5899,7 +5976,9 @@ static PyObject* pyrna_srna_Subtype(StructRNA *srna) // if (!descr) descr= "(no docs)"; // "__doc__", descr - if (RNA_struct_idprops_check(srna) && !PyObject_IsSubclass(py_base, (PyObject *)&pyrna_struct_meta_idprop_Type)) { + if ( RNA_struct_idprops_check(srna) && + !PyObject_IsSubclass(py_base, (PyObject *)&pyrna_struct_meta_idprop_Type)) + { metaclass= (PyObject *)&pyrna_struct_meta_idprop_Type; } else { @@ -5907,7 +5986,8 @@ static PyObject* pyrna_srna_Subtype(StructRNA *srna) } /* always use O not N when calling, N causes refcount errors */ - newclass= PyObject_CallFunction(metaclass, (char *)"s(O){sss()}", idname, py_base, "__module__","bpy.types", "__slots__"); + newclass= PyObject_CallFunction(metaclass, (char *)"s(O){sss()}", + idname, py_base, "__module__","bpy.types", "__slots__"); /* newclass will now have 2 ref's, ???, probably 1 is internal since decrefing here segfaults */ @@ -6535,7 +6615,8 @@ static int bpy_class_validate(PointerRNA *dummyptr, void *py_data, int *have_fun arg_count= ((PyCodeObject *)PyFunction_GET_CODE(item))->co_argcount; /* note, the number of args we check for and the number of args we give to - * @classmethods are different (quirk of python), this is why rna_function_arg_count() doesn't return the value -1*/ + * @classmethods are different (quirk of python), + * this is why rna_function_arg_count() doesn't return the value -1*/ if (flag & FUNC_NO_SELF) func_arg_count++; @@ -6870,7 +6951,9 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param /* only useful for single argument returns, we'll need another list loop for multiple */ if (flag & PROP_OUTPUT) { - err= pyrna_py_to_prop(&funcptr, parm, iter.data, PyTuple_GET_ITEM(ret, i++), "calling class function:"); + err= pyrna_py_to_prop(&funcptr, parm, iter.data, + PyTuple_GET_ITEM(ret, i++), + "calling class function:"); if (err) { break; } @@ -7069,7 +7152,8 @@ static PyObject *pyrna_register_class(PyObject *UNUSED(self), PyObject *py_class identifier= ((PyTypeObject*)py_class)->tp_name; - srna_new= reg(CTX_data_main(C), &reports, py_class, identifier, bpy_class_validate, bpy_class_call, bpy_class_free); + srna_new= reg(CTX_data_main(C), &reports, py_class, identifier, + bpy_class_validate, bpy_class_call, bpy_class_free); if (BPy_reports_to_error(&reports, PyExc_RuntimeError, TRUE) == -1) return NULL; @@ -7167,7 +7251,9 @@ static PyObject *pyrna_unregister_class(PyObject *UNUSED(self), PyObject *py_cla unreg= RNA_struct_unregister(srna); if (!unreg) { - PyErr_SetString(PyExc_ValueError, "unregister_class(...): expected a Type subclassed from a registerable rna type (no unregister supported)"); + PyErr_SetString(PyExc_ValueError, + "unregister_class(...): " + "expected a Type subclassed from a registerable rna type (no unregister supported)"); return NULL; } diff --git a/source/blender/python/intern/bpy_rna_anim.c b/source/blender/python/intern/bpy_rna_anim.c index edc6e672238..8f88814b3e4 100644 --- a/source/blender/python/intern/bpy_rna_anim.c +++ b/source/blender/python/intern/bpy_rna_anim.c @@ -55,8 +55,9 @@ #define FALSE 0 /* for keyframes and drivers */ -static int pyrna_struct_anim_args_parse(PointerRNA *ptr, const char *error_prefix, const char *path, - const char **path_full, int *index) +static int pyrna_struct_anim_args_parse( + PointerRNA *ptr, const char *error_prefix, const char *path, + const char **path_full, int *index) { const int is_idbase= RNA_struct_is_ID(ptr->type); PropertyRNA *prop; @@ -146,8 +147,9 @@ static int pyrna_struct_anim_args_parse(PointerRNA *ptr, const char *error_prefi } /* internal use for insert and delete */ -static int pyrna_struct_keyframe_parse(PointerRNA *ptr, PyObject *args, PyObject *kw, const char *parse_str, const char *error_prefix, - const char **path_full, int *index, float *cfra, const char **group_name) /* return values */ +static int pyrna_struct_keyframe_parse( + PointerRNA *ptr, PyObject *args, PyObject *kw, const char *parse_str, const char *error_prefix, + const char **path_full, int *index, float *cfra, const char **group_name) /* return values */ { static const char *kwlist[]= {"data_path", "index", "frame", "group", NULL}; const char *path; diff --git a/source/blender/python/intern/bpy_rna_array.c b/source/blender/python/intern/bpy_rna_array.c index 73e9e0a44d9..1d1cab1c66d 100644 --- a/source/blender/python/intern/bpy_rna_array.c +++ b/source/blender/python/intern/bpy_rna_array.c @@ -176,7 +176,8 @@ static int count_items(PyObject *seq, int dim) } /* Modifies property array length if needed and PROP_DYNAMIC flag is set. */ -static int validate_array_length(PyObject *rvalue, PointerRNA *ptr, PropertyRNA *prop, int lvalue_dim, int *totitem, const char *error_prefix) +static int validate_array_length(PyObject *rvalue, PointerRNA *ptr, PropertyRNA *prop, + int lvalue_dim, int *totitem, const char *error_prefix) { int dimsize[MAX_ARRAY_DIMENSION]; int tot, totdim, len; @@ -249,7 +250,9 @@ static int validate_array_length(PyObject *rvalue, PointerRNA *ptr, PropertyRNA return 0; } -static int validate_array(PyObject *rvalue, PointerRNA *ptr, PropertyRNA *prop, int lvalue_dim, ItemTypeCheckFunc check_item_type, const char *item_type_str, int *totitem, const char *error_prefix) +static int validate_array(PyObject *rvalue, PointerRNA *ptr, PropertyRNA *prop, + int lvalue_dim, ItemTypeCheckFunc check_item_type, const char *item_type_str, int *totitem, + const char *error_prefix) { int dimsize[MAX_ARRAY_DIMENSION]; int totdim= RNA_property_array_dimension(ptr, prop, dimsize); @@ -262,7 +265,9 @@ static int validate_array(PyObject *rvalue, PointerRNA *ptr, PropertyRNA *prop, return validate_array_length(rvalue, ptr, prop, lvalue_dim, totitem, error_prefix); } -static char *copy_value_single(PyObject *item, PointerRNA *ptr, PropertyRNA *prop, char *data, unsigned int item_size, int *index, ItemConvertFunc convert_item, RNA_SetIndexFunc rna_set_index) +static char *copy_value_single(PyObject *item, PointerRNA *ptr, PropertyRNA *prop, + char *data, unsigned int item_size, int *index, + ItemConvertFunc convert_item, RNA_SetIndexFunc rna_set_index) { if (!data) { char value[sizeof(int)]; @@ -279,7 +284,9 @@ static char *copy_value_single(PyObject *item, PointerRNA *ptr, PropertyRNA *pro return data; } -static char *copy_values(PyObject *seq, PointerRNA *ptr, PropertyRNA *prop, int dim, char *data, unsigned int item_size, int *index, ItemConvertFunc convert_item, RNA_SetIndexFunc rna_set_index) +static char *copy_values(PyObject *seq, PointerRNA *ptr, PropertyRNA *prop, + int dim, char *data, unsigned int item_size, int *index, + ItemConvertFunc convert_item, RNA_SetIndexFunc rna_set_index) { int totdim= RNA_property_array_dimension(ptr, prop, NULL); const Py_ssize_t seq_size= PySequence_Size(seq); @@ -320,7 +327,9 @@ static char *copy_values(PyObject *seq, PointerRNA *ptr, PropertyRNA *prop, int return data; } -static int py_to_array(PyObject *seq, PointerRNA *ptr, PropertyRNA *prop, char *param_data, ItemTypeCheckFunc check_item_type, const char *item_type_str, int item_size, ItemConvertFunc convert_item, RNA_SetArrayFunc rna_set_array, const char *error_prefix) +static int py_to_array(PyObject *seq, PointerRNA *ptr, PropertyRNA *prop, + char *param_data, ItemTypeCheckFunc check_item_type, const char *item_type_str, int item_size, + ItemConvertFunc convert_item, RNA_SetArrayFunc rna_set_array, const char *error_prefix) { /*int totdim, dim_size[MAX_ARRAY_DIMENSION];*/ int totitem; @@ -372,7 +381,10 @@ static int py_to_array(PyObject *seq, PointerRNA *ptr, PropertyRNA *prop, char * return 0; } -static int py_to_array_index(PyObject *py, PointerRNA *ptr, PropertyRNA *prop, int lvalue_dim, int arrayoffset, int index, ItemTypeCheckFunc check_item_type, const char *item_type_str, ItemConvertFunc convert_item, RNA_SetIndexFunc rna_set_index, const char *error_prefix) +static int py_to_array_index(PyObject *py, PointerRNA *ptr, PropertyRNA *prop, + int lvalue_dim, int arrayoffset, int index, + ItemTypeCheckFunc check_item_type, const char *item_type_str, + ItemConvertFunc convert_item, RNA_SetIndexFunc rna_set_index, const char *error_prefix) { int totdim, dimsize[MAX_ARRAY_DIMENSION]; int totitem, i; @@ -465,18 +477,22 @@ static void bool_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, void * RNA_property_boolean_set_index(ptr, prop, index, *(int*)value); } -int pyrna_py_to_array(PointerRNA *ptr, PropertyRNA *prop, char *param_data, PyObject *py, const char *error_prefix) +int pyrna_py_to_array(PointerRNA *ptr, PropertyRNA *prop, char *param_data, + PyObject *py, const char *error_prefix) { int ret; switch (RNA_property_type(prop)) { case PROP_FLOAT: - ret= py_to_array(py, ptr, prop, param_data, py_float_check, "float", sizeof(float), py_to_float, (RNA_SetArrayFunc)RNA_property_float_set_array, error_prefix); + ret= py_to_array(py, ptr, prop, param_data, py_float_check, "float", sizeof(float), + py_to_float, (RNA_SetArrayFunc)RNA_property_float_set_array, error_prefix); break; case PROP_INT: - ret= py_to_array(py, ptr, prop, param_data, py_int_check, "int", sizeof(int), py_to_int, (RNA_SetArrayFunc)RNA_property_int_set_array, error_prefix); + ret= py_to_array(py, ptr, prop, param_data, py_int_check, "int", sizeof(int), + py_to_int, (RNA_SetArrayFunc)RNA_property_int_set_array, error_prefix); break; case PROP_BOOLEAN: - ret= py_to_array(py, ptr, prop, param_data, py_bool_check, "boolean", sizeof(int), py_to_bool, (RNA_SetArrayFunc)RNA_property_boolean_set_array, error_prefix); + ret= py_to_array(py, ptr, prop, param_data, py_bool_check, "boolean", sizeof(int), + py_to_bool, (RNA_SetArrayFunc)RNA_property_boolean_set_array, error_prefix); break; default: PyErr_SetString(PyExc_TypeError, "not an array type"); @@ -486,18 +502,22 @@ int pyrna_py_to_array(PointerRNA *ptr, PropertyRNA *prop, char *param_data, PyOb return ret; } -int pyrna_py_to_array_index(PointerRNA *ptr, PropertyRNA *prop, int arraydim, int arrayoffset, int index, PyObject *py, const char *error_prefix) +int pyrna_py_to_array_index(PointerRNA *ptr, PropertyRNA *prop, int arraydim, int arrayoffset, int index, + PyObject *py, const char *error_prefix) { int ret; switch (RNA_property_type(prop)) { case PROP_FLOAT: - ret= py_to_array_index(py, ptr, prop, arraydim, arrayoffset, index, py_float_check, "float", py_to_float, float_set_index, error_prefix); + ret= py_to_array_index(py, ptr, prop, arraydim, arrayoffset, index, + py_float_check, "float", py_to_float, float_set_index, error_prefix); break; case PROP_INT: - ret= py_to_array_index(py, ptr, prop, arraydim, arrayoffset, index, py_int_check, "int", py_to_int, int_set_index, error_prefix); + ret= py_to_array_index(py, ptr, prop, arraydim, arrayoffset, index, + py_int_check, "int", py_to_int, int_set_index, error_prefix); break; case PROP_BOOLEAN: - ret= py_to_array_index(py, ptr, prop, arraydim, arrayoffset, index, py_bool_check, "boolean", py_to_bool, bool_set_index, error_prefix); + ret= py_to_array_index(py, ptr, prop, arraydim, arrayoffset, index, + py_bool_check, "boolean", py_to_bool, bool_set_index, error_prefix); break; default: PyErr_SetString(PyExc_TypeError, "not an array type"); diff --git a/source/blender/python/intern/bpy_traceback.c b/source/blender/python/intern/bpy_traceback.c index 5045f6708b5..599c4312985 100644 --- a/source/blender/python/intern/bpy_traceback.c +++ b/source/blender/python/intern/bpy_traceback.c @@ -146,7 +146,10 @@ void python_script_error_jump(const char *filepath, int *lineno, int *offset) PyErr_Restore(exception, value, (PyObject *)tb); /* takes away reference! */ PyErr_Print(); - for (tb= (PyTracebackObject *)PySys_GetObject("last_traceback"); tb && (PyObject *)tb != Py_None; tb= tb->tb_next) { + for (tb= (PyTracebackObject *)PySys_GetObject("last_traceback"); + tb && (PyObject *)tb != Py_None; + tb= tb->tb_next) + { PyObject *coerce; const char *tb_filepath= traceback_filepath(tb, &coerce); const int match= strcmp(tb_filepath, filepath) != 0; diff --git a/source/blender/python/intern/gpu.h b/source/blender/python/intern/gpu.h index 95656e7e147..bffbae13ba2 100644 --- a/source/blender/python/intern/gpu.h +++ b/source/blender/python/intern/gpu.h @@ -1,21 +1,18 @@ /* * ***** BEGIN GPL LICENSE BLOCK ***** * - * This shader is free software; you can redistribute it and/or + * 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. The Blender - * Foundation also sells licenses for use in proprietary software under - * the Blender License. See http://www.blender.org/BL/ for information - * about this. + * of the License, or (at your option) any later version. * - * This shader is distributed in the hope that it will be useful, + * 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 shader; if not, write to the Free Software Foundation, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2005 Blender Foundation. diff --git a/source/blender/python/mathutils/CMakeLists.txt b/source/blender/python/mathutils/CMakeLists.txt index b28496d612e..dae1c665ebc 100644 --- a/source/blender/python/mathutils/CMakeLists.txt +++ b/source/blender/python/mathutils/CMakeLists.txt @@ -38,6 +38,7 @@ set(SRC mathutils_Quaternion.c mathutils_Vector.c mathutils_geometry.c + mathutils_noise.c mathutils.h mathutils_Color.h @@ -46,6 +47,7 @@ set(SRC mathutils_Quaternion.h mathutils_Vector.h mathutils_geometry.h + mathutils_noise.h ) diff --git a/source/blender/python/mathutils/mathutils.c b/source/blender/python/mathutils/mathutils.c index 41c1568dbde..121c5e26e73 100644 --- a/source/blender/python/mathutils/mathutils.c +++ b/source/blender/python/mathutils/mathutils.c @@ -39,7 +39,9 @@ PyDoc_STRVAR(M_Mathutils_doc, "This module provides access to matrices, eulers, quaternions and vectors." ); -static int mathutils_array_parse_fast(float *array, int array_min, int array_max, PyObject *value, const char *error_prefix) +static int mathutils_array_parse_fast(float *array, + int array_min, int array_max, + PyObject *value, const char *error_prefix) { PyObject *value_fast= NULL; PyObject *item; @@ -72,7 +74,9 @@ static int mathutils_array_parse_fast(float *array, int array_min, int array_max i= size; do { i--; - if (((array[i]= PyFloat_AsDouble((item= PySequence_Fast_GET_ITEM(value_fast, i)))) == -1.0f) && PyErr_Occurred()) { + if ( ((array[i]= PyFloat_AsDouble((item= PySequence_Fast_GET_ITEM(value_fast, i)))) == -1.0f) && + PyErr_Occurred()) + { PyErr_Format(PyExc_TypeError, "%.200s: sequence index %d expected a number, " "found '%.200s' type, ", @@ -347,6 +351,7 @@ PyMODINIT_FUNC PyInit_mathutils(void) { PyObject *submodule; PyObject *item; + PyObject *sys_modules= PyThreadState_GET()->interp->modules; if (PyType_Ready(&vector_Type) < 0) return NULL; @@ -373,7 +378,12 @@ PyMODINIT_FUNC PyInit_mathutils(void) /* XXX, python doesnt do imports with this usefully yet * 'from mathutils.geometry import PolyFill' * ...fails without this. */ - PyDict_SetItemString(PyThreadState_GET()->interp->modules, "mathutils.geometry", item); + PyDict_SetItemString(sys_modules, "mathutils.geometry", item); + Py_INCREF(item); + + /* Noise submodule */ + PyModule_AddObject(submodule, "noise", (item=PyInit_mathutils_noise())); + PyDict_SetItemString(sys_modules, "mathutils.noise", item); Py_INCREF(item); mathutils_matrix_vector_cb_index= Mathutils_RegisterCallback(&mathutils_matrix_vector_cb); diff --git a/source/blender/python/mathutils/mathutils.h b/source/blender/python/mathutils/mathutils.h index 70b0ef93ebd..a8170b8145c 100644 --- a/source/blender/python/mathutils/mathutils.h +++ b/source/blender/python/mathutils/mathutils.h @@ -40,24 +40,30 @@ extern char BaseMathObject_Wrapped_doc[]; extern char BaseMathObject_Owner_doc[]; -#define BASE_MATH_MEMBERS(_data) \ - 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? */ \ +#define BASE_MATH_MEMBERS(_data) \ + 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? */ \ typedef struct { - BASE_MATH_MEMBERS(data) + BASE_MATH_MEMBERS(data); } BaseMathObject; +/* types */ #include "mathutils_Vector.h" #include "mathutils_Matrix.h" #include "mathutils_Quaternion.h" #include "mathutils_Euler.h" #include "mathutils_Color.h" + +/* utility submodules */ #include "mathutils_geometry.h" +#include "mathutils_noise.h" PyObject *BaseMathObject_getOwner( BaseMathObject * self, void * ); PyObject *BaseMathObject_getWrapped( BaseMathObject *self, void * ); @@ -76,11 +82,11 @@ int EXPP_VectorsAreEqual(float *vecA, float *vecB, int size, int floatSteps); typedef struct Mathutils_Callback Mathutils_Callback; -typedef int (*BaseMathCheckFunc)(BaseMathObject *); /* checks the user is still valid */ -typedef int (*BaseMathGetFunc)(BaseMathObject *, int); /* gets the vector from the user */ -typedef int (*BaseMathSetFunc)(BaseMathObject *, int); /* sets the users vector values once the vector is modified */ -typedef int (*BaseMathGetIndexFunc)(BaseMathObject *, int, int); /* same as above but only for an index */ -typedef int (*BaseMathSetIndexFunc)(BaseMathObject *, int, int); /* same as above but only for an index */ +typedef int (*BaseMathCheckFunc)(BaseMathObject *); /* checks the user is still valid */ +typedef int (*BaseMathGetFunc)(BaseMathObject *, int); /* gets the vector from the user */ +typedef int (*BaseMathSetFunc)(BaseMathObject *, int); /* sets the users vector values once its modified */ +typedef int (*BaseMathGetIndexFunc)(BaseMathObject *, int, int); /* same as above but only for an index */ +typedef int (*BaseMathSetIndexFunc)(BaseMathObject *, int, int); /* same as above but only for an index */ struct Mathutils_Callback { BaseMathCheckFunc check; @@ -98,10 +104,14 @@ 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):0)) -#define BaseMath_WriteCallback(_self) (((_self)->cb_user ?_BaseMathObject_WriteCallback((BaseMathObject *)_self):0)) -#define BaseMath_ReadIndexCallback(_self, _index) (((_self)->cb_user ? _BaseMathObject_ReadIndexCallback((BaseMathObject *)_self, _index):0)) -#define BaseMath_WriteIndexCallback(_self, _index) (((_self)->cb_user ? _BaseMathObject_WriteIndexCallback((BaseMathObject *)_self, _index):0)) +#define BaseMath_ReadCallback(_self) \ + (((_self)->cb_user ? _BaseMathObject_ReadCallback((BaseMathObject *)_self):0)) +#define BaseMath_WriteCallback(_self) \ + (((_self)->cb_user ?_BaseMathObject_WriteCallback((BaseMathObject *)_self):0)) +#define BaseMath_ReadIndexCallback(_self, _index) \ + (((_self)->cb_user ? _BaseMathObject_ReadIndexCallback((BaseMathObject *)_self, _index):0)) +#define BaseMath_WriteIndexCallback(_self, _index) \ + (((_self)->cb_user ? _BaseMathObject_WriteIndexCallback((BaseMathObject *)_self, _index):0)) /* utility func */ int mathutils_array_parse(float *array, int array_min, int array_max, PyObject *value, const char *error_prefix); diff --git a/source/blender/python/mathutils/mathutils_Color.h b/source/blender/python/mathutils/mathutils_Color.h index f218d653ec9..7e8a99089ad 100644 --- a/source/blender/python/mathutils/mathutils_Color.h +++ b/source/blender/python/mathutils/mathutils_Color.h @@ -39,7 +39,7 @@ extern PyTypeObject color_Type; #define ColorObject_Check(_v) PyObject_TypeCheck((_v), &color_Type) typedef struct { - BASE_MATH_MEMBERS(col) + BASE_MATH_MEMBERS(col); } ColorObject; /*struct data contains a pointer to the actual data that the diff --git a/source/blender/python/mathutils/mathutils_Euler.c b/source/blender/python/mathutils/mathutils_Euler.c index 9bf6687fb5e..7e769da14cb 100644 --- a/source/blender/python/mathutils/mathutils_Euler.c +++ b/source/blender/python/mathutils/mathutils_Euler.c @@ -264,8 +264,11 @@ static PyObject *Euler_make_compatible(EulerObject * self, PyObject *value) if (BaseMath_ReadCallback(self) == -1) return NULL; - if (mathutils_array_parse(teul, EULER_SIZE, EULER_SIZE, value, "euler.make_compatible(other), invalid 'other' arg") == -1) + if (mathutils_array_parse(teul, EULER_SIZE, EULER_SIZE, value, + "euler.make_compatible(other), invalid 'other' arg") == -1) + { return NULL; + } compatible_eul(self->eul, teul); diff --git a/source/blender/python/mathutils/mathutils_Euler.h b/source/blender/python/mathutils/mathutils_Euler.h index 5760d08e1f6..130384a1792 100644 --- a/source/blender/python/mathutils/mathutils_Euler.h +++ b/source/blender/python/mathutils/mathutils_Euler.h @@ -39,7 +39,7 @@ extern PyTypeObject euler_Type; #define EulerObject_Check(_v) PyObject_TypeCheck((_v), &euler_Type) typedef struct { - BASE_MATH_MEMBERS(eul) + BASE_MATH_MEMBERS(eul); unsigned char order; /* rotation order */ } EulerObject; diff --git a/source/blender/python/mathutils/mathutils_Matrix.c b/source/blender/python/mathutils/mathutils_Matrix.c index 2f62f7141cf..ea636ef52fb 100644 --- a/source/blender/python/mathutils/mathutils_Matrix.c +++ b/source/blender/python/mathutils/mathutils_Matrix.c @@ -125,7 +125,7 @@ static PyObject *Matrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds) switch(PyTuple_GET_SIZE(args)) { case 0: - return (PyObject *) Matrix_CreatePyObject(NULL, 4, 4, Py_NEW, type); + return Matrix_CreatePyObject(NULL, 4, 4, Py_NEW, type); case 1: { PyObject *arg= PyTuple_GET_ITEM(args, 0); @@ -478,7 +478,9 @@ static PyObject *C_Matrix_OrthoProjection(PyObject *cls, PyObject *args) int vec_size= (matSize == 2 ? 2 : 3); float tvec[4]; - if (mathutils_array_parse(tvec, vec_size, vec_size, axis, "Matrix.OrthoProjection(axis, size), invalid 'axis' arg") == -1) { + if (mathutils_array_parse(tvec, vec_size, vec_size, axis, + "Matrix.OrthoProjection(axis, size), invalid 'axis' arg") == -1) + { return NULL; } @@ -827,12 +829,12 @@ static PyObject *Matrix_to_4x4(MatrixObject *self) return NULL; if (self->col_size==4 && self->row_size==4) { - return (PyObject *)Matrix_CreatePyObject(self->contigPtr, 4, 4, Py_NEW, Py_TYPE(self)); + return Matrix_CreatePyObject(self->contigPtr, 4, 4, Py_NEW, Py_TYPE(self)); } else if (self->col_size==3 && self->row_size==3) { float mat[4][4]; copy_m4_m3(mat, (float (*)[3])self->contigPtr); - return (PyObject *)Matrix_CreatePyObject((float *)mat, 4, 4, Py_NEW, Py_TYPE(self)); + return Matrix_CreatePyObject((float *)mat, 4, 4, Py_NEW, Py_TYPE(self)); } /* TODO, 2x2 matrix */ @@ -1133,7 +1135,7 @@ static PyObject *Matrix_lerp(MatrixObject *self, PyObject *args) return NULL; } - return (PyObject*)Matrix_CreatePyObject(mat, self->row_size, self->col_size, Py_NEW, Py_TYPE(self)); + return Matrix_CreatePyObject(mat, self->row_size, self->col_size, Py_NEW, Py_TYPE(self)); } /*---------------------------matrix.determinant() ----------------*/ @@ -1286,7 +1288,7 @@ static PyObject *Matrix_copy(MatrixObject *self) if (BaseMath_ReadCallback(self) == -1) return NULL; - return (PyObject*)Matrix_CreatePyObject((float (*))self->contigPtr, self->row_size, self->col_size, Py_NEW, Py_TYPE(self)); + return Matrix_CreatePyObject((float (*))self->contigPtr, self->row_size, self->col_size, Py_NEW, Py_TYPE(self)); } /*----------------------------print object (internal)-------------*/ @@ -1470,7 +1472,9 @@ static int Matrix_ass_slice(MatrixObject *self, int begin, int end, PyObject *va /*parse each sub sequence*/ PyObject *item= PySequence_Fast_GET_ITEM(value_fast, i); - if (mathutils_array_parse(&mat[i * self->col_size], self->col_size, self->col_size, item, "matrix[begin:end] = value assignment") < 0) { + if (mathutils_array_parse(&mat[i * self->col_size], self->col_size, self->col_size, item, + "matrix[begin:end] = value assignment") < 0) + { return -1; } } @@ -1956,7 +1960,9 @@ self->matrix[1][1] = self->contigPtr[4] */ (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 *Matrix_CreatePyObject(float *mat, const unsigned short rowSize, const unsigned short colSize, int type, PyTypeObject *base_type) +PyObject *Matrix_CreatePyObject(float *mat, + const unsigned short rowSize, const unsigned short colSize, + int type, PyTypeObject *base_type) { MatrixObject *self; int x, row, col; diff --git a/source/blender/python/mathutils/mathutils_Matrix.h b/source/blender/python/mathutils/mathutils_Matrix.h index d1984d7299d..6dfcbb1faf9 100644 --- a/source/blender/python/mathutils/mathutils_Matrix.h +++ b/source/blender/python/mathutils/mathutils_Matrix.h @@ -39,7 +39,7 @@ extern PyTypeObject matrix_Type; #define MATRIX_MAX_DIM 4 typedef struct { - BASE_MATH_MEMBERS(contigPtr) + BASE_MATH_MEMBERS(contigPtr); float *matrix[MATRIX_MAX_DIM]; /* ptr to the contigPtr (accessor) */ unsigned short row_size; unsigned short col_size; @@ -51,7 +51,9 @@ be stored in py_data) or be a wrapper for data allocated through blender (stored in blend_data). This is an either/or struct not both*/ /*prototypes*/ -PyObject *Matrix_CreatePyObject(float *mat, const unsigned short row_size, const unsigned short col_size, int type, PyTypeObject *base_type); +PyObject *Matrix_CreatePyObject(float *mat, + const unsigned short row_size, const unsigned short col_size, + int type, PyTypeObject *base_type); PyObject *Matrix_CreatePyObject_cb(PyObject *user, int row_size, int col_size, int cb_type, int cb_subtype); extern int mathutils_matrix_vector_cb_index; diff --git a/source/blender/python/mathutils/mathutils_Quaternion.c b/source/blender/python/mathutils/mathutils_Quaternion.c index 44cd28a7c3d..cf817003a98 100644 --- a/source/blender/python/mathutils/mathutils_Quaternion.c +++ b/source/blender/python/mathutils/mathutils_Quaternion.c @@ -218,8 +218,11 @@ static PyObject *Quaternion_dot(QuaternionObject *self, PyObject *value) if (BaseMath_ReadCallback(self) == -1) return NULL; - if (mathutils_array_parse(tquat, QUAT_SIZE, QUAT_SIZE, value, "Quaternion.dot(other), invalid 'other' arg") == -1) + if (mathutils_array_parse(tquat, QUAT_SIZE, QUAT_SIZE, value, + "Quaternion.dot(other), invalid 'other' arg") == -1) + { return NULL; + } return PyFloat_FromDouble(dot_qtqt(self->quat, tquat)); } @@ -241,8 +244,11 @@ static PyObject *Quaternion_rotation_difference(QuaternionObject *self, PyObject if (BaseMath_ReadCallback(self) == -1) return NULL; - if (mathutils_array_parse(tquat, QUAT_SIZE, QUAT_SIZE, value, "Quaternion.difference(other), invalid 'other' arg") == -1) + if (mathutils_array_parse(tquat, QUAT_SIZE, QUAT_SIZE, value, + "Quaternion.difference(other), invalid 'other' arg") == -1) + { return NULL; + } rotation_between_quats_to_quat(quat, self->quat, tquat); @@ -276,8 +282,11 @@ static PyObject *Quaternion_slerp(QuaternionObject *self, PyObject *args) if (BaseMath_ReadCallback(self) == -1) return NULL; - if (mathutils_array_parse(tquat, QUAT_SIZE, QUAT_SIZE, value, "Quaternion.slerp(other), invalid 'other' arg") == -1) + if (mathutils_array_parse(tquat, QUAT_SIZE, QUAT_SIZE, value, + "Quaternion.slerp(other), invalid 'other' arg") == -1) + { return NULL; + } if (fac > 1.0f || fac < 0.0f) { PyErr_SetString(PyExc_ValueError, @@ -982,7 +991,7 @@ static PyObject *Quaternion_getAxisVec(QuaternionObject *self, void *UNUSED(clos quat__axis_angle_sanitize(axis, NULL); - return (PyObject *) Vector_CreatePyObject(axis, 3, Py_NEW, NULL); + return Vector_CreatePyObject(axis, 3, Py_NEW, NULL); } static int Quaternion_setAxisVec(QuaternionObject *self, PyObject *value, void *UNUSED(closure)) @@ -1054,7 +1063,7 @@ static PyObject *quat__apply_to_copy(PyNoArgsFunction quat_func, QuaternionObjec PyObject *ret_dummy= quat_func(ret); if (ret_dummy) { Py_DECREF(ret_dummy); - return (PyObject *)ret; + return ret; } else { /* error */ Py_DECREF(ret); diff --git a/source/blender/python/mathutils/mathutils_Quaternion.h b/source/blender/python/mathutils/mathutils_Quaternion.h index a34720769fa..edd5ec55312 100644 --- a/source/blender/python/mathutils/mathutils_Quaternion.h +++ b/source/blender/python/mathutils/mathutils_Quaternion.h @@ -39,7 +39,7 @@ extern PyTypeObject quaternion_Type; #define QuaternionObject_Check(_v) PyObject_TypeCheck((_v), &quaternion_Type) typedef struct { - BASE_MATH_MEMBERS(quat) + BASE_MATH_MEMBERS(quat); } QuaternionObject; /*struct data contains a pointer to the actual data that the diff --git a/source/blender/python/mathutils/mathutils_Vector.c b/source/blender/python/mathutils/mathutils_Vector.c index 1dff33887e3..9d1a22adb12 100644 --- a/source/blender/python/mathutils/mathutils_Vector.c +++ b/source/blender/python/mathutils/mathutils_Vector.c @@ -589,10 +589,10 @@ PyDoc_STRVAR(Vector_angle_doc, ); static PyObject *Vector_angle(VectorObject *self, PyObject *args) { - const int size= self->size; + const int size= MIN2(self->size, 3); /* 4D angle makes no sense */ float tvec[MAX_DIMENSIONS]; PyObject *value; - double dot = 0.0f, test_v1 = 0.0f, test_v2 = 0.0f; + double dot= 0.0f, dot_self= 0.0f, dot_other= 0.0f; int x; PyObject *fallback= NULL; @@ -602,14 +602,18 @@ static PyObject *Vector_angle(VectorObject *self, PyObject *args) if (BaseMath_ReadCallback(self) == -1) return NULL; - if (mathutils_array_parse(tvec, size, size, value, "Vector.angle(other), invalid 'other' arg") == -1) + /* don't use clamped size, rule of thumb is vector sizes must match, + * even though n this case 'w' is ignored */ + if (mathutils_array_parse(tvec, self->size, self->size, value, "Vector.angle(other), invalid 'other' arg") == -1) return NULL; for (x = 0; x < size; x++) { - test_v1 += (double)(self->vec[x] * self->vec[x]); - test_v2 += (double)(tvec[x] * tvec[x]); + dot_self += (double)self->vec[x] * (double)self->vec[x]; + dot_other += (double)tvec[x] * (double)tvec[x]; + dot += (double)self->vec[x] * (double)tvec[x]; } - if (!test_v1 || !test_v2) { + + if (!dot_self || !dot_other) { /* avoid exception */ if (fallback) { Py_INCREF(fallback); @@ -623,13 +627,7 @@ static PyObject *Vector_angle(VectorObject *self, PyObject *args) } } - //dot product - for (x = 0; x < self->size; x++) { - dot += (double)(self->vec[x] * tvec[x]); - } - dot /= (sqrt(test_v1) * sqrt(test_v2)); - - return PyFloat_FromDouble(saacos(dot)); + return PyFloat_FromDouble(saacos(dot / (sqrt(dot_self) * sqrt(dot_other)))); } PyDoc_STRVAR(Vector_rotation_difference_doc, @@ -1755,7 +1753,10 @@ static int Vector_setSwizzle(VectorObject *self, PyObject *value, void *closure) size_from= axis_from; } - else if (PyErr_Clear(), (size_from=mathutils_array_parse(vec_assign, 2, 4, value, "mathutils.Vector.**** = swizzle assignment")) == -1) { + else if ( (PyErr_Clear()), /* run but ignore the result */ + (size_from=mathutils_array_parse(vec_assign, 2, 4, value, + "mathutils.Vector.**** = swizzle assignment")) == -1) + { return -1; } diff --git a/source/blender/python/mathutils/mathutils_Vector.h b/source/blender/python/mathutils/mathutils_Vector.h index c1550aabb25..0f7fa174d18 100644 --- a/source/blender/python/mathutils/mathutils_Vector.h +++ b/source/blender/python/mathutils/mathutils_Vector.h @@ -39,7 +39,7 @@ extern PyTypeObject vector_Type; #define VectorObject_Check(_v) PyObject_TypeCheck((_v), &vector_Type) typedef struct { - BASE_MATH_MEMBERS(vec) + BASE_MATH_MEMBERS(vec); unsigned char size; /* vec size 2,3 or 4 */ } VectorObject; diff --git a/source/blender/python/mathutils/mathutils_noise.c b/source/blender/python/mathutils/mathutils_noise.c new file mode 100644 index 00000000000..bd490d62e94 --- /dev/null +++ b/source/blender/python/mathutils/mathutils_noise.c @@ -0,0 +1,911 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * This is a new part of Blender. + * + * Contributor(s): eeshlo, Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/python/mathutils/mathutils_noise.c + * \ingroup mathutils + * + * This file defines the 'noise' module, a general purpose module to access + * blenders noise functions. + */ + + +/************************/ +/* Blender Noise Module */ +/************************/ + +#include <Python.h> + +#include "structseq.h" + +#include "BLI_blenlib.h" +#include "BLI_math.h" +#include "BLI_utildefines.h" + +#include "MEM_guardedalloc.h" + +#include "DNA_texture_types.h" + +#include "mathutils.h" +#include "mathutils_noise.h" + +/* 2.6 update + * Moved to submodule of mathutils. + * All vector functions now return mathutils.Vector + * Updated docs to be compatible with autodocs generation. + * Updated vector functions to use nD array functions. + * noise.vl_vector --> noise.variable_lacunarity + * noise.vector --> noise.noise_vector + */ + +/*-----------------------------------------*/ +/* 'mersenne twister' random number generator */ + +/* + A C-program for MT19937, with initialization improved 2002/2/10. + Coded by Takuji Nishimura and Makoto Matsumoto. + This is a faster version by taking Shawn Cokus's optimization, + Matthe Bellew's simplification, Isaku Wada's real version. + + Before using, initialize the state by using init_genrand(seed) + or init_by_array(init_key, key_length). + + Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. The names of its contributors may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + Any feedback is very welcome. + http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html + email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space) +*/ + +/* Period parameters */ +#define N 624 +#define M 397 +#define MATRIX_A 0x9908b0dfUL /* constant vector a */ +#define UMASK 0x80000000UL /* most significant w-r bits */ +#define LMASK 0x7fffffffUL /* least significant r bits */ +#define MIXBITS(u,v) (((u) & UMASK) | ((v) & LMASK)) +#define TWIST(u,v) ((MIXBITS(u,v) >> 1) ^ ((v)&1UL ? MATRIX_A : 0UL)) + +static unsigned long state[N]; /* the array for the state vector */ +static int left = 1; +static int initf = 0; +static unsigned long *next; + +/* initializes state[N] with a seed */ +static void init_genrand(unsigned long s) +{ + int j; + state[0] = s & 0xffffffffUL; + for (j = 1; j < N; j++) { + state[j] = + (1812433253UL * + (state[j - 1] ^ (state[j - 1] >> 30)) + j); + /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ + /* In the previous versions, MSBs of the seed affect */ + /* only MSBs of the array state[]. */ + /* 2002/01/09 modified by Makoto Matsumoto */ + state[j] &= 0xffffffffUL; /* for >32 bit machines */ + } + left = 1; + initf = 1; +} + +static void next_state(void) +{ + unsigned long *p = state; + int j; + + /* if init_genrand() has not been called, */ + /* a default initial seed is used */ + if (initf == 0) + init_genrand(5489UL); + + left = N; + next = state; + + for (j = N - M + 1; --j; p++) + *p = p[M] ^ TWIST(p[0], p[1]); + + for (j = M; --j; p++) + *p = p[M - N] ^ TWIST(p[0], p[1]); + + *p = p[M - N] ^ TWIST(p[0], state[0]); +} + +/*------------------------------------------------------------*/ + +static void setRndSeed(int seed) +{ + if (seed == 0) + init_genrand(time(NULL)); + else + init_genrand(seed); +} + +/* float number in range [0, 1) using the mersenne twister rng */ +static float frand(void) +{ + unsigned long y; + + if (--left == 0) + next_state(); + y = *next++; + + /* Tempering */ + y ^= (y >> 11); + y ^= (y << 7) & 0x9d2c5680UL; + y ^= (y << 15) & 0xefc60000UL; + y ^= (y >> 18); + + return (float) y / 4294967296.f; +} + +/*------------------------------------------------------------*/ +/* Utility Functions */ +/*------------------------------------------------------------*/ + +/* Fills an array of length size with random numbers in the range (-1, 1)*/ +static void rand_vn(float *array_tar, const int size) +{ + float *array_pt= array_tar + (size-1); + int i= size; + while(i--) { *(array_pt--) = 2.0f * frand() - 1.0f; } +} + +/* Fills an array of length 3 with noise values */ +static void noise_vector(float x, float y, float z, int nb, float v[3]) +{ + /* Simply evaluate noise at 3 different positions */ + v[0]= (float)(2.0f * BLI_gNoise(1.f, x + 9.321f, y - 1.531f, z - 7.951f, 0, nb) - 1.0f); + v[1]= (float)(2.0f * BLI_gNoise(1.f, x, y, z, 0, nb) - 1.0f); + v[2]= (float)(2.0f * BLI_gNoise(1.f, x + 6.327f, y + 0.1671f, z - 2.672f, 0, nb) - 1.0f); +} + +/* Returns a turbulence value for a given position (x, y, z) */ +static float turb(float x, float y, float z, int oct, int hard, int nb, + float ampscale, float freqscale) +{ + float amp, out, t; + int i; + amp = 1.f; + out = (float)(2.0f * BLI_gNoise(1.f, x, y, z, 0, nb) - 1.0f); + if (hard) + out = fabsf(out); + for (i = 1; i < oct; i++) { + amp *= ampscale; + x *= freqscale; + y *= freqscale; + z *= freqscale; + t = (float)(amp * (2.0f * BLI_gNoise(1.f, x, y, z, 0, nb) - 1.0f)); + if (hard) + t = fabsf(t); + out += t; + } + return out; +} + +/* Fills an array of length 3 with the turbulence vector for a given +position (x, y, z) */ +static void vTurb(float x, float y, float z, int oct, int hard, int nb, + float ampscale, float freqscale, float v[3]) +{ + float amp, t[3]; + int i; + amp = 1.f; + noise_vector(x, y, z, nb, v); + if (hard) { + v[0] = fabsf(v[0]); + v[1] = fabsf(v[1]); + v[2] = fabsf(v[2]); + } + for (i = 1; i < oct; i++) { + amp *= ampscale; + x *= freqscale; + y *= freqscale; + z *= freqscale; + noise_vector(x, y, z, nb, t); + if (hard) { + t[0] = fabsf(t[0]); + t[1] = fabsf(t[1]); + t[2] = fabsf(t[2]); + } + v[0] += amp * t[0]; + v[1] += amp * t[1]; + v[2] += amp * t[2]; + } +} + +/*-------------------------DOC STRINGS ---------------------------*/ +PyDoc_STRVAR(M_Noise_doc, +"The Blender noise module" +); + +/*------------------------------------------------------------*/ +/* Python Functions */ +/*------------------------------------------------------------*/ + +PyDoc_STRVAR(M_Noise_random_doc, +".. function:: random()\n" +"\n" +" Returns a random number in the range [0, 1].\n" +"\n" +" :return: The random number.\n" +" :rtype: float\n" +); +static PyObject *M_Noise_random(PyObject *UNUSED(self)) +{ + return PyFloat_FromDouble(frand()); +} + +PyDoc_STRVAR(M_Noise_random_unit_vector_doc, +".. function:: random_unit_vector(size=3)\n" +"\n" +" Returns a unit vector with random entries.\n" +"\n" +" :arg size: The size of the vector to be produced.\n" +" :type size: Int\n" +" :return: The random unit vector.\n" +" :rtype: :class:`mathutils.Vector`\n" +); +static PyObject *M_Noise_random_unit_vector(PyObject *UNUSED(self), PyObject *args) +{ + float vec[4]= {0.0f, 0.0f, 0.0f, 0.0f}; + float norm= 2.0f; + int size= 3; + + if (!PyArg_ParseTuple(args, "|i:random_vector", &size)) + return NULL; + + if (size > 4 || size < 2) { + PyErr_SetString(PyExc_ValueError, "Vector(): invalid size"); + return NULL; + } + + while (norm==0.0f || norm>=1.0f) { + rand_vn(vec, size); + norm= normalize_vn(vec, size); + } + + return Vector_CreatePyObject(vec, size, Py_NEW, NULL); +} +/* This is dumb, most people will want a unit vector anyway, since this doesn't have uniform distribution over a sphere*/ +/* +PyDoc_STRVAR(M_Noise_random_vector_doc, +".. function:: random_vector(size=3)\n" +"\n" +" Returns a vector with random entries in the range [0, 1).\n" +"\n" +" :arg size: The size of the vector to be produced.\n" +" :type size: Int\n" +" :return: The random vector.\n" +" :rtype: :class:`mathutils.Vector`\n" +); +static PyObject *M_Noise_random_vector(PyObject *UNUSED(self), PyObject *args) +{ + float vec[4]= {0.0f, 0.0f, 0.0f, 0.0f}; + int size= 3; + + if (!PyArg_ParseTuple(args, "|i:random_vector", &size)) + return NULL; + + if (size > 4 || size < 2) { + PyErr_SetString(PyExc_ValueError, "Vector(): invalid size"); + return NULL; + } + + rand_vn(vec, size); + + return Vector_CreatePyObject(vec, size, Py_NEW, NULL); +} +*/ + +PyDoc_STRVAR(M_Noise_seed_set_doc, +".. function:: seed_set(seed)\n" +"\n" +" Sets the random seed used for random_unit_vector, random_vector and random.\n" +"\n" +" :arg seed: Seed used for the random generator.\n" +" :type seed: Int\n" +); +static PyObject *M_Noise_seed_set(PyObject *UNUSED(self), PyObject *args) +{ + int s; + if (!PyArg_ParseTuple(args, "i:seed_set", &s)) + return NULL; + setRndSeed(s); + Py_RETURN_NONE; +} + +PyDoc_STRVAR(M_Noise_noise_doc, +".. function:: noise(position, noise_basis=noise.types.STDPERLIN)\n" +"\n" +" Returns noise value from the noise basis at the position specified.\n" +"\n" +" :arg position: The position to evaluate the selected noise function at.\n" +" :type position: :class:`mathutils.Vector`\n" +" :arg noise_basis: The type of noise to be evaluated.\n" +" :type noise_basis: Value in noise.types or int\n" +" :return: The noise value.\n" +" :rtype: float\n" +); +static PyObject *M_Noise_noise(PyObject *UNUSED(self), PyObject *args) +{ + PyObject *value; + float vec[3]; + int nb= 1; + if (!PyArg_ParseTuple(args, "O|i:noise", &value, &nb)) + return NULL; + + if (mathutils_array_parse(vec, 3, 3, value, "noise: invalid 'position' arg") == -1) + return NULL; + + return PyFloat_FromDouble((2.0f * BLI_gNoise(1.0f, vec[0], vec[1], vec[2], 0, nb) - 1.0f)); +} + +PyDoc_STRVAR(M_Noise_noise_vector_doc, +".. function:: noise_vector(position, noise_basis=noise.types.STDPERLIN)\n" +"\n" +" Returns the noise vector from the noise basis at the specified position.\n" +"\n" +" :arg position: The position to evaluate the selected noise function at.\n" +" :type position: :class:`mathutils.Vector`\n" +" :arg noise_basis: The type of noise to be evaluated.\n" +" :type noise_basis: Value in noise.types or int\n" +" :return: The noise vector.\n" +" :rtype: :class:`mathutils.Vector`\n" +); +static PyObject *M_Noise_noise_vector(PyObject *UNUSED(self), PyObject *args) +{ + PyObject *value; + float vec[3], r_vec[3]; + int nb= 1; + + if (!PyArg_ParseTuple(args, "O|i:noise_vector", &value, &nb)) + return NULL; + + if (mathutils_array_parse(vec, 3, 3, value, "noise_vector: invalid 'position' arg") == -1) + return NULL; + + noise_vector(vec[0], vec[1], vec[2], nb, r_vec); + + return Vector_CreatePyObject(r_vec, 3, Py_NEW, NULL); +} + +PyDoc_STRVAR(M_Noise_turbulence_doc, +".. function:: turbulence(position, octaves, hard, noise_basis=noise.types.STDPERLIN, amplitude_scale=0.5, frequency_scale=2.0)\n" +"\n" +" Returns the turbulence value from the noise basis at the specified position.\n" +"\n" +" :arg position: The position to evaluate the selected noise function at.\n" +" :type position: :class:`mathutils.Vector`\n" +" :arg octaves: The number of different noise frequencies used.\n" +" :type octaves: int\n" +" :arg hard: Specifies whether returned turbulence is hard (sharp transitions) or soft (smooth transitions).\n" +" :type hard: :boolean\n" +" :arg noise_basis: The type of noise to be evaluated.\n" +" :type noise_basis: Value in mathutils.noise.types or int\n" +" :arg amplitude_scale: The amplitude scaling factor.\n" +" :type amplitude_scale: float\n" +" :arg frequency_scale: The frequency scaling factor\n" +" :type frequency_scale: Value in noise.types or int\n" +" :return: The turbulence value.\n" +" :rtype: float\n" +); +static PyObject *M_Noise_turbulence(PyObject *UNUSED(self), PyObject *args) +{ + PyObject *value; + float vec[3]; + int oct, hd, nb= 1; + float as= 0.5f, fs= 2.0f; + + if (!PyArg_ParseTuple(args, "Oii|iff:turbulence", &value, &oct, &hd, &nb, &as, &fs)) + return NULL; + + if (mathutils_array_parse(vec, 3, 3, value, "turbulence: invalid 'position' arg") == -1) + return NULL; + + return PyFloat_FromDouble(turb(vec[0], vec[1], vec[2], oct, hd, nb, as, fs)); +} + +PyDoc_STRVAR(M_Noise_turbulence_vector_doc, +".. function:: turbulence_vector(position, octaves, hard, noise_basis=noise.types.STDPERLIN, amplitude_scale=0.5, frequency_scale=2.0)\n" +"\n" +" Returns the turbulence vector from the noise basis at the specified position.\n" +"\n" +" :arg position: The position to evaluate the selected noise function at.\n" +" :type position: :class:`mathutils.Vector`\n" +" :arg octaves: The number of different noise frequencies used.\n" +" :type octaves: int\n" +" :arg hard: Specifies whether returned turbulence is hard (sharp transitions) or soft (smooth transitions).\n" +" :type hard: :boolean\n" +" :arg noise_basis: The type of noise to be evaluated.\n" +" :type noise_basis: Value in mathutils.noise.types or int\n" +" :arg amplitude_scale: The amplitude scaling factor.\n" +" :type amplitude_scale: float\n" +" :arg frequency_scale: The frequency scaling factor\n" +" :type frequency_scale: Value in noise.types or int\n" +" :return: The turbulence vector.\n" +" :rtype: :class:`mathutils.Vector`\n" +); +static PyObject *M_Noise_turbulence_vector(PyObject *UNUSED(self), PyObject *args) +{ + PyObject *value; + float vec[3], r_vec[3]; + int oct, hd, nb= 1; + float as =0.5f, fs= 2.0f; + if (!PyArg_ParseTuple(args, "Oii|iff:turbulence_vector", &value, &oct, &hd, &nb, &as, &fs)) + return NULL; + + if (mathutils_array_parse(vec, 3, 3, value, "turbulence_vector: invalid 'position' arg") == -1) + return NULL; + + vTurb(vec[0], vec[1], vec[2], oct, hd, nb, as, fs, r_vec); + return Vector_CreatePyObject(r_vec, 3, Py_NEW, NULL); +} + +/* F. Kenton Musgrave's fractal functions */ +PyDoc_STRVAR(M_Noise_fractal_doc, +".. function:: fractal(position, H, lacunarity, octaves, noise_basis=noise.types.STDPERLIN)\n" +"\n" +" Returns the fractal Brownian motion (fBm) noise value from the noise basis at the specified position.\n" +"\n" +" :arg position: The position to evaluate the selected noise function at.\n" +" :type position: :class:`mathutils.Vector`\n" +" :arg H: The fractal increment factor.\n" +" :type H: float\n" +" :arg lacunarity: The gap between successive frequencies.\n" +" :type lacunarity: float\n" +" :arg octaves: The number of different noise frequencies used.\n" +" :type octaves: int\n" +" :arg noise_basis: The type of noise to be evaluated.\n" +" :type noise_basis: Value in noise.types or int\n" +" :return: The fractal Brownian motion noise value.\n" +" :rtype: float\n" +); +static PyObject *M_Noise_fractal(PyObject *UNUSED(self), PyObject *args) +{ + PyObject *value; + float vec[3]; + float H, lac, oct; + int nb= 1; + + if (!PyArg_ParseTuple(args, "Offf|i:fractal", &value, &H, &lac, &oct, &nb)) + return NULL; + + if (mathutils_array_parse(vec, 3, 3, value, "fractal: invalid 'position' arg") == -1) + return NULL; + + return PyFloat_FromDouble(mg_fBm(vec[0], vec[1], vec[2], H, lac, oct, nb)); +} + +PyDoc_STRVAR(M_Noise_multi_fractal_doc, +".. function:: multi_fractal(position, H, lacunarity, octaves, noise_basis=noise.types.STDPERLIN)\n" +"\n" +" Returns multifractal noise value from the noise basis at the specified position.\n" +"\n" +" :arg position: The position to evaluate the selected noise function at.\n" +" :type position: :class:`mathutils.Vector`\n" +" :arg H: The fractal increment factor.\n" +" :type H: float\n" +" :arg lacunarity: The gap between successive frequencies.\n" +" :type lacunarity: float\n" +" :arg octaves: The number of different noise frequencies used.\n" +" :type octaves: int\n" +" :arg noise_basis: The type of noise to be evaluated.\n" +" :type noise_basis: Value in noise.types or int\n" +" :return: The multifractal noise value.\n" +" :rtype: float\n" +); +static PyObject *M_Noise_multi_fractal(PyObject *UNUSED(self), PyObject *args) +{ + PyObject *value; + float vec[3]; + float H, lac, oct; + int nb= 1; + + if (!PyArg_ParseTuple(args, "Offf|i:multi_fractal", &value, &H, &lac, &oct, &nb)) + return NULL; + + if (mathutils_array_parse(vec, 3, 3, value, "multi_fractal: invalid 'position' arg") == -1) + return NULL; + + return PyFloat_FromDouble(mg_MultiFractal(vec[0], vec[1], vec[2], H, lac, oct, nb)); +} + +PyDoc_STRVAR(M_Noise_variable_lacunarity_doc, +".. function:: variable_lacunarity(position, distortion, noise_type1=noise.types.STDPERLIN, noise_type2=noise.types.STDPERLIN)\n" +"\n" +" Returns variable lacunarity noise value, a distorted variety of noise, from noise type 1 distorted by noise type 2 at the specified position.\n" +"\n" +" :arg position: The position to evaluate the selected noise function at.\n" +" :type position: :class:`mathutils.Vector`\n" +" :arg distortion: The amount of distortion.\n" +" :type distortion: float\n" +" :arg noise_type1: The type of noise to be distorted.\n" +" :type noise_type1: Value in noise.types or int\n" +" :arg noise_type2: The type of noise used to distort noise_type1.\n" +" :type noise_type2: Value in noise.types or int\n" +" :return: The variable lacunarity noise value.\n" +" :rtype: float\n" +); +static PyObject *M_Noise_variable_lacunarity(PyObject *UNUSED(self), PyObject *args) +{ + PyObject *value; + float vec[3]; + float d; + int nt1= 1, nt2= 1; + + if (!PyArg_ParseTuple(args, "Of|ii:variable_lacunarity", &value, &d, &nt1, &nt2)) + return NULL; + + if (mathutils_array_parse(vec, 3, 3, value, "variable_lacunarity: invalid 'position' arg") == -1) + return NULL; + + return PyFloat_FromDouble(mg_VLNoise(vec[0], vec[1], vec[2], d, nt1, nt2)); +} + +PyDoc_STRVAR(M_Noise_hetero_terrain_doc, +".. function:: hetero_terrain(position, H, lacunarity, octaves, offset, noise_basis=noise.types.STDPERLIN)\n" +"\n" +" Returns the heterogeneous terrain value from the noise basis at the specified position.\n" +"\n" +" :arg position: The position to evaluate the selected noise function at.\n" +" :type position: :class:`mathutils.Vector`\n" +" :arg H: The fractal dimension of the roughest areas.\n" +" :type H: float\n" +" :arg lacunarity: The gap between successive frequencies.\n" +" :type lacunarity: float\n" +" :arg octaves: The number of different noise frequencies used.\n" +" :type octaves: int\n" +" :arg offset: The height of the terrain above 'sea level'.\n" +" :type offset: float\n" +" :arg noise_basis: The type of noise to be evaluated.\n" +" :type noise_basis: Value in noise.types or int\n" +" :return: The heterogeneous terrain value.\n" +" :rtype: float\n" +); +static PyObject *M_Noise_hetero_terrain(PyObject *UNUSED(self), PyObject *args) +{ + PyObject *value; + float vec[3]; + float H, lac, oct, ofs; + int nb= 1; + + if (!PyArg_ParseTuple(args, "Offff|i:hetero_terrain", &value, &H, &lac, &oct, &ofs, &nb)) + return NULL; + + if (mathutils_array_parse(vec, 3, 3, value, "hetero_terrain: invalid 'position' arg") == -1) + return NULL; + + return PyFloat_FromDouble(mg_HeteroTerrain(vec[0], vec[1], vec[2], H, lac, oct, ofs, nb)); +} + +PyDoc_STRVAR(M_Noise_hybrid_multi_fractal_doc, +".. function:: hybrid_multi_fractal(position, H, lacunarity, octaves, offset, gain, noise_basis=noise.types.STDPERLIN)\n" +"\n" +" Returns hybrid multifractal value from the noise basis at the specified position.\n" +"\n" +" :arg position: The position to evaluate the selected noise function at.\n" +" :type position: :class:`mathutils.Vector`\n" +" :arg H: The fractal dimension of the roughest areas.\n" +" :type H: float\n" +" :arg lacunarity: The gap between successive frequencies.\n" +" :type lacunarity: float\n" +" :arg octaves: The number of different noise frequencies used.\n" +" :type octaves: int\n" +" :arg offset: The height of the terrain above 'sea level'.\n" +" :type offset: float\n" +" :arg gain: Scaling applied to the values.\n" +" :type gain: float\n" +" :arg noise_basis: The type of noise to be evaluated.\n" +" :type noise_basis: Value in noise.types or int\n" +" :return: The hybrid multifractal value.\n" +" :rtype: float\n" +); +static PyObject *M_Noise_hybrid_multi_fractal(PyObject *UNUSED(self), PyObject *args) +{ + PyObject *value; + float vec[3]; + float H, lac, oct, ofs, gn; + int nb= 1; + + if (!PyArg_ParseTuple(args, "Offfff|i:hybrid_multi_fractal", &value, &H, &lac, &oct, &ofs, &gn, &nb)) + return NULL; + + if (mathutils_array_parse(vec, 3, 3, value, "hybrid_multi_fractal: invalid 'position' arg") == -1) + return NULL; + + return PyFloat_FromDouble(mg_HybridMultiFractal(vec[0], vec[1], vec[2], H, lac, oct, ofs, gn, nb)); +} + +PyDoc_STRVAR(M_Noise_ridged_multi_fractal_doc, +".. function:: ridged_multi_fractal(position, H, lacunarity, octaves, offset, gain, noise_basis=noise.types.STDPERLIN)\n" +"\n" +" Returns ridged multifractal value from the noise basis at the specified position.\n" +"\n" +" :arg position: The position to evaluate the selected noise function at.\n" +" :type position: :class:`mathutils.Vector`\n" +" :arg H: The fractal dimension of the roughest areas.\n" +" :type H: float\n" +" :arg lacunarity: The gap between successive frequencies.\n" +" :type lacunarity: float\n" +" :arg octaves: The number of different noise frequencies used.\n" +" :type octaves: int\n" +" :arg offset: The height of the terrain above 'sea level'.\n" +" :type offset: float\n" +" :arg gain: Scaling applied to the values.\n" +" :type gain: float\n" +" :arg noise_basis: The type of noise to be evaluated.\n" +" :type noise_basis: Value in noise.types or int\n" +" :return: The ridged multifractal value.\n" +" :rtype: float\n" +); +static PyObject *M_Noise_ridged_multi_fractal(PyObject *UNUSED(self), PyObject *args) +{ + PyObject *value; + float vec[3]; + float H, lac, oct, ofs, gn; + int nb= 1; + + if (!PyArg_ParseTuple(args, "Offfff|i:ridged_multi_fractal", &value, &H, &lac, &oct, &ofs, &gn, &nb)) + return NULL; + + if (mathutils_array_parse(vec, 3, 3, value, "ridged_multi_fractal: invalid 'position' arg") == -1) + return NULL; + + return PyFloat_FromDouble(mg_RidgedMultiFractal(vec[0], vec[1], vec[2], H, lac, oct, ofs, gn, nb)); +} + +PyDoc_STRVAR(M_Noise_voronoi_doc, +".. function:: voronoi(position, distance_metric=noise.distance_metrics.DISTANCE, exponent=2.5)\n" +"\n" +" Returns a list of distances to the four closest features and their locations.\n" +"\n" +" :arg position: The position to evaluate the selected noise function at.\n" +" :type position: :class:`mathutils.Vector`\n" +" :arg distance_metric: Method of measuring distance.\n" +" :type distance_metric: Value in noise.distance_metrics or int\n" +" :arg exponent: The exponent for Minkovsky distance metric.\n" +" :type exponent: float\n" +" :return: A list of distances to the four closest features and their locations.\n" +" :rtype: [list of four floats, list of four :class:`mathutils.Vector`s]\n" +); +static PyObject *M_Noise_voronoi(PyObject *UNUSED(self), PyObject *args) +{ + PyObject *value; + PyObject *list; + float vec[3]; + float da[4], pa[12]; + int dtype= 0; + float me= 2.5f; /* default minkovsky exponent */ + + int i; + + if (!PyArg_ParseTuple(args, "O|if:voronoi", &value, &dtype, &me)) + return NULL; + + if (mathutils_array_parse(vec, 3, 3, value, "voronoi: invalid 'position' arg") == -1) + return NULL; + + list= PyList_New(4); + + voronoi(vec[0], vec[1], vec[2], da, pa, me, dtype); + + for (i=0; i<4; i++) { + PyList_SET_ITEM(list, i, Vector_CreatePyObject(pa + 3*i, 3, Py_NEW, NULL)); + } + + return Py_BuildValue("[[ffff]O]", da[0], da[1], da[2], da[3], list); +} + +PyDoc_STRVAR(M_Noise_cell_doc, +".. function:: cell(position)\n" +"\n" +" Returns cell noise value at the specified position.\n" +"\n" +" :arg position: The position to evaluate the selected noise function at.\n" +" :type position: :class:`mathutils.Vector`\n" +" :return: The cell noise value.\n" +" :rtype: float\n" +); +static PyObject *M_Noise_cell(PyObject *UNUSED(self), PyObject *args) +{ + PyObject *value; + float vec[3]; + + if (!PyArg_ParseTuple(args, "O:cell", &value)) + return NULL; + + if (mathutils_array_parse(vec, 3, 3, value, "cell: invalid 'position' arg") == -1) + return NULL; + + return PyFloat_FromDouble(cellNoise(vec[0], vec[1], vec[2])); +} + +PyDoc_STRVAR(M_Noise_cell_vector_doc, +".. function:: cell_vector(position)\n" +"\n" +" Returns cell noise vector at the specified position.\n" +"\n" +" :arg position: The position to evaluate the selected noise function at.\n" +" :type position: :class:`mathutils.Vector`\n" +" :return: The cell noise vector.\n" +" :rtype: :class:`mathutils.Vector`\n" +); +static PyObject *M_Noise_cell_vector(PyObject *UNUSED(self), PyObject *args) +{ + PyObject *value; + float vec[3], r_vec[3]; + + if (!PyArg_ParseTuple(args, "O:cell_vector", &value)) + return NULL; + + if (mathutils_array_parse(vec, 3, 3, value, "cell_vector: invalid 'position' arg") == -1) + return NULL; + + cellNoiseV(vec[0], vec[1], vec[2], r_vec); + return Vector_CreatePyObject(NULL, 3, Py_NEW, NULL);; +} + +static PyMethodDef M_Noise_methods[] = { + {"seed_set", (PyCFunction) M_Noise_seed_set, METH_VARARGS, M_Noise_seed_set_doc}, + {"random", (PyCFunction) M_Noise_random, METH_NOARGS, M_Noise_random_doc}, + {"random_unit_vector", (PyCFunction) M_Noise_random_unit_vector, METH_VARARGS, M_Noise_random_unit_vector_doc}, + /*{"random_vector", (PyCFunction) M_Noise_random_vector, METH_VARARGS, M_Noise_random_vector_doc},*/ + {"noise", (PyCFunction) M_Noise_noise, METH_VARARGS, M_Noise_noise_doc}, + {"noise_vector", (PyCFunction) M_Noise_noise_vector, METH_VARARGS, M_Noise_noise_vector_doc}, + {"turbulence", (PyCFunction) M_Noise_turbulence, METH_VARARGS, M_Noise_turbulence_doc}, + {"turbulence_vector", (PyCFunction) M_Noise_turbulence_vector, METH_VARARGS, M_Noise_turbulence_vector_doc}, + {"fractal", (PyCFunction) M_Noise_fractal, METH_VARARGS, M_Noise_fractal_doc}, + {"multi_fractal", (PyCFunction) M_Noise_multi_fractal, METH_VARARGS, M_Noise_multi_fractal_doc}, + {"variable_lacunarity", (PyCFunction) M_Noise_variable_lacunarity, METH_VARARGS, M_Noise_variable_lacunarity_doc}, + {"hetero_terrain", (PyCFunction) M_Noise_hetero_terrain, METH_VARARGS, M_Noise_hetero_terrain_doc}, + {"hybrid_multi_fractal", (PyCFunction) M_Noise_hybrid_multi_fractal, METH_VARARGS, M_Noise_hybrid_multi_fractal_doc}, + {"ridged_multi_fractal", (PyCFunction) M_Noise_ridged_multi_fractal, METH_VARARGS, M_Noise_ridged_multi_fractal_doc}, + {"voronoi", (PyCFunction) M_Noise_voronoi, METH_VARARGS, M_Noise_voronoi_doc}, + {"cell", (PyCFunction) M_Noise_cell, METH_VARARGS, M_Noise_cell_doc}, + {"cell_vector", (PyCFunction) M_Noise_cell_vector, METH_VARARGS, M_Noise_cell_vector_doc}, + {NULL, NULL, 0, NULL} +}; + +static struct PyModuleDef M_Noise_module_def = { + PyModuleDef_HEAD_INIT, + "mathutils.noise", /* m_name */ + M_Noise_doc, /* m_doc */ + 0, /* m_size */ + M_Noise_methods, /* m_methods */ + NULL, /* m_reload */ + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL, /* m_free */ +}; + +/*----------------------------MODULE INIT-------------------------*/ +PyMODINIT_FUNC PyInit_mathutils_noise(void) +{ + PyObject *submodule = PyModule_Create(&M_Noise_module_def); + PyObject *item_types, *item_metrics; + + /* use current time as seed for random number generator by default */ + setRndSeed(0); + + PyModule_AddObject(submodule, "types", (item_types=PyInit_mathutils_noise_types())); + PyDict_SetItemString(PyThreadState_GET()->interp->modules, "noise.types", item_types); + Py_INCREF(item_types); + + PyModule_AddObject(submodule, "distance_metrics", (item_metrics=PyInit_mathutils_noise_metrics())); + PyDict_SetItemString(PyThreadState_GET()->interp->modules, "noise.distance_metrics", item_metrics); + Py_INCREF(item_metrics); + + return submodule; +} + +/*----------------------------SUBMODULE INIT-------------------------*/ +static struct PyModuleDef M_NoiseTypes_module_def = { + PyModuleDef_HEAD_INIT, + "mathutils.noise.types", /* m_name */ + NULL, /* m_doc */ + 0, /* m_size */ + NULL, /* m_methods */ + NULL, /* m_reload */ + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL, /* m_free */ +}; + +PyMODINIT_FUNC PyInit_mathutils_noise_types(void) +{ + PyObject *submodule = PyModule_Create(&M_NoiseTypes_module_def); + + PyModule_AddIntConstant(submodule, (char *)"BLENDER", TEX_BLENDER); + PyModule_AddIntConstant(submodule, (char *)"STDPERLIN", TEX_STDPERLIN); + PyModule_AddIntConstant(submodule, (char *)"NEWPERLIN", TEX_NEWPERLIN); + PyModule_AddIntConstant(submodule, (char *)"VORONOI_F1", TEX_VORONOI_F1); + PyModule_AddIntConstant(submodule, (char *)"VORONOI_F2", TEX_VORONOI_F2); + PyModule_AddIntConstant(submodule, (char *)"VORONOI_F3", TEX_VORONOI_F3); + PyModule_AddIntConstant(submodule, (char *)"VORONOI_F4", TEX_VORONOI_F4); + PyModule_AddIntConstant(submodule, (char *)"VORONOI_F2F1", TEX_VORONOI_F2F1); + PyModule_AddIntConstant(submodule, (char *)"VORONOI_CRACKLE", TEX_VORONOI_CRACKLE); + PyModule_AddIntConstant(submodule, (char *)"CELLNOISE", TEX_CELLNOISE); + + return submodule; +} + +static struct PyModuleDef M_NoiseMetrics_module_def = { + PyModuleDef_HEAD_INIT, + "mathutils.noise.distance_metrics", /* m_name */ + NULL, /* m_doc */ + 0, /* m_size */ + NULL, /* m_methods */ + NULL, /* m_reload */ + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL, /* m_free */ +}; + +PyMODINIT_FUNC PyInit_mathutils_noise_metrics(void) +{ + PyObject *submodule = PyModule_Create(&M_NoiseMetrics_module_def); + + PyModule_AddIntConstant(submodule, (char *)"DISTANCE", TEX_DISTANCE); + PyModule_AddIntConstant(submodule, (char *)"DISTANCE_SQUARED", TEX_DISTANCE_SQUARED); + PyModule_AddIntConstant(submodule, (char *)"MANHATTAN", TEX_MANHATTAN); + PyModule_AddIntConstant(submodule, (char *)"CHEBYCHEV", TEX_CHEBYCHEV); + PyModule_AddIntConstant(submodule, (char *)"MINKOVSKY_HALF", TEX_MINKOVSKY_HALF); + PyModule_AddIntConstant(submodule, (char *)"MINKOVSKY_FOUR", TEX_MINKOVSKY_FOUR); + PyModule_AddIntConstant(submodule, (char *)"MINKOVSKY", TEX_MINKOVSKY); + + return submodule; +} diff --git a/source/blender/python/generic/noise_py_api.h b/source/blender/python/mathutils/mathutils_noise.h index 60f43e16158..6a6527588ef 100644 --- a/source/blender/python/generic/noise_py_api.h +++ b/source/blender/python/mathutils/mathutils_noise.h @@ -20,13 +20,17 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file blender/python/generic/noise_py_api.h - * \ingroup pygen +/** \file blender/python/mathutils/mathutils_noise.h + * \ingroup mathutils */ -#ifndef NOISE_PY_API_H -#define NOISE_PY_API_H +#ifndef MATHUTILS_NOISE_H +#define MATHUTILS_NOISE_H -PyObject *BPyInit_noise(void); +#include "mathutils.h" -#endif // NOISE_PY_API_H +PyMODINIT_FUNC PyInit_mathutils_noise(void); +PyMODINIT_FUNC PyInit_mathutils_noise_types(void); +PyMODINIT_FUNC PyInit_mathutils_noise_metrics(void); + +#endif // MATHUTILS_NOISE_H |