forked from bartvdbraak/blender
soc-2008-mxcurioni: merged changes to revision 14798, compilation works for rendering/ directry. Still needs to figure out how to compile on non-Unix machines.
This commit is contained in:
commit
c785d7493e
@ -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
|
||||
|
@ -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);
|
||||
|
@ -1,5 +1,5 @@
|
||||
#!BPY
|
||||
|
||||
# coding: utf-8
|
||||
"""
|
||||
Name: '3D Studio (.3ds)...'
|
||||
Blender: 243
|
||||
|
@ -1,5 +1,5 @@
|
||||
#!BPY
|
||||
|
||||
# coding: utf-8
|
||||
""" Registration info for Blender menus
|
||||
Name: 'Bevel Center'
|
||||
Blender: 243
|
||||
|
@ -1,5 +1,5 @@
|
||||
#!BPY
|
||||
|
||||
# coding: utf-8
|
||||
"""
|
||||
Name: 'BlenderLipSynchro'
|
||||
Blender: 242
|
||||
|
@ -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()
|
||||
gui()
|
||||
|
||||
|
@ -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)
|
||||
Register(draw, event, bevent)
|
||||
|
@ -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)
|
||||
"""
|
||||
"""
|
||||
|
||||
|
@ -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)
|
||||
Blender.Window.FileSelector (fonctionSELECT, text)
|
||||
|
||||
|
@ -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)
|
||||
Blender.Window.EditMode(EDITMODE)
|
||||
|
@ -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);
|
||||
|
@ -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 + \
|
||||
|
@ -281,7 +281,7 @@ void GLRenderer::visitLineRep( LineRep& iLine)
|
||||
}
|
||||
|
||||
const vector<Vec3r>& vertices = iLine.vertices();
|
||||
float step=1.f/vertices.size();
|
||||
//soc unused float step=1.f/vertices.size();
|
||||
vector<Vec3r>::const_iterator v;
|
||||
|
||||
for(v=vertices.begin(); v!=vertices.end(); v++)
|
||||
|
@ -19,12 +19,18 @@
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <qimage.h>
|
||||
#include <qfileinfo.h>
|
||||
#include <qgl.h>
|
||||
#include <qfile.h>
|
||||
#include "GLStrokeRenderer.h"
|
||||
|
||||
//soc
|
||||
// #include <qimage.h>
|
||||
// #include <qfileinfo.h>
|
||||
// #include <qgl.h>
|
||||
// #include <qfile.h>
|
||||
#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<size;++i){
|
||||
for(unsigned i=0;i<size;++i){
|
||||
_papertexname[i] = tmp[i];
|
||||
}
|
||||
delete [] tmp;
|
||||
@ -308,13 +314,14 @@ GLTextureManager::loadBrush(string sname, Stroke::MediumType mediumType)
|
||||
glGenTextures(1, &texId);
|
||||
bool found = false;
|
||||
vector<string> pathnames;
|
||||
QString path;
|
||||
string path; //soc
|
||||
StringUtils::getPathName(TextureManager::Options::getBrushesPath(),
|
||||
sname,
|
||||
pathnames);
|
||||
for (vector<string>::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<char *>(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 "<<qim.depth()<<" bits/pixel"<<endl;
|
||||
cerr<<" Error: \""<< name <<"\" has "<< qim->depth <<" bits/pixel"<<endl; //soc
|
||||
return false;
|
||||
}
|
||||
// qim=QGLWidget::convertToGLFormat( qimOri );
|
||||
@ -369,11 +386,12 @@ GLTextureManager::prepareTextureAlpha (string sname, GLuint itexname)
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
|
||||
GL_LINEAR);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, qim.width(), qim.height(), 0,
|
||||
GL_ALPHA, GL_UNSIGNED_BYTE, qim.bits());
|
||||
|
||||
cout << " \"" << filename.toAscii().data() << "\" loaded with "<< qim.depth() << " bits per pixel" << endl;
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, qim->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: \""<<name<<"\" has "<<qim.depth()<<" bits/pixel"<<endl;
|
||||
cerr<<" Error: \""<<name<<"\" has "<<qim->depth <<" bits/pixel"<<endl;//soc
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -408,11 +433,12 @@ GLTextureManager::prepareTextureLuminance (string sname, GLuint itexname)
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
|
||||
GL_LINEAR);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, qim.width(), qim.height(), 0,
|
||||
GL_LUMINANCE, GL_UNSIGNED_BYTE, qim.bits());
|
||||
|
||||
cout << " \"" << filename.toAscii().data() << "\" loaded with "<< qim.depth() << " bits per pixel" << endl;
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, qim->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: \""<<name<<"\" has "<<qim.depth()<<" bits/pixel"<<endl;
|
||||
cerr<<" Error: \""<<name<<"\" has "<<qim->depth<<" bits/pixel"<<endl; //soc
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -447,12 +480,13 @@ GLTextureManager::prepareTextureLuminanceAndAlpha (string sname, GLuint itexname
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
|
||||
GL_LINEAR);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, qim.width(), qim.height(), 0,
|
||||
GL_LUMINANCE, GL_UNSIGNED_BYTE, qim.bits());
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, qim.width(), qim.height(), 0,
|
||||
GL_ALPHA, GL_UNSIGNED_BYTE, qim.bits());
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, qim->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: \""<<name<<"\" has "<<qim.depth()<<" bits/pixel"<<endl;
|
||||
cerr<<" Error: \""<<name<<"\" has "<<qim->depth<<" bits/pixel"<<endl; //soc
|
||||
return false;
|
||||
}
|
||||
QImage qim2=QGLWidget::convertToGLFormat( qim );
|
||||
//soc QImage qim2=QGLWidget::convertToGLFormat( qim );
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, itexname);
|
||||
|
||||
@ -485,11 +524,11 @@ GLTextureManager::preparePaper (const char *name, GLuint itexname)
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
|
||||
GL_LINEAR);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, qim.width(), qim.height(), 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, qim2.bits());
|
||||
|
||||
cout << " \"" << filename.toAscii().data() << "\" loaded with "<< qim.depth() << " bits per pixel" << endl;
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, qim->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;
|
||||
}
|
||||
|
||||
|
@ -63,6 +63,8 @@ void *glutils_extgl_GetProcAddress(const char *name)
|
||||
#ifdef _WIN32
|
||||
void *t = wglGetProcAddress(name);
|
||||
return t;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -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
|
@ -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 <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include <malloc.h>
|
||||
#include <math.h>
|
||||
#include <limits.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/times.h>
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glx.h>
|
||||
#include <GL/glu.h>
|
||||
|
||||
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
|
||||
//
|
||||
// <Return Values>
|
||||
// 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
|
||||
//
|
||||
// <Return Values>
|
||||
// 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
|
@ -1,4 +1,4 @@
|
||||
#include <pbuffer.h>
|
||||
#include "pbuffer.h"
|
||||
|
||||
#include <memory.h>
|
||||
|
||||
|
@ -1,13 +1,12 @@
|
||||
#ifndef PBUFFERS_H
|
||||
#define PBUFFERS_H
|
||||
|
||||
#ifndef WIN32
|
||||
# ifdef __MACH__
|
||||
# ifdef __MACH__
|
||||
# include <OpenGL/gl.h>
|
||||
# else
|
||||
# else
|
||||
# include <GL/gl.h>
|
||||
# include <GL/glx.h>
|
||||
# endif
|
||||
# endif
|
||||
|
||||
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
// Interface of PBuffer
|
||||
@ -74,4 +73,3 @@ private:
|
||||
};
|
||||
|
||||
#endif //PBUFFERS_H
|
||||
#endif //WIN32
|
||||
|
@ -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<string>& 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
|
||||
|
@ -30,14 +30,21 @@
|
||||
|
||||
# include <vector>
|
||||
# include <string>
|
||||
# include <sstream>
|
||||
# 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<string>& pathnames);
|
||||
string toAscii( const string &str );
|
||||
const char* toAscii( const char *str );
|
||||
|
||||
// STL related
|
||||
struct ltstr{
|
||||
|
@ -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;
|
||||
|
@ -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());
|
||||
|
@ -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 */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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 <Python.h>
|
||||
#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 */
|
||||
|
@ -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<NLA>} (*)
|
||||
- L{Particle}
|
||||
- L{Registry}
|
||||
- L{Scene} (*)
|
||||
- L{Radio}
|
||||
|
@ -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
|
||||
|
367
source/blender/python/api2_2x/doc/Particle.py
Normal file
367
source/blender/python/api2_2x/doc/Particle.py
Normal file
@ -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).
|
||||
"""
|
@ -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, "");
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -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; a<PSYS_TOT_VG; a++)
|
||||
if(psys->vgroup[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--;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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, "");
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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__},
|
||||
|
@ -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
|
||||
"""
|
||||
|
Loading…
Reference in New Issue
Block a user