diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index 6f3876c1d96..2426146184a 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -73,7 +73,9 @@ GHOST_NDOFManager::deviceOpen(GHOST_IWindow* window, if (ndofLibraryInit && ndofDeviceOpen) { Pid= ndofLibraryInit(); +#if 0 printf("%i client \n", Pid); +#endif #if defined(_WIN32) || defined(__APPLE__) m_DeviceHandle = ndofDeviceOpen((void *)¤tNdofValues); #else diff --git a/intern/ghost/intern/GHOST_System.cpp b/intern/ghost/intern/GHOST_System.cpp index 458a35bf34b..87e5f375958 100644 --- a/intern/ghost/intern/GHOST_System.cpp +++ b/intern/ghost/intern/GHOST_System.cpp @@ -283,9 +283,11 @@ GHOST_TSuccess GHOST_System::init() m_eventManager = new GHOST_EventManager (); m_ndofManager = new GHOST_NDOFManager(); +#if 0 if(m_ndofManager) printf("ndof manager \n"); - +#endif + #ifdef GHOST_DEBUG if (m_eventManager) { m_eventManager->addConsumer(&m_eventPrinter); diff --git a/release/scripts/3ds_export.py b/release/scripts/3ds_export.py index 0209b04844a..54e1ea3db33 100644 --- a/release/scripts/3ds_export.py +++ b/release/scripts/3ds_export.py @@ -1,5 +1,5 @@ #!BPY - +# coding: utf-8 """ Name: '3D Studio (.3ds)...' Blender: 243 diff --git a/release/scripts/bevel_center.py b/release/scripts/bevel_center.py index 0ea305a0120..a68b382ad2b 100644 --- a/release/scripts/bevel_center.py +++ b/release/scripts/bevel_center.py @@ -1,5 +1,5 @@ #!BPY - +# coding: utf-8 """ Registration info for Blender menus Name: 'Bevel Center' Blender: 243 diff --git a/release/scripts/blenderLipSynchro.py b/release/scripts/blenderLipSynchro.py index ef765086e25..c4815811512 100644 --- a/release/scripts/blenderLipSynchro.py +++ b/release/scripts/blenderLipSynchro.py @@ -1,5 +1,5 @@ #!BPY - +# coding: utf-8 """ Name: 'BlenderLipSynchro' Blender: 242 diff --git a/release/scripts/export_m3g.py b/release/scripts/export_m3g.py index 08215b3d027..86ac03cc407 100644 --- a/release/scripts/export_m3g.py +++ b/release/scripts/export_m3g.py @@ -1,4 +1,5 @@ #!BPY +# coding: utf-8 """ Registration info for Blender menus: Name: 'M3G (.m3g, .java)...' Blender: 244 @@ -3069,4 +3070,5 @@ def file_callback_m3g(filename): Window.RedrawAll() if __name__ == '__main__': - gui() \ No newline at end of file + gui() + diff --git a/release/scripts/hotkeys.py b/release/scripts/hotkeys.py index bfaac252b21..929132933ec 100644 --- a/release/scripts/hotkeys.py +++ b/release/scripts/hotkeys.py @@ -1,5 +1,5 @@ #!BPY - +# coding: utf-8 """ Registration info for Blender menus: Name: 'HotKey and MouseAction Reference' Blender: 242 @@ -918,4 +918,4 @@ def bevent(evt): Blender.Window.Redraw() if __name__ == '__main__': - Register(draw, event, bevent) \ No newline at end of file + Register(draw, event, bevent) diff --git a/release/scripts/import_dxf.py b/release/scripts/import_dxf.py index 4fa7a6472cf..88b42e3e564 100644 --- a/release/scripts/import_dxf.py +++ b/release/scripts/import_dxf.py @@ -1,5 +1,5 @@ #!BPY - +# coding: utf-8 """ Name: 'Autodesk DXF (.dxf)' Blender: 244 @@ -5942,4 +5942,5 @@ if 1: main(_dxf) print 'TOTAL TIME: %.6f' % (Blender.sys.time() - TIME) -""" \ No newline at end of file +""" + diff --git a/release/scripts/paths_import.py b/release/scripts/paths_import.py index f36454978ba..788c6b0216b 100644 --- a/release/scripts/paths_import.py +++ b/release/scripts/paths_import.py @@ -1,5 +1,5 @@ #!BPY - +# coding: utf-8 """ Name: 'Paths (.svg, .ps, .eps, .ai, Gimp)' Blender: 233 @@ -92,4 +92,5 @@ elif argv=='Gimp_2_0': fonctionSELECT = functionSELECT # can they all be called function? text = 'Import %s' % argv -Blender.Window.FileSelector (fonctionSELECT, text) \ No newline at end of file +Blender.Window.FileSelector (fonctionSELECT, text) + diff --git a/release/scripts/rvk1_torvk2.py b/release/scripts/rvk1_torvk2.py index 754d2d0af2d..c490ba328c8 100644 --- a/release/scripts/rvk1_torvk2.py +++ b/release/scripts/rvk1_torvk2.py @@ -1,5 +1,5 @@ #!BPY - +# coding: utf-8 """ Registration info for Blender menus: <- these words are ignored Name: 'Deformed mesh to Rvk' Blender: 243 @@ -270,4 +270,4 @@ def deform2rvk(): EDITMODE=Blender.Window.EditMode() Blender.Window.EditMode(0) deform2rvk() -Blender.Window.EditMode(EDITMODE) \ No newline at end of file +Blender.Window.EditMode(EDITMODE) diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 88f0971ac1d..bd8e0da3232 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -1054,7 +1054,11 @@ ParticleSystem *copy_particlesystem(ParticleSystem *psys) psysn->childcache= NULL; psysn->edit= NULL; psysn->effectors.first= psysn->effectors.last= 0; - + + psysn->pathcachebufs.first = psysn->pathcachebufs.last = NULL; + psysn->reactevents.first = psysn->reactevents.last = NULL; + psysn->renderdata = NULL; + psysn->pointcache= BKE_ptcache_copy(psys->pointcache); id_us_plus((ID *)psysn->part); diff --git a/source/blender/freestyle/SConscript b/source/blender/freestyle/SConscript index 2bc08822a6e..b56c0c66c6e 100644 --- a/source/blender/freestyle/SConscript +++ b/source/blender/freestyle/SConscript @@ -45,6 +45,12 @@ prefix = 'intern/stroke' stroke_sources = env.Glob(prefix + '/*.cpp') # rendering +prefix = 'intern/rendering' +stroke_sources = env.Glob(prefix + '/GL*.cpp') + +if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw'): + stroke_sources = env.Glob(prefix + '/extgl.cpp') + # app sources = system_sources + image_sources + geometry_sources + scene_graph_sources + \ diff --git a/source/blender/freestyle/intern/rendering/GLRenderer.cpp b/source/blender/freestyle/intern/rendering/GLRenderer.cpp index d566060dfc7..016b159da5c 100755 --- a/source/blender/freestyle/intern/rendering/GLRenderer.cpp +++ b/source/blender/freestyle/intern/rendering/GLRenderer.cpp @@ -281,7 +281,7 @@ void GLRenderer::visitLineRep( LineRep& iLine) } const vector& vertices = iLine.vertices(); - float step=1.f/vertices.size(); + //soc unused float step=1.f/vertices.size(); vector::const_iterator v; for(v=vertices.begin(); v!=vertices.end(); v++) diff --git a/source/blender/freestyle/intern/rendering/GLStrokeRenderer.cpp b/source/blender/freestyle/intern/rendering/GLStrokeRenderer.cpp index 7525807da47..8177f3b02db 100755 --- a/source/blender/freestyle/intern/rendering/GLStrokeRenderer.cpp +++ b/source/blender/freestyle/intern/rendering/GLStrokeRenderer.cpp @@ -19,12 +19,18 @@ // /////////////////////////////////////////////////////////////////////////////// -#include -#include -#include -#include #include "GLStrokeRenderer.h" +//soc +// #include +// #include +// #include +// #include +#include "BLI_blenlib.h" +#include "IMB_imbuf.h" +#include "IMB_imbuf_types.h" +#include "../system/StringUtils.h" + #ifdef WIN32 # include "extgl.h" #endif // WIN32 @@ -77,7 +83,7 @@ void GLStrokeRenderer::RenderStrokeRep(StrokeRep *iStrokeRep) const // renderNoTexture(iStrokeRep); // return; // } - int i; + //soc unused - int i; glDisable(GL_CULL_FACE); glDisable(GL_LIGHTING); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); @@ -150,8 +156,8 @@ void GLStrokeRenderer::RenderStrokeRep(StrokeRep *iStrokeRep) const void GLStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const { glPushAttrib(GL_COLOR_BUFFER_BIT); - Stroke::MediumType strokeType = iStrokeRep->getMediumType(); - int i; + //soc unused - Stroke::MediumType strokeType = iStrokeRep->getMediumType(); + //soc unused - int i; glDisable(GL_CULL_FACE); glDisable(GL_LIGHTING); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); @@ -273,7 +279,7 @@ GLTextureManager::loadPapers () _papertexname = new unsigned[size]; GLuint *tmp = new GLuint[size]; glGenTextures(size, tmp); - for(int i=0;i pathnames; - QString path; + string path; //soc StringUtils::getPathName(TextureManager::Options::getBrushesPath(), sname, pathnames); for (vector::const_iterator j = pathnames.begin(); j != pathnames.end(); j++) { path = j->c_str(); - if(QFile::exists(path)){ + //soc if(QFile::exists(path)){ + if( BLI_exists( const_cast(path.c_str()) ) ) { found = true; break; } @@ -325,12 +332,14 @@ GLTextureManager::loadBrush(string sname, Stroke::MediumType mediumType) cout << "Loading brush texture..." << endl; switch(mediumType){ case Stroke::DRY_MEDIUM: - prepareTextureLuminance((const char*)path.toAscii(), texId); + //soc prepareTextureLuminance((const char*)path.toAscii(), texId); + prepareTextureLuminance(StringUtils::toAscii(path), texId); break; case Stroke::HUMID_MEDIUM: case Stroke::OPAQUE_MEDIUM: default: - prepareTextureAlpha((const char*)path.toAscii(), texId); + //soc prepareTextureAlpha((const char*)path.toAscii(), texId); + prepareTextureAlpha(StringUtils::toAscii(path), texId); break; } cout << "Done." << endl << endl; @@ -341,18 +350,26 @@ GLTextureManager::loadBrush(string sname, Stroke::MediumType mediumType) bool GLTextureManager::prepareTextureAlpha (string sname, GLuint itexname) { - const char * name = sname.c_str(); - QImage qim(name); - QFileInfo fi(name); - QString filename = fi.fileName(); - if (qim.isNull()) + //soc const char * name = sname.c_str(); + char * name = (char *) sname.c_str(); + + //soc + // QImage qim(name); + // QFileInfo fi(name); + // QString filename = fi.fileName(); + ImBuf *qim = IMB_loadiffname(name, 0); + char filename[FILE_MAXFILE]; + BLI_splitdirstring(name, filename); + +//soc if (qim.isNull()) + if( qim ) { cerr << " Error: unable to read \"" << name << "\"" << endl; return false; } - if (qim.depth()>8) + if( qim->depth > 8) //soc { - cerr<<" Error: \""<< name <<"\" has "<depth <<" bits/pixel"<x, qim->y, 0, + GL_ALPHA, GL_UNSIGNED_BYTE, qim->rect); //soc + //soc cout << " \"" << filename.toAscii().data() << "\" loaded with "<< qim.depth() << " bits per pixel" << endl; + cout << " \"" << StringUtils::toAscii(filename) << "\" loaded with "<< qim->depth << " bits per pixel" << endl; + return true; } @@ -381,18 +399,25 @@ GLTextureManager::prepareTextureAlpha (string sname, GLuint itexname) bool GLTextureManager::prepareTextureLuminance (string sname, GLuint itexname) { - const char * name = sname.c_str(); - QImage qim(name); - QFileInfo fi(name); - QString filename = fi.fileName(); - if (qim.isNull()) + //soc const char * name = sname.c_str(); + char * name = (char *) sname.c_str(); + + //soc + // QImage qim(name); + // QFileInfo fi(name); + // QString filename = fi.fileName(); + ImBuf *qim = IMB_loadiffname(name, 0); + char filename[FILE_MAXFILE]; + BLI_splitdirstring(name, filename); + + if (qim) //soc { cerr << " Error: unable to read \"" << name << "\"" << endl; return false; } - if (qim.depth() > 8) + if (qim->depth > 8) //soc { - cerr<<" Error: \""<depth <<" bits/pixel"<x, qim->y, 0, + GL_LUMINANCE, GL_UNSIGNED_BYTE, qim->rect); //soc + //soc cout << " \"" << filename.toAscii().data() << "\" loaded with "<< qim.depth() << " bits per pixel" << endl; + cout << " \"" << StringUtils::toAscii(filename) << "\" loaded with "<< qim->depth << " bits per pixel" << endl; + return true; } @@ -420,18 +446,25 @@ GLTextureManager::prepareTextureLuminance (string sname, GLuint itexname) bool GLTextureManager::prepareTextureLuminanceAndAlpha (string sname, GLuint itexname) { - const char * name = sname.c_str(); - QImage qim(name); - QFileInfo fi(name); - QString filename = fi.fileName(); - if (qim.isNull()) + //soc const char * name = sname.c_str(); + char * name = (char *) sname.c_str(); + + //soc + // QImage qim(name); + // QFileInfo fi(name); + // QString filename = fi.fileName(); + ImBuf *qim = IMB_loadiffname(name, 0); + char filename[FILE_MAXFILE]; + BLI_splitdirstring(name, filename); + + if (qim) //soc { cerr << " Error: unable to read \"" << name << "\"" << endl; return false; } - if (qim.depth() > 8) + if (qim->depth > 8) //soc { - cerr<<" Error: \""<depth<<" bits/pixel"<x, qim->y, 0, + GL_LUMINANCE, GL_UNSIGNED_BYTE, qim->rect); //soc + glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, qim->x, qim->y, 0, + GL_ALPHA, GL_UNSIGNED_BYTE, qim->rect); //soc - cout << " \"" << filename.toAscii().data() << "\" loaded with "<< qim.depth() << " bits per pixel" << endl; + //soc cout << " \"" << filename.toAscii().data() << "\" loaded with "<< qim.depth() << " bits per pixel" << endl; + cout << " \"" << StringUtils::toAscii(filename) << "\" loaded with "<< qim->depth << " bits per pixel" << endl; return true; @@ -461,20 +495,25 @@ GLTextureManager::prepareTextureLuminanceAndAlpha (string sname, GLuint itexname bool GLTextureManager::preparePaper (const char *name, GLuint itexname) { - QImage qim(name); - QFileInfo fi(name); - QString filename = fi.fileName(); - if (qim.isNull()) + //soc + // QImage qim(name); + // QFileInfo fi(name); + // QString filename = fi.fileName(); + ImBuf *qim = IMB_loadiffname(name, 0); + char filename[FILE_MAXFILE]; + BLI_splitdirstring((char *)name, filename); + + if (qim) //soc { cerr << " Error: unable to read \"" << name << "\"" << endl; return false; } - if (qim.depth()!=32) + if (qim->depth !=32) //soc { - cerr<<" Error: \""<depth<<" bits/pixel"<x, qim->y, 0, + GL_RGBA, GL_UNSIGNED_BYTE, qim->rect); //soc: here qim->rect, not qim2->rect, used + //cout << " \"" << filename.toAscii().data() << "\" loaded with "<< qim.depth() << " bits per pixel" << endl; + cout << " \"" << StringUtils::toAscii(filename) << "\" loaded with "<< qim->depth << " bits per pixel" << endl; return true; } diff --git a/source/blender/freestyle/intern/rendering/GLUtils.cpp b/source/blender/freestyle/intern/rendering/GLUtils.cpp index 5e9ba2a5bf4..f086f86e2cd 100755 --- a/source/blender/freestyle/intern/rendering/GLUtils.cpp +++ b/source/blender/freestyle/intern/rendering/GLUtils.cpp @@ -63,6 +63,8 @@ void *glutils_extgl_GetProcAddress(const char *name) #ifdef _WIN32 void *t = wglGetProcAddress(name); return t; +#else + return NULL; #endif } diff --git a/source/blender/freestyle/intern/rendering/GLXOffscreenViewer.cpp b/source/blender/freestyle/intern/rendering/GLXOffscreenViewer.cpp deleted file mode 100755 index 7135cedd7ad..00000000000 --- a/source/blender/freestyle/intern/rendering/GLXOffscreenViewer.cpp +++ /dev/null @@ -1,86 +0,0 @@ - -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef WIN32 -# include "GLRenderer.h" -# include "GLXOffscreenViewer.h" - - -GLXOffscreenViewer::GLXOffscreenViewer(int w, int h){ - _offscreenArea = new OffScreenArea(OffScreenArea::PIXMAP_OFFSCREEN_TYPE); - _offscreenArea->AllocateOffScreenArea(w,h); - _RootNode.SetLightingEnabled(false); - _RootNode.SetLineWidth(1.0); - _pGLRenderer = new GLRenderer; -} - -GLXOffscreenViewer::~GLXOffscreenViewer(){ - if(_offscreenArea) - delete _offscreenArea; - if(_pGLRenderer) - delete _pGLRenderer; - _RootNode.destroy(); -} - -void GLXOffscreenViewer::AddNode(Node* iNode){ - _RootNode.AddChild(iNode); -} - -void GLXOffscreenViewer::DetachNode(Node* iNode){ - _RootNode.DetachChild(iNode); -} - -void GLXOffscreenViewer::init(){ - glClearColor(_clearColor[0],_clearColor[1],_clearColor[2],1); -} - -void GLXOffscreenViewer::readPixels(int x, - int y, - int width, - int height, - float *pixels){ - _offscreenArea->MakeCurrent(); - glReadBuffer(GL_FRONT); - GLenum glformat = GL_RED; - glReadPixels(x,y,width, height, glformat, GL_FLOAT, (GLfloat*)pixels); -} - - - -void GLXOffscreenViewer::draw() -{ - _offscreenArea->MakeCurrent(); - glPushAttrib(GL_ALL_ATTRIB_BITS); - glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); - //Modelview Matrix - //================ - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - glEnable(GL_BLEND); - glBlendFunc(GL_ONE, GL_ONE); - glDisable(GL_DEPTH_TEST); - _RootNode.accept(*_pGLRenderer); - glFlush(); - glPopAttrib(); -} - -#endif diff --git a/source/blender/freestyle/intern/rendering/GLXOffscreenViewer.h b/source/blender/freestyle/intern/rendering/GLXOffscreenViewer.h deleted file mode 100755 index c09a23f500b..00000000000 --- a/source/blender/freestyle/intern/rendering/GLXOffscreenViewer.h +++ /dev/null @@ -1,545 +0,0 @@ - -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// -#ifndef GLXOFFSCREENVIEWER_H -# define GLXOFFSCREENVIEWER_H - -# ifdef 0 -//#ifndef WIN32 -// -// @(#)OffScreen.h 1.4 10/11/00 -// - - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -namespace OFFSCREEN { // I put this here to avoid conflicts between Qt and - // X11 in the definition of INT32 - - /*! \namespace OFFSCREEN - * \bugs attention a la restauration de context quand il n'avait rien avant l'OffScreenArea !! - */ - -static bool OutOfMemory = false ; -static XErrorHandler oldHandler = NULL ; - -static int myXErrorHandler (Display *_d, XErrorEvent *_xee) -{ - OutOfMemory = True; - if(oldHandler) - { - return (*oldHandler)(_d,_xee); - } - else - { - return false; - } - - return 0; -} - -class OffScreenArea -{ - public: - static const int UNKNOWN_OFFSCREEN_TYPE = 0 ; - static const int PIXMAP_OFFSCREEN_TYPE = 1 ; - static const int PBUFFER_OFFSCREEN_TYPE = 2 ; - static const int KEEP_PIXMAP = 1 ; - - OffScreenArea (int type = UNKNOWN_OFFSCREEN_TYPE,GLXContext shareCtx = NULL) - { - DefaultType = type ; - i_Screen = -1; - i_Height = 0; - i_Width = 0; - - i_OffScreenAreaType = UNKNOWN_OFFSCREEN_TYPE ; - i_GLContext = NULL; - i_Drawable = GLXDrawable(0); - i_XPix = Pixmap(0); - i_pXVisual = NULL; - i_pDisplay = NULL; - - SetDisplayAndScreen((Display *)NULL,(int)-1) ; - } - - GLXContext GetGLXContext() { return i_GLContext ; } - ~OffScreenArea () - { - DestroyOffScreenArea(); - } - - /* - * 0 : cannot allocate - * 1 : allocation done - * FIRST : try to allocate PixelBuffer (Single, double buffer) - * SECOND : try to allocate GLXPixmap if PixelBuffer is not available - */ - /* - * Here, we try to allocate an OffScreen Area - * first, with PBuffer (if this GLX_ext. is - * available and we can create one) - * second, with a pixmap - */ - int AllocateOffScreenArea(int width,int height) - { - save_GLContext = glXGetCurrentContext(); - save_pDisplay = glXGetCurrentDisplay(); - save_Drawable = glXGetCurrentDrawable(); - - int AlreadyThere = 0; -#ifdef A_VIRER - static int AlreadyThere = 0; - - if ( ( width != i_Width ) || ( height != i_Height ) ) - { - AlreadyThere = 0; - DestroyOffScreenArea(); - } -#endif - if(!AlreadyThere) - { - AlreadyThere = 1; - - /** Before to use a Pixmap, we try with pbuffer **/ - if(TryPBuffer(false,width,height)) - { -#ifdef DEBUG - fprintf(stderr, "Using single-buffer PBuffer for off-screen rendering.\n") ; -#endif - return true ; - } - - fprintf(stderr, "Cannot use a single-buffer PBuffer, trying double buffer.\n") ; - - if(TryPBuffer(true,width,height)) - { -#ifdef DEBUG - fprintf(stderr, "Using double-buffer PBuffer for off-screen rendering.\n") ; -#endif - return true ; - } -#ifdef DEBUG - fprintf(stderr, "Warning : cannot create a PBuffer, trying Pixmap\n"); -#endif - if(TryPixmap(width,height)) - { -#ifdef DEBUG - fprintf(stderr, "Notice : using Pixmap for offScreen rendering\n"); -#endif - return true ; - } -#ifdef DEBUG - fprintf (stderr, "Warning : cannot create a Pixmap\n"); -#endif - - return false; - } - return true ; - } - - void MakeCurrent() - { - glXMakeCurrent(i_pDisplay,i_Drawable,i_GLContext); - } - - protected: - inline Display * XServer ( void ) { return i_pDisplay; } - inline GLXContext GraphicContext ( void ) { return i_GLContext; } - inline GLXDrawable Drawable ( void ) { return i_Drawable; } - inline XVisualInfo * XVisual ( void ) { return i_pXVisual; } - - int DefaultType ; - int i_OffScreenAreaType; - int i_Height; - int i_Width; - - GLXContext save_GLContext; - Display * save_pDisplay; - GLXDrawable save_Drawable; - - Display * i_pDisplay; - int i_Screen; - GLXContext i_GLContext; - GLXContext i_shareContext; - GLXDrawable i_Drawable; - Pixmap i_XPix; - XVisualInfo * i_pXVisual; - - /* - * Define Display and screen - * IF display == NULL THEN try to open default Display - * IF screenNumber is < 0 THEN take default Screen - */ - void SetDisplayAndScreen ( Display *pDisplay , int Screen ) - { - if ( pDisplay == NULL ) - i_pDisplay = XOpenDisplay ( NULL ); - else - i_pDisplay = pDisplay; - - if ( Screen < 0 ) - i_Screen = DefaultScreen ( i_pDisplay ); - else - i_Screen = Screen; - } - - // - // Creates a PBuffer - // - // - // 0 : failure - // 1 : succeed - // - - bool CreatePBuffer (unsigned int width, unsigned int height , int * pAttribList) - { -#ifdef DEBUG - int error = 0 ; - while((error = glGetError()) > 0) - std::cerr << "GLError " << (void *)error << " encountered." << std::endl ; -#endif - GLXFBConfig *pfbConfigs; - int nbConfigs; - static int pbAttribs[] = { GLX_LARGEST_PBUFFER, true, - GLX_PRESERVED_CONTENTS, true, - GLX_PBUFFER_WIDTH,0, - GLX_PBUFFER_HEIGHT,0, - None }; - - pbAttribs[5] = width ; - pbAttribs[7] = height ; - - // Looks for a config that matches pAttribList - pfbConfigs = glXChooseFBConfig(i_pDisplay,i_Screen,pAttribList,&nbConfigs) ; -#ifdef DEBUG - std::cout << nbConfigs << " found for pbuffer." << std::endl ; -#endif - - if(pfbConfigs == NULL) - return false ; - - i_pXVisual = glXGetVisualFromFBConfig(i_pDisplay,pfbConfigs[0]); - i_OffScreenAreaType = PBUFFER_OFFSCREEN_TYPE; - - // Sets current error handler - OutOfMemory = False; - oldHandler = XSetErrorHandler( myXErrorHandler ); - - i_Drawable = glXCreatePbuffer(i_pDisplay,pfbConfigs[0],pbAttribs); - - if(i_Drawable == 0) - { - i_pXVisual = NULL; - return false ; - } - unsigned int w=0,h=0; - glXQueryDrawable(i_pDisplay,i_Drawable,GLX_WIDTH,&w) ; - glXQueryDrawable(i_pDisplay,i_Drawable,GLX_HEIGHT,&h) ; - - if((w != width)||(h != height)) - { -#ifdef DEBUG - std::cerr << "Could not allocate Pbuffer. Only size " << w << "x" << h << " found." << std::endl ; -#endif - return false ; - } -#ifdef DEBUG - else - std::cerr << "Could allocate Pbuffer. Size " << w << "x" << h << " found." << std::endl ; -#endif -#ifdef DEBUG - while((error = glGetError()) > 0) - std::cerr << "GLError " << (void *)error << " encountered." << std::endl ; -#endif - // now create GLXContext - - if((i_GLContext = glXCreateContext(i_pDisplay,i_pXVisual,NULL,true)) == NULL) - { - DestroyOffScreenArea() ; - return false ; - } - - /* Restore original X error handler */ - (void) XSetErrorHandler( oldHandler ); - - if(!OutOfMemory) - { - i_Height = height; - i_Width = width; - - return true ; - } - else - return false ; - } - - // - // Creates a Pixmap - // - // - // false : failure - // true : succeed - // - - bool CreatePixmap (int width, int height , int * pAttribList) - { - int depth; - int totdepth=0; - XErrorHandler oldHandler; - XVisualInfo * pvisP; - - pvisP = glXChooseVisual ( i_pDisplay, i_Screen , pAttribList); - - if ( pvisP == NULL) - { - fprintf( stderr , "Warning : no 24-bit true color visual available\n" ); - return false ; - } - - OutOfMemory = False; - oldHandler = XSetErrorHandler(myXErrorHandler); - if(i_XPix == Pixmap(NULL)) - { - depth = 0; - for (unsigned int i=0,j=0; (pAttribList[i] != None) && (j<3) ; i++ ) - { - switch ( pAttribList[i] ) - { - case GLX_RED_SIZE: glXGetConfig(i_pDisplay,pvisP,GLX_RED_SIZE,&depth) ; - totdepth += depth ; - i++ ; - j++ ; - break; - - case GLX_GREEN_SIZE: glXGetConfig(i_pDisplay,pvisP,GLX_GREEN_SIZE,&depth) ; - totdepth += depth ; - i++ ; - j++ ; - break; - - case GLX_BLUE_SIZE: glXGetConfig(i_pDisplay,pvisP,GLX_BLUE_SIZE,&depth) ; - totdepth += depth ; - i++ ; - j++ ; - break; - default: - break; - } - } - - fprintf(stderr,"%d bits color buffer found\n",depth) ; - i_XPix = XCreatePixmap(i_pDisplay,RootWindow (i_pDisplay,0),width,height,totdepth); - XSync(i_pDisplay,False); - if(OutOfMemory) - { - i_XPix = Pixmap(0); - XSetErrorHandler(oldHandler); - oldHandler = NULL ; - fprintf(stderr,"Warning : could not allocate Pixmap\n"); - return false ; - } - } - - // Perhaps should we verify th type of Area (Pixmap) ? - if ( i_Drawable == GLXDrawable(NULL) ) - { - // i_Drawable = i_XPix; - i_Drawable = glXCreateGLXPixmap ( i_pDisplay , pvisP , i_XPix ); - XSync ( i_pDisplay , False ); - if(OutOfMemory) - { - i_Drawable = GLXDrawable(0); - DestroyOffScreenArea(); - fprintf ( stderr , "Warning : could not allocate GLX Pixmap\n"); - return false ; - } - else - { - if(i_GLContext != NULL) - { - glXDestroyContext ( i_pDisplay , i_GLContext ); - i_GLContext = NULL; - } - if((i_GLContext = glXCreateContext(i_pDisplay,pvisP,NULL,GL_FALSE)) == NULL) - { - DestroyOffScreenArea(); - fprintf(stderr, "Warning : could not create rendering context"); - } - } - } - XSetErrorHandler(oldHandler); - - i_pXVisual = (i_Drawable != GLXDrawable(NULL) ? pvisP : NULL); - - i_Height = height; - i_Width = width; - - if(i_Drawable != GLXDrawable(NULL)) - { - i_OffScreenAreaType = PIXMAP_OFFSCREEN_TYPE; - return true ; - } - - return false ; - } - - bool TryPixmap(int width,int height) - { - int attrList[30]; - int n = 0; - - attrList[n++] = GLX_RED_SIZE; - attrList[n++] = 8; - attrList[n++] = GLX_GREEN_SIZE; - attrList[n++] = 8; - attrList[n++] = GLX_BLUE_SIZE; - attrList[n++] = 8; - attrList[n++] = GLX_RGBA; - attrList[n++] = GLX_DEPTH_SIZE; - attrList[n++] = 16; - attrList[n++] = GLX_STENCIL_SIZE; - attrList[n++] = 1; - attrList[n++] = None; - - return CreatePixmap(width,height,attrList) ; - } - - bool TryPBuffer(bool double_buffer,int width,int height) - { - int attrList[30]; - int n = 0; - - attrList[n++] = GLX_RENDER_TYPE; - attrList[n++] = GLX_RGBA_BIT; - attrList[n++] = GLX_DRAWABLE_TYPE; - attrList[n++] = GLX_PBUFFER_BIT; - attrList[n++] = GLX_RED_SIZE; - attrList[n++] = 8; - attrList[n++] = GLX_GREEN_SIZE; - attrList[n++] = 8; - attrList[n++] = GLX_BLUE_SIZE; - attrList[n++] = 8; - attrList[n++] = GLX_DEPTH_SIZE; - attrList[n++] = 8; - attrList[n++] = GLX_DOUBLEBUFFER; - attrList[n++] = double_buffer; - attrList[n++] = None; - - return CreatePBuffer(width,height,attrList) ; - } - - void DestroyOffScreenArea() - { - glXMakeCurrent(save_pDisplay,save_Drawable,save_GLContext); - - switch ( i_OffScreenAreaType ) - { - case PIXMAP_OFFSCREEN_TYPE : if(i_Drawable != 0) - glXDestroyGLXPixmap(i_pDisplay,i_Drawable); - - if (i_XPix != 0) - { - XFreePixmap (i_pDisplay,i_XPix); - i_XPix = 0; - } - break; - case PBUFFER_OFFSCREEN_TYPE : if(i_Drawable != 0) - glXDestroyPbuffer(i_pDisplay,i_Drawable); - break; - default: break; - } - - if (i_GLContext != NULL) - { - glXDestroyContext(i_pDisplay,i_GLContext); - i_GLContext = NULL; - } - - i_Drawable = 0; - i_OffScreenAreaType = UNKNOWN_OFFSCREEN_TYPE; - } -} ; - -} - - -#include "Geom.h" -#include "NodeDrawingStyle.h" -using namespace Geometry; -//using namespace OFFSCREEN; -class GLXOffscreenViewer{ -public: - GLXOffscreenViewer(int w, int h); - virtual ~GLXOffscreenViewer(); - - /*! Adds a node directly under the root node */ - void AddNode(Node* iNode); - /*! Detach the node iNode which must - * be directly under the root node. - */ - void DetachNode(Node *iNode); - - /*! reads the frame buffer pixels as luminance . - * \param x - * The lower-left corner x-coordinate of the - * rectangle we want to grab. - * \param y - * The lower-left corner y-coordinate of the - * rectangle we want to grab. - * \param width - * The width of the rectangle we want to grab. - * \param height - * The height of the rectangle we want to grab. - * \params pixels - * The array of float (of size width*height) in which - * the read values are stored. - */ - void readPixels(int x,int y,int width,int height,float *pixels) ; - - inline void SetClearColor(const Vec3f& c) {_clearColor = c;} - inline Vec3f getClearColor() const {return _clearColor;} - - void init(); - void draw(); - -protected: - OffScreenArea *_offscreenArea; - NodeDrawingStyle _RootNode; - Vec3f _clearColor; - GLRenderer *_pGLRenderer; - -}; - -#endif // WIN32 - -#endif diff --git a/source/blender/freestyle/intern/rendering/pbuffer.cpp b/source/blender/freestyle/intern/rendering/pbuffer.cpp index ec73fc52ae4..0cb9013ddcd 100755 --- a/source/blender/freestyle/intern/rendering/pbuffer.cpp +++ b/source/blender/freestyle/intern/rendering/pbuffer.cpp @@ -1,4 +1,4 @@ -#include +#include "pbuffer.h" #include diff --git a/source/blender/freestyle/intern/rendering/pbuffer.h b/source/blender/freestyle/intern/rendering/pbuffer.h index 7f11f461b1c..35fd24484b6 100755 --- a/source/blender/freestyle/intern/rendering/pbuffer.h +++ b/source/blender/freestyle/intern/rendering/pbuffer.h @@ -1,13 +1,12 @@ #ifndef PBUFFERS_H #define PBUFFERS_H -#ifndef WIN32 -# ifdef __MACH__ +# ifdef __MACH__ # include -# else +# else # include # include -# endif +# endif //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Interface of PBuffer @@ -74,4 +73,3 @@ private: }; #endif //PBUFFERS_H -#endif //WIN32 diff --git a/source/blender/freestyle/intern/system/StringUtils.cpp b/source/blender/freestyle/intern/system/StringUtils.cpp index 1afee94d962..556299e45c5 100755 --- a/source/blender/freestyle/intern/system/StringUtils.cpp +++ b/source/blender/freestyle/intern/system/StringUtils.cpp @@ -23,10 +23,6 @@ #include "FreestyleConfig.h" #include "StringUtils.h" -//soc -#include "BKE_utildefines.h" -#include "BLI_blenlib.h" - namespace StringUtils { void getPathName(const string& path, const string& base, vector& pathnames) { @@ -45,7 +41,7 @@ namespace StringUtils { char cleaned[FILE_MAX]; BLI_strncpy(cleaned, dir.c_str(), FILE_MAX); BLI_cleanup_file(NULL, cleaned); - string res(cleaned); + string res = toAscii( string(cleaned) ); if (!base.empty()) res += Config::DIR_SEP + base; @@ -53,4 +49,22 @@ namespace StringUtils { } } + string toAscii( const string &str ){ + stringstream out(""); + char s; + + for(uint i=0; i < str.size() ; i++){ + s = ((char)(str.at(i) & 0x7F)); + out << s; + } + + return out.str(); + } + + const char* toAscii( const char *str ){ + return toAscii(string(str)).c_str(); + } + + + } // end of namespace StringUtils diff --git a/source/blender/freestyle/intern/system/StringUtils.h b/source/blender/freestyle/intern/system/StringUtils.h index 44adfc2b044..efc16953e48 100755 --- a/source/blender/freestyle/intern/system/StringUtils.h +++ b/source/blender/freestyle/intern/system/StringUtils.h @@ -30,14 +30,21 @@ # include # include +# include # include "FreestyleConfig.h" +//soc +#include "BKE_utildefines.h" +#include "BLI_blenlib.h" + using namespace std; namespace StringUtils { LIB_SYSTEM_EXPORT void getPathName(const string& path, const string& base, vector& pathnames); + string toAscii( const string &str ); + const char* toAscii( const char *str ); // STL related struct ltstr{ diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h index e5f781a3365..4f62cd084cc 100644 --- a/source/blender/makesdna/DNA_particle_types.h +++ b/source/blender/makesdna/DNA_particle_types.h @@ -168,7 +168,7 @@ typedef struct ParticleSettings { struct PartDeflect *pd; } ParticleSettings; -typedef struct ParticleSystem{ +typedef struct ParticleSystem{ /* note, make sure all (runtime) are NULL's in copy_particlesystem */ struct ParticleSystem *next, *prev; ParticleSettings *part; /* particle settings */ @@ -199,7 +199,7 @@ typedef struct ParticleSystem{ char bb_uvname[3][32]; /* billboard uv name */ /* if you change these remember to update array lengths to PSYS_TOT_VG! */ - short vgroup[11], vg_neg, rt3[2]; /* vertex groups */ + short vgroup[12], vg_neg, rt3; /* vertex groups */ /* temporary storage during render */ void *renderdata; diff --git a/source/blender/python/api2_2x/Blender.c b/source/blender/python/api2_2x/Blender.c index 4fc68d138e0..6fce0864189 100644 --- a/source/blender/python/api2_2x/Blender.c +++ b/source/blender/python/api2_2x/Blender.c @@ -96,6 +96,7 @@ struct ID; /*keep me up here */ #include "Window.h" #include "World.h" #include "Types.h" +#include "Particle.h" /**********************************************************/ /* Python API function prototypes for the Blender module. */ @@ -1074,6 +1075,7 @@ void M_Blender_Init(void) PyDict_SetItemString(dict, "Node", Node_Init()); PyDict_SetItemString(dict, "Noise", Noise_Init()); PyDict_SetItemString(dict, "Object", Object_Init()); + PyDict_SetItemString(dict, "Particle", ParticleSys_Init()); PyDict_SetItemString(dict, "Group", Group_Init()); PyDict_SetItemString(dict, "Registry", Registry_Init()); PyDict_SetItemString(dict, "Scene", Scene_Init()); diff --git a/source/blender/python/api2_2x/Object.c b/source/blender/python/api2_2x/Object.c index 4d8caf5a55e..82f99adcdb1 100644 --- a/source/blender/python/api2_2x/Object.c +++ b/source/blender/python/api2_2x/Object.c @@ -27,7 +27,7 @@ * * Contributor(s): Michel Selten, Willian Germano, Jacques Guignot, * Joseph Gilbert, Stephen Swaney, Bala Gi, Campbell Barton, Johnny Matthews, - * Ken Hughes, Alex Mole, Jean-Michel Soler + * Ken Hughes, Alex Mole, Jean-Michel Soler, Cedric Paille * * ***** END GPL LICENSE BLOCK ***** */ @@ -68,6 +68,8 @@ struct rctf; #include "BKE_object.h" #include "BKE_key.h" /* for setting the activeShape */ #include "BKE_displist.h" +#include "BKE_pointcache.h" +#include "BKE_particle.h" #include "BSE_editipo.h" #include "BSE_edit.h" @@ -117,6 +119,7 @@ struct rctf; #include "EXPP_interface.h" #include "BIF_editkey.h" #include "IDProp.h" +#include "Particle.h" /* Defines for insertIpoKey */ @@ -336,6 +339,9 @@ struct PyMethodDef M_Object_methods[] = { static int setupSB(Object* ob); /*Make sure Softbody Pointer is initialized */ static int setupPI(Object* ob); +static PyObject *Object_getParticleSys( BPy_Object * self ); +/* fixme Object_newParticleSys( self, default-partsys-name ) */ +static PyObject *Object_newParticleSys( BPy_Object * self ); static PyObject *Object_buildParts( BPy_Object * self ); static PyObject *Object_clearIpo( BPy_Object * self ); static PyObject *Object_clrParent( BPy_Object * self, PyObject * args ); @@ -465,6 +471,10 @@ static PyObject *Object_upAxis(BPy_Object * self); /*****************************************************************************/ static PyMethodDef BPy_Object_methods[] = { /* name, method, flags, doc */ + {"getParticleSystems", ( PyCFunction ) Object_getParticleSys, METH_NOARGS, + "Return a list of particle systems"}, + {"newParticleSystem", ( PyCFunction ) Object_newParticleSys, METH_NOARGS, + "Create and link a new particle system"}, {"buildParts", ( PyCFunction ) Object_buildParts, METH_NOARGS, "Recalcs particle system (if any), (depricated, will always return an empty list in version 2.46)"}, {"getIpo", ( PyCFunction ) Object_getIpo, METH_NOARGS, @@ -1026,6 +1036,79 @@ static PyObject *M_Object_Duplicate( PyObject * self_unused, /* Python BPy_Object methods: */ /*****************************************************************************/ +PyObject *Object_getParticleSys( BPy_Object * self ){ + ParticleSystem *blparticlesys = 0; + Object *ob = self->object; + PyObject *partsyslist,*current; + + blparticlesys = ob->particlesystem.first; + + partsyslist = PyList_New( 0 ); + + if (!blparticlesys) + return partsyslist; + +/* fixme: for(;;) */ + current = ParticleSys_CreatePyObject( blparticlesys, ob ); + PyList_Append(partsyslist,current); + + while((blparticlesys = blparticlesys->next)){ + current = ParticleSys_CreatePyObject( blparticlesys, ob ); + PyList_Append(partsyslist,current); + } + + return partsyslist; +} + +PyObject *Object_newParticleSys( BPy_Object * self ){ + ParticleSystem *psys = 0; + ParticleSystem *rpsys = 0; + ModifierData *md; + ParticleSystemModifierData *psmd; + Object *ob = self->object; +/* char *name = NULL; optional name param */ + ID *id; + int nr; + + id = (ID *)psys_new_settings("PSys", G.main); + + psys = MEM_callocN(sizeof(ParticleSystem), "particle_system"); + psys->pointcache = BKE_ptcache_add(); + psys->flag |= PSYS_ENABLED; + BLI_addtail(&ob->particlesystem,psys); + + md = modifier_new(eModifierType_ParticleSystem); + sprintf(md->name, "ParticleSystem %i", BLI_countlist(&ob->particlesystem)); + psmd = (ParticleSystemModifierData*) md; + psmd->psys=psys; + BLI_addtail(&ob->modifiers, md); + + psys->part=(ParticleSettings*)id; + psys->totpart=0; + psys->flag=PSYS_ENABLED|PSYS_CURRENT; + psys->cfra=bsystem_time(ob,(float)G.scene->r.cfra+1,0.0); + rpsys = psys; + + /* check need for dupliobjects */ + + nr=0; + for(psys=ob->particlesystem.first; psys; psys=psys->next){ + if(ELEM(psys->part->draw_as,PART_DRAW_OB,PART_DRAW_GR)) + nr++; + } + if(nr) + ob->transflag |= OB_DUPLIPARTS; + else + ob->transflag &= ~OB_DUPLIPARTS; + + BIF_undo_push("Browse Particle System"); + + DAG_scene_sort(G.scene); + DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); + + return ParticleSys_CreatePyObject(rpsys,ob); +} + static PyObject *Object_buildParts( BPy_Object * self ) { /* This is now handles by modifiers */ diff --git a/source/blender/python/api2_2x/Particle.c b/source/blender/python/api2_2x/Particle.c index 1de0360cd77..15307cc2be5 100644 --- a/source/blender/python/api2_2x/Particle.c +++ b/source/blender/python/api2_2x/Particle.c @@ -22,941 +22,1812 @@ * * This is a new part of Blender. * - * Contributor(s): Jacques Guignot, Jean-Michel Soler + * Contributor(s): + * Original version: Jacques Guignot, Jean-Michel Soler + * Rewrite : Cedric Paille, Stephen Swaney, Joilnen Leite * * ***** END GPL LICENSE BLOCK ***** */ -#include "Particle.h" /*This must come first */ - -#include "DNA_object_types.h" -#include "BKE_effect.h" -#include "BKE_global.h" -#include "BKE_main.h" -#include "BKE_object.h" -#include "BLI_blenlib.h" +#include "Particle.h" #include "gen_utils.h" +#include "BKE_object.h" +#include "BKE_main.h" +#include "BKE_particle.h" +#include "BKE_global.h" +#include "BKE_depsgraph.h" +#include "BKE_modifier.h" +#include "BKE_material.h" +#include "BKE_utildefines.h" +#include "BKE_pointcache.h" +#include "BIF_editparticle.h" +#include "BIF_space.h" +#include "blendef.h" +#include "DNA_modifier_types.h" +#include "DNA_scene_types.h" +#include "DNA_material_types.h" +#include "BLI_blenlib.h" +#include "mydevice.h" +#include "Object.h" +#include "Material.h" -/*****************************************************************************/ -/* Python API function prototypes for the Particle module. */ -/*****************************************************************************/ -PyObject *M_Particle_New( PyObject * self, PyObject * args ); -PyObject *M_Particle_Get( PyObject * self, PyObject * args ); - -/*****************************************************************************/ -/* Python BPy_Particle methods declarations: */ -/*****************************************************************************/ -PyObject *Effect_getType( BPy_Effect * self ); -PyObject *Effect_setType( BPy_Effect * self, PyObject * args ); -PyObject *Effect_getFlag( BPy_Effect * self ); -PyObject *Effect_setFlag( BPy_Effect * self, PyObject * args ); -PyObject *Particle_getSta( BPy_Particle * self ); -PyObject *Particle_setSta( BPy_Particle * self, PyObject * a ); -PyObject *Particle_getEnd( BPy_Particle * self ); -PyObject *Particle_setEnd( BPy_Particle * self, PyObject * a ); -PyObject *Particle_getLifetime( BPy_Particle * self ); -PyObject *Particle_setLifetime( BPy_Particle * self, PyObject * a ); -PyObject *Particle_getNormfac( BPy_Particle * self ); -PyObject *Particle_setNormfac( BPy_Particle * self, PyObject * a ); -PyObject *Particle_getObfac( BPy_Particle * self ); -PyObject *Particle_setObfac( BPy_Particle * self, PyObject * a ); -PyObject *Particle_getRandfac( BPy_Particle * self ); -PyObject *Particle_setRandfac( BPy_Particle * self, PyObject * a ); -PyObject *Particle_getTexfac( BPy_Particle * self ); -PyObject *Particle_setTexfac( BPy_Particle * self, PyObject * a ); -PyObject *Particle_getRandlife( BPy_Particle * self ); -PyObject *Particle_setRandlife( BPy_Particle * self, PyObject * a ); -PyObject *Particle_getNabla( BPy_Particle * self ); -PyObject *Particle_setNabla( BPy_Particle * self, PyObject * a ); -PyObject *Particle_getVectsize( BPy_Particle * self ); -PyObject *Particle_setVectsize( BPy_Particle * self, PyObject * a ); -PyObject *Particle_getTotpart( BPy_Particle * self ); -PyObject *Particle_setTotpart( BPy_Particle * self, PyObject * a ); -PyObject *Particle_getTotkey( BPy_Particle * self ); -PyObject *Particle_setTotkey( BPy_Particle * self, PyObject * a ); -PyObject *Particle_getSeed( BPy_Particle * self ); -PyObject *Particle_setSeed( BPy_Particle * self, PyObject * a ); -PyObject *Particle_getForce( BPy_Particle * self ); -PyObject *Particle_setForce( BPy_Particle * self, PyObject * a ); -PyObject *Particle_getMult( BPy_Particle * self ); -PyObject *Particle_setMult( BPy_Particle * self, PyObject * a ); -PyObject *Particle_getLife( BPy_Particle * self ); -PyObject *Particle_setLife( BPy_Particle * self, PyObject * a ); -PyObject *Particle_getMat( BPy_Particle * self ); -PyObject *Particle_setMat( BPy_Particle * self, PyObject * a ); -PyObject *Particle_getChild( BPy_Particle * self ); -PyObject *Particle_setChild( BPy_Particle * self, PyObject * a ); -PyObject *Particle_getDefvec( BPy_Particle * self ); -PyObject *Particle_setDefvec( BPy_Particle * self, PyObject * a ); - -/*****************************************************************************/ -/* Python Particle_Type callback function prototypes: */ -/*****************************************************************************/ -void ParticleDeAlloc( BPy_Particle * msh ); -//int ParticlePrint (BPy_Particle *msh, FILE *fp, int flags); -int ParticleSetAttr( BPy_Particle * msh, char *name, PyObject * v ); -PyObject *ParticleGetAttr( BPy_Particle * msh, char *name ); -PyObject *ParticleRepr( void ); -PyObject *ParticleCreatePyObject( struct Effect *particle ); -int ParticleCheckPyObject( PyObject * py_obj ); -struct Particle *ParticleFromPyObject( PyObject * py_obj ); - - -/*****************************************************************************/ -/* Python BPy_Particle methods table: */ -/*****************************************************************************/ -static PyMethodDef BPy_Particle_methods[] = { - {"getType", ( PyCFunction ) Effect_getType, - METH_NOARGS, "() - Return Effect type"}, - {"setType", ( PyCFunction ) Effect_setType, - METH_VARARGS, "() - Set Effect type"}, - {"getFlag", ( PyCFunction ) Effect_getFlag, - METH_NOARGS, "() - Return Effect flag"}, - {"setFlag", ( PyCFunction ) Effect_setFlag, - METH_VARARGS, "() - Set Effect flag"}, - {"getStartTime", ( PyCFunction ) Particle_getSta, - METH_NOARGS, "()-Return particle start time"}, - {"setStartTime", ( PyCFunction ) Particle_setSta, METH_VARARGS, - "()- Sets particle start time"}, - {"getEndTime", ( PyCFunction ) Particle_getEnd, - METH_NOARGS, "()-Return particle end time"}, - {"setEndTime", ( PyCFunction ) Particle_setEnd, METH_VARARGS, - "()- Sets particle end time"}, - {"getLifetime", ( PyCFunction ) Particle_getLifetime, - METH_NOARGS, "()-Return particle life time"}, - {"setLifetime", ( PyCFunction ) Particle_setLifetime, METH_VARARGS, - "()- Sets particle life time "}, - {"getNormfac", ( PyCFunction ) Particle_getNormfac, - METH_NOARGS, "()-Return particle life time"}, - {"setNormfac", ( PyCFunction ) Particle_setNormfac, METH_VARARGS, - "()- Sets particle life time "}, - {"getObfac", ( PyCFunction ) Particle_getObfac, - METH_NOARGS, "()-Return particle life time"}, - {"setObfac", ( PyCFunction ) Particle_setObfac, METH_VARARGS, - "()- Sets particle life time "}, - {"getRandfac", ( PyCFunction ) Particle_getRandfac, - METH_NOARGS, "()-Return particle life time"}, - {"setRandfac", ( PyCFunction ) Particle_setRandfac, METH_VARARGS, - "()- Sets particle life time "}, - {"getTexfac", ( PyCFunction ) Particle_getTexfac, - METH_NOARGS, "()-Return particle life time"}, - {"setTexfac", ( PyCFunction ) Particle_setTexfac, METH_VARARGS, - "()- Sets particle life time "}, - {"getRandlife", ( PyCFunction ) Particle_getRandlife, - METH_NOARGS, "()-Return particle life time"}, - {"setRandlife", ( PyCFunction ) Particle_setRandlife, METH_VARARGS, - "()- Sets particle life time "}, - {"getNabla", ( PyCFunction ) Particle_getNabla, - METH_NOARGS, "()-Return particle life time"}, - {"setNabla", ( PyCFunction ) Particle_setNabla, METH_VARARGS, - "()- Sets particle life time "}, - {"getVectsize", ( PyCFunction ) Particle_getVectsize, - METH_NOARGS, "()-Return particle life time"}, - {"setVectsize", ( PyCFunction ) Particle_setVectsize, METH_VARARGS, - "()- Sets particle life time "}, - {"getTotpart", ( PyCFunction ) Particle_getTotpart, - METH_NOARGS, "()-Return particle life time"}, - {"setTotpart", ( PyCFunction ) Particle_setTotpart, METH_VARARGS, - "()- Sets particle life time "}, - {"getTotkey", ( PyCFunction ) Particle_getTotkey, - METH_NOARGS, "()-Return particle life time"}, - {"setTotkey", ( PyCFunction ) Particle_setTotkey, METH_VARARGS, - "()- Sets particle life time "}, - {"getSeed", ( PyCFunction ) Particle_getSeed, - METH_NOARGS, "()-Return particle life time"}, - {"setSeed", ( PyCFunction ) Particle_setSeed, METH_VARARGS, - "()- Sets particle life time "}, - {"getForce", ( PyCFunction ) Particle_getForce, - METH_NOARGS, "()-Return particle life time"}, - {"setForce", ( PyCFunction ) Particle_setForce, METH_VARARGS, - "()- Sets particle life time "}, - {"getMult", ( PyCFunction ) Particle_getMult, - METH_NOARGS, "()-Return particle life time"}, - {"setMult", ( PyCFunction ) Particle_setMult, METH_VARARGS, - "()- Sets particle life time "}, - {"getLife", ( PyCFunction ) Particle_getLife, - METH_NOARGS, "()-Return particle life time"}, - {"setLife", ( PyCFunction ) Particle_setLife, METH_VARARGS, - "()- Sets particle life time "}, - {"getMat", ( PyCFunction ) Particle_getMat, - METH_NOARGS, "()-Return particle life time"}, - {"setMat", ( PyCFunction ) Particle_setMat, METH_VARARGS, - "()- Sets particle life time "}, - {"getChild", ( PyCFunction ) Particle_getChild, - METH_NOARGS, "()-Return particle life time"}, - {"setChild", ( PyCFunction ) Particle_setChild, METH_VARARGS, - "()- Sets particle life time "}, - {"getDefvec", ( PyCFunction ) Particle_getDefvec, - METH_NOARGS, "()-Return particle life time"}, - {"setDefvec", ( PyCFunction ) Particle_setDefvec, METH_VARARGS, - "()- Sets particle life time "}, - - - {NULL, NULL, 0, NULL} -}; - -/**************** prototypes ********************/ -PyObject *Particle_Init( void ); +#include "MEM_guardedalloc.h" -/*****************************************************************************/ -/* Python Particle_Type structure definition: */ -/*****************************************************************************/ -PyTypeObject Particle_Type = { - PyObject_HEAD_INIT( NULL ) - 0, - "Particle", - sizeof( BPy_Particle ), - 0, +/* Type Methods */ +static PyObject *M_ParticleSys_New( PyObject * self, PyObject * args ); +static PyObject *M_ParticleSys_Get( PyObject * self, PyObject * args ); + +/* Particle Methods */ +static PyObject *Part_freeEdit( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_GetLoc( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_GetRot( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_GetMat( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_GetSize( BPy_PartSys * self, PyObject * args ); +static int Part_setSeed( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getSeed( BPy_PartSys * self ); +static int Part_setType( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getType( BPy_PartSys * self ); +static int Part_setResol( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getResol( BPy_PartSys * self ); +static int Part_setStart( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getStart( BPy_PartSys * self ); +static int Part_setEnd( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getEnd( BPy_PartSys * self ); +static int Part_setEditable( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getEditable( BPy_PartSys * self ); +static int Part_setAmount( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getAmount( BPy_PartSys * self ); +static int Part_setMultiReact( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getMultiReact( BPy_PartSys * self ); +static int Part_setReactShape( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getReactShape( BPy_PartSys * self ); +static int Part_setSegments( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getSegments( BPy_PartSys * self ); +static int Part_setLife( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getLife( BPy_PartSys * self ); +static int Part_setRandLife( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getRandLife( BPy_PartSys * self ); +static int Part_set2d( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_get2d( BPy_PartSys * self ); +static int Part_setMaxVel( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getMaxVel( BPy_PartSys * self ); +static int Part_setAvVel( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getAvVel( BPy_PartSys * self ); +static int Part_setLatAcc( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getLatAcc( BPy_PartSys * self ); +static int Part_setMaxTan( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getMaxTan( BPy_PartSys * self ); +static int Part_setGroundZ( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getGroundZ( BPy_PartSys * self ); +static int Part_setOb( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getOb( BPy_PartSys * self ); +static PyObject *Part_getRandEmission( BPy_PartSys * self ); +static int Part_setRandEmission( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getRandEmission( BPy_PartSys * self ); +static int Part_setParticleDist( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getParticleDist( BPy_PartSys * self ); +static int Part_setEvenDist( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getEvenDist( BPy_PartSys * self ); +static int Part_setDist( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getDist( BPy_PartSys * self ); +static int Part_setParticleDisp( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getParticleDisp( BPy_PartSys * self ); +static int Part_setJitterAmount( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getJitterAmount( BPy_PartSys * self ); +static int Part_setPF( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getPF( BPy_PartSys * self ); +static int Part_setInvert( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getInvert( BPy_PartSys * self ); +static int Part_setTargetOb( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getTargetOb( BPy_PartSys * self ); +static int Part_setTargetPsys( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getTargetPsys( BPy_PartSys * self ); +static int Part_setRenderObject( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getRenderObject( BPy_PartSys * self ); +static int Part_setStep( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getStep( BPy_PartSys * self ); +static int Part_setRenderStep( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getRenderStep( BPy_PartSys * self ); +static PyObject *Part_getDupOb( BPy_PartSys * self ); +static PyObject *Part_getDrawAs( BPy_PartSys * self ); +static PyObject *Part_GetAge( BPy_PartSys * self, PyObject * args ); + +/*****************************************************************************/ +/* Python Effect_Type callback function prototypes: */ +/*****************************************************************************/ +static PyObject *ParticleSys_repr( void ); - ( destructor ) ParticleDeAlloc, - 0, - ( getattrfunc ) ParticleGetAttr, - ( setattrfunc ) ParticleSetAttr, - 0, - ( reprfunc ) ParticleRepr, - 0, - 0, - 0, - 0, - 0, 0, 0, 0, 0, 0, - 0, - 0, 0, 0, 0, 0, 0, - BPy_Particle_methods, - 0, -}; /*****************************************************************************/ /* The following string definitions are used for documentation strings. */ /* In Python these will be written to the console when doing a */ /* Blender.Particle.__doc__ */ /*****************************************************************************/ -char M_Particle_doc[] = "The Blender Particle module\n\n\ +static char M_ParticleSys_doc[] = "The Blender Effect module\n\n\ This module provides access to **Object Data** in Blender.\n\ Functions :\n\ - New(object mesh's name) : creates a new part object and adds it to the given mesh object \n\ - Get(name) : retreives a particle with the given name (mandatory)\n\ - get(name) : same as Get. Kept for compatibility reasons.\n"; -char M_Particle_New_doc[] = "New(name) : creates a new part object and adds it to the given mesh object\n"; -char M_Particle_Get_doc[] = "xxx"; + Get(name) : retreives particle system (as list) with the given name\n"; +static char M_ParticleSys_Get_doc[] = "xxx"; +static char M_ParticleSys_New_doc[] = "xxx"; +/*****************************************************************************/ +/* Python BPy_ParticleSys methods table: */ +/*****************************************************************************/ + +static PyMethodDef BPy_ParticleSys_methods[] = { + {"freeEdit", ( PyCFunction ) Part_freeEdit, + METH_NOARGS, "() - Free from edit mode"}, + {"getLoc", ( PyCFunction ) Part_GetLoc, + METH_VARARGS, "() - Get particles location"}, + {"getRot", ( PyCFunction ) Part_GetRot, + METH_VARARGS, "() - Get particles rotations (list of 4 floats quaternion)"}, + {"getMat", ( PyCFunction ) Part_GetMat, + METH_NOARGS, "() - Get particles material"}, + {"getSize", ( PyCFunction ) Part_GetSize, + METH_VARARGS, "() - Get particles size in a list"}, + {"getAge", ( PyCFunction ) Part_GetAge, + METH_VARARGS, "() - Get particles life in a list"}, + {NULL, NULL, 0, NULL} +}; + +/*****************************************************************************/ +/* Python BPy_ParticleSys attributes get/set structure: */ +/*****************************************************************************/ +static PyGetSetDef BPy_ParticleSys_getseters[] = { +/* Extras */ + {"seed", + (getter)Part_getSeed, (setter)Part_setSeed, + "Set an offset in the random table", + NULL}, + /* basics */ + {"type", + (getter)Part_getType, (setter)Part_setType, + "Type of particle system ( Particle.TYPE[ 'HAIR' | 'REACTOR' | 'EMITTER' ] )", + NULL}, + {"resolutionGrid", + (getter)Part_getResol, (setter)Part_setResol, + "The resolution of the particle grid", + NULL}, + {"startFrame", + (getter)Part_getStart, (setter)Part_setStart, + "Frame # to start emitting particles", + NULL}, + {"endFrame", + (getter)Part_getEnd, (setter)Part_setEnd, + "Frame # to stop emitting particles", + NULL}, + {"editable", + (getter)Part_getEditable, (setter)Part_setEditable, + "Finalize hair to enable editing in particle mode", + NULL}, + {"amount", + (getter)Part_getAmount, (setter)Part_setAmount, + "The total number of particles", + NULL}, + {"multireact", + (getter)Part_getMultiReact, (setter)Part_setMultiReact, + "React multiple times ( Paricle.REACTON[ 'NEAR' | 'COLLISION' | 'DEATH' ] )", + NULL}, + {"reactshape", + (getter)Part_getReactShape, (setter)Part_setReactShape, + "Power of reaction strength dependence on distance to target", + NULL}, + {"hairSegments", + (getter)Part_getSegments, (setter)Part_setSegments, + "Amount of hair segments", + NULL}, + {"lifetime", + (getter)Part_getLife, (setter)Part_setLife, + "Specify the life span of the particles", + NULL}, + {"randlife", + (getter)Part_getRandLife, (setter)Part_setRandLife, + "Give the particle life a random variation", + NULL}, + {"randemission", + (getter)Part_getRandEmission, (setter)Part_setRandEmission, + "Give the particle life a random variation", + NULL}, + {"particleDistribution", + (getter)Part_getParticleDist, (setter)Part_setParticleDist, + "Where to emit particles from Paricle.EMITFROM[ 'PARTICLE' | 'VOLUME' | 'FACES' | 'VERTS' ] )", + NULL}, + {"evenDistribution", + (getter)Part_getEvenDist, (setter)Part_setEvenDist, + "Use even distribution from faces based on face areas or edge lengths", + NULL}, + {"distribution", + (getter)Part_getDist, (setter)Part_setDist, + "How to distribute particles on selected element Paricle.DISTRIBUTION[ 'GRID' | 'RANDOM' | 'JITTERED' ] )", + NULL}, + {"jitterAmount", + (getter)Part_getJitterAmount, (setter)Part_setJitterAmount, + "Amount of jitter applied to the sampling", + NULL}, + {"pf", + (getter)Part_getPF, (setter)Part_setPF, + "Emission locations / face (0 = automatic)", + NULL}, + {"invert", + (getter)Part_getInvert, (setter)Part_setInvert, + "Invert what is considered object and what is not.", + NULL}, + {"targetObject", + (getter)Part_getTargetOb, (setter)Part_setTargetOb, + "The object that has the target particle system (empty if same object)", + NULL}, + {"targetpsys", + (getter)Part_getTargetPsys, (setter)Part_setTargetPsys, + "The target particle system number in the object", + NULL}, +/* Physics */ + {"2d", + (getter)Part_get2d, (setter)Part_set2d, + "Constrain boids to a surface", + NULL}, + {"maxvel", + (getter)Part_getMaxVel, (setter)Part_setMaxVel, + "Maximum velocity", + NULL}, + {"avvel", + (getter)Part_getAvVel, (setter)Part_setAvVel, + "The usual speed % of max velocity", + NULL}, + {"latacc", + (getter)Part_getLatAcc, (setter)Part_setLatAcc, + "Lateral acceleration % of max velocity", + NULL}, + {"tanacc", + (getter)Part_getMaxTan, (setter)Part_setMaxTan, + "Tangential acceleration % of max velocity", + NULL}, + {"groundz", + (getter)Part_getGroundZ, (setter)Part_setGroundZ, + "Default Z value", + NULL}, + {"object", + (getter)Part_getOb, (setter)Part_setOb, + "Constrain boids to object's surface", + NULL}, +/* Visualisation */ + {"renderEmitter", + (getter)Part_getRenderObject, (setter)Part_setRenderObject, + "Render emitter object", + NULL}, + {"displayPercentage", + (getter)Part_getParticleDisp, (setter)Part_setParticleDisp, + "Particle display percentage", + NULL}, + {"hairDisplayStep", + (getter)Part_getStep, (setter)Part_setStep, + "How many steps paths are drawn with (power of 2)", + NULL}, + {"hairRenderStep", + (getter)Part_getRenderStep, (setter)Part_setRenderStep, + "How many steps paths are rendered with (power of 2)", + NULL}, + {"duplicateObject", + (getter)Part_getDupOb, NULL, + "Get the duplicate ob", + NULL}, + {"drawAs", + (getter)Part_getDrawAs, NULL, + "Get draw type Particle.DRAWAS([ 'NONE' | 'OBJECT' | 'POINT' | ... ] )", + NULL}, + {NULL,NULL,NULL,NULL,NULL} /* Sentinel */ +}; /*****************************************************************************/ /* Python method structure definition for Blender.Particle module: */ /*****************************************************************************/ -struct PyMethodDef M_Particle_methods[] = { - {"New", ( PyCFunction ) M_Particle_New, METH_VARARGS, M_Particle_New_doc}, - {"Get", M_Particle_Get, METH_VARARGS, M_Particle_Get_doc}, - {"get", M_Particle_Get, METH_VARARGS, M_Particle_Get_doc}, +static struct PyMethodDef M_ParticleSys_methods[] = { + {"New", ( PyCFunction ) M_ParticleSys_New, METH_VARARGS, M_ParticleSys_New_doc}, + {"Get", M_ParticleSys_Get, METH_VARARGS, M_ParticleSys_Get_doc}, {NULL, NULL, 0, NULL} }; +/*****************************************************************************/ +/* Python ParticleSys_Type structure definition: */ +/*****************************************************************************/ +PyTypeObject ParticleSys_Type = { + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ + /* For printing, in format "." */ + "Blender ParticleSys", /* char *tp_name; */ + sizeof( BPy_PartSys ), /* int tp_basicsize; */ + 0, /* tp_itemsize; For allocation */ + + /* Methods to implement standard operations */ + + NULL, /* destructor tp_dealloc; */ + NULL, /* printfunc tp_print; */ + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ + NULL, /* cmpfunc tp_compare; */ + ( reprfunc ) ParticleSys_repr,/* reprfunc tp_repr; */ + + /* Method suites for standard classes */ + + NULL, /* PyNumberMethods *tp_as_number; */ + NULL, /* PySequenceMethods *tp_as_sequence; */ + NULL, /* PyMappingMethods *tp_as_mapping; */ + + /* More standard operations (here for binary compatibility) */ + + NULL, /* hashfunc tp_hash; */ + NULL, /* ternaryfunc tp_call; */ + NULL, /* reprfunc tp_str; */ + NULL, /* getattrofunc tp_getattro; */ + NULL, /* setattrofunc tp_setattro; */ + + /* Functions to access object as input/output buffer */ + NULL, /* PyBufferProcs *tp_as_buffer; */ + + /*** Flags to define presence of optional/expanded features ***/ + Py_TPFLAGS_DEFAULT, /* long tp_flags; */ + + NULL, /* char *tp_doc; Documentation string */ + /*** Assigned meaning in release 2.0 ***/ + /* call function for all accessible objects */ + NULL, /* traverseproc tp_traverse; */ + + /* delete references to contained objects */ + NULL, /* inquiry tp_clear; */ + + /*** Assigned meaning in release 2.1 ***/ + /*** rich comparisons ***/ + NULL, /* richcmpfunc tp_richcompare; */ + + /*** weak reference enabler ***/ + 0, /* long tp_weaklistoffset; */ + + /*** Added in release 2.2 ***/ + /* Iterators */ + NULL, /* getiterfunc tp_iter; */ + NULL, /* iternextfunc tp_iternext; */ + + /*** Attribute descriptor and subclassing stuff ***/ + BPy_ParticleSys_methods, /* struct PyMethodDef *tp_methods; */ + NULL, /* struct PyMemberDef *tp_members; */ + BPy_ParticleSys_getseters, /* struct PyGetSetDef *tp_getset; */ + NULL, /* struct _typeobject *tp_base; */ + NULL, /* PyObject *tp_dict; */ + NULL, /* descrgetfunc tp_descr_get; */ + NULL, /* descrsetfunc tp_descr_set; */ + 0, /* long tp_dictoffset; */ + NULL, /* initproc tp_init; */ + NULL, /* allocfunc tp_alloc; */ + NULL, /* newfunc tp_new; */ + /* Low-level free-memory routine */ + NULL, /* freefunc tp_free; */ + /* For PyObject_IS_GC */ + NULL, /* inquiry tp_is_gc; */ + NULL, /* PyObject *tp_bases; */ + /* method resolution order */ + NULL, /* PyObject *tp_mro; */ + NULL, /* PyObject *tp_cache; */ + NULL, /* PyObject *tp_subclasses; */ + NULL, /* PyObject *tp_weaklist; */ + NULL +}; /*****************************************************************************/ -/* Function: M_Particle_New */ -/* Python equivalent: Blender.Effect.Particle.New */ -/* Description : Create a particle effect and add a link */ -/* to the given mesh-type Object */ -/* Data : String mesh object name */ -/* Return : pyobject particle */ +/* Function: PARTICLESYS_repr */ +/* Description: This is a callback function for the BPy_Effect type. It */ +/* builds a meaninful string to represent effcte objects. */ /*****************************************************************************/ -PyObject *M_Particle_New( PyObject * self, PyObject * args ) + +static PyObject *ParticleSys_repr( void ) { - printf("warning, static particles api removed\n"); - Py_INCREF( Py_None ); - return Py_None; + return PyString_FromString( "ParticleSys" ); } /*****************************************************************************/ -/* Function: M_Particle_Get */ -/* Python equivalent: Blender.Effect.Particle.Get */ +/* Function : P_sys_FromPyObject */ /*****************************************************************************/ -PyObject *M_Particle_Get( PyObject * self, PyObject * args ) + +struct ParticleSystem *P_sys_FromPyObject( BPy_PartSys * py_obj ) { - printf("warning, static particles api removed\n"); - Py_INCREF( Py_None ); - return Py_None; + BPy_PartSys *blen_obj; + + blen_obj = ( BPy_PartSys * ) py_obj; + return ( blen_obj->psys ); } /*****************************************************************************/ -/* Function: Particle_Init */ +/* Function : ParticleSysCreatePyObject */ /*****************************************************************************/ -PyObject *Particle_Init( void ) +PyObject *ParticleSys_CreatePyObject( ParticleSystem * psystem, Object *ob ) { + BPy_PartSys *blen_object; + + blen_object = + ( BPy_PartSys * ) PyObject_NEW( BPy_PartSys, &ParticleSys_Type ); + + if( blen_object ) + blen_object->psys = (ParticleSystem *)psystem; + + blen_object->object = ob; + + return ( PyObject * ) blen_object; +} + + +PyObject *M_ParticleSys_New( PyObject * self, PyObject * args ){ + ParticleSystem *psys = 0; + ParticleSystem *rpsys = 0; + ModifierData *md; + ParticleSystemModifierData *psmd; + Object *ob = NULL; + char *name = NULL; + ID *id; + int nr; + + if( !PyArg_ParseTuple( args, "s", &name ) ) + return EXPP_ReturnPyObjError( PyExc_TypeError, + "expected string argument" ); + + for( ob = G.main->object.first; ob; ob = ob->id.next ) + if( !strcmp( name, ob->id.name + 2 ) ) + break; + + if( !ob ) + return EXPP_ReturnPyObjError( PyExc_AttributeError, + "object does not exist" ); + + id = (ID *)psys_new_settings("PSys", G.main); + + psys = MEM_callocN(sizeof(ParticleSystem), "particle_system"); + psys->pointcache = BKE_ptcache_add(); + psys->flag |= PSYS_ENABLED; + BLI_addtail(&ob->particlesystem,psys); + + md = modifier_new(eModifierType_ParticleSystem); + sprintf(md->name, "ParticleSystem %i", BLI_countlist(&ob->particlesystem)); + psmd = (ParticleSystemModifierData*) md; + psmd->psys=psys; + BLI_addtail(&ob->modifiers, md); + + psys->part=(ParticleSettings*)id; + psys->totpart=0; + psys->flag=PSYS_ENABLED|PSYS_CURRENT; + psys->cfra=bsystem_time(ob,(float)G.scene->r.cfra+1,0.0); + rpsys = psys; + + /* check need for dupliobjects */ + + nr=0; + for(psys=ob->particlesystem.first; psys; psys=psys->next){ + if(ELEM(psys->part->draw_as,PART_DRAW_OB,PART_DRAW_GR)) + nr++; + } + if(nr) + ob->transflag |= OB_DUPLIPARTS; + else + ob->transflag &= ~OB_DUPLIPARTS; + + BIF_undo_push("Browse Particle System"); + + DAG_scene_sort(G.scene); + DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); + + return ParticleSys_CreatePyObject(rpsys,ob); +} + + +/* + +Get( name ) returns named particle sys or list of all +throws NameError if name not found + +*/ + +PyObject *M_ParticleSys_Get( PyObject * self, PyObject * args ) +{ + ParticleSettings *psys_iter; + char *name = NULL; +#if 0 + + ParticleSystem *blparticlesys = 0; + Object *ob; + + PyObject *partsyslist,*current; +#endif + if( !PyArg_ParseTuple( args, "|s", &name ) ) + return EXPP_ReturnPyObjError( PyExc_TypeError, + "expected string argument" ); + + psys_iter = G.main->particle.first; /* initialize our iterator */ + + if( name ) { /* find psys by name */ + + PyObject *wanted_obj = NULL; + + while( psys_iter && ! wanted_obj ){ + if( !strcmp( name, psys_iter->id.name + 2)){ + printf("** found %s\n", psys_iter->id.name+2); + //wanted_obj = ParticleSys_CreatePyObject( psys_iter ); + break; + } + psys_iter = psys_iter->id.next; + } + + if( !wanted_obj){ /* requested object not found */ + char error_msg[64]; + PyOS_snprintf( error_msg, sizeof( error_msg ), + "Particle System '%s' not found", name); + return EXPP_ReturnPyObjError( PyExc_NameError, error_msg ); + } + + return wanted_obj; + + }else { /* no arg - return a list of bpy objs all P. systems */ + + PyObject *pylist; + int index = 0; + + pylist = PyList_New( BLI_countlist( &G.main->particle )); + printf("** list is %d long\n", PyList_Size( pylist)); + if( ! pylist ){ + return EXPP_ReturnPyObjError( + PyExc_MemoryError, + "could not create ParticleSystem list"); + } + + while( psys_iter ){ +#if 0 + pyobj = ParticleSystem_CreatePyObject( psys_iter); + if( !pyobj){ + Py_DECREF( pylist ); + return EXPP_ReturnPyObjError( + PyExc_MemoryError, + "could not create ParticleSystem PyObject"); + } + PyList_SET_ITEM( pylist, index, pyobj); +#endif + printf("name is %s\n", psys_iter->id.name+2); + psys_iter = psys_iter->id.next; + index++; + } + + return pylist; + + } + + + +#if 0 + + for( ob = G.main->particlesystem.first; ob; ob = ob->id.next ) + if( !strcmp( name, ob->id.name + 2 ) ) + break; + + if( !ob ) + return EXPP_ReturnPyObjError( PyExc_AttributeError, + "object does not exist" ); + + blparticlesys = ob->particlesystem.first; + + + partsyslist = PyList_New( 0 ); + + if (!blparticlesys) + return partsyslist; + + current = ParticleSys_CreatePyObject( blparticlesys, ob ); + PyList_Append(partsyslist,current); + + + while((blparticlesys = blparticlesys->next)){ + current = ParticleSys_CreatePyObject( blparticlesys, ob ); + PyList_Append(partsyslist,current); + } + + return partsyslist; + +#endif +} + + +/*****************************************************************************/ +/* Function: ParticleSys_Init */ +/*****************************************************************************/ + +/* create the Blender.Particle.Type constant dict */ + +static PyObject *Particle_TypeDict( void ) +{ + PyObject *Types = PyConstant_New( ); + + if( Types ) { + BPy_constant *c = ( BPy_constant * ) Types; + + PyConstant_Insert( c, "HAIR", + PyInt_FromLong( 2 ) ); + PyConstant_Insert( c, "REACTOR", + PyInt_FromLong( 1 ) ); + PyConstant_Insert( c, "EMITTER", + PyInt_FromLong( 0 ) ); + } + return Types; +} + +/* create the Blender.Particle.Distribution constant dict */ + +static PyObject *Particle_DistrDict( void ) +{ + PyObject *Distr = PyConstant_New( ); + + if( Distr ) { + BPy_constant *c = ( BPy_constant * ) Distr; + + PyConstant_Insert( c, "GRID", + PyInt_FromLong( 2 ) ); + PyConstant_Insert( c, "RANDOM", + PyInt_FromLong( 1 ) ); + PyConstant_Insert( c, "JITTERED", + PyInt_FromLong( 0 ) ); + } + return Distr; +} + +/* create the Blender.Particle.EmitFrom constant dict */ + +static PyObject *Particle_EmitFrom( void ) +{ + PyObject *EmitFrom = PyConstant_New( ); + + if( EmitFrom ) { + BPy_constant *c = ( BPy_constant * ) EmitFrom; + + PyConstant_Insert( c, "VERTS", + PyInt_FromLong( 0 ) ); + PyConstant_Insert( c, "FACES", + PyInt_FromLong( 1 ) ); + PyConstant_Insert( c, "VOLUME", + PyInt_FromLong( 2 ) ); + PyConstant_Insert( c, "PARTICLE", + PyInt_FromLong( 3 ) ); + } + return EmitFrom; +} + +/* create the Blender.Particle.Collision constant dict */ + +static PyObject *Particle_ReactOnDict( void ) +{ + PyObject *ReactOn = PyConstant_New( ); + + if( ReactOn ) { + BPy_constant *c = ( BPy_constant * ) ReactOn; + + PyConstant_Insert( c, "NEAR", + PyInt_FromLong( 2 ) ); + PyConstant_Insert( c, "COLLISION", + PyInt_FromLong( 1 ) ); + PyConstant_Insert( c, "DEATH", + PyInt_FromLong( 0 ) ); + } + return ReactOn; +} + +static PyObject *Particle_DrawAs( void ) +{ + PyObject *DrawAs = PyConstant_New( ); + + if( DrawAs ) { + BPy_constant *c = ( BPy_constant * ) DrawAs; + + PyConstant_Insert( c, "NONE", + PyInt_FromLong( 0 ) ); + PyConstant_Insert( c, "POINT", + PyInt_FromLong( 1 ) ); + PyConstant_Insert( c, "CIRCLE", + PyInt_FromLong( 2 ) ); + PyConstant_Insert( c, "CROSS", + PyInt_FromLong( 3 ) ); + PyConstant_Insert( c, "AXIS", + PyInt_FromLong( 4 ) ); + PyConstant_Insert( c, "LINE", + PyInt_FromLong( 5 ) ); + PyConstant_Insert( c, "PATH", + PyInt_FromLong( 6 ) ); + PyConstant_Insert( c, "OBJECT", + PyInt_FromLong( 7 ) ); + PyConstant_Insert( c, "GROUP", + PyInt_FromLong( 8 ) ); + PyConstant_Insert( c, "BILLBOARD", + PyInt_FromLong( 9 ) ); + } + return DrawAs; +} + +void Particle_Recalc(BPy_PartSys* self,int child){ + psys_flush_settings(self->psys->part,0,child ); +} + +void Particle_RecalcPsys_distr(BPy_PartSys* self,int child){ + psys_flush_settings(self->psys->part,PSYS_DISTR,child); +} + +PyObject *ParticleSys_Init( void ){ PyObject *submodule; - - if( PyType_Ready( &Particle_Type) < 0) + PyObject *Types; + PyObject *React; + PyObject *EmitFrom; + PyObject *Dist; + PyObject *DrawAs; + + if( PyType_Ready( &ParticleSys_Type ) < 0) return NULL; - - submodule = - Py_InitModule3( "Blender.Particle", M_Particle_methods, M_Particle_doc ); + + Types = Particle_TypeDict (); + React = Particle_ReactOnDict(); + EmitFrom = Particle_EmitFrom(); + DrawAs = Particle_DrawAs(); + Dist = Particle_DistrDict(); + + submodule = Py_InitModule3( "Blender.Particle", + M_ParticleSys_methods, M_ParticleSys_doc ); + + if( Types ) + PyModule_AddObject( submodule, "TYPE", Types ); + if( React ) + PyModule_AddObject( submodule, "REACTON", React ); + if( EmitFrom ) + PyModule_AddObject( submodule, "EMITFROM", EmitFrom ); + if( Dist ) + PyModule_AddObject( submodule, "DISTRIBUTION", Dist ); + if( DrawAs ) + PyModule_AddObject( submodule, "DRAWAS", DrawAs ); + return ( submodule ); } -/*****************************************************************************/ -/* Python BPy_Particle methods: */ -/*****************************************************************************/ +static PyObject *Part_freeEdit( BPy_PartSys * self, PyObject * args ){ -PyObject *Particle_getSta( BPy_Particle * self ) -{ + if(self->psys->flag & PSYS_EDITED){ + if(self->psys->edit) + PE_free_particle_edit(self->psys); - PartEff *ptr = ( PartEff * ) self->particle; - return PyFloat_FromDouble( ptr->sta ); + self->psys->flag &= ~PSYS_EDITED; + self->psys->recalc |= PSYS_RECALC_HAIR; + + DAG_object_flush_update(G.scene, self->object, OB_RECALC_DATA); + } + Py_RETURN_NONE; +} + +static PyObject *Part_GetLoc( BPy_PartSys * self, PyObject * args ){ + ParticleSystem *psys = 0L; + Object *ob = 0L; + PyObject *partlist,*seglist; + PyObject* loc = 0L; + ParticleCacheKey **cache,*path; + ParticleKey state; + float cfra=bsystem_time(ob,(float)CFRA,0.0); + int i,j,k; + int childexists = 0; + int all = 0; + int id = 0; + + if( !PyArg_ParseTuple( args, "|ii", &all,&id ) ) + return EXPP_ReturnPyObjError( PyExc_TypeError, + "expected one optional integer as argument" ); + + psys = self->psys; + ob = self->object; + + if (!ob || !psys) + Py_RETURN_NONE; + + if (psys->part->type == 2){ + cache=psys->pathcache; + + /* little hack to calculate hair steps in render mode */ + psys->renderdata = (void*)(int)1; + + psys_cache_paths(ob, psys, cfra, 0); + + psys->renderdata = NULL; + + partlist = PyList_New( 0 ); + if( !partlist ) + return EXPP_ReturnPyObjError( PyExc_MemoryError, "PyList() failed" ); + + for(i = 0; i < psys->totpart; i++){ + path=cache[i]; + seglist = PyList_New( 0 ); + k = path->steps+1; + for( j = 0; j < k ; j++){ + loc = PyTuple_New(3); + + PyTuple_SetItem(loc,0,PyFloat_FromDouble((double)path->co[0])); + PyTuple_SetItem(loc,1,PyFloat_FromDouble((double)path->co[1])); + PyTuple_SetItem(loc,2,PyFloat_FromDouble((double)path->co[2])); + + if ( (PyList_Append(seglist,loc) < 0) ){ + Py_DECREF(seglist); + Py_DECREF(partlist); + Py_XDECREF(loc); + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Couldn't append item to PyList" ); + } + + path++; + } + + if ( PyList_Append(partlist,seglist) < 0 ){ + Py_DECREF(seglist); + Py_DECREF(partlist); + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Couldn't append item to PyList" ); + } + } + + cache=psys->childcache; + + for(i = 0; i < psys->totchild; i++){ + path=cache[i]; + seglist = PyList_New( 0 ); + k = path->steps+1; + for( j = 0; j < k ; j++){ + loc = PyTuple_New(3); + + PyTuple_SetItem(loc,0,PyFloat_FromDouble((double)path->co[0])); + PyTuple_SetItem(loc,1,PyFloat_FromDouble((double)path->co[1])); + PyTuple_SetItem(loc,2,PyFloat_FromDouble((double)path->co[2])); + + if ( PyList_Append(seglist,loc) < 0){ + Py_DECREF(partlist); + Py_XDECREF(loc); + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Couldn't append item to PyList" ); + } + + path++; + } + + if ( PyList_Append(partlist,seglist) < 0){ + Py_DECREF(partlist); + Py_XDECREF(loc); + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Couldn't append item to PyList" ); + } + } + + } else { + int init; + partlist = PyList_New( 0 ); + if( !partlist ) + return EXPP_ReturnPyObjError( PyExc_MemoryError, "PyList() failed" ); + + if (psys->totchild > 0 && !(psys->part->draw & PART_DRAW_PARENT)) + childexists = 1; + + for (i = 0; i < psys->totpart + psys->totchild; i++){ + if (childexists && (i < psys->totpart)) + continue; + + state.time = cfra; + if(psys_get_particle_state(ob,psys,i,&state,0)==0) + init = 0; + else + init = 1; + + if (init){ + if (!id) + loc = PyTuple_New(3); + else + loc = PyTuple_New(4); + PyTuple_SetItem(loc,0,PyFloat_FromDouble((double)state.co[0])); + PyTuple_SetItem(loc,1,PyFloat_FromDouble((double)state.co[1])); + PyTuple_SetItem(loc,2,PyFloat_FromDouble((double)state.co[2])); + if (id) + PyTuple_SetItem(loc,3,PyInt_FromLong(i)); + + if ( PyList_Append(partlist,loc) < 0 ){ + Py_DECREF(partlist); + Py_XDECREF(loc); + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Couldn't append item to PyList" ); + } + } + else { + if ( all ){ + if ( PyList_Append(partlist,Py_None) < 0 ){ + Py_DECREF(partlist); + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Couldn't append item to PyList" ); + } + } + } + } + } + return partlist; +} + +static PyObject *Part_GetRot( BPy_PartSys * self, PyObject * args ){ + ParticleSystem *psys = 0L; + Object *ob = 0L; + PyObject *partlist = 0L; + PyObject* loc = 0L; + ParticleKey state; + int i; + int childexists = 0; + int all = 0; + int id = 0; + + float cfra=bsystem_time(ob,(float)CFRA,0.0); + + if( !PyArg_ParseTuple( args, "|ii", &all, &id ) ) + return EXPP_ReturnPyObjError( PyExc_TypeError, + "expected one optional integer as argument" ); + + psys = self->psys; + ob = self->object; + + if (!ob || !psys) + Py_RETURN_NONE; + + if (psys->part->type != 2){ + partlist = PyList_New( 0 ); + + if (psys->totchild > 0 && !(psys->part->draw & PART_DRAW_PARENT)) + childexists = 1; + + for (i = 0; i < psys->totpart + psys->totchild; i++){ + if (childexists && (i < psys->totpart)) + continue; + + state.time = cfra; + if(psys_get_particle_state(ob,psys,i,&state,0)==0){ + if ( all ){ + PyList_Append(partlist,Py_None); + continue; + } else { + continue; + } + } + if (!id) + loc = PyTuple_New(4); + else + loc = PyTuple_New(5); + PyTuple_SetItem(loc,0,PyFloat_FromDouble((double)state.rot[0])); + PyTuple_SetItem(loc,1,PyFloat_FromDouble((double)state.rot[1])); + PyTuple_SetItem(loc,2,PyFloat_FromDouble((double)state.rot[2])); + PyTuple_SetItem(loc,3,PyFloat_FromDouble((double)state.rot[3])); + if (id) + PyTuple_SetItem(loc,4,PyInt_FromLong(i)); + PyList_Append(partlist,loc); + } + } + return partlist; +} + +static PyObject *Part_GetSize( BPy_PartSys * self, PyObject * args ){ + ParticleKey state; + ParticleSystem *psys = 0L; + ParticleData *data; + Object *ob = 0L; + PyObject *partlist,*tuple; + PyObject* siz = 0L; + float size; + int i; + int childexists = 0; + int all = 0; + int id = 0; + + float cfra=bsystem_time(ob,(float)CFRA,0.0); + + if( !PyArg_ParseTuple( args, "|ii", &all, &id ) ) + return EXPP_ReturnPyObjError( PyExc_TypeError, + "expected one optional integer as argument" ); + + data = self->psys->particles; + + psys = self->psys; + ob = self->object; + + if (!ob || !psys) + Py_RETURN_NONE; + + partlist = PyList_New( 0 ); + + if (psys->totchild > 0 && !(psys->part->draw & PART_DRAW_PARENT)) + childexists = 1; + + for (i = 0; i < psys->totpart + psys->totchild; i++, data++){ + if (psys->part->type != 2){ + if (childexists && (i < psys->totpart)) + continue; + + if ( !all ){ + state.time = cfra; + if(psys_get_particle_state(ob,psys,i,&state,0)==0) + continue; + } + + if (i < psys->totpart){ + size = data->size; + } else { + ChildParticle *cpa= &psys->child[i-psys->totpart]; + size = psys_get_child_size(psys,cpa,cfra,0); + } + if (id){ + tuple = PyTuple_New(2); + PyTuple_SetItem(tuple,0,PyFloat_FromDouble((double)size)); + PyTuple_SetItem(tuple,1,PyInt_FromLong(i)); + PyList_Append(partlist,tuple); + } else { + siz = PyFloat_FromDouble((double)size); + PyList_Append(partlist,siz); + } + } + } + return partlist; } +static PyObject *Part_GetAge( BPy_PartSys * self, PyObject * args ){ + ParticleKey state; + ParticleSystem *psys = 0L; + ParticleData *data; + Object *ob = 0L; + PyObject *partlist,*tuple; + PyObject* lif = 0L; + float life; + int i; + int childexists = 0; + int all = 0; + int id = 0; -PyObject *Particle_setSta( BPy_Particle * self, PyObject * args ) -{ - PartEff *ptr = ( PartEff * ) self->particle; - float val = 0; - if( !PyArg_ParseTuple( args, "f", &val ) ) - return ( EXPP_ReturnPyObjError( PyExc_AttributeError, - "expected float argument" ) ); - ptr->sta = val; - Py_INCREF( Py_None ); - return Py_None; -} + float cfra=bsystem_time(ob,(float)CFRA,0.0); -PyObject *Particle_getEnd( BPy_Particle * self ) -{ + if( !PyArg_ParseTuple( args, "|ii", &all, &id ) ) + return EXPP_ReturnPyObjError( PyExc_TypeError, + "expected one optional integer as argument" ); - PartEff *ptr = ( PartEff * ) self->particle; - return PyFloat_FromDouble( ptr->end ); + data = self->psys->particles; + + psys = self->psys; + ob = self->object; + + if (!ob || !psys) + Py_RETURN_NONE; + + partlist = PyList_New( 0 ); + + if (psys->totchild > 0 && !(psys->part->draw & PART_DRAW_PARENT)) + childexists = 1; + + for (i = 0; i < psys->totpart + psys->totchild; i++, data++){ + if (psys->part->type != 2){ + + if (childexists && (i < psys->totpart)) + continue; + + if ( !all ){ + state.time = cfra; + if(psys_get_particle_state(ob,psys,i,&state,0)==0) + continue; + } + + if (i < psys->totpart){ + life = (cfra-data->time)/data->lifetime; + } else { + ChildParticle *cpa= &psys->child[i-psys->totpart]; + life = psys_get_child_time(psys,cpa,cfra); + } + if (id){ + tuple = PyTuple_New(2); + PyTuple_SetItem(tuple,0,PyFloat_FromDouble((double)life)); + PyTuple_SetItem(tuple,1,PyInt_FromLong(i)); + PyList_Append(partlist,tuple); + } else { + lif = PyFloat_FromDouble((double)life); + PyList_Append(partlist,lif); + } + } + } + return partlist; } - -PyObject *Particle_setEnd( BPy_Particle * self, PyObject * args ) -{ - float val = 0; - PartEff *ptr = ( PartEff * ) self->particle; - if( !PyArg_ParseTuple( args, "f", &val ) ) - return ( EXPP_ReturnPyObjError( PyExc_AttributeError, - "expected float argument" ) ); - ptr->end = val; - Py_INCREF( Py_None ); - return Py_None; -} - -PyObject *Particle_getLifetime( BPy_Particle * self ) -{ - - PartEff *ptr = ( PartEff * ) self->particle; - return PyFloat_FromDouble( ptr->lifetime ); -} - - - -PyObject *Particle_setLifetime( BPy_Particle * self, PyObject * args ) -{ - PartEff *ptr = ( PartEff * ) self->particle; - float val = 0; - if( !PyArg_ParseTuple( args, "f", &val ) ) - return ( EXPP_ReturnPyObjError( PyExc_AttributeError, - "expected float argument" ) ); - ptr->lifetime = val; - Py_INCREF( Py_None ); - return Py_None; -} - - -PyObject *Particle_getNormfac( BPy_Particle * self ) -{ - - PartEff *ptr = ( PartEff * ) self->particle; - return PyFloat_FromDouble( ptr->normfac ); -} - - - -PyObject *Particle_setNormfac( BPy_Particle * self, PyObject * args ) -{ - PartEff *ptr = ( PartEff * ) self->particle; - float val = 0; - if( !PyArg_ParseTuple( args, "f", &val ) ) - return ( EXPP_ReturnPyObjError( PyExc_AttributeError, - "expected float argument" ) ); - ptr->normfac = val; - Py_INCREF( Py_None ); - return Py_None; -} - - - -PyObject *Particle_getObfac( BPy_Particle * self ) -{ - - PartEff *ptr = ( PartEff * ) self->particle; - return PyFloat_FromDouble( ptr->obfac ); -} - - - -PyObject *Particle_setObfac( BPy_Particle * self, PyObject * args ) -{ - float val = 0; - PartEff *ptr = ( PartEff * ) self->particle; - if( !PyArg_ParseTuple( args, "f", &val ) ) - return ( EXPP_ReturnPyObjError( PyExc_AttributeError, - "expected float argument" ) ); - ptr->obfac = val; - Py_INCREF( Py_None ); - return Py_None; -} - - - -PyObject *Particle_getRandfac( BPy_Particle * self ) -{ - - PartEff *ptr = ( PartEff * ) self->particle; - return PyFloat_FromDouble( ptr->randfac ); -} - - - -PyObject *Particle_setRandfac( BPy_Particle * self, PyObject * args ) -{ - float val = 0; - PartEff *ptr = ( PartEff * ) self->particle; - if( !PyArg_ParseTuple( args, "f", &val ) ) - return ( EXPP_ReturnPyObjError( PyExc_AttributeError, - "expected float argument" ) ); - ptr->randfac = val; - Py_INCREF( Py_None ); - return Py_None; -} - - - -PyObject *Particle_getTexfac( BPy_Particle * self ) -{ - - PartEff *ptr = ( PartEff * ) self->particle; - return PyFloat_FromDouble( ptr->texfac ); -} - - - -PyObject *Particle_setTexfac( BPy_Particle * self, PyObject * args ) -{ - PartEff *ptr = ( PartEff * ) self->particle; - float val = 0; - if( !PyArg_ParseTuple( args, "f", &val ) ) - return ( EXPP_ReturnPyObjError( PyExc_AttributeError, - "expected float argument" ) ); - ptr->texfac = val; - Py_INCREF( Py_None ); - return Py_None; -} - - - -PyObject *Particle_getRandlife( BPy_Particle * self ) -{ - - PartEff *ptr = ( PartEff * ) self->particle; - return PyFloat_FromDouble( ptr->randlife ); -} - - - -PyObject *Particle_setRandlife( BPy_Particle * self, PyObject * args ) -{ - PartEff *ptr = ( PartEff * ) self->particle; - float val = 0; - if( !PyArg_ParseTuple( args, "f", &val ) ) - return ( EXPP_ReturnPyObjError( PyExc_AttributeError, - "expected float argument" ) ); - ptr->randlife = val; - Py_INCREF( Py_None ); - return Py_None; -} - - - -PyObject *Particle_getNabla( BPy_Particle * self ) -{ - - PartEff *ptr = ( PartEff * ) self->particle; - return PyFloat_FromDouble( ptr->nabla ); -} - - - -PyObject *Particle_setNabla( BPy_Particle * self, PyObject * args ) -{ - PartEff *ptr = ( PartEff * ) self->particle; - float val = 0; - if( !PyArg_ParseTuple( args, "f", &val ) ) - return ( EXPP_ReturnPyObjError( PyExc_AttributeError, - "expected float argument" ) ); - ptr->nabla = val; - Py_INCREF( Py_None ); - return Py_None; -} - - - -PyObject *Particle_getVectsize( BPy_Particle * self ) -{ - - PartEff *ptr = ( PartEff * ) self->particle; - return PyFloat_FromDouble( ptr->vectsize ); -} - - - -PyObject *Particle_setVectsize( BPy_Particle * self, PyObject * args ) -{ - PartEff *ptr = ( PartEff * ) self->particle; - float val = 0; - if( !PyArg_ParseTuple( args, "f", &val ) ) - return ( EXPP_ReturnPyObjError( PyExc_AttributeError, - "expected float argument" ) ); - ptr->vectsize = val; - Py_INCREF( Py_None ); - return Py_None; -} - - -PyObject *Particle_getTotpart( BPy_Particle * self ) -{ - - PartEff *ptr = ( PartEff * ) self->particle; - return PyInt_FromLong( ptr->totpart ); -} - - - -PyObject *Particle_setTotpart( BPy_Particle * self, PyObject * args ) -{ - int val = 0; - PartEff *ptr = ( PartEff * ) self->particle; - if( !PyArg_ParseTuple( args, "i", &val ) ) - return ( EXPP_ReturnPyObjError( PyExc_AttributeError, - "expected int argument" ) ); - ptr->totpart = val; - Py_INCREF( Py_None ); - return Py_None; -} - - -PyObject *Particle_getTotkey( BPy_Particle * self ) -{ - - PartEff *ptr = ( PartEff * ) self->particle; - return PyInt_FromLong( ptr->totkey ); -} - - - -PyObject *Particle_setTotkey( BPy_Particle * self, PyObject * args ) -{ - PartEff *ptr = ( PartEff * ) self->particle; - int val = 0; - if( !PyArg_ParseTuple( args, "i", &val ) ) - return ( EXPP_ReturnPyObjError( PyExc_AttributeError, - "expected int argument" ) ); - ptr->totkey = val; - Py_INCREF( Py_None ); - return Py_None; -} - - - -PyObject *Particle_getSeed( BPy_Particle * self ) -{ - - PartEff *ptr = ( PartEff * ) self->particle; - return PyInt_FromLong( ptr->seed ); -} - - - -PyObject *Particle_setSeed( BPy_Particle * self, PyObject * args ) -{ - PartEff *ptr = ( PartEff * ) self->particle; - int val = 0; - if( !PyArg_ParseTuple( args, "i", &val ) ) - return ( EXPP_ReturnPyObjError( PyExc_AttributeError, - "expected int argument" ) ); - ptr->seed = val; - Py_INCREF( Py_None ); - return Py_None; -} - -PyObject *Particle_getForce( BPy_Particle * self ) -{ - - PartEff *ptr = ( PartEff * ) self->particle; - return Py_BuildValue( "(f,f,f)", ptr->force[0], ptr->force[1], - ptr->force[2] ); -} - - -PyObject *Particle_setForce( BPy_Particle * self, PyObject * args ) -{ - PartEff *ptr = ( PartEff * ) self->particle; - float val[3]; - if( PyTuple_Size( args ) == 1 ) - args = PyTuple_GetItem( args, 0 ); - val[0] = (float)PyFloat_AsDouble( PyTuple_GetItem( args, 0 ) ); - val[1] = (float)PyFloat_AsDouble( PyTuple_GetItem( args, 1 ) ); - val[2] = (float)PyFloat_AsDouble( PyTuple_GetItem( args, 2 ) ); - /* - if (!PyArg_ParseTuple(args, "fff", val,val+1,val+2 )) - return(EXPP_ReturnPyObjError(PyExc_AttributeError,\ - "expected three float arguments")); - */ - ptr->force[0] = val[0]; - ptr->force[1] = val[1]; - ptr->force[2] = val[2]; - Py_INCREF( Py_None ); - return Py_None; -} - -PyObject *Particle_getMult( BPy_Particle * self ) -{ - - PartEff *ptr = ( PartEff * ) self->particle; - return Py_BuildValue( "(f,f,f,f)", - ptr->mult[0], ptr->mult[1], ptr->mult[2], - ptr->mult[3] ); -} - - -PyObject *Particle_setMult( BPy_Particle * self, PyObject * args ) -{ - PartEff *ptr = ( PartEff * ) self->particle; - float val[4]; - if( PyTuple_Size( args ) == 1 ) - args = PyTuple_GetItem( args, 0 ); - val[0] = (float)PyFloat_AsDouble( PyTuple_GetItem( args, 0 ) ); - val[1] = (float)PyFloat_AsDouble( PyTuple_GetItem( args, 1 ) ); - val[2] = (float)PyFloat_AsDouble( PyTuple_GetItem( args, 2 ) ); - val[3] = (float)PyFloat_AsDouble( PyTuple_GetItem( args, 3 ) ); - ptr->mult[0] = val[0]; - ptr->mult[1] = val[1]; - ptr->mult[2] = val[2]; - ptr->mult[3] = val[3]; - Py_INCREF( Py_None ); - return Py_None; -} - - - - -PyObject *Particle_getLife( BPy_Particle * self ) -{ - - PartEff *ptr = ( PartEff * ) self->particle; - return Py_BuildValue( "(f,f,f,f)", - ptr->life[0], ptr->life[1], ptr->life[2], - ptr->life[3] ); -} - - -PyObject *Particle_setLife( BPy_Particle * self, PyObject * args ) -{ - PartEff *ptr = ( PartEff * ) self->particle; - float val[4]; - if( PyTuple_Size( args ) == 1 ) - args = PyTuple_GetItem( args, 0 ); - val[0] = (float)PyFloat_AsDouble( PyTuple_GetItem( args, 0 ) ); - val[1] = (float)PyFloat_AsDouble( PyTuple_GetItem( args, 1 ) ); - val[2] = (float)PyFloat_AsDouble( PyTuple_GetItem( args, 2 ) ); - val[3] = (float)PyFloat_AsDouble( PyTuple_GetItem( args, 3 ) ); - ptr->life[0] = val[0]; - ptr->life[1] = val[1]; - ptr->life[2] = val[2]; - ptr->life[3] = val[3]; - Py_INCREF( Py_None ); - return Py_None; -} - - - -PyObject *Particle_getChild( BPy_Particle * self ) -{ - - PartEff *ptr = ( PartEff * ) self->particle; - return Py_BuildValue( "(f,f,f,f)", - ptr->child[0], ptr->child[1], ptr->child[2], - ptr->child[3] ); -} - - -PyObject *Particle_setChild( BPy_Particle * self, PyObject * args ) -{ - PartEff *ptr = ( PartEff * ) self->particle; - float val[4]; - if( PyTuple_Size( args ) == 1 ) - args = PyTuple_GetItem( args, 0 ); - val[0] = (float)PyFloat_AsDouble( PyTuple_GetItem( args, 0 ) ); - val[1] = (float)PyFloat_AsDouble( PyTuple_GetItem( args, 1 ) ); - val[2] = (float)PyFloat_AsDouble( PyTuple_GetItem( args, 2 ) ); - val[3] = (float)PyFloat_AsDouble( PyTuple_GetItem( args, 3 ) ); - ptr->child[0] = (short)val[0]; - ptr->child[1] = (short)val[1]; - ptr->child[2] = (short)val[2]; - ptr->child[3] = (short)val[3]; - Py_INCREF( Py_None ); - return Py_None; -} - - - -PyObject *Particle_getMat( BPy_Particle * self ) -{ - - PartEff *ptr = ( PartEff * ) self->particle; - return Py_BuildValue( "(f,f,f,f)", - ptr->mat[0], ptr->mat[1], ptr->mat[2], - ptr->mat[3] ); -} - - -PyObject *Particle_setMat( BPy_Particle * self, PyObject * args ) -{ - PartEff *ptr = ( PartEff * ) self->particle; - float val[4]; - if( PyTuple_Size( args ) == 1 ) - args = PyTuple_GetItem( args, 0 ); - val[0] = (float)PyFloat_AsDouble( PyTuple_GetItem( args, 0 ) ); - val[1] = (float)PyFloat_AsDouble( PyTuple_GetItem( args, 1 ) ); - val[2] = (float)PyFloat_AsDouble( PyTuple_GetItem( args, 2 ) ); - val[3] = (float)PyFloat_AsDouble( PyTuple_GetItem( args, 3 ) ); - ptr->mat[0] = (short)val[0]; - ptr->mat[1] = (short)val[1]; - ptr->mat[2] = (short)val[2]; - ptr->mat[3] = (short)val[3]; - Py_INCREF( Py_None ); - return Py_None; -} - - -PyObject *Particle_getDefvec( BPy_Particle * self ) -{ - - PartEff *ptr = ( PartEff * ) self->particle; - return Py_BuildValue( "(f,f,f)", - ptr->defvec[0], ptr->defvec[1], ptr->defvec[2] ); -} - - -PyObject *Particle_setDefvec( BPy_Particle * self, PyObject * args ) -{ - PartEff *ptr = ( PartEff * ) self->particle; - float val[3]; - if( PyTuple_Size( args ) == 1 ) - args = PyTuple_GetItem( args, 0 ); - val[0] = (float)PyFloat_AsDouble( PyTuple_GetItem( args, 0 ) ); - val[1] = (float)PyFloat_AsDouble( PyTuple_GetItem( args, 1 ) ); - val[2] = (float)PyFloat_AsDouble( PyTuple_GetItem( args, 2 ) ); - ptr->defvec[0] = val[0]; - ptr->defvec[1] = val[1]; - ptr->defvec[2] = val[2]; - Py_INCREF( Py_None ); - return Py_None; +static PyObject *Part_GetMat( BPy_PartSys * self, PyObject * args ){ + Material *ma; + PyObject* mat = 0L; + ma = give_current_material(self->object,self->psys->part->omat); + if(!ma) + Py_RETURN_NONE; + + mat = Material_CreatePyObject(ma); + return mat; } /*****************************************************************************/ -/* Function: ParticleDeAlloc */ -/* Description: This is a callback function for the BPy_Particle type. It is */ -/* the destructor function. */ +/* Function: Set/Get Seed */ /*****************************************************************************/ -void ParticleDeAlloc( BPy_Particle * self ) + +static int Part_setSeed( BPy_PartSys * self, PyObject * args ) { - PartEff *ptr = ( PartEff * ) self; - PyObject_DEL( ptr ); + return EXPP_setIValueRange( args, &self->psys->seed, + 0, 255, 'i' ); } -/*****************************************************************************/ -/* Function: ParticleGetAttr */ -/* Description: This is a callback function for the BPy_Particle type. It is */ -/* the function that accesses BPy_Particle "member variables" */ -/* and methods. */ -/*****************************************************************************/ - - -PyObject *ParticleGetAttr( BPy_Particle * self, char *name ) +static PyObject *Part_getSeed( BPy_PartSys * self ) { - - if( strcmp( name, "seed" ) == 0 ) - return Particle_getSeed( self ); - else if( strcmp( name, "nabla" ) == 0 ) - return Particle_getNabla( self ); - else if( strcmp( name, "sta" ) == 0 ) - return Particle_getSta( self ); - else if( strcmp( name, "end" ) == 0 ) - return Particle_getEnd( self ); - else if( strcmp( name, "lifetime" ) == 0 ) - return Particle_getLifetime( self ); - else if( strcmp( name, "normfac" ) == 0 ) - return Particle_getNormfac( self ); - else if( strcmp( name, "obfac" ) == 0 ) - return Particle_getObfac( self ); - else if( strcmp( name, "randfac" ) == 0 ) - return Particle_getRandfac( self ); - else if( strcmp( name, "texfac" ) == 0 ) - return Particle_getTexfac( self ); - else if( strcmp( name, "randlife" ) == 0 ) - return Particle_getRandlife( self ); - else if( strcmp( name, "vectsize" ) == 0 ) - return Particle_getVectsize( self ); - else if( strcmp( name, "totpart" ) == 0 ) - return Particle_getTotpart( self ); - else if( strcmp( name, "force" ) == 0 ) - return Particle_getForce( self ); - else if( strcmp( name, "mult" ) == 0 ) - return Particle_getMult( self ); - else if( strcmp( name, "life" ) == 0 ) - return Particle_getLife( self ); - else if( strcmp( name, "child" ) == 0 ) - return Particle_getChild( self ); - else if( strcmp( name, "mat" ) == 0 ) - return Particle_getMat( self ); - else if( strcmp( name, "defvec" ) == 0 ) - return Particle_getDefvec( self ); - - - return Py_FindMethod( BPy_Particle_methods, ( PyObject * ) self, - name ); + return PyInt_FromLong( (long)( self->psys->seed ) ); } -/*****************************************************************************/ -/* Function: ParticleSetAttr */ -/* Description: This is a callback function for the BPy_Particle type. */ -/* It is the function that sets Particle Data attributes */ -/* (member vars) */ -/*****************************************************************************/ -int ParticleSetAttr( BPy_Particle * self, char *name, PyObject * value ) +static int Part_setType( BPy_PartSys * self, PyObject * args ) { + int res = EXPP_setIValueRange( args, &self->psys->part->type, + 0, 2, 'h' ); - PyObject *valtuple; - PyObject *error = NULL; + psys_flush_settings( self->psys->part, PSYS_TYPE, 1 ); - valtuple = Py_BuildValue( "(N)", value ); + return res; +} - if( !valtuple ) - return EXPP_ReturnIntError( PyExc_MemoryError, - "ParticleSetAttr: couldn't create PyTuple" ); +static PyObject *Part_getType( BPy_PartSys * self ) +{ + return PyInt_FromLong( (short)( self->psys->part->type ) ); +} - if( strcmp( name, "seed" ) == 0 ) - error = Particle_setSeed( self, valtuple ); - else if( strcmp( name, "nabla" ) == 0 ) - error = Particle_setNabla( self, valtuple ); - else if( strcmp( name, "sta" ) == 0 ) - error = Particle_setSta( self, valtuple ); - else if( strcmp( name, "end" ) == 0 ) - error = Particle_setEnd( self, valtuple ); - else if( strcmp( name, "lifetime" ) == 0 ) - error = Particle_setLifetime( self, valtuple ); - else if( strcmp( name, "normfac" ) == 0 ) - error = Particle_setNormfac( self, valtuple ); - else if( strcmp( name, "obfac" ) == 0 ) - error = Particle_setObfac( self, valtuple ); - else if( strcmp( name, "randfac" ) == 0 ) - error = Particle_setRandfac( self, valtuple ); - else if( strcmp( name, "texfac" ) == 0 ) - error = Particle_setTexfac( self, valtuple ); - else if( strcmp( name, "randlife" ) == 0 ) - error = Particle_setRandlife( self, valtuple ); - else if( strcmp( name, "nabla" ) == 0 ) - error = Particle_setNabla( self, valtuple ); - else if( strcmp( name, "vectsize" ) == 0 ) - error = Particle_setVectsize( self, valtuple ); - else if( strcmp( name, "totpart" ) == 0 ) - error = Particle_setTotpart( self, valtuple ); - else if( strcmp( name, "seed" ) == 0 ) - error = Particle_setSeed( self, valtuple ); - else if( strcmp( name, "force" ) == 0 ) - error = Particle_setForce( self, valtuple ); - else if( strcmp( name, "mult" ) == 0 ) - error = Particle_setMult( self, valtuple ); - else if( strcmp( name, "life" ) == 0 ) - error = Particle_setLife( self, valtuple ); - else if( strcmp( name, "child" ) == 0 ) - error = Particle_setChild( self, valtuple ); - else if( strcmp( name, "mat" ) == 0 ) - error = Particle_setMat( self, valtuple ); - else if( strcmp( name, "defvec" ) == 0 ) - error = Particle_setDefvec( self, valtuple ); +static int Part_setResol( BPy_PartSys * self, PyObject * args ) +{ + int res = EXPP_setIValueRange( args, &self->psys->part->grid_res, + 0, 100, 'i' ); - else { - Py_DECREF( valtuple ); + psys_flush_settings( self->psys->part, PSYS_ALLOC, 1 ); - if( ( strcmp( name, "Types" ) == 0 ) || - ( strcmp( name, "Modes" ) == 0 ) ) - return ( EXPP_ReturnIntError( PyExc_AttributeError, - "constant dictionary -- cannot be changed" ) ); + return res; +} - else - return ( EXPP_ReturnIntError( PyExc_KeyError, - "attribute not found" ) ); +static PyObject *Part_getResol( BPy_PartSys * self ) +{ + return PyInt_FromLong( ((int)( self->psys->part->grid_res )) ); +} + +static int Part_setStart( BPy_PartSys * self, PyObject * args ) +{ + int res = EXPP_setFloatRange( args, &self->psys->part->sta, + 0.0f, 100000.0f ); + + psys_flush_settings(self->psys->part,PSYS_INIT,1); + + return res; +} + +static PyObject *Part_getStart( BPy_PartSys * self ) +{ + return PyFloat_FromDouble( (float)( self->psys->part->sta ) ); +} + +static int Part_setEnd( BPy_PartSys * self, PyObject * args ) +{ + int res = EXPP_setFloatRange( args, &self->psys->part->end, + 0.0f, 100000.0f ); + + psys_flush_settings(self->psys->part,PSYS_INIT,1); + + return res; +} + +static PyObject *Part_getEnd( BPy_PartSys * self ) +{ + return PyFloat_FromDouble( (long)( self->psys->part->end ) ); +} + +static int Part_setEditable( BPy_PartSys * self, PyObject * args ) +{ + int number; + + if( !PyInt_Check( args ) ) { + char errstr[128]; + sprintf ( errstr, "expected int argument" ); + return EXPP_ReturnIntError( PyExc_TypeError, errstr ); } - Py_DECREF(valtuple); - if( error != Py_None ) - return -1; + number = PyInt_AS_LONG( args ); + + if(!number){ + if(self->psys->edit) + PE_free_particle_edit(self->psys); + + self->psys->flag &= ~PSYS_EDITED; + self->psys->recalc |= PSYS_RECALC_HAIR; + + DAG_object_flush_update(G.scene, self->object, OB_RECALC_DATA); + } + else + { + self->psys->flag |= PSYS_EDITED; + if(G.f & G_PARTICLEEDIT) + PE_create_particle_edit(self->object, self->psys); + } - Py_DECREF( Py_None ); return 0; } -/*****************************************************************************/ -/* Function: ParticlePrint */ -/* Description: This is a callback function for the BPy_Particle type. It */ -/* particles a meaninful string to 'print' particle objects. */ -/*****************************************************************************/ -/* -int ParticlePrint(BPy_Particle *self, FILE *fp, int flags) -{ - printf("Hi, I'm a particle!"); - return 0; -} -*/ -/*****************************************************************************/ -/* Function: ParticleRepr */ -/* Description: This is a callback function for the BPy_Particle type. It */ -/* particles a meaninful string to represent particle objects. */ -/*****************************************************************************/ -PyObject *ParticleRepr( void ) +static PyObject *Part_getEditable( BPy_PartSys * self ) { - return PyString_FromString( "Particle" ); + return PyInt_FromLong( ((long)( self->psys->flag & PSYS_EDITED )) > 0 ); } -PyObject *ParticleCreatePyObject( struct Effect * particle ) +static int Part_setAmount( BPy_PartSys * self, PyObject * args ) { - BPy_Particle *blen_object; + int res = EXPP_setIValueRange( args, &self->psys->part->totpart, + 0, 100000, 'i' ); + psys_flush_settings( self->psys->part, PSYS_ALLOC, 1 ); - blen_object = - ( BPy_Particle * ) PyObject_NEW( BPy_Particle, - &Particle_Type ); + return res; +} - if( blen_object == NULL ) { - return ( NULL ); +static PyObject *Part_getAmount( BPy_PartSys * self ) +{ + return PyInt_FromLong( ((int)( self->psys->part->totpart )) ); +} + +static int Part_setMultiReact( BPy_PartSys * self, PyObject * args ) +{ + int number; + + if( !PyInt_Check( args ) ) { + char errstr[128]; + sprintf ( errstr, "expected int argument" ); + return EXPP_ReturnIntError( PyExc_TypeError, errstr ); } - blen_object->particle = particle; - return ( ( PyObject * ) blen_object ); + number = PyInt_AS_LONG( args ); + + + if (number){ + self->psys->part->flag |= PART_REACT_MULTIPLE; + }else{ + self->psys->part->flag &= ~PART_REACT_MULTIPLE; + } + + Particle_Recalc(self,1); + + return 0; } -int ParticleCheckPyObject( PyObject * py_obj ) +static PyObject *Part_getMultiReact( BPy_PartSys * self ) { - return ( py_obj->ob_type == &Particle_Type ); + return PyInt_FromLong( ((long)( self->psys->part->flag & PART_REACT_MULTIPLE )) > 0 ); } - -struct Particle *ParticleFromPyObject( PyObject * py_obj ) +static int Part_setReactShape( BPy_PartSys * self, PyObject * args ) { - BPy_Particle *blen_obj; + int res = EXPP_setFloatRange( args, &self->psys->part->reactshape, + 0.0f, 10.0f ); - blen_obj = ( BPy_Particle * ) py_obj; - return ( ( struct Particle * ) blen_obj->particle ); + Particle_Recalc(self,1); + return res; +} + +static PyObject *Part_getReactShape( BPy_PartSys * self ) +{ + return PyFloat_FromDouble( ((double)( self->psys->part->reactshape )) ); +} + +static int Part_setSegments( BPy_PartSys * self, PyObject * args ) +{ + int res = EXPP_setIValueRange( args, &self->psys->part->hair_step, + 2, 50, 'h' ); + + Particle_Recalc(self,1); + + return res; +} + +static PyObject *Part_getSegments( BPy_PartSys * self ) +{ + return PyInt_FromLong( ((long)( self->psys->part->hair_step )) ); +} + +static int Part_setLife( BPy_PartSys * self, PyObject * args ) +{ + int res = EXPP_setFloatRange( args, &self->psys->part->lifetime, + 1.0f, MAXFRAMEF ); + + Particle_Recalc(self,1); + + return res; +} + +static PyObject *Part_getLife( BPy_PartSys * self ) +{ + return PyFloat_FromDouble( ((double)( self->psys->part->lifetime )) ); +} + +static int Part_setRandLife( BPy_PartSys * self, PyObject * args ) +{ + int res = EXPP_setFloatRange( args, &self->psys->part->randlife, + 0.0f, 2.0f ); + + Particle_Recalc(self,1); + + return res; +} + +static PyObject *Part_getRandLife( BPy_PartSys * self ) +{ + return PyFloat_FromDouble( ((double)( self->psys->part->randlife )) ); +} + +static int Part_set2d( BPy_PartSys * self, PyObject * args ) +{ + int number; + + if( !PyInt_Check( args ) ) { + char errstr[128]; + sprintf ( errstr, "expected int argument" ); + return EXPP_ReturnIntError( PyExc_TypeError, errstr ); + } + + number = PyInt_AS_LONG( args ); + + if (number){ + self->psys->part->flag |= PART_BOIDS_2D; + }else{ + self->psys->part->flag &= ~PART_BOIDS_2D; + } + + Particle_Recalc(self,1); + + return 0; +} + +static PyObject *Part_get2d( BPy_PartSys * self ) +{ + return PyInt_FromLong( ((long)( self->psys->part->flag & PART_BOIDS_2D )) > 0 ); +} + +static int Part_setMaxVel( BPy_PartSys * self, PyObject * args ) +{ + int res = EXPP_setFloatRange( args, &self->psys->part->max_vel, + 0.0f, 200.0f ); + + Particle_Recalc(self,1); + + return res; +} + +static PyObject *Part_getMaxVel( BPy_PartSys * self ) +{ + return PyFloat_FromDouble( ((double)( self->psys->part->max_vel )) ); +} + +static int Part_setAvVel( BPy_PartSys * self, PyObject * args ) +{ + int res = EXPP_setFloatRange( args, &self->psys->part->average_vel, + 0.0f, 1.0f ); + + Particle_Recalc(self,1); + + return res; +} + +static PyObject *Part_getAvVel( BPy_PartSys * self ) +{ + return PyFloat_FromDouble( ((double)( self->psys->part->average_vel )) ); +} + +static int Part_setLatAcc( BPy_PartSys * self, PyObject * args ) +{ + int res = EXPP_setFloatRange( args, &self->psys->part->max_lat_acc, + 0.0f, 1.0f ); + + Particle_Recalc(self,1); + + return res; +} + +static PyObject *Part_getLatAcc( BPy_PartSys * self ) +{ + return PyFloat_FromDouble( ((double)( self->psys->part->max_lat_acc )) ); +} + +static int Part_setMaxTan( BPy_PartSys * self, PyObject * args ) +{ + int res = EXPP_setFloatRange( args, &self->psys->part->max_tan_acc, + 0.0f, 1.0f ); + + Particle_Recalc(self,1); + + return res; +} + +static PyObject *Part_getMaxTan( BPy_PartSys * self ) +{ + return PyFloat_FromDouble( ((double)( self->psys->part->max_tan_acc )) ); +} + +static int Part_setGroundZ( BPy_PartSys * self, PyObject * args ) +{ + int res = EXPP_setFloatRange( args, &self->psys->part->groundz, + -100.0f, 100.0f ); + + Particle_Recalc(self,1); + + return res; +} + +static PyObject *Part_getGroundZ( BPy_PartSys * self ) +{ + return PyFloat_FromDouble( ((double)( self->psys->part->groundz )) ); +} + +static int Part_setOb( BPy_PartSys * self, PyObject * args ) +{ + Object *obj; + if( !BPy_Object_Check( args ) ) { + char errstr[128]; + sprintf ( errstr, "expected object argument" ); + return EXPP_ReturnIntError( PyExc_TypeError, errstr ); + } + + obj = Object_FromPyObject(args); + + self->psys->keyed_ob = obj; + + return 0; +} + +static PyObject *Part_getOb( BPy_PartSys * self ) +{ + Object * obj; + obj = self->psys->keyed_ob; + if (!obj) + Py_RETURN_NONE; + + return Object_CreatePyObject( obj ); +} + +static int Part_setRandEmission( BPy_PartSys * self, PyObject * args ) +{ + int number; + + if( !PyInt_Check( args ) ) { + char errstr[128]; + sprintf ( errstr, "expected int argument" ); + return EXPP_ReturnIntError( PyExc_TypeError, errstr ); + } + + number = PyInt_AS_LONG( args ); + + if (number){ + self->psys->part->flag |= PART_TRAND; + }else{ + self->psys->part->flag &= ~PART_TRAND; + } + + Particle_RecalcPsys_distr(self,1); + + return 0; +} + +static PyObject *Part_getRandEmission( BPy_PartSys * self ) +{ + return PyInt_FromLong( ((long)( self->psys->part->flag & PART_BOIDS_2D )) > 0 ); +} + +static int Part_setParticleDist( BPy_PartSys * self, PyObject * args ) +{ + int number; + char errstr[128]; + + if( !PyInt_Check( args ) ) { + sprintf ( errstr, "expected int argument" ); + return EXPP_ReturnIntError( PyExc_TypeError, errstr ); + } + + number = PyInt_AS_LONG( args ); + + if (number < 0 || number > 3){ + sprintf ( errstr, "expected int argument between 0 - 3" ); + return EXPP_ReturnIntError( PyExc_TypeError, errstr ); + } + + self->psys->part->from = number; + + Particle_RecalcPsys_distr(self,1); + + return 0; +} + +static PyObject *Part_getParticleDist( BPy_PartSys * self ) +{ + return PyInt_FromLong( (long)( self->psys->part->from ) ); +} + +static int Part_setEvenDist( BPy_PartSys * self, PyObject * args ) +{ + int number; + + if( !PyInt_Check( args ) ) { + char errstr[128]; + sprintf ( errstr, "expected int argument" ); + return EXPP_ReturnIntError( PyExc_TypeError, errstr ); + } + + number = PyInt_AS_LONG( args ); + + if (number){ + self->psys->part->flag |= PART_EDISTR; + }else{ + self->psys->part->flag &= ~PART_EDISTR; + } + + Particle_RecalcPsys_distr(self,1); + + return 0; +} + +static PyObject *Part_getEvenDist( BPy_PartSys * self ) +{ + return PyInt_FromLong( ((long)( self->psys->part->flag & PART_EDISTR )) > 0 ); +} + +static int Part_setDist( BPy_PartSys * self, PyObject * args ) +{ + int number; + char errstr[128]; + + if( !PyInt_Check( args ) ) { + sprintf ( errstr, "expected int argument" ); + return EXPP_ReturnIntError( PyExc_TypeError, errstr ); + } + + number = PyInt_AS_LONG( args ); + + if (number < 0 || number > 2){ + sprintf ( errstr, "expected int argument between 0 - 2" ); + return EXPP_ReturnIntError( PyExc_TypeError, errstr ); + } + + self->psys->part->distr = number; + + Particle_RecalcPsys_distr(self,1); + + return 0; +} + +static PyObject *Part_getDist( BPy_PartSys * self ) +{ + return PyInt_FromLong( (long)( self->psys->part->distr ) ); +} + +static int Part_setJitterAmount( BPy_PartSys * self, PyObject * args ) +{ + int res = EXPP_setFloatRange( args, &self->psys->part->jitfac, + 0.0f, 2.0f ); + + Particle_RecalcPsys_distr(self,1); + + return res; +} + +static PyObject *Part_getJitterAmount( BPy_PartSys * self ) +{ + return PyFloat_FromDouble( ((double)( self->psys->part->jitfac )) ); +} + + + +static int Part_setPF( BPy_PartSys * self, PyObject * args ) +{ + int res = EXPP_setIValueRange( args, &self->psys->part->userjit, + 0, 1000, 'i' ); + + Particle_RecalcPsys_distr(self,1); + + return res; +} + +static PyObject *Part_getPF( BPy_PartSys * self ) +{ + return PyInt_FromLong( ((short)( self->psys->part->userjit )) ); +} + +static int Part_setInvert( BPy_PartSys * self, PyObject * args ) +{ + int number; + + if( !PyInt_Check( args ) ) { + char errstr[128]; + sprintf ( errstr, "expected int argument" ); + return EXPP_ReturnIntError( PyExc_TypeError, errstr ); + } + + number = PyInt_AS_LONG( args ); + + if (number){ + self->psys->part->flag |= PART_GRID_INVERT; + }else{ + self->psys->part->flag &= ~PART_GRID_INVERT; + } + + Particle_RecalcPsys_distr(self,1); + + return 0; +} + +static PyObject *Part_getInvert( BPy_PartSys * self ) +{ + return PyInt_FromLong( ((long)( self->psys->part->flag & PART_GRID_INVERT )) > 0 ); +} + +static int Part_setTargetOb( BPy_PartSys * self, PyObject * args ) +{ + Object *obj; + if( !BPy_Object_Check( args ) ) { + char errstr[128]; + sprintf ( errstr, "expected object argument" ); + return EXPP_ReturnIntError( PyExc_TypeError, errstr ); + } + + obj = Object_FromPyObject(args); + + self->psys->target_ob = obj; + + return 0; +} + +static PyObject *Part_getTargetOb( BPy_PartSys * self ) +{ + Object * obj; + obj = self->psys->target_ob; + if (!obj) + Py_RETURN_NONE; + + return Object_CreatePyObject( obj ); +} + + + +PyObject *Part_getDupOb( BPy_PartSys * self ) +{ + Object * obj; + obj = self->psys->part->dup_ob; + if (!obj) + Py_RETURN_NONE; + + return Object_CreatePyObject( obj ); +} + +static int Part_setTargetPsys( BPy_PartSys * self, PyObject * args ){ + int tottpsys; + int res; + Object *tob=0; + ParticleSystem *psys = self->psys; + Object *ob; + + ob = self->object; + + if(psys->target_ob) + tob=psys->target_ob; + else + tob=ob; + + tottpsys = BLI_countlist(&tob->particlesystem); + + res = EXPP_setIValueRange( args, &self->psys->target_psys, 0, tottpsys, 'h' ); + + if((psys=psys_get_current(ob))){ + if(psys->keyed_ob==ob || psys->target_ob==ob){ + if(psys->keyed_ob==ob) + psys->keyed_ob=NULL; + else + psys->target_ob=NULL; + } + else{ + DAG_scene_sort(G.scene); + DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); + } + } + + return res; +} + +static PyObject *Part_getTargetPsys( BPy_PartSys * self ){ + return PyInt_FromLong( (short)( self->psys->target_psys ) ); +} + +static int Part_setRenderObject( BPy_PartSys * self, PyObject * args ) +{ + int number,nr; + ParticleSystem *psys = 0L; + + if( !PyInt_Check( args ) ) { + char errstr[128]; + sprintf ( errstr, "expected int argument" ); + return EXPP_ReturnIntError( PyExc_TypeError, errstr ); + } + + number = PyInt_AS_LONG( args ); + + if (number){ + self->psys->part->draw |= PART_DRAW_EMITTER; + }else{ + self->psys->part->draw &= ~PART_DRAW_EMITTER; + } + + /* check need for dupliobjects */ + nr=0; + for(psys=self->object->particlesystem.first; psys; psys=psys->next){ + if(ELEM(psys->part->draw_as,PART_DRAW_OB,PART_DRAW_GR)) + nr++; + } + if(nr) + self->object->transflag |= OB_DUPLIPARTS; + else + self->object->transflag &= ~OB_DUPLIPARTS; + + return 0; +} + +static PyObject *Part_getRenderObject( BPy_PartSys * self ) +{ + return PyInt_FromLong( ((long)( self->psys->part->draw & PART_DRAW_EMITTER )) > 0 ); +} + +static int Part_setParticleDisp( BPy_PartSys * self, PyObject * args ) +{ + int res = EXPP_setIValueRange( args, &self->psys->part->disp, + 0, 100, 'i' ); + + Particle_Recalc(self,0); + + + return res; +} + +static PyObject *Part_getParticleDisp( BPy_PartSys * self ) +{ + return PyInt_FromLong( ((short)( self->psys->part->disp )) ); +} + +static int Part_setStep( BPy_PartSys * self, PyObject * args ) +{ + int res = EXPP_setIValueRange( args, &self->psys->part->draw_step, + 0, 7, 'i' ); + + Particle_Recalc(self,1); + + + return res; +} + +static PyObject *Part_getStep( BPy_PartSys * self ) +{ + return PyInt_FromLong( ((short)( self->psys->part->draw_step )) ); +} + +static int Part_setRenderStep( BPy_PartSys * self, PyObject * args ) +{ + int res = EXPP_setIValueRange( args, &self->psys->part->ren_step, + 0, 7, 'i' ); + + /*Particle_Recalc(self,1);*/ + + + return res; +} + +static PyObject *Part_getRenderStep( BPy_PartSys * self ) +{ + return PyInt_FromLong( ((short)( self->psys->part->ren_step )) ); +} + +static PyObject *Part_getDrawAs( BPy_PartSys * self ) +{ + return PyInt_FromLong( (long)( self->psys->part->draw_as ) ); } diff --git a/source/blender/python/api2_2x/Particle.h b/source/blender/python/api2_2x/Particle.h index 13e6fadaaa0..416e3a99bea 100644 --- a/source/blender/python/api2_2x/Particle.h +++ b/source/blender/python/api2_2x/Particle.h @@ -22,43 +22,32 @@ * * This is a new part of Blender. * - * Contributor(s): Jacques Guignot + * Contributor(s): Jacques Guignot, Cedric Paille * * ***** END GPL LICENSE BLOCK ***** - */ +*/ -#ifndef EXPP_PARTICLE_H -#define EXPP_PARTICLE_H +#ifndef EXPP_PARTICLESYS_H +#define EXPP_PARTICLESYS_H #include -#include "DNA_effect_types.h" +#include "DNA_particle_types.h" +#include "DNA_object_types.h" -extern PyTypeObject Particle_Type; +extern PyTypeObject ParticleSys_Type; -#define BPy_Particle_Check(v) ((v)->ob_type==&Particle_Type) +#define BPy_ParticleSys_Check(v) \ + ((v)->ob_type == &ParticleSys_Type) /* for type checking */ -/* Python BPy_Particle structure definition */ +/* Python BPy_Effect structure definition */ typedef struct { PyObject_HEAD /* required py macro */ - Effect * particle; -} BPy_Particle; + ParticleSystem *psys; + Object *object; /* fixeme: if this points back to the parent object,it is wrong */ +} BPy_PartSys; -#include "Effect.h" - -/*****************************************************************************/ -/* Python Particle_Type callback function prototypes: */ -/*****************************************************************************/ -#if 0 -void ParticleDeAlloc( BPy_Particle * msh ); -//int ParticlePrint (BPy_Particle *msh, FILE *fp, int flags); -int ParticleSetAttr( BPy_Particle * msh, char *name, PyObject * v ); -PyObject *ParticleGetAttr( BPy_Particle * msh, char *name ); -PyObject *ParticleRepr( void ); -PyObject *ParticleCreatePyObject( struct Effect *particle ); -int ParticleCheckPyObject( PyObject * py_obj ); -struct Particle *ParticleFromPyObject( PyObject * py_obj ); -#endif +PyObject *ParticleSys_Init( void ); +PyObject *ParticleSys_CreatePyObject( ParticleSystem * psystem, Object *ob ); - -#endif /* EXPP_PARTICLE_H */ +#endif /* EXPP_EFFECT_H */ diff --git a/source/blender/python/api2_2x/doc/API_intro.py b/source/blender/python/api2_2x/doc/API_intro.py index a630c47229e..ec1d42bce43 100644 --- a/source/blender/python/api2_2x/doc/API_intro.py +++ b/source/blender/python/api2_2x/doc/API_intro.py @@ -29,7 +29,7 @@ The Blender Python API Reference - L{Group} (*) - L{Image} (*) - L{Ipo} (*) - - L{IpoCurve} (*) + - L{IpoCurve} (*) - L{Key} (*) - L{Lamp} - L{Lattice} (*) @@ -46,6 +46,7 @@ The Blender Python API Reference - L{Pose} (*) - L{Constraint} (*) - L{ActionStrips} (*) + - L{Particle} - L{Registry} - L{Scene} (*) - L{Radio} diff --git a/source/blender/python/api2_2x/doc/Object.py b/source/blender/python/api2_2x/doc/Object.py index a3238f2615e..521be3b0cea 100644 --- a/source/blender/python/api2_2x/doc/Object.py +++ b/source/blender/python/api2_2x/doc/Object.py @@ -641,7 +641,16 @@ class Object: @ivar upAxis: Up axis. Return string 'Y' | 'Y' | 'Z' (readonly) @type upAxis: string """ - + def getParticleSystems(): + """ + Return a list of particle systems linked to this object (see Blender.Particle). + """ + + def newParticleSystem(): + """ + Link a new particle system (see Blender.Particle). + """ + def buildParts(): """ Recomputes the particle system. This method only applies to an Object of diff --git a/source/blender/python/api2_2x/doc/Particle.py b/source/blender/python/api2_2x/doc/Particle.py new file mode 100644 index 00000000000..192ecd5355b --- /dev/null +++ b/source/blender/python/api2_2x/doc/Particle.py @@ -0,0 +1,367 @@ +# Blender.Object module and the Object PyType object + +""" +The Blender.Particle submodule + + +Particle +======== + +This module provides access to the B{Particle} in Blender. + +@type TYPE: readonly dictionary +@var TYPE: Constant dict used for with L{Particle.TYPE} + - HAIR: set particle system to hair mode. + - REACTOR: set particle system to reactor mode. + - EMITTER: set particle system to emitter mode. +@type DISTRIBUTION: readonly dictionary +@var DISTRIBUTION: Constant dict used for with L{Particle.DISTRIBUTION} + - GRID: set grid distribution. + - RANDOM: set random distribution. + - JITTERED: set jittered distribution. +@type EMITFROM: readonly dictionary +@var EMITFROM: Constant dict used for with L{Particle.EMITFROM} + - VERTS: set particles emit from vertices + - FACES: set particles emit from faces + - VOLUME: set particles emit from volume + - PARTICLE: set particles emit from particles +@type REACTON: readonly dictionary +@var REACTON: Constant dict used for with L{Particle.REACTON} + - NEAR: react on near + - COLLISION: react on collision + - DEATH: react on death +@type DRAWAS: readonly dictionary +@var DRAWAS: Constant dict used for with L{Particle.DRAWAS} + - NONE: Don't draw + - POINT: Draw as point + - CIRCLE: Draw as circles + - CROSS: Draw as crosses + - AXIS: Draw as axis + - LINE: Draw as lines + - PATH: Draw pathes + - OBJECT: Draw object + - GROUP: Draw goup + - BILLBOARD: Draw as billboard +""" + +class Particle: + """ + The Particle object + =================== + This object gives access to paticles data. + + @ivar seed: Set an offset in the random table. + @type seed: int + @ivar type: Type of particle system ( Particle.TYPE[ 'HAIR' | 'REACTOR' | 'EMITTER' ] ). + @type type: int + @ivar resolutionGrid: The resolution of the particle grid. + @type resolutionGrid: int + @ivar startFrame: Frame # to start emitting particles. + @type startFrame: float + @ivar endFrame: Frame # to stop emitting particles. + @type endFrame: float + @ivar editable: Finalize hair to enable editing in particle mode. + @type editable: int + @ivar amount: The total number of particles. + @type amount: int + @ivar multireact: React multiple times ( Paricle.REACTON[ 'NEAR' | 'COLLISION' | 'DEATH' ] ). + @type multireact: int + @ivar reactshape: Power of reaction strength dependence on distance to target. + @type reactshape: float + @ivar hairSegments: Amount of hair segments. + @type hairSegments: int + @ivar lifetime: Specify the life span of the particles. + @type lifetime: float + @ivar randlife: Give the particle life a random variation. + @type randlife: float + @ivar randemission: Give the particle life a random variation + @type randemission: int + @ivar particleDistribution: Where to emit particles from Paricle.EMITFROM[ 'PARTICLE' | 'VOLUME' | 'FACES' | 'VERTS' ] ) + @type particleDistribution: int + @ivar evenDistribution: Use even distribution from faces based on face areas or edge lengths. + @type evenDistribution: int + @ivar distribution: How to distribute particles on selected element Paricle.DISTRIBUTION[ 'GRID' | 'RANDOM' | 'JITTERED' ] ). + @type distribution: int + @ivar jitterAmount: Amount of jitter applied to the sampling. + @type jitterAmount: float + @ivar pf: Emission locations / face (0 = automatic). + @type pf:int + @ivar invert: Invert what is considered object and what is not. + @type invert: int + @ivar targetObject: The object that has the target particle system (empty if same object). + @type targetObject: Blender object + @ivar targetpsys: The target particle system number in the object. + @type targetpsys: int + @ivar 2d: Constrain boids to a surface. + @type 2d: float + @ivar maxvel: Maximum velocity. + @type maxvel: float + @ivar avvel: The usual speed % of max velocity. + @type avvel: float + @ivar latacc: Lateral acceleration % of max velocity + @type latacc: float + @ivar tanacc: Tangential acceleration % of max velocity + @type tanacc: float + @ivar groundz: Default Z value. + @type groundz: float + @ivar object: Constrain boids to object's surface. + @type object: Blender Object + @ivar renderEmitter: Render emitter object. + @type renderEmitter: int + @ivar displayPercentage: Particle display percentage. + @type displayPercentage: int + @ivar hairDisplayStep: How many steps paths are drawn with (power of 2) in visu mode. + @type hairDisplayStep: int + @ivar hairRenderStep: How many steps paths are rendered with (power of 2) in render mode." + @type hairRenderStep: int + @ivar duplicateObject: Get the duplicate object. + @type duplicateObject: Blender Object + @ivar drawAs: Get draw type Particle.DRAWAS([ 'NONE' | 'OBJECT' | 'POINT' | ... ]). + @type drawAs: int + """ + + def freeEdit(): + """ + Free edit mode. + @return: None + """ + + def getLoc(all=0,id=0): + """ + Get the particles locations. + A list of tuple is returned in particle mode. + A list of list of tuple is returned in hair mode. + The tuple is a vector list of 3 or 4 floats in world space (x,y,z, optionnaly the particle's id). + @type all: int + @param all: if not 0 export all particles (uninitialized (unborn or died)particles exported as None). + @type id: int + @param id: add the particle id in the end of the vector tuple + @rtype: list of vectors (tuple of 3 floats and optionnaly the id) or list of list of vectors + @return: list of vectors or list of list of vectors (hair mode) + """ + def getRot(all=0,id=0): + """ + Get the particles rotations as quaternion. + A list of tuple is returned in particle mode. + The tuple is a vector list of 4 or 5 floats (x,y,z,w, optionnaly the id of the particle). + + @type all: int + @param all: if not 0 export all particles (uninitialized (unborn or died) particles exported as None). + @type id: int + @param id: add the particle id in the return tuple + @rtype: list of tuple of 4 or 5 elements (if id is not zero) + @return: list of 4-tuples + """ + + def getMat(): + """ + Get the particles material. + @rtype: Blender Material + @return: The marterial assigned to particles + """ + + def getSize(all=0,id=0): + """ + Get the particles size. + A list of float or list of tuple (particle's size,particle's id). + @type all: int + @param all: if not 0 export all particles (uninitialized (unborn or died) particles exported as None). + @type id: int + @param id: add the particle id in the return tuple + @rtype: list of floats + @return: list of floats or list of tuples if id is not zero (size,id). + """ + + def getAge(all=0,id=0): + """ + Get the particles age. + A list of float or list of tuple (particle's age,particle's id). + @type all: int + @param all: if not 0 export all particles (uninitialized (unborn or died) particles exported as None). + @type id: int + @param id: add the particle id in the return tuple + @rtype: list of floats + @return: list of floats or list of tuples if id is not zero (size,id). + """ +# Blender.Object module and the Object PyType object + +""" +The Blender.Particle submodule + + +Particle +======== + +This module provides access to the B{Particle} in Blender. + +@type TYPE: readonly dictionary +@var TYPE: Constant dict used for with L{Particle.TYPE} + - HAIR: set particle system to hair mode. + - REACTOR: set particle system to reactor mode. + - EMITTER: set particle system to emitter mode. +@type DISTRIBUTION: readonly dictionary +@var DISTRIBUTION: Constant dict used for with L{Particle.DISTRIBUTION} + - GRID: set grid distribution. + - RANDOM: set random distribution. + - JITTERED: set jittered distribution. +@type EMITFROM: readonly dictionary +@var EMITFROM: Constant dict used for with L{Particle.EMITFROM} + - VERTS: set particles emit from vertices + - FACES: set particles emit from faces + - VOLUME: set particles emit from volume + - PARTICLE: set particles emit from particles +@type REACTON: readonly dictionary +@var REACTON: Constant dict used for with L{Particle.REACTON} + - NEAR: react on near + - COLLISION: react on collision + - DEATH: react on death +@type DRAWAS: readonly dictionary +@var DRAWAS: Constant dict used for with L{Particle.DRAWAS} + - NONE: Don't draw + - POINT: Draw as point + - CIRCLE: Draw as circles + - CROSS: Draw as crosses + - AXIS: Draw as axis + - LINE: Draw as lines + - PATH: Draw pathes + - OBJECT: Draw object + - GROUP: Draw goup + - BILLBOARD: Draw as billboard +""" + +def Get(name): + """ + Get the particle system of the object "name". + @type name: string + @return: The particle system of the object. + """ +def New(name): + """ + Assign a new particle system to the object "name". + @type name: string + @return: The newly created particle system. + """ + +class Particle: + """ + The Particle object + =================== + This object gives access to paticles data. + + @ivar seed: Set an offset in the random table. + @type seed: int + @ivar type: Type of particle system ( Particle.TYPE[ 'HAIR' | 'REACTOR' | 'EMITTER' ] ). + @type type: int + @ivar resolutionGrid: The resolution of the particle grid. + @type resolutionGrid: int + @ivar startFrame: Frame # to start emitting particles. + @type startFrame: float + @ivar endFrame: Frame # to stop emitting particles. + @type endFrame: float + @ivar editable: Finalize hair to enable editing in particle mode. + @type editable: int + @ivar amount: The total number of particles. + @type amount: int + @ivar multireact: React multiple times ( Paricle.REACTON[ 'NEAR' | 'COLLISION' | 'DEATH' ] ). + @type multireact: int + @ivar reactshape: Power of reaction strength dependence on distance to target. + @type reactshape: float + @ivar hairSegments: Amount of hair segments. + @type hairSegments: int + @ivar lifetime: Specify the life span of the particles. + @type lifetime: float + @ivar randlife: Give the particle life a random variation. + @type randlife: float + @ivar randemission: Give the particle life a random variation + @type randemission: int + @ivar particleDistribution: Where to emit particles from Paricle.EMITFROM[ 'PARTICLE' | 'VOLUME' | 'FACES' | 'VERTS' ] ) + @type particleDistribution: int + @ivar evenDistribution: Use even distribution from faces based on face areas or edge lengths. + @type evenDistribution: int + @ivar distribution: How to distribute particles on selected element Paricle.DISTRIBUTION[ 'GRID' | 'RANDOM' | 'JITTERED' ] ). + @type distribution: int + @ivar jitterAmount: Amount of jitter applied to the sampling. + @type jitterAmount: float + @ivar pf: Emission locations / face (0 = automatic). + @type pf:int + @ivar invert: Invert what is considered object and what is not. + @type invert: int + @ivar targetObject: The object that has the target particle system (empty if same object). + @type targetObject: Blender object + @ivar targetpsys: The target particle system number in the object. + @type targetpsys: int + @ivar 2d: Constrain boids to a surface. + @type 2d: float + @ivar maxvel: Maximum velocity. + @type maxvel: float + @ivar avvel: The usual speed % of max velocity. + @type avvel: float + @ivar latacc: Lateral acceleration % of max velocity + @type latacc: float + @ivar tanacc: Tangential acceleration % of max velocity + @type tanacc: float + @ivar groundz: Default Z value. + @type groundz: float + @ivar object: Constrain boids to object's surface. + @type object: Blender Object + @ivar renderEmitter: Render emitter object. + @type renderEmitter: int + @ivar displayPercentage: Particle display percentage. + @type displayPercentage: int + @ivar hairDisplayStep: How many steps paths are drawn with (power of 2) in visu mode. + @type hairDisplayStep: int + @ivar hairRenderStep: How many steps paths are rendered with (power of 2) in render mode." + @type hairRenderStep: int + @ivar duplicateObject: Get the duplicate object. + @type duplicateObject: Blender Object + @ivar drawAs: Get draw type Particle.DRAWAS([ 'NONE' | 'OBJECT' | 'POINT' | ... ]). + @type drawAs: int + """ + def freeEdit(): + """ + Free edit mode. + @return: None + """ + + def getLoc(all=0,id=0): + """ + Get the particles locations. + A list of tuple is returned in particle mode. + A list of list of tuple is returned in hair mode. + The tuple is a vector list of 3 floats in world space. + @type all: int + @param all: if not 0 export all particles (uninitialized (unborn or died)particles exported as None). + @type id: int + @param id: add the particle id in the end of the vector tuple + @rtype: list of vectors (tuple of 3 floats and optionnaly the id) or list of list of vectors + @return: list of vectors or list of list of vectors (hair mode) + """ + def getRot(all=0,id=0): + """ + Get the particles rotations as quaternion. + A list of tuple is returned in particle mode. + The tuple is a vector list of 4 floats (quaternion). + @type all: int + @param all: if not 0 export all particles (uninitialized (unborn or died) particles exported as None). + @type id: int + @param id: add the particle id in the return tuple + @rtype: list of tuple of 4 or 5 elements (if id is not zero) + @return: list of 4-tuples + """ + def getMat(): + """ + Get the particles material. + @rtype: Blender Material + @return: The marterial assigned to particles + """ + def getSize(all=0,id=0): + """ + Get the particles size. + A list of float. + @type all: int + @param all: if not 0 export all particles (uninitialized (unborn or died) particles exported as None). + @type id: int + @param id: add the particle id in the return tuple + @rtype: list of floats + @return: list of floats or list of tuples if id is not zero (size,id). + """ diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index 0e21c39fd4b..9b0a7c23759 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -2723,7 +2723,7 @@ static void object_panel_draw(Object *ob) uiSetButLock(object_is_libdata(ob), ERROR_LIBDATA_MESSAGE); /* LAYERS */ - xco= 80; + xco= 65; dx= 35; dy= 30; @@ -2745,7 +2745,10 @@ static void object_panel_draw(Object *ob) uiBlockEndAlign(block); /* Object Color */ - uiDefButF(block, COL, REDRAWVIEW3D, "", 270, 165,30, 30, ob->col, 0, 0, 0, 0, "Object color, used when faces have the ObCol mode enabled"); + uiBlockBeginAlign(block); + uiDefButF(block, COL, REDRAWVIEW3D, "", 250, 180, 50, 15, ob->col, 0, 0, 0, 0, "Object color, used when faces have the ObCol mode enabled"); + uiDefButF(block, NUM, REDRAWVIEW3D, "A:", 250, 165, 50, 15, &ob->col[3], 0.0f, 1.0f, 10, 2, "Object alpha, used when faces have the ObCol mode enabled"); + uiBlockEndAlign(block); uiDefBut(block, LABEL, 0, "Drawtype", 10,120,100,20, NULL, 0, 0, 0, 0, ""); diff --git a/source/blender/src/buttons_shading.c b/source/blender/src/buttons_shading.c index b46679898b4..600632f8776 100644 --- a/source/blender/src/buttons_shading.c +++ b/source/blender/src/buttons_shading.c @@ -2652,7 +2652,7 @@ static void lamp_panel_spot(Object *ob, Lamp *la) uiDefButF(block, NUM,B_LAMPREDRAW,"Soft:", 200,40,100,19, &la->soft,1.0,100.0, 100, 0, "Sets the size of the shadow sample area"); } else { /* LA_SHADBUF_IRREGULAR */ - uiDefButF(block, NUM,B_LAMPREDRAW,"Bias:", 100,40,100,19, &la->bias, 0.01, 5.0, 1, 0, "Sets the shadow map sampling bias"); + uiDefButF(block, NUM,B_LAMPREDRAW,"Bias:", 100,40,100,19, &la->bias, 0.001, 5.0, 1, 0, "Sets the shadow map sampling bias"); } uiBlockBeginAlign(block); diff --git a/source/blender/src/drawseq.c b/source/blender/src/drawseq.c index fb97a369dd8..a59ffc05cab 100644 --- a/source/blender/src/drawseq.c +++ b/source/blender/src/drawseq.c @@ -857,15 +857,18 @@ static void draw_image_seq(ScrArea *sa) zoom = -1.0/sseq->zoom; } - /* calc location */ - x1= (sa->winx-zoom*ibuf->x)/2 + sseq->xof; - y1= (sa->winy-zoom*ibuf->y)/2 + sseq->yof; - /* needed for gla draw */ glaDefine2DArea(&curarea->winrct); + if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) { + zoomx = zoom * ((float)G.scene->r.xasp / (float)G.scene->r.yasp); + zoomy = zoom; + } else { + zoomx = zoomy = zoom; + } - zoomx = zoom * ((float)G.scene->r.xasp / (float)G.scene->r.yasp); - zoomy = zoom; + /* calc location */ + x1= (sa->winx-zoomx*ibuf->x)/2 + sseq->xof; + y1= (sa->winy-zoomy*ibuf->y)/2 + sseq->yof; glPixelZoom(zoomx, zoomy); diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index be009536022..15b7f3dbe67 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -3731,8 +3731,20 @@ int play_anim(int mode) else if(G.qual & LR_CTRLKEY) viewmove(2); else viewmove(0); } - } - else if(event==MKEY) { + } else if (event==WHEELDOWNMOUSE || (val && event==PADMINUS)) { /* copied from persptoetsen */ + /* this min and max is also in viewmove() */ + if(G.vd->persp==V3D_CAMOB) { + G.vd->camzoom-= 10; + if(G.vd->camzoom<-30) G.vd->camzoom= -30; + } + else if(G.vd->dist<10.0*G.vd->far) G.vd->dist*=1.2f; + } else if (event==WHEELUPMOUSE || (val && event==PADPLUSKEY)) { /* copied from persptoetsen */ + if(G.vd->persp==V3D_CAMOB) { + G.vd->camzoom+= 10; + if(G.vd->camzoom>300) G.vd->camzoom= 300; + } + else if(G.vd->dist> 0.001*G.vd->grid) G.vd->dist*=.83333f; + } else if(event==MKEY) { if(val) add_marker(CFRA-1); } } diff --git a/source/blender/src/editarmature.c b/source/blender/src/editarmature.c index 99c87097bd3..f87eb321fc8 100644 --- a/source/blender/src/editarmature.c +++ b/source/blender/src/editarmature.c @@ -180,7 +180,7 @@ void make_boneList(ListBase *list, ListBase *bones, EditBone *parent) /* Add children if necessary */ if (curBone->childbase.first) - make_boneList (list, &curBone->childbase, eBone); + make_boneList(list, &curBone->childbase, eBone); } } @@ -549,7 +549,7 @@ int join_armature(void) bPoseChannel *pchan, *pchann; ListBase ebbase, eblist; EditBone *curbone; - float mat[4][4], imat[4][4]; + float mat[4][4], oimat[4][4]; /* Ensure we're not in editmode and that the active object is an armature*/ /* if(G.obedit) return; */ /* Alredy checked in join_menu() */ @@ -565,7 +565,11 @@ int join_armature(void) /* Get editbones of active armature to add editbones to */ ebbase.first=ebbase.last= NULL; make_boneList(&ebbase, &arm->bonebase, NULL); + + /* get pose of active object and move it out of posemode */ pose= ob->pose; + ob->flag &= ~OB_POSEMODE; + BASACT->flag &= ~OB_POSEMODE; for (base=FIRSTBASE; base; base=nextbase) { nextbase = base->next; @@ -577,10 +581,12 @@ int join_armature(void) /* Get Pose of current armature */ opose= base->object->pose; + base->object->flag &= ~OB_POSEMODE; + BASACT->flag &= ~OB_POSEMODE; /* Find the difference matrix */ - Mat4Invert(imat, ob->obmat); - Mat4MulMat4(mat, base->object->obmat, imat); + Mat4Invert(oimat, ob->obmat); + Mat4MulMat4(mat, base->object->obmat, oimat); /* Copy bones and posechannels from the object to the edit armature */ for (pchan=opose->chanbase.first; pchan; pchan=pchann) { @@ -600,25 +606,24 @@ int join_armature(void) float delta[3]; /* Get the premat */ - VecSubf (delta, curbone->tail, curbone->head); + VecSubf(delta, curbone->tail, curbone->head); vec_roll_to_mat3(delta, curbone->roll, temp); - Mat4MulMat34 (premat, temp, mat); + Mat4MulMat34(premat, temp, mat); Mat4MulVecfl(mat, curbone->head); Mat4MulVecfl(mat, curbone->tail); /* Get the postmat */ - VecSubf (delta, curbone->tail, curbone->head); + VecSubf(delta, curbone->tail, curbone->head); vec_roll_to_mat3(delta, curbone->roll, temp); Mat4CpyMat3(postmat, temp); /* Find the roll */ - Mat4Invert (imat, premat); - Mat4MulMat4 (difmat, postmat, imat); + Mat4Invert(imat, premat); + Mat4MulMat4(difmat, postmat, imat); curbone->roll -= atan2(difmat[2][0], difmat[2][2]); - } /* Fix Constraints and Other Links to this Bone and Armature */ @@ -651,12 +656,15 @@ int join_armature(void) } /* Helper function for armature separating - link fixing */ -static void separated_armature_fix_links(Object *origArm, Object *newArm, ListBase *edbo) +static void separated_armature_fix_links(Object *origArm, Object *newArm) { Object *ob; - bPoseChannel *pchan; + bPoseChannel *pchan, *pcha, *pchb; bConstraint *con; - EditBone *ebo, *ebn; + ListBase *npchans; + + /* get reference to list of bones in new armature */ + npchans= &newArm->pose->chanbase; /* let's go through all objects in database */ for (ob= G.main->object.first; ob; ob= ob->id.next) { @@ -675,27 +683,21 @@ static void separated_armature_fix_links(Object *origArm, Object *newArm, ListBa for (ct= targets.first; ct; ct= ct->next) { /* any targets which point to original armature are redirected to the new one only if: * - the target isn't the original armature itself - * - the target is one of the bones which were moved into newArm + * - the target is one that can be found in newArm */ if ((ct->tar == origArm) && (ct->subtarget[0] != 0)) { - for (ebo=edbo->first, ebn=edbo->last; ebo && ebn; ebo=ebo->next, ebn=ebn->prev) { + for (pcha=npchans->first, pchb=npchans->last; pcha && pchb; pcha=pcha->next, pchb=pchb->prev) { /* check if either one matches */ - if ( (strcmp(ebo->name, ct->subtarget)==0) || - (strcmp(ebn->name, ct->subtarget)==0) ) + if ( (strcmp(pcha->name, ct->subtarget)==0) || + (strcmp(pchb->name, ct->subtarget)==0) ) { ct->tar= newArm; - printf("arm = '%s' pchan = '%s', ebo = '%s', YES \n", ob->id.name+2, pchan->name, ebo->name); - printf("arm = '%s' pchan = '%s', ebn = '%s', YES \n", ob->id.name+2, pchan->name, ebn->name); break; } - else { - printf("arm = '%s' pchan = '%s', ebo = '%s', NOT\n", ob->id.name+2, pchan->name, ebo->name); - printf("arm = '%s' pchan = '%s', ebn = '%s', NOT \n", ob->id.name+2, pchan->name, ebn->name); - } /* check if both ends have met (to stop checking) */ - if (ebo == ebn) break; - } + if (pcha == pchb) break; + } } } @@ -723,17 +725,17 @@ static void separated_armature_fix_links(Object *origArm, Object *newArm, ListBa * - the target is one of the bones which were moved into newArm */ if ((ct->tar == origArm) && (ct->subtarget[0] != 0)) { - for (ebo=edbo->first, ebn=edbo->last; ebo && ebn; ebo=ebo->next, ebn=ebn->prev) { + for (pcha=npchans->first, pchb=npchans->last; pcha && pchb; pcha=pcha->next, pchb=pchb->prev) { /* check if either one matches */ - if ( (strcmp(ebo->name, ct->subtarget)==0) || - (strcmp(ebn->name, ct->subtarget)==0) ) + if ( (strcmp(pcha->name, ct->subtarget)==0) || + (strcmp(pchb->name, ct->subtarget)==0) ) { ct->tar= newArm; break; } /* check if both ends have met (to stop checking) */ - if (ebo == ebn) break; + if (pcha == pchb) break; } } } @@ -749,37 +751,89 @@ static void separated_armature_fix_links(Object *origArm, Object *newArm, ListBa /* Is object parented to a bone of this src armature? */ if (ob->partype==PARBONE) { /* bone name in object */ - for (ebo=edbo->first, ebn=edbo->last; ebo && ebn; ebo=ebo->next, ebn=ebn->prev) { + for (pcha=npchans->first, pchb=npchans->last; pcha && pchb; pcha=pcha->next, pchb=pchb->prev) { /* check if either one matches */ - if ( (strcmp(ebo->name, ob->parsubstr)==0) || - (strcmp(ebn->name, ob->parsubstr)==0) ) + if ( (strcmp(pcha->name, ob->parsubstr)==0) || + (strcmp(pchb->name, ob->parsubstr)==0) ) { ob->parent= newArm; break; } /* check if both ends have met (to stop checking) */ - if (ebo == ebn) break; + if (pcha == pchb) break; } } } } } +/* Helper function for armature separating - remove certain bones from the given armature + * sel: remove selected bones from the armature, otherwise the unselected bones are removed + */ +static void separate_armature_bones (Object *ob, short sel) +{ + ListBase edbo = {NULL, NULL}; + bArmature *arm= (bArmature *)ob->data; + bPoseChannel *pchan, *pchann; + EditBone *curbone; + + /* make local set of editbones to manipulate here */ + make_boneList(&edbo, &arm->bonebase, NULL); + + /* go through pose-channels, checking if a bone should be removed */ + for (pchan=ob->pose->chanbase.first; pchan; pchan=pchann) { + pchann= pchan->next; + curbone= editbone_name_exists(&edbo, pchan->name); + + /* check if bone needs to be removed */ + if ( (sel && (curbone->flag & BONE_SELECTED)) || + (!sel && !(curbone->flag & BONE_SELECTED)) ) + { + EditBone *ebo; + bPoseChannel *pchn; + + /* clear the bone->parent var of any bone that had this as its parent */ + for (ebo= edbo.first; ebo; ebo= ebo->next) { + if (ebo->parent == curbone) { + ebo->parent= NULL; + ebo->temp= NULL; /* this is needed to prevent random crashes with in editbones_to_armature */ + ebo->flag &= ~BONE_CONNECTED; + } + } + + /* clear the pchan->parent var of any pchan that had this as its parent */ + for (pchn= ob->pose->chanbase.first; pchn; pchn=pchn->next) { + if (pchn->parent == pchan) + pchn->parent= NULL; + } + + /* free any of the extra-data this pchan might have */ + if (pchan->path) MEM_freeN(pchan->path); + free_constraints(&pchan->constraints); + + /* get rid of unneeded bone */ + BLI_freelinkN(&edbo, curbone); + BLI_freelinkN(&ob->pose->chanbase, pchan); + } + } + + /* exit editmode (recalculates pchans too) */ + editbones_to_armature(&edbo, ob); + BLI_freelistN(&edbo); +} + void separate_armature (void) { - EditBone *ebo, *ebn; - Object *oldob; - Base *base, *oldbase; + Object *oldob, *newob; + Base *base, *oldbase, *newbase; bArmature *arm; - ListBase edbo = {NULL, NULL}; - // 31Mar08 - Aligorith: - // this tool is currently not ready for production use, as it will still - // crash in some cases, and also constraint relinking isn't working yet + // 31 Mar 08 \ 11 May 08 - Aligorith: + // currently, this is still too unstable to be enabled for general consumption. // remove the following two lines to test this tool... you have been warned! - okee("Not implemented (WIP)"); - return; + // okee("Not implemented (WIP)"); + // return; if ( G.vd==0 || (G.vd->lay & G.obedit->lay)==0 ) return; if ( okee("Separate")==0 ) return; @@ -788,83 +842,68 @@ void separate_armature (void) arm= G.obedit->data; - /* we are going to trick everything as follows: - * 1. duplicate base: this is the new one, remember old pointer - * 2. set aside all NOT selected bones - * 3. load_editArmature(): this will be the new base - * 4. freelist and restore old armature + /* we are going to do this as follows (unlike every other instance of separate): + * 1. exit editmode +posemode for active armature/base. Take note of what this is. + * 2. duplicate base - BASACT is the new one now + * 3. for each of the two armatures, enter editmode -> remove appropriate bones -> exit editmode + recalc + * 4. fix constraint links + * 5. make original armature active and enter editmode */ - /* only edit-base selected */ + /* 1) only edit-base selected */ base= FIRSTBASE; - while(base) { - if(base->lay & G.vd->lay) { - if(base->object==G.obedit) base->flag |= 1; + for (base= FIRSTBASE; base; base= base->next) { + if (base->lay & G.vd->lay) { + if (base->object==G.obedit) base->flag |= 1; else base->flag &= ~1; } - base= base->next; } - - /* set aside: everything that is not selected */ - for (ebo= G.edbo.first; ebo; ebo= ebn) { - ebn= ebo->next; - - /* remove from original, and move to duplicate if not-selected */ - if ((ebo->flag & BONE_SELECTED)==0) { - EditBone *curbone; - - /* need to make sure children don't still refer to this only if they are selected - * - potentially slow O(n*n) situation here... - */ - for (curbone= G.edbo.first; curbone; curbone=curbone->next) { - if ((curbone->parent == ebo) && (curbone->flag & BONE_SELECTED)) { - curbone->parent= ebo->parent; - curbone->flag &= ~BONE_CONNECTED; - } - } - - BLI_remlink(&G.edbo, ebo); - BLI_addtail(&edbo, ebo); - } - } - + + /* 1) store starting settings and exit editmode */ oldob= G.obedit; oldbase= BASACT; - - adduplicate(1, 0); /* no transform and zero so do get a linked dupli */ - - G.obedit= BASACT->object; /* basact is set in adduplicate() */ - - G.obedit->data= copy_armature(arm); - /* because new armature is a copy: reduce user count */ - arm->id.us--; + oldob->flag &= ~OB_POSEMODE; + oldbase->flag &= ~OB_POSEMODE; load_editArmature(); + free_editArmature(); - BASACT->flag &= ~SELECT; + /* 2) duplicate base */ + adduplicate(1, USER_DUP_ARM); /* no transform and zero so do get a linked dupli */ - /* fix links before depsgraph flushes */ // err... or after? - printf("oldob = %p, obact = %p \n", oldob, G.obedit); - separated_armature_fix_links(oldob, G.obedit, &G.edbo); + newbase= BASACT; /* basact is set in adduplicate() */ + newob= newbase->object; + newbase->flag &= ~SELECT; - if (G.edbo.first) free_editArmature(); - G.edbo = edbo; + /* 3) remove bones that shouldn't still be around on both armatures */ + separate_armature_bones(oldob, 1); + separate_armature_bones(newob, 0); + + + /* 4) fix links before depsgraph flushes */ // err... or after? + separated_armature_fix_links(oldob, newob); - G.obedit= 0; /* displists behave different in edit mode */ // needed? - DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA); /* this is the separated one */ DAG_object_flush_update(G.scene, oldob, OB_RECALC_DATA); /* this is the original one */ + DAG_object_flush_update(G.scene, newob, OB_RECALC_DATA); /* this is the separated one */ + + /* 5) restore original conditions */ G.obedit= oldob; BASACT= oldbase; BASACT->flag |= SELECT; + make_editArmature(); + + /* recalc/redraw + cleanup */ waitcursor(0); countall(); allqueue(REDRAWVIEW3D, 0); allqueue(REDRAWBUTSEDIT, 0); allqueue(REDRAWOOPS, 0); + + BIF_undo_push("Separate Armature"); } /* **************** END tools on Editmode Armature **************** */ @@ -1442,9 +1481,10 @@ void delete_armature(void) for (curBone=G.edbo.first;curBone;curBone=next) { next=curBone->next; - if (arm->layer & curBone->layer) + if (arm->layer & curBone->layer) { if (curBone->flag & BONE_SELECTED) delete_bone(curBone); + } } diff --git a/source/blender/src/editdeform.c b/source/blender/src/editdeform.c index a072898327f..5de4c6ed23c 100644 --- a/source/blender/src/editdeform.c +++ b/source/blender/src/editdeform.c @@ -33,11 +33,15 @@ #include "MEM_guardedalloc.h" +#include "DNA_cloth_types.h" #include "DNA_curve_types.h" #include "DNA_lattice_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" +#include "DNA_modifier_types.h" #include "DNA_object_types.h" +#include "DNA_object_force.h" +#include "DNA_particle_types.h" #include "BLI_blenlib.h" #include "BLI_editVert.h" @@ -256,6 +260,66 @@ void duplicate_defgroup ( Object *ob ) } } +static void del_defgroup_update_users(Object *ob, int id) +{ + ExplodeModifierData *emd; + ModifierData *md; + ParticleSystem *psys; + ClothModifierData *clmd; + ClothSimSettings *clsim; + int a; + + /* these cases don't use names to refer to vertex groups, so when + * they get deleted the numbers get out of synce, this corrects that */ + + if(ob->soft) { + if(ob->soft->vertgroup == id) + ob->soft->vertgroup= 0; + else if(ob->soft->vertgroup > id) + ob->soft->vertgroup--; + } + + for(md=ob->modifiers.first; md; md=md->next) { + if(md->type == eModifierType_Explode) { + emd= (ExplodeModifierData*)md; + + if(emd->vgroup == id) + emd->vgroup= 0; + else if(emd->vgroup > id) + emd->vgroup--; + } + else if(md->type == eModifierType_Cloth) { + clmd= (ClothModifierData*)md; + clsim= clmd->sim_parms; + + if(clsim) { + if(clsim->vgroup_mass == id) + clsim->vgroup_mass= 0; + else if(clsim->vgroup_mass > id) + clsim->vgroup_mass--; + + if(clsim->vgroup_bend == id) + clsim->vgroup_bend= 0; + else if(clsim->vgroup_bend > id) + clsim->vgroup_bend--; + + if(clsim->vgroup_struct == id) + clsim->vgroup_struct= 0; + else if(clsim->vgroup_struct > id) + clsim->vgroup_struct--; + } + } + } + + for(psys=ob->particlesystem.first; psys; psys=psys->next) { + for(a=0; avgroup[a] == id) + psys->vgroup[a]= 0; + else if(psys->vgroup[a] > id) + psys->vgroup[a]--; + } +} + void del_defgroup_in_object_mode ( Object *ob ) { bDeformGroup *dg; @@ -291,6 +355,8 @@ void del_defgroup_in_object_mode ( Object *ob ) } } + del_defgroup_update_users(ob, ob->actdef); + /* Update the active deform index if necessary */ if (ob->actdef == BLI_countlist(&ob->defbase)) ob->actdef--; @@ -348,6 +414,8 @@ void del_defgroup (Object *ob) } } + del_defgroup_update_users(ob, ob->actdef); + /* Update the active deform index if necessary */ if (ob->actdef==BLI_countlist(&ob->defbase)) ob->actdef--; diff --git a/source/blender/src/editface.c b/source/blender/src/editface.c index e74401cb622..d89af858f21 100644 --- a/source/blender/src/editface.c +++ b/source/blender/src/editface.c @@ -151,6 +151,7 @@ int facesel_face_pick(Mesh *me, short *mval, unsigned int *index, short rect) return 1; } +#if 0 // not used /* returns 0 if not found, otherwise 1 */ static int facesel_edge_pick(Mesh *me, short *mval, unsigned int *index) { @@ -175,6 +176,7 @@ static int facesel_edge_pick(Mesh *me, short *mval, unsigned int *index) return 1; } +#endif /* only operates on the edit object - this is all thats needed at the moment */ static void uv_calc_center_vector(float *result, Object *ob, EditMesh *em) @@ -958,7 +960,6 @@ int edgetag_shortest_path(EditEdge *source, EditEdge *target) EditVert *ev; Heap *heap; - EdgeHash *ehash; float *cost; int a, totvert=0, totedge=0, *nedges, *edges, *prevedge, mednum = -1, nedgeswap = 0; diff --git a/source/blender/src/editmesh_mods.c b/source/blender/src/editmesh_mods.c index 84971e8ce0b..81d79de08c5 100644 --- a/source/blender/src/editmesh_mods.c +++ b/source/blender/src/editmesh_mods.c @@ -2548,6 +2548,10 @@ void hide_mesh(int swap) efa->e2->f1 |= a; efa->e3->f1 |= a; if(efa->e4) efa->e4->f1 |= a; + /* When edges are not delt with in their own loop, we need to explicitly re-selct select edges that are joined to unselected faces */ + if (swap && (G.scene->selectmode == SCE_SELECT_FACE) && (efa->f & SELECT)) { + EM_select_face(efa, 1); + } } } @@ -2751,7 +2755,7 @@ void reveal_tface_uv(void) for (efa= em->faces.first; efa; efa= efa->next) { if (!(efa->h) && !(efa->f & SELECT)) { tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - efa->f |= SELECT; + EM_select_face(efa, 1); tface->flag |= TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4; } } diff --git a/source/blender/src/header_view3d.c b/source/blender/src/header_view3d.c index 45440965859..cb3cfce62c3 100644 --- a/source/blender/src/header_view3d.c +++ b/source/blender/src/header_view3d.c @@ -3964,7 +3964,7 @@ static uiBlock *view3d_edit_armaturemenu(void *arg_unused) uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Fill Between Joints|F", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 18, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Delete|X", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Separate|Ctrl Shift P", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 22, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Separate|Ctrl Alt P", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 22, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); diff --git a/source/blender/src/space.c b/source/blender/src/space.c index 63836101d49..08a073d45b2 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -1194,7 +1194,14 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) if(event==UI_BUT_EVENT) do_butspace(val); /* temporal, view3d deserves own queue? */ /* we consider manipulator a button, defaulting to leftmouse */ - if(event==LEFTMOUSE) if(BIF_do_manipulator(sa)) return; + if(event==LEFTMOUSE) { + /* run any view3d event handler script links */ + if (event && sa->scriptlink.totscript) + if (BPY_do_spacehandlers(sa, event, SPACEHANDLER_VIEW3D_EVENT)) + return; /* return if event was processed (swallowed) by handler(s) */ + + if(BIF_do_manipulator(sa)) return; + } /* swap mouse buttons based on user preference */ if (U.flag & USER_LMOUSESELECT) { @@ -2404,7 +2411,7 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) clear_bone_parent(); else if((G.qual==0) && (G.obedit->type==OB_ARMATURE)) select_bone_parent(); - else if((G.qual==(LR_CTRLKEY|LR_SHIFTKEY)) && (G.obedit->type==OB_ARMATURE)) + else if((G.qual==(LR_CTRLKEY|LR_ALTKEY)) && (G.obedit->type==OB_ARMATURE)) separate_armature(); else if((G.qual==0) && G.obedit->type==OB_MESH) separatemenu(); diff --git a/source/blender/src/toets.c b/source/blender/src/toets.c index a71be6bc425..5b6af61949f 100644 --- a/source/blender/src/toets.c +++ b/source/blender/src/toets.c @@ -106,7 +106,7 @@ #include "mydevice.h" -#include "BIF_poseobject.h" +#include "transform.h" #define VIEW_ZOOM_OUT_FACTOR (1.15f) #define VIEW_ZOOM_IN_FACTOR (1.0f/VIEW_ZOOM_OUT_FACTOR) @@ -322,6 +322,7 @@ void persptoetsen(unsigned short event) if(((G.qual & LR_CTRLKEY) && (G.qual & LR_ALTKEY)) || (G.qual & LR_SHIFTKEY)) { void setcameratoview3d(void); // view.c setcameratoview3d(); + autokeyframe_ob_cb_func(G.scene->camera, TFM_TRANSLATION|TFM_ROTATION); DAG_object_flush_update(G.scene, G.scene->camera, OB_RECALC_OB); BIF_undo_push("View to Camera position"); allqueue(REDRAWVIEW3D, 0); diff --git a/source/blender/src/transform_conversions.c b/source/blender/src/transform_conversions.c index 8859194ff9c..9a9a454ef3d 100644 --- a/source/blender/src/transform_conversions.c +++ b/source/blender/src/transform_conversions.c @@ -2726,9 +2726,10 @@ static void createTransNlaData(TransInfo *t) if (base->object->action) { /* exclude if strip is selected too */ for (strip=base->object->nlastrips.first; strip; strip=strip->next) { - if (strip->flag & ACTSTRIP_SELECT) + if (strip->flag & ACTSTRIP_SELECT) { if (strip->act == base->object->action) break; + } } if (strip==NULL) { cfra = get_action_frame(base->object, CFRA); @@ -2790,9 +2791,10 @@ static void createTransNlaData(TransInfo *t) if (base->object->action) { /* exclude if strip that active action belongs to is selected too */ for (strip=base->object->nlastrips.first; strip; strip=strip->next) { - if (strip->flag & ACTSTRIP_SELECT) + if (strip->flag & ACTSTRIP_SELECT) { if (strip->act == base->object->action) break; + } } /* can include if no strip found */ diff --git a/source/blender/src/transform_generics.c b/source/blender/src/transform_generics.c index 1a803bf00a8..a0dde01ba8e 100644 --- a/source/blender/src/transform_generics.c +++ b/source/blender/src/transform_generics.c @@ -39,6 +39,7 @@ #include "DNA_lattice_types.h" #include "DNA_mesh_types.h" #include "DNA_modifier_types.h" +#include "DNA_nla_types.h" #include "DNA_object_types.h" #include "DNA_object_force.h" #include "DNA_particle_types.h" @@ -303,10 +304,50 @@ void recalcData(TransInfo *t) if (base->object->recalc) base->object->ctime= -1234567.0f; // eveil! + + /* recalculate scale of selected nla-strips */ + if (base->object->nlastrips.first) { + Object *bob= base->object; + bActionStrip *strip; + + for (strip= bob->nlastrips.first; strip; strip= strip->next) { + if (strip->flag & ACTSTRIP_SELECT) { + float actlen= strip->actend - strip->actstart; + float len= strip->end - strip->start; + + strip->scale= len / (actlen * strip->repeat); + } + } + } } DAG_scene_flush_update(G.scene, screen_view3d_layers(), 0); } + else { + for (base=G.scene->base.first; base; base=base->next) { + /* recalculate scale of selected nla-strips */ + if (base->object->nlastrips.first) { + Object *bob= base->object; + bActionStrip *strip; + + for (strip= bob->nlastrips.first; strip; strip= strip->next) { + if (strip->flag & ACTSTRIP_SELECT) { + float actlen= strip->actend - strip->actstart; + float len= strip->end - strip->start; + + /* prevent 'negative' scaling */ + if (len < 0) { + SWAP(float, strip->start, strip->end); + len= fabs(len); + } + + /* calculate new scale */ + strip->scale= len / (actlen * strip->repeat); + } + } + } + } + } } else if (t->spacetype == SPACE_IPO) { EditIpo *ei; diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp index 8817bc98886..bc80c0a7612 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp @@ -562,13 +562,13 @@ int main(int argc, char** argv) STR_String exitstring = ""; GPG_Application app(system, NULL, exitstring); bool firstTimeRunning = true; + char *filename = get_filename(argc, argv); + char *titlename; + char pathname[160]; do { // Read the Blender file - char *filename = get_filename(argc, argv); - char *titlename; - char pathname[160]; BlendFileData *bfd; // if we got an exitcode 3 (KX_EXIT_REQUEST_START_OTHER_GAME) load a different file @@ -582,6 +582,17 @@ int main(int argc, char** argv) BLI_convertstringcode(basedpath, pathname); bfd = load_game_data(basedpath); + + if (!bfd) + { + // just add "//" in front of it + char temppath[242]; + strcpy(temppath, "//"); + strcat(temppath, basedpath); + + BLI_convertstringcode(temppath, pathname); + bfd = load_game_data(temppath); + } } else { @@ -607,7 +618,6 @@ int main(int argc, char** argv) #endif // WIN32 Main *maggie = bfd->main; Scene *scene = bfd->curscene; - strcpy (pathname, maggie->name); char *startscenename = scene->id.name + 2; G.fileflags = bfd->fileflags; @@ -651,7 +661,12 @@ int main(int argc, char** argv) if (firstTimeRunning) { firstTimeRunning = false; - + + // set the filename only the first time as in KetsjiEmbedded + strcpy (pathname, maggie->name); + // also copy here (used by GameLogic.getBaseDirectory) + strcpy (G.sce, maggie->name); + if (fullScreen) { #ifdef WIN32 diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index a2aff54d385..a80a7f04e8f 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -88,6 +88,10 @@ //#include "BPY_extern.h" #endif +#include "BKE_utildefines.h" +#include "BKE_global.h" +#include "BLI_blenlib.h" + static void setSandbox(TPythonSecurityLevel level); @@ -140,6 +144,32 @@ static PyObject* gPySetGravity(PyObject*, return NULL; } +static char gPyExpandPath_doc[] = +"(path) - Converts a blender internal path into a proper file system path.\n\ +path - the string path to convert.\n\n\ +Use / as directory separator in path\n\ +You can use '//' at the start of the string to define a relative path;\n\ +Blender replaces that string by the directory of the startup .blend or runtime\n\ +file to make a full path name (doesn't change during the game, even if you load\n\ +other .blend).\n\ +The function also converts the directory separator to the local file system format."; + +static PyObject* gPyExpandPath(PyObject*, + PyObject* args, + PyObject*) +{ + char expanded[FILE_MAXDIR + FILE_MAXFILE]; + char* filename; + + if (PyArg_ParseTuple(args,"s",&filename)) + { + BLI_strncpy(expanded, filename, FILE_MAXDIR + FILE_MAXFILE); + BLI_convertstringcode(expanded, G.sce); + return PyString_FromString(expanded); + } + return NULL; +} + static bool usedsp = false; @@ -361,6 +391,7 @@ static PyObject *pyPrintExt(PyObject *,PyObject *,PyObject *) static struct PyMethodDef game_methods[] = { + {"expandPath", (PyCFunction)gPyExpandPath, METH_VARARGS, gPyExpandPath_doc}, {"getCurrentController", (PyCFunction) SCA_PythonController::sPyGetCurrentController, METH_VARARGS, SCA_PythonController::sPyGetCurrentController__doc__}, diff --git a/source/gameengine/PyDoc/GameLogic.py b/source/gameengine/PyDoc/GameLogic.py index fcfd8bfc4eb..965c0522bd7 100644 --- a/source/gameengine/PyDoc/GameLogic.py +++ b/source/gameengine/PyDoc/GameLogic.py @@ -221,3 +221,18 @@ def setPhysicsTicRate(ticrate): @type ticrate: float """ +def expandPath(path): + """ + Converts a blender internal path into a proper file system path. + + Use / as directory separator in path + You can use '//' at the start of the string to define a relative path; + Blender replaces that string by the directory of the startup .blend or runtime file + to make a full path name (doesn't change during the game, even if you load other .blend). + The function also converts the directory separator to the local file system format. + + @param path: The path string to be converted/expanded. + @type path: string + @return: The converted string + @rtype: string + """