Merged changes in the trunk up to revision 25613.

This commit is contained in:
2009-12-29 21:46:36 +00:00
294 changed files with 19336 additions and 17280 deletions

View File

@@ -47,18 +47,21 @@ if MACOSX_ARCHITECTURE == 'ppc':
# CC = 'gcc-3.3'
# CXX = 'g++-3.3'
MAC_MIN_VERS = '10.4'
MACOSX_DEPLOYMENT_TARGET = '10.4'
MACOSX_SDK='/Developer/SDKs/MacOSX10.4u.sdk'
LCGDIR = '#../lib/darwin-8.0.0-powerpc'
CC = 'gcc-4.0'
CXX = 'g++-4.0'
elif MACOSX_ARCHITECTURE == 'i386':
MAC_MIN_VERS = '10.4'
MACOSX_DEPLOYMENT_TARGET = '10.4'
MACOSX_SDK='/Developer/SDKs/MacOSX10.4u.sdk'
LCGDIR = '#../lib/darwin-8.x.i386'
CC = 'gcc-4.0'
CXX = 'g++-4.0'
else :
MAC_MIN_VERS = '10.5'
MACOSX_DEPLOYMENT_TARGET = '10.5'
MACOSX_SDK='/Developer/SDKs/MacOSX10.5.sdk'
LCGDIR = '#../lib/darwin-9.x.universal'
CC = 'gcc-4.2'

View File

@@ -793,7 +793,7 @@ btSoftBody* btSoftBodyHelpers::CreateEllipsoid(btSoftBodyWorldInfo& worldInfo,c
//
btSoftBody* btSoftBodyHelpers::CreateFromTriMesh(btSoftBodyWorldInfo& worldInfo,const btScalar* vertices,
const int* triangles,
int ntriangles)
int ntriangles, bool randomizeConstraints)
{
int maxidx=0;
int i,j,ni;
@@ -828,14 +828,16 @@ btSoftBody* btSoftBodyHelpers::CreateFromTriMesh(btSoftBodyWorldInfo& worldInfo
#undef IDX
psb->appendFace(idx[0],idx[1],idx[2]);
}
// don't randomize now, let's give a chance to the application to set face data
//psb->randomizeConstraints();
if (randomizeConstraints)
{
psb->randomizeConstraints();
}
return(psb);
}
//
btSoftBody* btSoftBodyHelpers::CreateFromConvexHull(btSoftBodyWorldInfo& worldInfo, const btVector3* vertices,
int nvertices)
int nvertices, bool randomizeConstraints)
{
HullDesc hdsc(QF_TRIANGLES,nvertices,vertices);
HullResult hres;
@@ -855,6 +857,9 @@ btSoftBody* btSoftBodyHelpers::CreateFromConvexHull(btSoftBodyWorldInfo& worldI
psb->appendFace(idx[0],idx[1],idx[2]);
}
hlib.ReleaseResult(hres);
psb->randomizeConstraints();
if (randomizeConstraints)
{
psb->randomizeConstraints();
}
return(psb);
}

View File

@@ -109,11 +109,13 @@ struct btSoftBodyHelpers
static btSoftBody* CreateFromTriMesh( btSoftBodyWorldInfo& worldInfo,
const btScalar* vertices,
const int* triangles,
int ntriangles);
int ntriangles,
bool randomizeConstraints = true);
/* Create from convex-hull */
static btSoftBody* CreateFromConvexHull( btSoftBodyWorldInfo& worldInfo,
const btVector3* vertices,
int nvertices);
int nvertices,
bool randomizeConstraints = true);
};
#endif //SOFT_BODY_HELPERS_H

View File

@@ -40,11 +40,6 @@ IF(WITH_OPENAL)
SET(INC ${INC} OpenAL ${OPENAL_INCLUDE_DIR})
FILE(GLOB OPENALSRC OpenAL/*.cpp)
ADD_DEFINITIONS(-DWITH_OPENAL)
STRING(REGEX MATCH ".*ramework.*" FRAMEWORK ${OPENAL_INCLUDE_DIR})
IF(FRAMEWORK)
ADD_DEFINITIONS(-DAPPLE_FRAMEWORK_FIX)
ENDIF(FRAMEWORK)
ENDIF(WITH_OPENAL)
IF(WITH_JACK)
@@ -59,6 +54,12 @@ IF(WITH_SNDFILE)
ADD_DEFINITIONS(-DWITH_SNDFILE)
ENDIF(WITH_SNDFILE)
SET(SRC ${SRC} ${FFMPEGSRC} ${SNDFILESRC} ${SDLSRC} ${OPENALSRC} ${JACKSRC})
IF(WITH_FFTW3)
SET(INC ${INC} fftw ${FFTW3_INC})
FILE(GLOB FFTW3SRC fftw/*.cpp)
ADD_DEFINITIONS(-DWITH_FFTW3)
ENDIF(WITH_FFTW3)
SET(SRC ${SRC} ${FFMPEGSRC} ${SNDFILESRC} ${FFTW3SRC} ${SDLSRC} ${OPENALSRC} ${JACKSRC})
BLENDERLIB(bf_audaspace "${SRC}" "${INC}")

View File

@@ -38,7 +38,7 @@ private:
/**
* The loop count.
*/
float m_loop;
int m_loop;
public:
/**

View File

@@ -0,0 +1,45 @@
/*
* $Id$
*
* ***** BEGIN LGPL LICENSE BLOCK *****
*
* Copyright 2009 Jörg Hermann Müller
*
* This file is part of AudaSpace.
*
* AudaSpace is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AudaSpace 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
*
* ***** END LGPL LICENSE BLOCK *****
*/
#include "AUD_RectifyFactory.h"
#include "AUD_RectifyReader.h"
AUD_RectifyFactory::AUD_RectifyFactory(AUD_IFactory* factory) :
AUD_EffectFactory(factory) {}
AUD_RectifyFactory::AUD_RectifyFactory() :
AUD_EffectFactory(0) {}
AUD_IReader* AUD_RectifyFactory::createReader()
{
AUD_IReader* reader = getReader();
if(reader != 0)
{
reader = new AUD_RectifyReader(reader); AUD_NEW("reader")
}
return reader;
}

View File

@@ -0,0 +1,51 @@
/*
* $Id$
*
* ***** BEGIN LGPL LICENSE BLOCK *****
*
* Copyright 2009 Jörg Hermann Müller
*
* This file is part of AudaSpace.
*
* AudaSpace is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AudaSpace 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
*
* ***** END LGPL LICENSE BLOCK *****
*/
#ifndef AUD_RECTIFYFACTORY
#define AUD_RECTIFYFACTORY
#include "AUD_EffectFactory.h"
/**
* This factory rectifies another factory.
*/
class AUD_RectifyFactory : public AUD_EffectFactory
{
public:
/**
* Creates a new rectify factory.
* \param factory The input factory.
*/
AUD_RectifyFactory(AUD_IFactory* factory = 0);
/**
* Creates a new rectify factory.
*/
AUD_RectifyFactory();
virtual AUD_IReader* createReader();
};
#endif //AUD_RECTIFYFACTORY

View File

@@ -0,0 +1,82 @@
/*
* $Id$
*
* ***** BEGIN LGPL LICENSE BLOCK *****
*
* Copyright 2009 Jörg Hermann Müller
*
* This file is part of AudaSpace.
*
* AudaSpace is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AudaSpace 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
*
* ***** END LGPL LICENSE BLOCK *****
*/
#include "AUD_RectifyReader.h"
#include "AUD_Buffer.h"
#include <cstring>
AUD_RectifyReader::AUD_RectifyReader(AUD_IReader* reader) :
AUD_EffectReader(reader)
{
int bigendian = 1;
bigendian = (((char*)&bigendian)[0]) ? 0: 1; // 1 if Big Endian
switch(m_reader->getSpecs().format)
{
case AUD_FORMAT_S16:
m_rectify = AUD_rectify<int16_t>;
break;
case AUD_FORMAT_S32:
m_rectify = AUD_rectify<int32_t>;
break;
case AUD_FORMAT_FLOAT32:
m_rectify = AUD_rectify<float>;
break;
case AUD_FORMAT_FLOAT64:
m_rectify = AUD_rectify<double>;
break;
case AUD_FORMAT_U8:
m_rectify = AUD_rectify_u8;
break;
case AUD_FORMAT_S24:
m_rectify = bigendian ? AUD_rectify_s24_be : AUD_rectify_s24_le;
break;
default:
delete m_reader;
AUD_THROW(AUD_ERROR_READER);
}
m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
}
AUD_RectifyReader::~AUD_RectifyReader()
{
delete m_buffer; AUD_DELETE("buffer")
}
void AUD_RectifyReader::read(int & length, sample_t* & buffer)
{
sample_t* buf;
AUD_Specs specs = m_reader->getSpecs();
m_reader->read(length, buf);
if(m_buffer->getSize() < length*AUD_SAMPLE_SIZE(specs))
m_buffer->resize(length*AUD_SAMPLE_SIZE(specs));
buffer = m_buffer->getBuffer();
m_rectify(buffer, buf, length * specs.channels);
}

View File

@@ -0,0 +1,65 @@
/*
* $Id$
*
* ***** BEGIN LGPL LICENSE BLOCK *****
*
* Copyright 2009 Jörg Hermann Müller
*
* This file is part of AudaSpace.
*
* AudaSpace is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AudaSpace 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
*
* ***** END LGPL LICENSE BLOCK *****
*/
#ifndef AUD_RECTIFYREADER
#define AUD_RECTIFYREADER
#include "AUD_EffectReader.h"
#include "AUD_ConverterFunctions.h"
class AUD_Buffer;
/**
* This class reads another reader and rectifies it.
*/
class AUD_RectifyReader : public AUD_EffectReader
{
private:
/**
* The playback buffer.
*/
AUD_Buffer *m_buffer;
/**
* Rectifying function.
*/
AUD_rectify_f m_rectify;
public:
/**
* Creates a new rectify reader.
* \param reader The reader to read from.
* \exception AUD_Exception Thrown if the reader specified is NULL.
*/
AUD_RectifyReader(AUD_IReader* reader);
/**
* Destroys the reader.
*/
virtual ~AUD_RectifyReader();
virtual void read(int & length, sample_t* & buffer);
};
#endif //AUD_RECTIFYREADER

View File

@@ -56,6 +56,10 @@ ifeq ($(WITH_SNDFILE),true)
DIRS += sndfile
endif
ifeq ($(WITH_FFTW3),true)
DIRS += fftw
endif
include nan_subdirs.mk
install: $(ALL_OR_DEBUG)
@@ -80,6 +84,10 @@ ifeq ($(WITH_SNDFILE),true)
@../tools/cpifdiff.sh $(DIR)/$(DEBUG_DIR)libaud_sndfile.a $(NAN_AUDASPACE)/lib/$(DEBUG_DIR)
endif
ifeq ($(WITH_FFTW3),true)
@../tools/cpifdiff.sh $(DIR)/$(DEBUG_DIR)libaud_fftw.a $(NAN_AUDASPACE)/lib/$(DEBUG_DIR)
endif
ifeq ($(OS),darwin)
ranlib $(NAN_AUDASPACE)/lib/$(DEBUG_DIR)libaudaspace.a
ranlib $(NAN_AUDASPACE)/lib/$(DEBUG_DIR)libaud_src.a
@@ -102,5 +110,9 @@ ifeq ($(WITH_SNDFILE),true)
ranlib $(NAN_AUDASPACE)/lib/$(DEBUG_DIR)libaud_sndfile.a
endif
ifeq ($(WITH_FFTW3),true)
ranlib $(NAN_AUDASPACE)/lib/$(DEBUG_DIR)libaud_fftw.a
endif
endif
@../tools/cpifdiff.sh intern/*.h $(NAN_AUDASPACE)/include/

View File

@@ -31,4 +31,9 @@ if env['WITH_BF_SNDFILE']:
incs += ' sndfile ' + env['BF_SNDFILE_INC']
defs.append('WITH_SNDFILE')
if env['WITH_BF_FFTW3']:
sources += env.Glob('fftw/*.cpp')
incs += ' fftw ' + env['BF_FFTW3_INC']
defs.append('WITH_FFTW3')
env.BlenderLib ('bf_audaspace', sources, Split(incs), defs, libtype=['intern','player'], priority = [25,215] )

View File

@@ -0,0 +1,79 @@
/*
* $Id$
*
* ***** BEGIN LGPL LICENSE BLOCK *****
*
* Copyright 2009 Jörg Hermann Müller
*
* This file is part of AudaSpace.
*
* AudaSpace is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AudaSpace 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
*
* ***** END LGPL LICENSE BLOCK *****
*/
#include "AUD_BandPassFactory.h"
#include "AUD_BandPassReader.h"
AUD_BandPassFactory::AUD_BandPassFactory(AUD_IFactory* factory, float low,
float high) :
AUD_EffectFactory(factory),
m_low(low),
m_high(high) {}
AUD_BandPassFactory::AUD_BandPassFactory(float low, float high) :
AUD_EffectFactory(0),
m_low(low),
m_high(high) {}
float AUD_BandPassFactory::getLow()
{
return m_low;
}
float AUD_BandPassFactory::getHigh()
{
return m_high;
}
void AUD_BandPassFactory::setLow(float low)
{
m_low = low;
}
void AUD_BandPassFactory::setHigh(float high)
{
m_high = high;
}
AUD_IReader* AUD_BandPassFactory::createReader()
{
AUD_IReader* reader = getReader();
if(reader != 0)
{
if(reader->getSpecs().format == AUD_FORMAT_FLOAT32)
{
reader = new AUD_BandPassReader(reader, m_low, m_high);
AUD_NEW("reader")
}
else
{
delete reader; AUD_DELETE("reader")
return 0;
}
}
return reader;
}

View File

@@ -0,0 +1,88 @@
/*
* $Id$
*
* ***** BEGIN LGPL LICENSE BLOCK *****
*
* Copyright 2009 Jörg Hermann Müller
*
* This file is part of AudaSpace.
*
* AudaSpace is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AudaSpace 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
*
* ***** END LGPL LICENSE BLOCK *****
*/
#ifndef AUD_BANDPASSFACTORY
#define AUD_BANDPASSFACTORY
#include "AUD_EffectFactory.h"
/**
* This factory creates a band pass filter for a sound wave.
*/
class AUD_BandPassFactory : public AUD_EffectFactory
{
private:
/**
* The lowest frequency to be passed.
*/
float m_low;
/**
* The highest frequency to be passed.
*/
float m_high;
public:
/**
* Creates a new band pass factory.
* \param factory The input factory.
* \param low The lowest passed frequency.
* \param high The highest passed frequency.
*/
AUD_BandPassFactory(AUD_IFactory* factory, float low, float high);
/**
* Creates a new band pass factory.
* \param low The lowest passed frequency.
* \param high The highest passed frequency.
*/
AUD_BandPassFactory(float low, float high);
/**
* Returns the lowest passed frequency.
*/
float getLow();
/**
* Returns the highest passed frequency.
*/
float getHigh();
/**
* Sets the lowest passed frequency.
* \param low The lowest passed frequency.
*/
void setLow(float low);
/**
* Sets the highest passed frequency.
* \param high The highest passed frequency.
*/
void setHigh(float hight);
virtual AUD_IReader* createReader();
};
#endif //AUD_BANDPASSFACTORY

View File

@@ -0,0 +1,126 @@
/*
* $Id$
*
* ***** BEGIN LGPL LICENSE BLOCK *****
*
* Copyright 2009 Jörg Hermann Müller
*
* This file is part of AudaSpace.
*
* AudaSpace is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AudaSpace 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
*
* ***** END LGPL LICENSE BLOCK *****
*/
#include "AUD_BandPassReader.h"
#include "AUD_Buffer.h"
#include <cstring>
#include <stdio.h>
AUD_BandPassReader::AUD_BandPassReader(AUD_IReader* reader, float low,
float high) :
AUD_EffectReader(reader), m_low(low), m_high(high)
{
m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
m_in = new AUD_Buffer(); AUD_NEW("buffer")
m_out = new AUD_Buffer(); AUD_NEW("buffer")
m_length = 0;
}
AUD_BandPassReader::~AUD_BandPassReader()
{
if(m_length != 0)
{
fftw_destroy_plan(m_forward);
fftw_destroy_plan(m_backward);
}
delete m_buffer; AUD_DELETE("buffer")
delete m_in; AUD_DELETE("buffer")
delete m_out; AUD_DELETE("buffer")
}
AUD_ReaderType AUD_BandPassReader::getType()
{
return m_reader->getType();
}
void AUD_BandPassReader::read(int & length, sample_t* & buffer)
{
AUD_Specs specs = m_reader->getSpecs();
m_reader->read(length, buffer);
if(length > 0)
{
if(length * AUD_SAMPLE_SIZE(specs) > m_buffer->getSize())
m_buffer->resize(length * AUD_SAMPLE_SIZE(specs));
if(length != m_length)
{
if(m_length != 0)
{
fftw_destroy_plan(m_forward);
fftw_destroy_plan(m_backward);
}
m_length = length;
printf("WINDOW: %d\n", m_length);
if(m_length * sizeof(double) > m_in->getSize())
{
m_in->resize(m_length * sizeof(double));
m_out->resize((m_length / 2 + 1) * sizeof(fftw_complex));
}
m_forward = fftw_plan_dft_r2c_1d(m_length,
(double*)m_in->getBuffer(),
(fftw_complex*)m_out->getBuffer(),
FFTW_ESTIMATE);
m_backward = fftw_plan_dft_c2r_1d(m_length,
(fftw_complex*)m_out->getBuffer(),
(double*)m_in->getBuffer(),
FFTW_ESTIMATE);
}
float* source = (float*) buffer;
double* target = (double*) m_in->getBuffer();
float* target2 = (float*) m_buffer->getBuffer();
fftw_complex* complex = (fftw_complex*) m_out->getBuffer();
float frequency;
for(int channel = 0; channel < specs.channels; channel++)
{
for(int i = 0; i < m_length; i++)
target[i] = source[i * specs.channels + channel];
fftw_execute(m_forward);
for(int i = 0; i < m_length / 2 + 1; i++)
{
frequency = i * specs.rate / (m_length / 2.0 + 1.0);
if((frequency < m_low) || (frequency > m_high))
complex[i][0] = complex[i][1] = 0.0;
}
fftw_execute(m_backward);
for(int i = 0; i < m_length; i++)
target2[i * specs.channels + channel] = target[i] / m_length;
}
}
buffer = m_buffer->getBuffer();
}

View File

@@ -0,0 +1,99 @@
/*
* $Id$
*
* ***** BEGIN LGPL LICENSE BLOCK *****
*
* Copyright 2009 Jörg Hermann Müller
*
* This file is part of AudaSpace.
*
* AudaSpace is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AudaSpace 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
*
* ***** END LGPL LICENSE BLOCK *****
*/
#ifndef AUD_BANDPASSREADER
#define AUD_BANDPASSREADER
#include <fftw3.h>
#include "AUD_EffectReader.h"
class AUD_Buffer;
/**
* This class only passes a specific frequency band of another reader.
*/
class AUD_BandPassReader : public AUD_EffectReader
{
private:
/**
* The playback buffer.
*/
AUD_Buffer *m_buffer;
/**
* The input buffer for fourier transformations.
*/
AUD_Buffer *m_in;
/**
* The output buffer for fourier transformations.
*/
AUD_Buffer *m_out;
/**
* The lowest passed frequency.
*/
float m_low;
/**
* The highest passed frequency.
*/
float m_high;
/**
* The fftw plan for forward transformation.
*/
fftw_plan m_forward;
/**
* The fftw plan for backward transformation.
*/
fftw_plan m_backward;
/**
* The length of the plans.
*/
int m_length;
public:
/**
* Creates a new band pass reader.
* \param reader The reader to read from.
* \param low The lowest passed frequency.
* \param high The highest passed frequency.
* \exception AUD_Exception Thrown if the reader specified is NULL.
*/
AUD_BandPassReader(AUD_IReader* reader, float low, float high);
/**
* Destroys the reader.
*/
virtual ~AUD_BandPassReader();
virtual AUD_ReaderType getType();
virtual void read(int & length, sample_t* & buffer);
};
#endif //AUD_BANDPASSREADER

View File

@@ -0,0 +1,42 @@
#
# $Id$
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
# All rights reserved.
#
# The Original Code is: all of this file.
#
# Contributor(s): none yet.
#
# ***** END GPL LICENSE BLOCK *****
#
#
LIBNAME = aud_fftw
DIR = $(OCGDIR)/intern/audaspace
include nan_compile.mk
CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
CPPFLAGS += -I../intern
CPPFLAGS += -I../FX
CPPFLAGS += -I..
CPPFLAGS += -I.
CPPFLAGS += -I$(BF_FFTW3)/include

View File

@@ -81,7 +81,7 @@ void AUD_BufferReader::read(int & length, sample_t* & buffer)
buffer = m_buffer.get()->getBuffer()+m_position*sample_size;
// in case the end of the buffer is reach
// in case the end of the buffer is reached
if(m_buffer.get()->getSize() < (m_position+length)*sample_size)
length = m_buffer.get()->getSize()/sample_size-m_position;

View File

@@ -31,6 +31,7 @@
#include "AUD_LimiterFactory.h"
#include "AUD_PingPongFactory.h"
#include "AUD_LoopFactory.h"
#include "AUD_RectifyFactory.h"
#include "AUD_ReadDevice.h"
#include "AUD_SourceCaps.h"
#include "AUD_IReader.h"
@@ -285,6 +286,20 @@ int AUD_stopLoop(AUD_Handle* handle)
return false;
}
AUD_Sound* AUD_rectifySound(AUD_Sound* sound)
{
assert(sound);
try
{
return new AUD_RectifyFactory(sound);
}
catch(AUD_Exception)
{
return NULL;
}
}
void AUD_unload(AUD_Sound* sound)
{
assert(sound);

View File

@@ -149,6 +149,13 @@ extern AUD_Sound* AUD_loopSound(AUD_Sound* sound);
*/
extern int AUD_stopLoop(AUD_Handle* handle);
/**
* Rectifies a sound.
* \param sound The sound to rectify.
* \return A handle of the rectified sound.
*/
extern AUD_Sound* AUD_rectifySound(AUD_Sound* sound);
/**
* Unloads a sound of any type.
* \param sound The handle of the sound.

View File

@@ -500,3 +500,43 @@ void AUD_volume_adjust_s24_be(sample_t* target, sample_t* source,
}
}
void AUD_rectify_u8(sample_t* target, sample_t* source, int count)
{
for(int i=0; i<count; i++)
target[i] = source[i] < 0x80 ? 0x0100 - source[i] : source[i];
}
void AUD_rectify_s24_le(sample_t* target, sample_t* source, int count)
{
count *= 3;
int value;
for(int i=0; i<count; i+=3)
{
value = source[i+2] << 16 | source[i+1] << 8 | source[i];
value |= (((value & 0x800000) >> 23) * 255) << 24;
if(value < 0)
value = -value;
target[i+2] = value >> 16;
target[i+1] = value >> 8;
target[i] = value;
}
}
void AUD_rectify_s24_be(sample_t* target, sample_t* source, int count)
{
count *= 3;
int value;
for(int i=0; i < count; i+=3)
{
value = source[i] << 16 | source[i+1] << 8 | source[i+2];
value |= (((value & 0x800000) >> 23) * 255) << 24;
if(value < 0)
value = -value;
target[i] = value >> 16;
target[i+1] = value >> 8;
target[i+2] = value;
}
}

View File

@@ -46,6 +46,8 @@ typedef void (*AUD_convert_f)(sample_t* target, sample_t* source, int length);
typedef void (*AUD_volume_adjust_f)(sample_t* target, sample_t* source,
int count, float volume);
typedef void (*AUD_rectify_f)(sample_t* target, sample_t* source, int count);
template <class T>
void AUD_convert_copy(sample_t* target, sample_t* source, int length)
{
@@ -153,4 +155,19 @@ void AUD_volume_adjust_s24_le(sample_t* target, sample_t* source,
void AUD_volume_adjust_s24_be(sample_t* target, sample_t* source,
int count, float volume);
template <class T>
void AUD_rectify(sample_t* target, sample_t* source, int count)
{
T* t = (T*)target;
T* s = (T*)source;
for(int i=0; i < count; i++)
t[i] = s[i] < 0 ? -s[i] : s[i];
}
void AUD_rectify_u8(sample_t* target, sample_t* source, int count);
void AUD_rectify_s24_le(sample_t* target, sample_t* source, int count);
void AUD_rectify_s24_be(sample_t* target, sample_t* source, int count);
#endif //AUD_CONVERTERFUNCTIONS

View File

@@ -59,9 +59,10 @@ endif
ifeq ($(WITH_SNDFILE),true)
CPPFLAGS += -DWITH_SNDFILE
CPPFLAGS += -I../sndfile
CPPFLAGS += -I$(NAN_SNDFILE)/include
endif
CPPFLAGS += -I$(LCGDIR)/samplerate/include/
CPPFLAGS += -I$(NAN_SAMPLERATE)/include/
CPPFLAGS += -I../ffmpeg
CPPFLAGS += -I../FX
CPPFLAGS += -I../SDL

View File

@@ -44,7 +44,7 @@
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="2"
AdditionalIncludeDirectories="..\..;..\..\ffmpeg;..\..\FX;..\..\intern;..\..\OpenAL;..\..\SDL;..\..\SRC;..\..\sndfile;..\..\..\..\..\lib\windows\pthreads\include;..\..\..\..\..\lib\windows\samplerate\include;..\..\..\..\..\lib\windows\ffmpeg\include;..\..\..\..\..\lib\windows\ffmpeg\include\msvc;..\..\..\..\..\lib\windows\sdl\include;..\..\..\..\..\lib\windows\openal\include;..\..\..\..\..\lib\windows\jack\include;..\..\..\..\..\lib\windows\sndfile\include"
AdditionalIncludeDirectories="..\..;..\..\ffmpeg;..\..\FX;..\..\intern;..\..\OpenAL;..\..\SDL;..\..\SRC;..\..\sndfile;..\..\..\..\..\lib\windows\pthreads\include;..\..\..\..\..\lib\windows\samplerate\include;..\..\..\..\..\lib\windows\ffmpeg\include;..\..\..\..\..\lib\windows\ffmpeg\include\msvc;..\..\..\..\..\lib\windows\sdl\include;..\..\..\..\..\lib\windows\openal\include;..\..\..\..\..\lib\windows\jack\include;..\..\..\..\..\lib\windows\sndfile\include;..\..\..\..\..\lib\windows\fftw3\include"
PreprocessorDefinitions="WIN32,NDEBUG,_LIB,WITH_FFMPEG,WITH_SDL,WITH_OPENAL"
StringPooling="true"
RuntimeLibrary="0"
@@ -118,7 +118,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..;..\..\ffmpeg;..\..\FX;..\..\intern;..\..\OpenAL;..\..\SDL;..\..\SRC;..\..\sndfile;..\..\..\..\..\lib\windows\pthreads\include;..\..\..\..\..\lib\windows\samplerate\include;..\..\..\..\..\lib\windows\ffmpeg\include;..\..\..\..\..\lib\windows\ffmpeg\include\msvc;..\..\..\..\..\lib\windows\sdl\include;..\..\..\..\..\lib\windows\openal\include;..\..\..\..\..\lib\windows\jack\include;..\..\..\..\..\lib\windows\sndfile\include"
AdditionalIncludeDirectories="..\..;..\..\ffmpeg;..\..\FX;..\..\intern;..\..\OpenAL;..\..\SDL;..\..\SRC;..\..\sndfile;..\..\..\..\..\lib\windows\pthreads\include;..\..\..\..\..\lib\windows\samplerate\include;..\..\..\..\..\lib\windows\ffmpeg\include;..\..\..\..\..\lib\windows\ffmpeg\include\msvc;..\..\..\..\..\lib\windows\sdl\include;..\..\..\..\..\lib\windows\openal\include;..\..\..\..\..\lib\windows\jack\include;..\..\..\..\..\lib\windows\sndfile\include;..\..\..\..\..\lib\windows\fftw3\include"
PreprocessorDefinitions="WIN32,_DEBUG,_LIB,WITH_FFMPEG,WITH_SDL,WITH_OPENAL"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
@@ -193,7 +193,7 @@
<Tool
Name="VCCLCompilerTool"
InlineFunctionExpansion="2"
AdditionalIncludeDirectories="..\..;..\..\ffmpeg;..\..\FX;..\..\intern;..\..\OpenAL;..\..\SDL;..\..\SRC;..\..\sndfile;..\..\..\..\..\lib\windows\pthreads\include;..\..\..\..\..\lib\windows\samplerate\include;..\..\..\..\..\lib\windows\ffmpeg\include;..\..\..\..\..\lib\windows\ffmpeg\include\msvc;..\..\..\..\..\lib\windows\sdl\include;..\..\..\..\..\lib\windows\openal\include;..\..\..\..\..\lib\windows\jack\include;..\..\..\..\..\lib\windows\sndfile\include"
AdditionalIncludeDirectories="..\..;..\..\ffmpeg;..\..\FX;..\..\intern;..\..\OpenAL;..\..\SDL;..\..\SRC;..\..\sndfile;..\..\..\..\..\lib\windows\pthreads\include;..\..\..\..\..\lib\windows\samplerate\include;..\..\..\..\..\lib\windows\ffmpeg\include;..\..\..\..\..\lib\windows\ffmpeg\include\msvc;..\..\..\..\..\lib\windows\sdl\include;..\..\..\..\..\lib\windows\openal\include;..\..\..\..\..\lib\windows\jack\include;..\..\..\..\..\lib\windows\sndfile\include;..\..\..\..\..\lib\windows\fftw3\include"
PreprocessorDefinitions="WIN32,NDEBUG,_LIB,WITH_FFMPEG,WITH_SDL,WITH_OPENAL"
StringPooling="true"
RuntimeLibrary="2"
@@ -267,7 +267,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..;..\..\ffmpeg;..\..\FX;..\..\intern;..\..\OpenAL;..\..\SDL;..\..\SRC;..\..\sndfile;..\..\..\..\..\lib\windows\pthreads\include;..\..\..\..\..\lib\windows\samplerate\include;..\..\..\..\..\lib\windows\ffmpeg\include;..\..\..\..\..\lib\windows\ffmpeg\include\msvc;..\..\..\..\..\lib\windows\sdl\include;..\..\..\..\..\lib\windows\openal\include;..\..\..\..\..\lib\windows\jack\include;..\..\..\..\..\lib\windows\sndfile\include"
AdditionalIncludeDirectories="..\..;..\..\ffmpeg;..\..\FX;..\..\intern;..\..\OpenAL;..\..\SDL;..\..\SRC;..\..\sndfile;..\..\..\..\..\lib\windows\pthreads\include;..\..\..\..\..\lib\windows\samplerate\include;..\..\..\..\..\lib\windows\ffmpeg\include;..\..\..\..\..\lib\windows\ffmpeg\include\msvc;..\..\..\..\..\lib\windows\sdl\include;..\..\..\..\..\lib\windows\openal\include;..\..\..\..\..\lib\windows\jack\include;..\..\..\..\..\lib\windows\sndfile\include;..\..\..\..\..\lib\windows\fftw3\include"
PreprocessorDefinitions="WIN32,_DEBUG,_LIB,WITH_FFMPEG,WITH_SDL,WITH_OPENAL"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
@@ -629,6 +629,22 @@
RelativePath="..\..\FX\AUD_PitchReader.h"
>
</File>
<File
RelativePath="..\..\FX\AUD_RectifyFactory.cpp"
>
</File>
<File
RelativePath="..\..\FX\AUD_RectifyFactory.h"
>
</File>
<File
RelativePath="..\..\FX\AUD_RectifyReader.cpp"
>
</File>
<File
RelativePath="..\..\FX\AUD_RectifyReader.h"
>
</File>
<File
RelativePath="..\..\FX\AUD_ReverseFactory.cpp"
>
@@ -762,6 +778,26 @@
>
</File>
</Filter>
<Filter
Name="fftw"
>
<File
RelativePath="..\..\fftw\AUD_BandPassFactory.cpp"
>
</File>
<File
RelativePath="..\..\fftw\AUD_BandPassFactory.h"
>
</File>
<File
RelativePath="..\..\fftw\AUD_BandPassReader.cpp"
>
</File>
<File
RelativePath="..\..\fftw\AUD_BandPassReader.h"
>
</File>
</Filter>
</Files>
<Globals>
</Globals>

View File

@@ -35,6 +35,7 @@ include nan_compile.mk
CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
CPPFLAGS += -I$(NAN_SNDFILE)/include
CPPFLAGS += -I../intern
CPPFLAGS += -I..
CPPFLAGS += -I.

View File

@@ -283,8 +283,12 @@ sgstrf (superlu_options_t *options, SuperMatrix *A,
* -------------------------------------- */
/* Determine the union of the row structure of the snode */
if ( (*info = ssnode_dfs(jcol, kcol, asub, xa_begin, xa_end,
xprune, marker, &Glu)) != 0 )
xprune, marker, &Glu)) != 0 ) {
if ( iperm_r_allocated ) SUPERLU_FREE (iperm_r);
SUPERLU_FREE (iperm_c);
SUPERLU_FREE (relax_end);
return;
}
nextu = xusub[jcol];
nextlu = xlusup[jcol];
@@ -293,8 +297,12 @@ sgstrf (superlu_options_t *options, SuperMatrix *A,
new_next = nextlu + (xlsub[fsupc+1]-xlsub[fsupc])*(kcol-jcol+1);
nzlumax = Glu.nzlumax;
while ( new_next > nzlumax ) {
if ( (*info = sLUMemXpand(jcol, nextlu, LUSUP, &nzlumax, &Glu)) )
return;
if ( (*info = sLUMemXpand(jcol, nextlu, LUSUP, &nzlumax, &Glu)) ) {
if ( iperm_r_allocated ) SUPERLU_FREE (iperm_r);
SUPERLU_FREE (iperm_c);
SUPERLU_FREE (relax_end);
return;
}
}
for (icol = jcol; icol<= kcol; icol++) {
@@ -350,17 +358,31 @@ sgstrf (superlu_options_t *options, SuperMatrix *A,
if ((*info = scolumn_dfs(m, jj, perm_r, &nseg, &panel_lsub[k],
segrep, &repfnz[k], xprune, marker,
parent, xplore, &Glu)) != 0) return;
parent, xplore, &Glu)) != 0) {
if ( iperm_r_allocated ) SUPERLU_FREE (iperm_r);
SUPERLU_FREE (iperm_c);
SUPERLU_FREE (relax_end);
return;
}
/* Numeric updates */
if ((*info = scolumn_bmod(jj, (nseg - nseg1), &dense[k],
tempv, &segrep[nseg1], &repfnz[k],
jcol, &Glu, stat)) != 0) return;
jcol, &Glu, stat)) != 0) {
if ( iperm_r_allocated ) SUPERLU_FREE (iperm_r);
SUPERLU_FREE (iperm_c);
SUPERLU_FREE (relax_end);
return;
}
/* Copy the U-segments to ucol[*] */
if ((*info = scopy_to_ucol(jj, nseg, segrep, &repfnz[k],
perm_r, &dense[k], &Glu)) != 0)
return;
perm_r, &dense[k], &Glu)) != 0) {
if ( iperm_r_allocated ) SUPERLU_FREE (iperm_r);
SUPERLU_FREE (iperm_c);
SUPERLU_FREE (relax_end);
return;
}
if ( (*info = spivotL(jj, diag_pivot_thresh, &usepr, perm_r,
iperm_r, iperm_c, &pivrow, &Glu, stat)) )
@@ -429,5 +451,4 @@ sgstrf (superlu_options_t *options, SuperMatrix *A,
if ( iperm_r_allocated ) SUPERLU_FREE (iperm_r);
SUPERLU_FREE (iperm_c);
SUPERLU_FREE (relax_end);
}

View File

@@ -415,6 +415,10 @@
RelativePath="..\..\..\source\blender\editors\interface\interface_layout.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\editors\interface\interface_ops.c"
>
</File>
<File
RelativePath="..\..\..\source\blender\editors\interface\interface_panel.c"
>

View File

@@ -1126,23 +1126,21 @@ class Export3DS(bpy.types.Operator):
def execute(self, context):
save_3ds(self.properties.path, context)
return ('FINISHED',)
return {'FINISHED'}
def invoke(self, context, event):
wm = context.manager
wm.add_fileselect(self)
return ('RUNNING_MODAL',)
return {'RUNNING_MODAL'}
def poll(self, context): # Poll isnt working yet
return context.active_object != None
bpy.ops.add(Export3DS)
bpy.types.register(Export3DS)
# Add to a menu
import dynamic_menu
def menu_func(self, context):
default_path = bpy.data.filename.replace(".blend", ".3ds")
self.layout.operator(Export3DS.bl_idname, text="Autodesk 3DS...").path = default_path
menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_export, menu_func)
bpy.types.INFO_MT_file_export.append(menu_func)

View File

@@ -651,8 +651,8 @@ def write(filename, batch_objects = None, \
}''' % (curtime))
file.write('\nCreationTime: "%.4i-%.2i-%.2i %.2i:%.2i:%.2i:000"' % curtime)
file.write('\nCreator: "Blender3D version 2.5"')
# file.write('\nCreator: "Blender3D version %.2f"' % Blender.Get('version'))
file.write('\nCreator: "Blender3D version %s"' % bpy.version_string)
pose_items = [] # list of (fbxName, matrix) to write pose data for, easier to collect allong the way
@@ -3361,7 +3361,7 @@ class ExportFBX(bpy.types.Operator):
# to the class instance from the operator settings before calling.
path = StringProperty(name="File Path", description="File path used for exporting the FBX file", maxlen= 1024, default= "")
path = StringProperty(name="File Path", description="File path used for exporting the FBX file", maxlen= 1024, default="")
EXP_OBS_SELECTED = BoolProperty(name="Selected Objects", description="Export selected objects on visible layers", default=True)
# EXP_OBS_SCENE = BoolProperty(name="Scene Objects", description="Export all objects in this scene", default=True)
@@ -3387,7 +3387,7 @@ class ExportFBX(bpy.types.Operator):
BATCH_ENABLE = BoolProperty(name="Enable Batch", description="Automate exporting multiple scenes or groups to files", default=False)
BATCH_GROUP = BoolProperty(name="Group > File", description="Export each group as an FBX file, if false, export each scene as an FBX file", default=False)
BATCH_OWN_DIR = BoolProperty(name="Own Dir", description="Create a dir for each exported file", default=True)
BATCH_FILE_PREFIX = StringProperty(name="Prefix", description="Prefix each file with this name", maxlen= 1024, default="")
BATCH_FILE_PREFIX = StringProperty(name="Prefix", description="Prefix each file with this name", maxlen=1024, default="")
def poll(self, context):
@@ -3426,15 +3426,15 @@ class ExportFBX(bpy.types.Operator):
self.properties.BATCH_FILE_PREFIX,
self.properties.BATCH_OWN_DIR)
return ('FINISHED',)
return {'FINISHED'}
def invoke(self, context, event):
wm = context.manager
wm.add_fileselect(self)
return ('RUNNING_MODAL',)
return {'RUNNING_MODAL'}
bpy.ops.add(ExportFBX)
bpy.types.register(ExportFBX)
# if __name__ == "__main__":
# bpy.ops.EXPORT_OT_ply(filename="/tmp/test.ply")
@@ -3462,13 +3462,8 @@ bpy.ops.add(ExportFBX)
# SMALL or COSMETICAL
# - find a way to get blender version, and put it in bpy.util?, old was Blender.Get('version')
# Add to a menu
import dynamic_menu
def menu_func(self, context):
default_path = bpy.data.filename.replace(".blend", ".fbx")
self.layout.operator(ExportFBX.bl_idname, text="Autodesk FBX...").path = default_path
menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_export, menu_func)
menu_item = bpy.types.INFO_MT_file_export.append(menu_func)

View File

@@ -96,7 +96,7 @@ def write(filename, sce, ob, PREF_STARTFRAME, PREF_ENDFRAME, PREF_FPS):
numverts = len(me.verts)
numframes = PREF_ENDFRAME-PREF_STARTFRAME + 1
numframes = PREF_ENDFRAME - PREF_STARTFRAME + 1
PREF_FPS = float(PREF_FPS)
f = open(filename, 'wb') #no Errors yet:Safe to create file
@@ -104,7 +104,7 @@ def write(filename, sce, ob, PREF_STARTFRAME, PREF_ENDFRAME, PREF_FPS):
f.write(pack(">2i", numframes, numverts))
# Write the frame times (should we use the time IPO??)
f.write( pack(">%df" % (numframes), *[frame / PREF_FPS for frame in range(numframes)]) ) # seconds
f.write(pack(">%df" % (numframes), *[frame / PREF_FPS for frame in range(numframes)])) # seconds
#rest frame needed to keep frames in sync
"""
@@ -159,8 +159,8 @@ class ExportMDD(bpy.types.Operator):
# List of operator properties, the attributes will be assigned
# to the class instance from the operator settings before calling.
path = StringProperty(name="File Path", description="File path used for exporting the MDD file", maxlen= 1024, default= "")
fps = IntProperty(name="Frames Per Second", description="Number of frames/second", min=minfps, max=maxfps, default= 25)
path = StringProperty(name="File Path", description="File path used for exporting the MDD file", maxlen=1024)
fps = IntProperty(name="Frames Per Second", description="Number of frames/second", min=minfps, max=maxfps, default=25)
start_frame = IntProperty(name="Start Frame", description="Start frame for baking", min=minframe, max=maxframe, default=1)
end_frame = IntProperty(name="End Frame", description="End frame for baking", min=minframe, max=maxframe, default=250)
@@ -173,24 +173,21 @@ class ExportMDD(bpy.types.Operator):
raise Exception("filename not set")
write(self.properties.path, context.scene, context.active_object,
self.properties.start_frame, self.properties.end_frame, self.properties.fps)
return ('FINISHED',)
return {'FINISHED'}
def invoke(self, context, event):
wm = context.manager
wm.add_fileselect(self)
return ('RUNNING_MODAL',)
return {'RUNNING_MODAL'}
bpy.ops.add(ExportMDD)
# Add to a menu
import dynamic_menu
bpy.types.register(ExportMDD)
def menu_func(self, context):
default_path = bpy.data.filename.replace(".blend", ".mdd")
self.layout.operator(ExportMDD.bl_idname, text="Vertex Keyframe Animation (.mdd)...").path = default_path
menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_export, menu_func)
bpy.types.INFO_MT_file_export.append(menu_func)
if __name__ == '__main__':
bpy.ops.export.mdd(path="/tmp/test.mdd")

View File

@@ -40,29 +40,6 @@ All objects that can be represented as a mesh (mesh, curve, metaball, surface, t
will be exported as mesh data.
"""
# --------------------------------------------------------------------------
# OBJ Export v1.1 by Campbell Barton (AKA Ideasman)
# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
# import math and other in functions that use them for the sake of fast Blender startup
# import math
import os
@@ -384,8 +361,7 @@ def write(filename, objects, scene,
file = open(filename, "w")
# Write Header
version = "2.5"
file.write('# Blender3D v%s OBJ File: %s\n' % (version, bpy.data.filename.split('/')[-1].split('\\')[-1] ))
file.write('# Blender3D v%s OBJ File: %s\n' % (bpy.version_string, bpy.data.filename.split('/')[-1].split('\\')[-1] ))
file.write('# www.blender3d.org\n')
# Tell the obj file what material file to use.
@@ -444,7 +420,7 @@ def write(filename, objects, scene,
me = ob.create_mesh(EXPORT_APPLY_MODIFIERS, 'PREVIEW')
if EXPORT_ROTX90:
me.transform(ob_mat * mat_xrot90)
me.transform(mat_xrot90 * ob_mat)
else:
me.transform(ob_mat)
@@ -980,26 +956,20 @@ class ExportOBJ(bpy.types.Operator):
EXPORT_SEL_ONLY=self.properties.use_selection,
EXPORT_ALL_SCENES=self.properties.use_all_scenes)
return ('FINISHED',)
return {'FINISHED'}
def invoke(self, context, event):
wm = context.manager
wm.add_fileselect(self)
return ('RUNNING_MODAL',)
return {'RUNNING_MODAL'}
bpy.ops.add(ExportOBJ)
import dynamic_menu
bpy.types.register(ExportOBJ)
def menu_func(self, context):
default_path = bpy.data.filename.replace(".blend", ".obj")
self.layout.operator(ExportOBJ.bl_idname, text="Wavefront (.obj)...").path = default_path
menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_export, menu_func)
menu_item = bpy.types.INFO_MT_file_export.append(menu_func)
if __name__ == "__main__":
bpy.ops.EXPORT_OT_obj(filename="/tmp/test.obj")

View File

@@ -180,7 +180,7 @@ def write(filename, scene, ob, \
normal_key = rvec3d(normal)
if faceUV:
uvcoord = uv[j][0], 1.0-uv[j][1]
uvcoord = uv[j][0], 1.0 - uv[j][1]
uvcoord_key = rvec2d(uvcoord)
elif vertexUV:
uvcoord = v.uvco[0], 1.0 - v.uvco[1]
@@ -205,8 +205,7 @@ def write(filename, scene, ob, \
file.write('ply\n')
file.write('format ascii 1.0\n')
version = "2.5" # Blender.Get('version')
file.write('comment Created by Blender3D %s - www.blender.org, source file: %s\n' % (version, bpy.data.filename.split('/')[-1].split('\\')[-1]))
file.write('comment Created by Blender3D %s - www.blender.org, source file: %s\n' % (bpy.version_string, bpy.data.filename.split('/')[-1].split('\\')[-1]))
file.write('element vertex %d\n' % len(ply_verts))
@@ -246,7 +245,7 @@ def write(filename, scene, ob, \
file.write('\n')
for pf in ply_faces:
if len(pf)==3:
if len(pf) == 3:
file.write('3 %d %d %d\n' % tuple(pf))
else:
file.write('4 %d %d %d %d\n' % tuple(pf))
@@ -297,12 +296,12 @@ class ExportPLY(bpy.types.Operator):
EXPORT_COLORS=self.properties.use_colors,
)
return ('FINISHED',)
return {'FINISHED'}
def invoke(self, context, event):
wm = context.manager
wm.add_fileselect(self)
return ('RUNNING_MODAL',)
return {'RUNNING_MODAL'}
def draw(self, context):
layout = self.layout
@@ -316,16 +315,15 @@ class ExportPLY(bpy.types.Operator):
row.prop(props, "use_colors")
bpy.ops.add(ExportPLY)
import dynamic_menu
bpy.types.register(ExportPLY)
def menu_func(self, context):
default_path = bpy.data.filename.replace(".blend", ".ply")
self.layout.operator(ExportPLY.bl_idname, text="Stanford (.ply)...").path = default_path
menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_export, menu_func)
bpy.types.INFO_MT_file_export.append(menu_func)
if __name__ == "__main__":
bpy.ops.export.ply(path="/tmp/test.ply")

View File

@@ -1233,22 +1233,21 @@ class ExportX3D(bpy.types.Operator):
def execute(self, context):
x3d_export(self.properties.path, context, self.properties.apply_modifiers, self.properties.triangulate, self.properties.compress)
return ('FINISHED',)
return {'FINISHED'}
def invoke(self, context, event):
wm = context.manager
wm.add_fileselect(self)
return ('RUNNING_MODAL',)
return {'RUNNING_MODAL'}
bpy.ops.add(ExportX3D)
bpy.types.register(ExportX3D)
import dynamic_menu
def menu_func(self, context):
default_path = bpy.data.filename.replace(".blend", ".x3d")
self.layout.operator(ExportX3D.bl_idname, text="X3D Extensible 3D (.x3d)...").path = default_path
menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_export, menu_func)
bpy.types.INFO_MT_file_export.append(menu_func)
# NOTES
# - blender version is hardcoded

View File

@@ -887,17 +887,15 @@ class BvhImporter(bpy.types.Operator):
read_bvh(context, self.properties.path)
return ('FINISHED',)
return {'FINISHED'}
def invoke(self, context, event):
wm = context.manager
wm.add_fileselect(self)
return ('RUNNING_MODAL',)
return {'RUNNING_MODAL'}
bpy.ops.add(BvhImporter)
bpy.types.register(BvhImporter)
import dynamic_menu
menu_func = lambda self, context: self.layout.operator(BvhImporter.bl_idname, text="Motion Capture (.bvh)...")
menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_import, menu_func)
bpy.types.INFO_MT_file_import.append(menu_func)

View File

@@ -1151,7 +1151,7 @@ class IMPORT_OT_autodesk_3ds(bpy.types.Operator):
# List of operator properties, the attributes will be assigned
# to the class instance from the operator settings before calling.
path = StringProperty(name="File Path", description="File path used for importing the 3DS file", maxlen= 1024, default= ""),
path = StringProperty(name="File Path", description="File path used for importing the 3DS file", maxlen= 1024, default= "")
# size_constraint = FloatProperty(name="Size Constraint", description="Scale the model by 10 until it reacehs the size constraint. Zero Disables.", min=0.0, max=1000.0, soft_min=0.0, soft_max=1000.0, default=10.0),
# search_images = BoolProperty(name="Image Search", description="Search subdirectories for any assosiated images (Warning, may be slow)", default=True),
@@ -1159,19 +1159,18 @@ class IMPORT_OT_autodesk_3ds(bpy.types.Operator):
def execute(self, context):
load_3ds(self.properties.path, context, 0.0, False, False)
return ('FINISHED',)
return {'FINISHED'}
def invoke(self, context, event):
wm = context.manager
wm.add_fileselect(self)
return ('RUNNING_MODAL',)
return {'RUNNING_MODAL'}
bpy.ops.add(IMPORT_OT_autodesk_3ds)
bpy.types.register(IMPORT_OT_autodesk_3ds)
import dynamic_menu
menu_func = lambda self, context: self.layout.operator(IMPORT_OT_autodesk_3ds.bl_idname, text="3D Studio (.3ds)...")
menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_import, menu_func)
bpy.types.INFO_MT_file_import.append(menu_func)
# NOTES:
# why add 1 extra vertex? and remove it when done?
# why add 1 extra vertex? and remove it when done? - "Answer - eekadoodle - would need to re-order UV's without this since face order isnt always what we give blender, BMesh will solve :D"
# disabled scaling to size, this requires exposing bb (easy) and understanding how it works (needs some time)

View File

@@ -1616,20 +1616,19 @@ class IMPORT_OT_obj(bpy.types.Operator):
self.properties.IMAGE_SEARCH,
self.properties.POLYGROUPS)
return ('FINISHED',)
return {'FINISHED'}
def invoke(self, context, event):
wm = context.manager
wm.add_fileselect(self)
return ('RUNNING_MODAL',)
return {'RUNNING_MODAL'}
bpy.ops.add(IMPORT_OT_obj)
bpy.types.register(IMPORT_OT_obj)
import dynamic_menu
menu_func = lambda self, context: self.layout.operator(IMPORT_OT_obj.bl_idname, text="Wavefront (.obj)...")
menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_import, menu_func)
menu_item = bpy.types.INFO_MT_file_import.append(menu_func)
# NOTES (all line numbers refer to 2.4x import_obj.py, not this file)

View File

@@ -4,12 +4,12 @@
# 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.

View File

@@ -4,12 +4,12 @@
# 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.
@@ -22,129 +22,129 @@ from netrender.utils import *
import netrender.model
class RatingRule:
def rate(self, job):
return 0
def rate(self, job):
return 0
class ExclusionRule:
def test(self, job):
return False
def test(self, job):
return False
class PriorityRule:
def test(self, job):
return False
def test(self, job):
return False
class Balancer:
def __init__(self):
self.rules = []
self.priorities = []
self.exceptions = []
def addRule(self, rule):
self.rules.append(rule)
def addPriority(self, priority):
self.priorities.append(priority)
def addException(self, exception):
self.exceptions.append(exception)
def applyRules(self, job):
return sum((rule.rate(job) for rule in self.rules))
def applyPriorities(self, job):
for priority in self.priorities:
if priority.test(job):
return True # priorities are first
return False
def applyExceptions(self, job):
for exception in self.exceptions:
if exception.test(job):
return True # exceptions are last
return False
def sortKey(self, job):
return (1 if self.applyExceptions(job) else 0, # exceptions after
0 if self.applyPriorities(job) else 1, # priorities first
self.applyRules(job))
def balance(self, jobs):
if jobs:
# use inline copy to make sure the list is still accessible while sorting
jobs[:] = sorted(jobs, key=self.sortKey)
return jobs[0]
else:
return None
def __init__(self):
self.rules = []
self.priorities = []
self.exceptions = []
def addRule(self, rule):
self.rules.append(rule)
def addPriority(self, priority):
self.priorities.append(priority)
def addException(self, exception):
self.exceptions.append(exception)
def applyRules(self, job):
return sum((rule.rate(job) for rule in self.rules))
def applyPriorities(self, job):
for priority in self.priorities:
if priority.test(job):
return True # priorities are first
return False
def applyExceptions(self, job):
for exception in self.exceptions:
if exception.test(job):
return True # exceptions are last
return False
def sortKey(self, job):
return (1 if self.applyExceptions(job) else 0, # exceptions after
0 if self.applyPriorities(job) else 1, # priorities first
self.applyRules(job))
def balance(self, jobs):
if jobs:
# use inline copy to make sure the list is still accessible while sorting
jobs[:] = sorted(jobs, key=self.sortKey)
return jobs[0]
else:
return None
# ==========================
class RatingUsage(RatingRule):
def __str__(self):
return "Usage rating"
def rate(self, job):
# less usage is better
return job.usage / job.priority
def __str__(self):
return "Usage rating"
def rate(self, job):
# less usage is better
return job.usage / job.priority
class RatingUsageByCategory(RatingRule):
def __str__(self):
return "Usage per category rating"
def __init__(self, get_jobs):
self.getJobs = get_jobs
def rate(self, job):
total_category_usage = sum([j.usage for j in self.getJobs() if j.category == job.category])
maximum_priority = max([j.priority for j in self.getJobs() if j.category == job.category])
# less usage is better
return total_category_usage / maximum_priority
class NewJobPriority(PriorityRule):
def str_limit(self):
return "less than %i frame%s done" % (self.limit, "s" if self.limit > 1 else "")
def __str__(self):
return "Usage per category rating"
def __str__(self):
return "Priority to new jobs"
def __init__(self, limit = 1):
self.limit = limit
def test(self, job):
return job.countFrames(status = DONE) < self.limit
def __init__(self, get_jobs):
self.getJobs = get_jobs
def rate(self, job):
total_category_usage = sum([j.usage for j in self.getJobs() if j.category == job.category])
maximum_priority = max([j.priority for j in self.getJobs() if j.category == job.category])
# less usage is better
return total_category_usage / maximum_priority
class NewJobPriority(PriorityRule):
def str_limit(self):
return "less than %i frame%s done" % (self.limit, "s" if self.limit > 1 else "")
def __str__(self):
return "Priority to new jobs"
def __init__(self, limit = 1):
self.limit = limit
def test(self, job):
return job.countFrames(status = DONE) < self.limit
class MinimumTimeBetweenDispatchPriority(PriorityRule):
def str_limit(self):
return "more than %i minute%s since last" % (self.limit, "s" if self.limit > 1 else "")
def str_limit(self):
return "more than %i minute%s since last" % (self.limit, "s" if self.limit > 1 else "")
def __str__(self):
return "Priority to jobs that haven't been dispatched recently"
def __init__(self, limit = 10):
self.limit = limit
def test(self, job):
return job.countFrames(status = DISPATCHED) == 0 and (time.time() - job.last_dispatched) / 60 > self.limit
def __str__(self):
return "Priority to jobs that haven't been dispatched recently"
def __init__(self, limit = 10):
self.limit = limit
def test(self, job):
return job.countFrames(status = DISPATCHED) == 0 and (time.time() - job.last_dispatched) / 60 > self.limit
class ExcludeQueuedEmptyJob(ExclusionRule):
def __str__(self):
return "Exclude queued and empty jobs"
def test(self, job):
return job.status != JOB_QUEUED or job.countFrames(status = QUEUED) == 0
class ExcludeSlavesLimit(ExclusionRule):
def str_limit(self):
return "more than %.0f%% of all slaves" % (self.limit * 100)
def __str__(self):
return "Exclude queued and empty jobs"
def __str__(self):
return "Exclude jobs that would use too many slaves"
def __init__(self, count_jobs, count_slaves, limit = 0.75):
self.count_jobs = count_jobs
self.count_slaves = count_slaves
self.limit = limit
def test(self, job):
return not ( self.count_jobs() == 1 or self.count_slaves() <= 1 or float(job.countSlaves() + 1) / self.count_slaves() <= self.limit )
def test(self, job):
return job.status != JOB_QUEUED or job.countFrames(status = QUEUED) == 0
class ExcludeSlavesLimit(ExclusionRule):
def str_limit(self):
return "more than %.0f%% of all slaves" % (self.limit * 100)
def __str__(self):
return "Exclude jobs that would use too many slaves"
def __init__(self, count_jobs, count_slaves, limit = 0.75):
self.count_jobs = count_jobs
self.count_slaves = count_slaves
self.limit = limit
def test(self, job):
return not ( self.count_jobs() == 1 or self.count_slaves() <= 1 or float(job.countSlaves() + 1) / self.count_slaves() <= self.limit )

View File

@@ -4,12 +4,12 @@
# 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.
@@ -28,253 +28,253 @@ import netrender.master as master
from netrender.utils import *
def addFluidFiles(job, path):
if os.path.exists(path):
pattern = re.compile("fluidsurface_(final|preview)_([0-9]+)\.(bobj|bvel)\.gz")
if os.path.exists(path):
pattern = re.compile("fluidsurface_(final|preview)_([0-9]+)\.(bobj|bvel)\.gz")
for fluid_file in sorted(os.listdir(path)):
match = pattern.match(fluid_file)
if match:
# fluid frames starts at 0, which explains the +1
# This is stupid
current_frame = int(match.groups()[1]) + 1
job.addFile(path + fluid_file, current_frame, current_frame)
for fluid_file in sorted(os.listdir(path)):
match = pattern.match(fluid_file)
if match:
# fluid frames starts at 0, which explains the +1
# This is stupid
current_frame = int(match.groups()[1]) + 1
job.addFile(path + fluid_file, current_frame, current_frame)
def addPointCache(job, ob, point_cache, default_path):
if not point_cache.disk_cache:
return
name = point_cache.name
if name == "":
name = "".join(["%02X" % ord(c) for c in ob.name])
cache_path = bpy.utils.expandpath(point_cache.filepath) if point_cache.external else default_path
index = "%02i" % point_cache.index
if os.path.exists(cache_path):
pattern = re.compile(name + "_([0-9]+)_" + index + "\.bphys")
cache_files = []
if not point_cache.disk_cache:
return
name = point_cache.name
if name == "":
name = "".join(["%02X" % ord(c) for c in ob.name])
cache_path = bpy.utils.expandpath(point_cache.filepath) if point_cache.external else default_path
index = "%02i" % point_cache.index
if os.path.exists(cache_path):
pattern = re.compile(name + "_([0-9]+)_" + index + "\.bphys")
cache_files = []
for cache_file in sorted(os.listdir(cache_path)):
match = pattern.match(cache_file)
if match:
cache_frame = int(match.groups()[0])
cache_files.append((cache_frame, cache_file))
cache_files.sort()
if len(cache_files) == 1:
cache_frame, cache_file = cache_files[0]
job.addFile(cache_path + cache_file, cache_frame, cache_frame)
else:
for i in range(len(cache_files)):
current_item = cache_files[i]
next_item = cache_files[i+1] if i + 1 < len(cache_files) else None
previous_item = cache_files[i - 1] if i > 0 else None
current_frame, current_file = current_item
if not next_item and not previous_item:
job.addFile(cache_path + current_file, current_frame, current_frame)
elif next_item and not previous_item:
next_frame = next_item[0]
job.addFile(cache_path + current_file, current_frame, next_frame - 1)
elif not next_item and previous_item:
previous_frame = previous_item[0]
job.addFile(cache_path + current_file, previous_frame + 1, current_frame)
else:
next_frame = next_item[0]
previous_frame = previous_item[0]
job.addFile(cache_path + current_file, previous_frame + 1, next_frame - 1)
for cache_file in sorted(os.listdir(cache_path)):
match = pattern.match(cache_file)
if match:
cache_frame = int(match.groups()[0])
cache_files.append((cache_frame, cache_file))
cache_files.sort()
if len(cache_files) == 1:
cache_frame, cache_file = cache_files[0]
job.addFile(cache_path + cache_file, cache_frame, cache_frame)
else:
for i in range(len(cache_files)):
current_item = cache_files[i]
next_item = cache_files[i+1] if i + 1 < len(cache_files) else None
previous_item = cache_files[i - 1] if i > 0 else None
current_frame, current_file = current_item
if not next_item and not previous_item:
job.addFile(cache_path + current_file, current_frame, current_frame)
elif next_item and not previous_item:
next_frame = next_item[0]
job.addFile(cache_path + current_file, current_frame, next_frame - 1)
elif not next_item and previous_item:
previous_frame = previous_item[0]
job.addFile(cache_path + current_file, previous_frame + 1, current_frame)
else:
next_frame = next_item[0]
previous_frame = previous_item[0]
job.addFile(cache_path + current_file, previous_frame + 1, next_frame - 1)
def clientSendJob(conn, scene, anim = False):
netsettings = scene.network_render
job = netrender.model.RenderJob()
if anim:
for f in range(scene.start_frame, scene.end_frame + 1):
job.addFrame(f)
else:
job.addFrame(scene.current_frame)
filename = bpy.data.filename
job.addFile(filename)
job_name = netsettings.job_name
path, name = os.path.split(filename)
if job_name == "[default]":
job_name = name
###########################
# LIBRARIES
###########################
for lib in bpy.data.libraries:
job.addFile(bpy.utils.expandpath(lib.filename))
###########################
# IMAGES
###########################
for image in bpy.data.images:
if image.source == "FILE" and not image.packed_file:
job.addFile(bpy.utils.expandpath(image.filename))
###########################
# FLUID + POINT CACHE
###########################
root, ext = os.path.splitext(name)
default_path = path + os.sep + "blendcache_" + root + os.sep # need an API call for that
netsettings = scene.network_render
job = netrender.model.RenderJob()
for object in bpy.data.objects:
for modifier in object.modifiers:
if modifier.type == 'FLUID_SIMULATION' and modifier.settings.type == "DOMAIN":
addFluidFiles(job, bpy.utils.expandpath(modifier.settings.path))
elif modifier.type == "CLOTH":
addPointCache(job, object, modifier.point_cache, default_path)
elif modifier.type == "SOFT_BODY":
addPointCache(job, object, modifier.point_cache, default_path)
elif modifier.type == "SMOKE" and modifier.smoke_type == "TYPE_DOMAIN":
addPointCache(job, object, modifier.domain_settings.point_cache_low, default_path)
if modifier.domain_settings.highres:
addPointCache(job, object, modifier.domain_settings.point_cache_high, default_path)
if anim:
for f in range(scene.start_frame, scene.end_frame + 1):
job.addFrame(f)
else:
job.addFrame(scene.current_frame)
# particles modifier are stupid and don't contain data
# we have to go through the object property
for psys in object.particle_systems:
addPointCache(job, object, psys.point_cache, default_path)
#print(job.files)
job.name = job_name
job.category = netsettings.job_category
for slave in netrender.blacklist:
job.blacklist.append(slave.id)
job.chunks = netsettings.chunks
job.priority = netsettings.priority
# try to send path first
conn.request("POST", "/job", repr(job.serialize()))
response = conn.getresponse()
job_id = response.getheader("job-id")
# if not ACCEPTED (but not processed), send files
if response.status == http.client.ACCEPTED:
for rfile in job.files:
f = open(rfile.filepath, "rb")
conn.request("PUT", fileURL(job_id, rfile.index), f)
f.close()
response = conn.getresponse()
# server will reply with ACCEPTED until all files are found
return job_id
filename = bpy.data.filename
job.addFile(filename)
job_name = netsettings.job_name
path, name = os.path.split(filename)
if job_name == "[default]":
job_name = name
###########################
# LIBRARIES
###########################
for lib in bpy.data.libraries:
job.addFile(bpy.utils.expandpath(lib.filename))
###########################
# IMAGES
###########################
for image in bpy.data.images:
if image.source == "FILE" and not image.packed_file:
job.addFile(bpy.utils.expandpath(image.filename))
###########################
# FLUID + POINT CACHE
###########################
root, ext = os.path.splitext(name)
default_path = path + os.sep + "blendcache_" + root + os.sep # need an API call for that
for object in bpy.data.objects:
for modifier in object.modifiers:
if modifier.type == 'FLUID_SIMULATION' and modifier.settings.type == "DOMAIN":
addFluidFiles(job, bpy.utils.expandpath(modifier.settings.path))
elif modifier.type == "CLOTH":
addPointCache(job, object, modifier.point_cache, default_path)
elif modifier.type == "SOFT_BODY":
addPointCache(job, object, modifier.point_cache, default_path)
elif modifier.type == "SMOKE" and modifier.smoke_type == "TYPE_DOMAIN":
addPointCache(job, object, modifier.domain_settings.point_cache_low, default_path)
if modifier.domain_settings.highres:
addPointCache(job, object, modifier.domain_settings.point_cache_high, default_path)
# particles modifier are stupid and don't contain data
# we have to go through the object property
for psys in object.particle_systems:
addPointCache(job, object, psys.point_cache, default_path)
#print(job.files)
job.name = job_name
job.category = netsettings.job_category
for slave in netrender.blacklist:
job.blacklist.append(slave.id)
job.chunks = netsettings.chunks
job.priority = netsettings.priority
# try to send path first
conn.request("POST", "/job", repr(job.serialize()))
response = conn.getresponse()
job_id = response.getheader("job-id")
# if not ACCEPTED (but not processed), send files
if response.status == http.client.ACCEPTED:
for rfile in job.files:
f = open(rfile.filepath, "rb")
conn.request("PUT", fileURL(job_id, rfile.index), f)
f.close()
response = conn.getresponse()
# server will reply with ACCEPTED until all files are found
return job_id
def requestResult(conn, job_id, frame):
conn.request("GET", renderURL(job_id, frame))
conn.request("GET", renderURL(job_id, frame))
@rnaType
class NetworkRenderEngine(bpy.types.RenderEngine):
bl_idname = 'NET_RENDER'
bl_label = "Network Render"
def render(self, scene):
if scene.network_render.mode == "RENDER_CLIENT":
self.render_client(scene)
elif scene.network_render.mode == "RENDER_SLAVE":
self.render_slave(scene)
elif scene.network_render.mode == "RENDER_MASTER":
self.render_master(scene)
else:
print("UNKNOWN OPERATION MODE")
def render_master(self, scene):
netsettings = scene.network_render
address = "" if netsettings.server_address == "[default]" else netsettings.server_address
master.runMaster((address, netsettings.server_port), netsettings.server_broadcast, netsettings.path, self.update_stats, self.test_break)
bl_idname = 'NET_RENDER'
bl_label = "Network Render"
def render(self, scene):
if scene.network_render.mode == "RENDER_CLIENT":
self.render_client(scene)
elif scene.network_render.mode == "RENDER_SLAVE":
self.render_slave(scene)
elif scene.network_render.mode == "RENDER_MASTER":
self.render_master(scene)
else:
print("UNKNOWN OPERATION MODE")
def render_master(self, scene):
netsettings = scene.network_render
address = "" if netsettings.server_address == "[default]" else netsettings.server_address
master.runMaster((address, netsettings.server_port), netsettings.server_broadcast, netsettings.path, self.update_stats, self.test_break)
def render_slave(self, scene):
slave.render_slave(self, scene.network_render)
def render_client(self, scene):
netsettings = scene.network_render
self.update_stats("", "Network render client initiation")
conn = clientConnection(netsettings.server_address, netsettings.server_port)
if conn:
# Sending file
self.update_stats("", "Network render exporting")
new_job = False
job_id = netsettings.job_id
# reading back result
self.update_stats("", "Network render waiting for results")
requestResult(conn, job_id, scene.current_frame)
response = conn.getresponse()
if response.status == http.client.NO_CONTENT:
new_job = True
netsettings.job_id = clientSendJob(conn, scene)
job_id = netsettings.job_id
requestResult(conn, job_id, scene.current_frame)
response = conn.getresponse()
while response.status == http.client.ACCEPTED and not self.test_break():
time.sleep(1)
requestResult(conn, job_id, scene.current_frame)
response = conn.getresponse()
# cancel new jobs (animate on network) on break
if self.test_break() and new_job:
conn.request("POST", cancelURL(job_id))
response = conn.getresponse()
print( response.status, response.reason )
netsettings.job_id = 0
if response.status != http.client.OK:
conn.close()
return
r = scene.render_data
x= int(r.resolution_x*r.resolution_percentage*0.01)
y= int(r.resolution_y*r.resolution_percentage*0.01)
f = open(netsettings.path + "output.exr", "wb")
buf = response.read(1024)
while buf:
f.write(buf)
buf = response.read(1024)
f.close()
result = self.begin_result(0, 0, x, y)
result.load_from_file(netsettings.path + "output.exr", 0, 0)
self.end_result(result)
conn.close()
def render_slave(self, scene):
slave.render_slave(self, scene.network_render)
def render_client(self, scene):
netsettings = scene.network_render
self.update_stats("", "Network render client initiation")
conn = clientConnection(netsettings.server_address, netsettings.server_port)
if conn:
# Sending file
self.update_stats("", "Network render exporting")
new_job = False
job_id = netsettings.job_id
# reading back result
self.update_stats("", "Network render waiting for results")
requestResult(conn, job_id, scene.current_frame)
response = conn.getresponse()
if response.status == http.client.NO_CONTENT:
new_job = True
netsettings.job_id = clientSendJob(conn, scene)
job_id = netsettings.job_id
requestResult(conn, job_id, scene.current_frame)
response = conn.getresponse()
while response.status == http.client.ACCEPTED and not self.test_break():
time.sleep(1)
requestResult(conn, job_id, scene.current_frame)
response = conn.getresponse()
# cancel new jobs (animate on network) on break
if self.test_break() and new_job:
conn.request("POST", cancelURL(job_id))
response = conn.getresponse()
print( response.status, response.reason )
netsettings.job_id = 0
if response.status != http.client.OK:
conn.close()
return
r = scene.render_data
x= int(r.resolution_x*r.resolution_percentage*0.01)
y= int(r.resolution_y*r.resolution_percentage*0.01)
f = open(netsettings.path + "output.exr", "wb")
buf = response.read(1024)
while buf:
f.write(buf)
buf = response.read(1024)
f.close()
result = self.begin_result(0, 0, x, y)
result.load_from_file(netsettings.path + "output.exr", 0, 0)
self.end_result(result)
conn.close()
def compatible(module):
module = __import__(module)
for subclass in module.__dict__.values():
try: subclass.COMPAT_ENGINES.add('NET_RENDER')
except: pass
del module
module = __import__(module)
for subclass in module.__dict__.values():
try: subclass.COMPAT_ENGINES.add('NET_RENDER')
except: pass
del module
compatible("properties_render")
compatible("properties_world")

File diff suppressed because it is too large Load Diff

View File

@@ -4,12 +4,12 @@
# 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.
@@ -24,226 +24,226 @@ from netrender.utils import *
src_folder = os.path.split(__file__)[0]
def get(handler):
def output(text):
handler.wfile.write(bytes(text, encoding='utf8'))
def head(title):
output("<html><head>")
output("<script src='/html/netrender.js' type='text/javascript'></script>")
def output(text):
handler.wfile.write(bytes(text, encoding='utf8'))
def head(title):
output("<html><head>")
output("<script src='/html/netrender.js' type='text/javascript'></script>")
# output("<script src='/html/json2.js' type='text/javascript'></script>")
output("<title>")
output(title)
output("</title></head><body>")
output("<link rel='stylesheet' href='/html/netrender.css' type='text/css'>")
output("<title>")
output(title)
output("</title></head><body>")
output("<link rel='stylesheet' href='/html/netrender.css' type='text/css'>")
def link(text, url):
return "<a href='%s'>%s</a>" % (url, text)
def startTable(border=1, class_style = None, caption = None):
output("<table border='%i'" % border)
if class_style:
output(" class='%s'" % class_style)
output(">")
if caption:
output("<caption>%s</caption>" % caption)
def headerTable(*headers):
output("<thead><tr>")
for c in headers:
output("<td>" + c + "</td>")
output("</tr></thead>")
def rowTable(*data, id = None, class_style = None, extra = None):
output("<tr")
if id:
output(" id='%s'" % id)
if class_style:
output(" class='%s'" % class_style)
if extra:
output(" %s" % extra)
def link(text, url):
return "<a href='%s'>%s</a>" % (url, text)
output(">")
for c in data:
output("<td>" + str(c) + "</td>")
output("</tr>")
def endTable():
output("</table>")
if handler.path == "/html/netrender.js":
f = open(os.path.join(src_folder, "netrender.js"), 'rb')
handler.send_head(content = "text/javascript")
shutil.copyfileobj(f, handler.wfile)
f.close()
elif handler.path == "/html/netrender.css":
f = open(os.path.join(src_folder, "netrender.css"), 'rb')
handler.send_head(content = "text/css")
shutil.copyfileobj(f, handler.wfile)
f.close()
elif handler.path == "/html" or handler.path == "/":
handler.send_head(content = "text/html")
head("NetRender")
output("<h2>Master</h2>")
output("""<button title="remove all jobs" onclick="request('/clear', null);">CLEAR JOB LIST</button>""")
def startTable(border=1, class_style = None, caption = None):
output("<table border='%i'" % border)
startTable(caption = "Rules", class_style = "rules")
if class_style:
output(" class='%s'" % class_style)
headerTable("type", "description", "limit")
output(">")
for rule in handler.server.balancer.rules:
rowTable("rating", rule, rule.str_limit() if hasattr(rule, "limit") else "&nbsp;")
if caption:
output("<caption>%s</caption>" % caption)
for rule in handler.server.balancer.priorities:
rowTable("priority", rule, rule.str_limit() if hasattr(rule, "limit") else "&nbsp;")
for rule in handler.server.balancer.exceptions:
rowTable("exception", rule, rule.str_limit() if hasattr(rule, "limit") else "&nbsp;")
def headerTable(*headers):
output("<thead><tr>")
endTable()
for c in headers:
output("<td>" + c + "</td>")
output("<h2>Slaves</h2>")
startTable()
headerTable("name", "address", "last seen", "stats", "job")
for slave in handler.server.slaves:
rowTable(slave.name, slave.address[0], time.ctime(slave.last_seen), slave.stats, link(slave.job.name, "/html/job" + slave.job.id) if slave.job else "None")
endTable()
output("<h2>Jobs</h2>")
startTable()
headerTable(
"&nbsp;",
"id",
"name",
"category",
"chunks",
"priority",
"usage",
"wait",
"status",
"length",
"done",
"dispatched",
"error",
"first",
"exception"
)
output("</tr></thead>")
handler.server.balance()
for job in handler.server.jobs:
results = job.framesStatus()
rowTable(
"""<button title="cancel job" onclick="request('/cancel_%s', null);">X</button>""" % job.id +
"""<button title="reset all frames" onclick="request('/resetall_%s_0', null);">R</button>""" % job.id,
job.id,
link(job.name, "/html/job" + job.id),
job.category if job.category else "<i>None</i>",
str(job.chunks) +
"""<button title="increase priority" onclick="request('/edit_%s', &quot;{'chunks': %i}&quot;);">+</button>""" % (job.id, job.chunks + 1) +
"""<button title="decrease priority" onclick="request('/edit_%s', &quot;{'chunks': %i}&quot;);" %s>-</button>""" % (job.id, job.chunks - 1, "disabled=True" if job.chunks == 1 else ""),
str(job.priority) +
"""<button title="increase chunks size" onclick="request('/edit_%s', &quot;{'priority': %i}&quot;);">+</button>""" % (job.id, job.priority + 1) +
"""<button title="decrease chunks size" onclick="request('/edit_%s', &quot;{'priority': %i}&quot;);" %s>-</button>""" % (job.id, job.priority - 1, "disabled=True" if job.priority == 1 else ""),
"%0.1f%%" % (job.usage * 100),
"%is" % int(time.time() - job.last_dispatched),
job.statusText(),
len(job),
results[DONE],
results[DISPATCHED],
str(results[ERROR]) +
"""<button title="reset error frames" onclick="request('/reset_%s_0', null);" %s>R</button>""" % (job.id, "disabled=True" if not results[ERROR] else ""),
handler.server.balancer.applyPriorities(job), handler.server.balancer.applyExceptions(job)
)
endTable()
output("</body></html>")
elif handler.path.startswith("/html/job"):
handler.send_head(content = "text/html")
job_id = handler.path[9:]
head("NetRender")
job = handler.server.getJobID(job_id)
if job:
output("<h2>Files</h2>")
startTable()
headerTable("path")
tot_cache = 0
tot_fluid = 0
for file in job.files:
if file.filepath.endswith(".bphys"):
tot_cache += 1
elif file.filepath.endswith(".bobj.gz") or file.filepath.endswith(".bvel.gz"):
tot_fluid += 1
else:
rowTable(file.filepath)
def rowTable(*data, id = None, class_style = None, extra = None):
output("<tr")
if tot_cache > 0:
rowTable("%i physic cache files" % tot_cache, class_style = "toggle", extra = "onclick='toggleDisplay(&quot;.cache&quot;, &quot;none&quot;, &quot;table-row&quot;)'")
for file in job.files:
if file.filepath.endswith(".bphys"):
rowTable(os.path.split(file.filepath)[1], class_style = "cache")
if tot_fluid > 0:
rowTable("%i fluid bake files" % tot_fluid, class_style = "toggle", extra = "onclick='toggleDisplay(&quot;.fluid&quot;, &quot;none&quot;, &quot;table-row&quot;)'")
for file in job.files:
if file.filepath.endswith(".bobj.gz") or file.filepath.endswith(".bvel.gz"):
rowTable(os.path.split(file.filepath)[1], class_style = "fluid")
if id:
output(" id='%s'" % id)
endTable()
output("<h2>Blacklist</h2>")
if job.blacklist:
startTable()
headerTable("name", "address")
for slave_id in job.blacklist:
slave = handler.server.slaves_map[slave_id]
rowTable(slave.name, slave.address[0])
endTable()
else:
output("<i>Empty</i>")
if class_style:
output(" class='%s'" % class_style)
output("<h2>Frames</h2>")
startTable()
headerTable("no", "status", "render time", "slave", "log", "result")
for frame in job.frames:
rowTable(frame.number, frame.statusText(), "%.1fs" % frame.time, frame.slave.name if frame.slave else "&nbsp;", link("view log", logURL(job_id, frame.number)) if frame.log_path else "&nbsp;", link("view result", renderURL(job_id, frame.number)) if frame.status == DONE else "&nbsp;")
endTable()
else:
output("no such job")
output("</body></html>")
if extra:
output(" %s" % extra)
output(">")
for c in data:
output("<td>" + str(c) + "</td>")
output("</tr>")
def endTable():
output("</table>")
if handler.path == "/html/netrender.js":
f = open(os.path.join(src_folder, "netrender.js"), 'rb')
handler.send_head(content = "text/javascript")
shutil.copyfileobj(f, handler.wfile)
f.close()
elif handler.path == "/html/netrender.css":
f = open(os.path.join(src_folder, "netrender.css"), 'rb')
handler.send_head(content = "text/css")
shutil.copyfileobj(f, handler.wfile)
f.close()
elif handler.path == "/html" or handler.path == "/":
handler.send_head(content = "text/html")
head("NetRender")
output("<h2>Master</h2>")
output("""<button title="remove all jobs" onclick="request('/clear', null);">CLEAR JOB LIST</button>""")
startTable(caption = "Rules", class_style = "rules")
headerTable("type", "description", "limit")
for rule in handler.server.balancer.rules:
rowTable("rating", rule, rule.str_limit() if hasattr(rule, "limit") else "&nbsp;")
for rule in handler.server.balancer.priorities:
rowTable("priority", rule, rule.str_limit() if hasattr(rule, "limit") else "&nbsp;")
for rule in handler.server.balancer.exceptions:
rowTable("exception", rule, rule.str_limit() if hasattr(rule, "limit") else "&nbsp;")
endTable()
output("<h2>Slaves</h2>")
startTable()
headerTable("name", "address", "last seen", "stats", "job")
for slave in handler.server.slaves:
rowTable(slave.name, slave.address[0], time.ctime(slave.last_seen), slave.stats, link(slave.job.name, "/html/job" + slave.job.id) if slave.job else "None")
endTable()
output("<h2>Jobs</h2>")
startTable()
headerTable(
"&nbsp;",
"id",
"name",
"category",
"chunks",
"priority",
"usage",
"wait",
"status",
"length",
"done",
"dispatched",
"error",
"first",
"exception"
)
handler.server.balance()
for job in handler.server.jobs:
results = job.framesStatus()
rowTable(
"""<button title="cancel job" onclick="request('/cancel_%s', null);">X</button>""" % job.id +
"""<button title="reset all frames" onclick="request('/resetall_%s_0', null);">R</button>""" % job.id,
job.id,
link(job.name, "/html/job" + job.id),
job.category if job.category else "<i>None</i>",
str(job.chunks) +
"""<button title="increase priority" onclick="request('/edit_%s', &quot;{'chunks': %i}&quot;);">+</button>""" % (job.id, job.chunks + 1) +
"""<button title="decrease priority" onclick="request('/edit_%s', &quot;{'chunks': %i}&quot;);" %s>-</button>""" % (job.id, job.chunks - 1, "disabled=True" if job.chunks == 1 else ""),
str(job.priority) +
"""<button title="increase chunks size" onclick="request('/edit_%s', &quot;{'priority': %i}&quot;);">+</button>""" % (job.id, job.priority + 1) +
"""<button title="decrease chunks size" onclick="request('/edit_%s', &quot;{'priority': %i}&quot;);" %s>-</button>""" % (job.id, job.priority - 1, "disabled=True" if job.priority == 1 else ""),
"%0.1f%%" % (job.usage * 100),
"%is" % int(time.time() - job.last_dispatched),
job.statusText(),
len(job),
results[DONE],
results[DISPATCHED],
str(results[ERROR]) +
"""<button title="reset error frames" onclick="request('/reset_%s_0', null);" %s>R</button>""" % (job.id, "disabled=True" if not results[ERROR] else ""),
handler.server.balancer.applyPriorities(job), handler.server.balancer.applyExceptions(job)
)
endTable()
output("</body></html>")
elif handler.path.startswith("/html/job"):
handler.send_head(content = "text/html")
job_id = handler.path[9:]
head("NetRender")
job = handler.server.getJobID(job_id)
if job:
output("<h2>Files</h2>")
startTable()
headerTable("path")
tot_cache = 0
tot_fluid = 0
for file in job.files:
if file.filepath.endswith(".bphys"):
tot_cache += 1
elif file.filepath.endswith(".bobj.gz") or file.filepath.endswith(".bvel.gz"):
tot_fluid += 1
else:
rowTable(file.filepath)
if tot_cache > 0:
rowTable("%i physic cache files" % tot_cache, class_style = "toggle", extra = "onclick='toggleDisplay(&quot;.cache&quot;, &quot;none&quot;, &quot;table-row&quot;)'")
for file in job.files:
if file.filepath.endswith(".bphys"):
rowTable(os.path.split(file.filepath)[1], class_style = "cache")
if tot_fluid > 0:
rowTable("%i fluid bake files" % tot_fluid, class_style = "toggle", extra = "onclick='toggleDisplay(&quot;.fluid&quot;, &quot;none&quot;, &quot;table-row&quot;)'")
for file in job.files:
if file.filepath.endswith(".bobj.gz") or file.filepath.endswith(".bvel.gz"):
rowTable(os.path.split(file.filepath)[1], class_style = "fluid")
endTable()
output("<h2>Blacklist</h2>")
if job.blacklist:
startTable()
headerTable("name", "address")
for slave_id in job.blacklist:
slave = handler.server.slaves_map[slave_id]
rowTable(slave.name, slave.address[0])
endTable()
else:
output("<i>Empty</i>")
output("<h2>Frames</h2>")
startTable()
headerTable("no", "status", "render time", "slave", "log", "result")
for frame in job.frames:
rowTable(frame.number, frame.statusText(), "%.1fs" % frame.time, frame.slave.name if frame.slave else "&nbsp;", link("view log", logURL(job_id, frame.number)) if frame.log_path else "&nbsp;", link("view result", renderURL(job_id, frame.number)) if frame.status == DONE else "&nbsp;")
endTable()
else:
output("no such job")
output("</body></html>")

View File

@@ -4,12 +4,12 @@
# 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.
@@ -23,256 +23,256 @@ import subprocess, shutil, time, hashlib
from netrender.utils import *
class LogFile:
def __init__(self, job_id = 0, slave_id = 0, frames = []):
self.job_id = job_id
self.slave_id = slave_id
self.frames = frames
def serialize(self):
return {
"job_id": self.job_id,
"slave_id": self.slave_id,
"frames": self.frames
}
@staticmethod
def materialize(data):
if not data:
return None
logfile = LogFile()
logfile.job_id = data["job_id"]
logfile.slave_id = data["slave_id"]
logfile.frames = data["frames"]
return logfile
def __init__(self, job_id = 0, slave_id = 0, frames = []):
self.job_id = job_id
self.slave_id = slave_id
self.frames = frames
def serialize(self):
return {
"job_id": self.job_id,
"slave_id": self.slave_id,
"frames": self.frames
}
@staticmethod
def materialize(data):
if not data:
return None
logfile = LogFile()
logfile.job_id = data["job_id"]
logfile.slave_id = data["slave_id"]
logfile.frames = data["frames"]
return logfile
class RenderSlave:
_slave_map = {}
def __init__(self):
self.id = ""
self.name = ""
self.address = ("",0)
self.stats = ""
self.total_done = 0
self.total_error = 0
self.last_seen = 0.0
def serialize(self):
return {
"id": self.id,
"name": self.name,
"address": self.address,
"stats": self.stats,
"total_done": self.total_done,
"total_error": self.total_error,
"last_seen": self.last_seen
}
@staticmethod
def materialize(data, cache = True):
if not data:
return None
slave_id = data["id"]
_slave_map = {}
if cache and slave_id in RenderSlave._slave_map:
return RenderSlave._slave_map[slave_id]
def __init__(self):
self.id = ""
self.name = ""
self.address = ("",0)
self.stats = ""
self.total_done = 0
self.total_error = 0
self.last_seen = 0.0
slave = RenderSlave()
slave.id = slave_id
slave.name = data["name"]
slave.address = data["address"]
slave.stats = data["stats"]
slave.total_done = data["total_done"]
slave.total_error = data["total_error"]
slave.last_seen = data["last_seen"]
def serialize(self):
return {
"id": self.id,
"name": self.name,
"address": self.address,
"stats": self.stats,
"total_done": self.total_done,
"total_error": self.total_error,
"last_seen": self.last_seen
}
if cache:
RenderSlave._slave_map[slave_id] = slave
return slave
@staticmethod
def materialize(data, cache = True):
if not data:
return None
slave_id = data["id"]
if cache and slave_id in RenderSlave._slave_map:
return RenderSlave._slave_map[slave_id]
slave = RenderSlave()
slave.id = slave_id
slave.name = data["name"]
slave.address = data["address"]
slave.stats = data["stats"]
slave.total_done = data["total_done"]
slave.total_error = data["total_error"]
slave.last_seen = data["last_seen"]
if cache:
RenderSlave._slave_map[slave_id] = slave
return slave
JOB_BLENDER = 1
JOB_PROCESS = 2
JOB_TYPES = {
JOB_BLENDER: "Blender",
JOB_PROCESS: "Process"
}
JOB_BLENDER: "Blender",
JOB_PROCESS: "Process"
}
class RenderFile:
def __init__(self, filepath = "", index = 0, start = -1, end = -1):
self.filepath = filepath
self.index = index
self.start = start
self.end = end
def __init__(self, filepath = "", index = 0, start = -1, end = -1):
self.filepath = filepath
self.index = index
self.start = start
self.end = end
def serialize(self):
return {
"filepath": self.filepath,
"index": self.index,
"start": self.start,
"end": self.end
}
def serialize(self):
return {
"filepath": self.filepath,
"index": self.index,
"start": self.start,
"end": self.end
}
@staticmethod
def materialize(data):
if not data:
return None
rfile = RenderFile(data["filepath"], data["index"], data["start"], data["end"])
@staticmethod
def materialize(data):
if not data:
return None
return rfile
rfile = RenderFile(data["filepath"], data["index"], data["start"], data["end"])
return rfile
class RenderJob:
def __init__(self, job_info = None):
self.id = ""
self.type = JOB_BLENDER
self.name = ""
self.category = "None"
self.status = JOB_WAITING
self.files = []
self.chunks = 0
self.priority = 0
self.blacklist = []
def __init__(self, job_info = None):
self.id = ""
self.type = JOB_BLENDER
self.name = ""
self.category = "None"
self.status = JOB_WAITING
self.files = []
self.chunks = 0
self.priority = 0
self.blacklist = []
self.usage = 0.0
self.last_dispatched = 0.0
self.frames = []
if job_info:
self.type = job_info.type
self.name = job_info.name
self.category = job_info.category
self.status = job_info.status
self.files = job_info.files
self.chunks = job_info.chunks
self.priority = job_info.priority
self.blacklist = job_info.blacklist
def addFile(self, file_path, start=-1, end=-1):
self.files.append(RenderFile(file_path, len(self.files), start, end))
def addFrame(self, frame_number, command = ""):
frame = RenderFrame(frame_number, command)
self.frames.append(frame)
return frame
def __len__(self):
return len(self.frames)
def countFrames(self, status=QUEUED):
total = 0
for f in self.frames:
if f.status == status:
total += 1
return total
def countSlaves(self):
return len(set((frame.slave for frame in self.frames if frame.status == DISPATCHED)))
def statusText(self):
return JOB_STATUS_TEXT[self.status]
def framesStatus(self):
results = {
QUEUED: 0,
DISPATCHED: 0,
DONE: 0,
ERROR: 0
}
for frame in self.frames:
results[frame.status] += 1
return results
def __contains__(self, frame_number):
for f in self.frames:
if f.number == frame_number:
return True
else:
return False
def __getitem__(self, frame_number):
for f in self.frames:
if f.number == frame_number:
return f
else:
return None
def serialize(self, frames = None):
min_frame = min((f.number for f in frames)) if frames else -1
max_frame = max((f.number for f in frames)) if frames else -1
return {
"id": self.id,
"type": self.type,
"name": self.name,
"category": self.category,
"status": self.status,
"files": [f.serialize() for f in self.files if f.start == -1 or not frames or (f.start <= max_frame and f.end >= min_frame)],
"frames": [f.serialize() for f in self.frames if not frames or f in frames],
"chunks": self.chunks,
"priority": self.priority,
"usage": self.usage,
"blacklist": self.blacklist,
"last_dispatched": self.last_dispatched
}
self.usage = 0.0
self.last_dispatched = 0.0
self.frames = []
@staticmethod
def materialize(data):
if not data:
return None
job = RenderJob()
job.id = data["id"]
job.type = data["type"]
job.name = data["name"]
job.category = data["category"]
job.status = data["status"]
job.files = [RenderFile.materialize(f) for f in data["files"]]
job.frames = [RenderFrame.materialize(f) for f in data["frames"]]
job.chunks = data["chunks"]
job.priority = data["priority"]
job.usage = data["usage"]
job.blacklist = data["blacklist"]
job.last_dispatched = data["last_dispatched"]
if job_info:
self.type = job_info.type
self.name = job_info.name
self.category = job_info.category
self.status = job_info.status
self.files = job_info.files
self.chunks = job_info.chunks
self.priority = job_info.priority
self.blacklist = job_info.blacklist
return job
def addFile(self, file_path, start=-1, end=-1):
self.files.append(RenderFile(file_path, len(self.files), start, end))
def addFrame(self, frame_number, command = ""):
frame = RenderFrame(frame_number, command)
self.frames.append(frame)
return frame
def __len__(self):
return len(self.frames)
def countFrames(self, status=QUEUED):
total = 0
for f in self.frames:
if f.status == status:
total += 1
return total
def countSlaves(self):
return len(set((frame.slave for frame in self.frames if frame.status == DISPATCHED)))
def statusText(self):
return JOB_STATUS_TEXT[self.status]
def framesStatus(self):
results = {
QUEUED: 0,
DISPATCHED: 0,
DONE: 0,
ERROR: 0
}
for frame in self.frames:
results[frame.status] += 1
return results
def __contains__(self, frame_number):
for f in self.frames:
if f.number == frame_number:
return True
else:
return False
def __getitem__(self, frame_number):
for f in self.frames:
if f.number == frame_number:
return f
else:
return None
def serialize(self, frames = None):
min_frame = min((f.number for f in frames)) if frames else -1
max_frame = max((f.number for f in frames)) if frames else -1
return {
"id": self.id,
"type": self.type,
"name": self.name,
"category": self.category,
"status": self.status,
"files": [f.serialize() for f in self.files if f.start == -1 or not frames or (f.start <= max_frame and f.end >= min_frame)],
"frames": [f.serialize() for f in self.frames if not frames or f in frames],
"chunks": self.chunks,
"priority": self.priority,
"usage": self.usage,
"blacklist": self.blacklist,
"last_dispatched": self.last_dispatched
}
@staticmethod
def materialize(data):
if not data:
return None
job = RenderJob()
job.id = data["id"]
job.type = data["type"]
job.name = data["name"]
job.category = data["category"]
job.status = data["status"]
job.files = [RenderFile.materialize(f) for f in data["files"]]
job.frames = [RenderFrame.materialize(f) for f in data["frames"]]
job.chunks = data["chunks"]
job.priority = data["priority"]
job.usage = data["usage"]
job.blacklist = data["blacklist"]
job.last_dispatched = data["last_dispatched"]
return job
class RenderFrame:
def __init__(self, number = 0, command = ""):
self.number = number
self.time = 0
self.status = QUEUED
self.slave = None
self.command = command
def __init__(self, number = 0, command = ""):
self.number = number
self.time = 0
self.status = QUEUED
self.slave = None
self.command = command
def statusText(self):
return FRAME_STATUS_TEXT[self.status]
def statusText(self):
return FRAME_STATUS_TEXT[self.status]
def serialize(self):
return {
"number": self.number,
"time": self.time,
"status": self.status,
"slave": None if not self.slave else self.slave.serialize(),
"command": self.command
}
@staticmethod
def materialize(data):
if not data:
return None
frame = RenderFrame()
frame.number = data["number"]
frame.time = data["time"]
frame.status = data["status"]
frame.slave = RenderSlave.materialize(data["slave"])
frame.command = data["command"]
def serialize(self):
return {
"number": self.number,
"time": self.time,
"status": self.status,
"slave": None if not self.slave else self.slave.serialize(),
"command": self.command
}
return frame
@staticmethod
def materialize(data):
if not data:
return None
frame = RenderFrame()
frame.number = data["number"]
frame.time = data["time"]
frame.status = data["status"]
frame.slave = RenderSlave.materialize(data["slave"])
frame.command = data["command"]
return frame

View File

@@ -4,12 +4,12 @@
# 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.
@@ -26,413 +26,416 @@ from netrender.utils import *
import netrender.client as client
import netrender.model
@rnaOperator
@rnaType
class RENDER_OT_netslave_bake(bpy.types.Operator):
'''NEED DESCRIPTION'''
bl_idname = "render.netslavebake"
bl_label = "Bake all in file"
def poll(self, context):
return True
def execute(self, context):
scene = context.scene
netsettings = scene.network_render
filename = bpy.data.filename
path, name = os.path.split(filename)
root, ext = os.path.splitext(name)
default_path = path + os.sep + "blendcache_" + root + os.sep # need an API call for that
relative_path = os.sep + os.sep + "blendcache_" + root + os.sep
# Force all point cache next to the blend file
for object in bpy.data.objects:
for modifier in object.modifiers:
if modifier.type == 'FLUID_SIMULATION' and modifier.settings.type == "DOMAIN":
modifier.settings.path = relative_path
bpy.ops.fluid.bake({"active_object": object, "scene": scene})
elif modifier.type == "CLOTH":
modifier.point_cache.step = 1
modifier.point_cache.disk_cache = True
modifier.point_cache.external = False
elif modifier.type == "SOFT_BODY":
modifier.point_cache.step = 1
modifier.point_cache.disk_cache = True
modifier.point_cache.external = False
elif modifier.type == "SMOKE" and modifier.smoke_type == "TYPE_DOMAIN":
modifier.domain_settings.point_cache_low.step = 1
modifier.domain_settings.point_cache_low.disk_cache = True
modifier.domain_settings.point_cache_low.external = False
modifier.domain_settings.point_cache_high.step = 1
modifier.domain_settings.point_cache_high.disk_cache = True
modifier.domain_settings.point_cache_high.external = False
# particles modifier are stupid and don't contain data
# we have to go through the object property
for psys in object.particle_systems:
psys.point_cache.step = 1
psys.point_cache.disk_cache = True
psys.point_cache.external = False
psys.point_cache.filepath = relative_path
bpy.ops.ptcache.bake_all()
#bpy.ops.wm.save_mainfile(path = path + os.sep + root + "_baked.blend")
return ('FINISHED',)
def invoke(self, context, event):
return self.execute(context)
@rnaOperator
'''NEED DESCRIPTION'''
bl_idname = "render.netslavebake"
bl_label = "Bake all in file"
def poll(self, context):
return True
def execute(self, context):
scene = context.scene
netsettings = scene.network_render
filename = bpy.data.filename
path, name = os.path.split(filename)
root, ext = os.path.splitext(name)
default_path = path + os.sep + "blendcache_" + root + os.sep # need an API call for that
relative_path = os.sep + os.sep + "blendcache_" + root + os.sep
# Force all point cache next to the blend file
for object in bpy.data.objects:
for modifier in object.modifiers:
if modifier.type == 'FLUID_SIMULATION' and modifier.settings.type == "DOMAIN":
modifier.settings.path = relative_path
bpy.ops.fluid.bake({"active_object": object, "scene": scene})
elif modifier.type == "CLOTH":
modifier.point_cache.step = 1
modifier.point_cache.disk_cache = True
modifier.point_cache.external = False
elif modifier.type == "SOFT_BODY":
modifier.point_cache.step = 1
modifier.point_cache.disk_cache = True
modifier.point_cache.external = False
elif modifier.type == "SMOKE" and modifier.smoke_type == "TYPE_DOMAIN":
modifier.domain_settings.point_cache_low.step = 1
modifier.domain_settings.point_cache_low.disk_cache = True
modifier.domain_settings.point_cache_low.external = False
modifier.domain_settings.point_cache_high.step = 1
modifier.domain_settings.point_cache_high.disk_cache = True
modifier.domain_settings.point_cache_high.external = False
# particles modifier are stupid and don't contain data
# we have to go through the object property
for psys in object.particle_systems:
psys.point_cache.step = 1
psys.point_cache.disk_cache = True
psys.point_cache.external = False
psys.point_cache.filepath = relative_path
bpy.ops.ptcache.bake_all()
#bpy.ops.wm.save_mainfile(path = path + os.sep + root + "_baked.blend")
return {'FINISHED'}
def invoke(self, context, event):
return self.execute(context)
@rnaType
class RENDER_OT_netclientanim(bpy.types.Operator):
'''Start rendering an animation on network'''
bl_idname = "render.netclientanim"
bl_label = "Animation on network"
def poll(self, context):
return True
def execute(self, context):
scene = context.scene
netsettings = scene.network_render
conn = clientConnection(netsettings.server_address, netsettings.server_port, self.report)
'''Start rendering an animation on network'''
bl_idname = "render.netclientanim"
bl_label = "Animation on network"
if conn:
# Sending file
scene.network_render.job_id = client.clientSendJob(conn, scene, True)
conn.close()
bpy.ops.screen.render('INVOKE_AREA', animation=True)
return ('FINISHED',)
def invoke(self, context, event):
return self.execute(context)
def poll(self, context):
return True
@rnaOperator
def execute(self, context):
scene = context.scene
netsettings = scene.network_render
conn = clientConnection(netsettings.server_address, netsettings.server_port, self.report)
if conn:
# Sending file
scene.network_render.job_id = client.clientSendJob(conn, scene, True)
conn.close()
bpy.ops.screen.render('INVOKE_AREA', animation=True)
return {'FINISHED'}
def invoke(self, context, event):
return self.execute(context)
@rnaType
class RENDER_OT_netclientsend(bpy.types.Operator):
'''Send Render Job to the Network'''
bl_idname = "render.netclientsend"
bl_label = "Send job"
def poll(self, context):
return True
def execute(self, context):
scene = context.scene
netsettings = scene.network_render
try:
conn = clientConnection(netsettings.server_address, netsettings.server_port, self.report)
'''Send Render Job to the Network'''
bl_idname = "render.netclientsend"
bl_label = "Send job"
if conn:
# Sending file
scene.network_render.job_id = client.clientSendJob(conn, scene, True)
conn.close()
self.report('INFO', "Job sent to master")
except Exception as err:
self.report('ERROR', str(err))
return ('FINISHED',)
def invoke(self, context, event):
return self.execute(context)
def poll(self, context):
return True
@rnaOperator
def execute(self, context):
scene = context.scene
netsettings = scene.network_render
try:
conn = clientConnection(netsettings.server_address, netsettings.server_port, self.report)
if conn:
# Sending file
scene.network_render.job_id = client.clientSendJob(conn, scene, True)
conn.close()
self.report('INFO', "Job sent to master")
except Exception as err:
self.report('ERROR', str(err))
return {'FINISHED'}
def invoke(self, context, event):
return self.execute(context)
@rnaType
class RENDER_OT_netclientstatus(bpy.types.Operator):
'''Refresh the status of the current jobs'''
bl_idname = "render.netclientstatus"
bl_label = "Client Status"
def poll(self, context):
return True
def execute(self, context):
netsettings = context.scene.network_render
conn = clientConnection(netsettings.server_address, netsettings.server_port, self.report)
'''Refresh the status of the current jobs'''
bl_idname = "render.netclientstatus"
bl_label = "Client Status"
if conn:
conn.request("GET", "/status")
response = conn.getresponse()
print( response.status, response.reason )
jobs = (netrender.model.RenderJob.materialize(j) for j in eval(str(response.read(), encoding='utf8')))
while(len(netsettings.jobs) > 0):
netsettings.jobs.remove(0)
netrender.jobs = []
for j in jobs:
netrender.jobs.append(j)
netsettings.jobs.add()
job = netsettings.jobs[-1]
j.results = j.framesStatus() # cache frame status
job.name = j.name
return ('FINISHED',)
def invoke(self, context, event):
return self.execute(context)
def poll(self, context):
return True
@rnaOperator
def execute(self, context):
netsettings = context.scene.network_render
conn = clientConnection(netsettings.server_address, netsettings.server_port, self.report)
if conn:
conn.request("GET", "/status")
response = conn.getresponse()
print( response.status, response.reason )
jobs = (netrender.model.RenderJob.materialize(j) for j in eval(str(response.read(), encoding='utf8')))
while(len(netsettings.jobs) > 0):
netsettings.jobs.remove(0)
netrender.jobs = []
for j in jobs:
netrender.jobs.append(j)
netsettings.jobs.add()
job = netsettings.jobs[-1]
j.results = j.framesStatus() # cache frame status
job.name = j.name
return {'FINISHED'}
def invoke(self, context, event):
return self.execute(context)
@rnaType
class RENDER_OT_netclientblacklistslave(bpy.types.Operator):
'''Operator documentation text, will be used for the operator tooltip and python docs.'''
bl_idname = "render.netclientblacklistslave"
bl_label = "Client Blacklist Slave"
def poll(self, context):
return True
def execute(self, context):
netsettings = context.scene.network_render
if netsettings.active_slave_index >= 0:
# deal with data
slave = netrender.slaves.pop(netsettings.active_slave_index)
netrender.blacklist.append(slave)
# deal with rna
netsettings.slaves_blacklist.add()
netsettings.slaves_blacklist[-1].name = slave.name
netsettings.slaves.remove(netsettings.active_slave_index)
netsettings.active_slave_index = -1
return ('FINISHED',)
def invoke(self, context, event):
return self.execute(context)
'''Operator documentation text, will be used for the operator tooltip and python docs.'''
bl_idname = "render.netclientblacklistslave"
bl_label = "Client Blacklist Slave"
@rnaOperator
def poll(self, context):
return True
def execute(self, context):
netsettings = context.scene.network_render
if netsettings.active_slave_index >= 0:
# deal with data
slave = netrender.slaves.pop(netsettings.active_slave_index)
netrender.blacklist.append(slave)
# deal with rna
netsettings.slaves_blacklist.add()
netsettings.slaves_blacklist[-1].name = slave.name
netsettings.slaves.remove(netsettings.active_slave_index)
netsettings.active_slave_index = -1
return {'FINISHED'}
def invoke(self, context, event):
return self.execute(context)
@rnaType
class RENDER_OT_netclientwhitelistslave(bpy.types.Operator):
'''Operator documentation text, will be used for the operator tooltip and python docs.'''
bl_idname = "render.netclientwhitelistslave"
bl_label = "Client Whitelist Slave"
def poll(self, context):
return True
def execute(self, context):
netsettings = context.scene.network_render
if netsettings.active_blacklisted_slave_index >= 0:
# deal with data
slave = netrender.blacklist.pop(netsettings.active_blacklisted_slave_index)
netrender.slaves.append(slave)
# deal with rna
netsettings.slaves.add()
netsettings.slaves[-1].name = slave.name
netsettings.slaves_blacklist.remove(netsettings.active_blacklisted_slave_index)
netsettings.active_blacklisted_slave_index = -1
return ('FINISHED',)
def invoke(self, context, event):
return self.execute(context)
'''Operator documentation text, will be used for the operator tooltip and python docs.'''
bl_idname = "render.netclientwhitelistslave"
bl_label = "Client Whitelist Slave"
def poll(self, context):
return True
def execute(self, context):
netsettings = context.scene.network_render
if netsettings.active_blacklisted_slave_index >= 0:
# deal with data
slave = netrender.blacklist.pop(netsettings.active_blacklisted_slave_index)
netrender.slaves.append(slave)
# deal with rna
netsettings.slaves.add()
netsettings.slaves[-1].name = slave.name
netsettings.slaves_blacklist.remove(netsettings.active_blacklisted_slave_index)
netsettings.active_blacklisted_slave_index = -1
return {'FINISHED'}
def invoke(self, context, event):
return self.execute(context)
@rnaOperator
@rnaType
class RENDER_OT_netclientslaves(bpy.types.Operator):
'''Refresh status about available Render slaves'''
bl_idname = "render.netclientslaves"
bl_label = "Client Slaves"
def poll(self, context):
return True
def execute(self, context):
netsettings = context.scene.network_render
conn = clientConnection(netsettings.server_address, netsettings.server_port, self.report)
if conn:
conn.request("GET", "/slaves")
response = conn.getresponse()
print( response.status, response.reason )
slaves = (netrender.model.RenderSlave.materialize(s) for s in eval(str(response.read(), encoding='utf8')))
while(len(netsettings.slaves) > 0):
netsettings.slaves.remove(0)
netrender.slaves = []
for s in slaves:
for i in range(len(netrender.blacklist)):
slave = netrender.blacklist[i]
if slave.id == s.id:
netrender.blacklist[i] = s
netsettings.slaves_blacklist[i].name = s.name
break
else:
netrender.slaves.append(s)
netsettings.slaves.add()
slave = netsettings.slaves[-1]
slave.name = s.name
return ('FINISHED',)
def invoke(self, context, event):
return self.execute(context)
'''Refresh status about available Render slaves'''
bl_idname = "render.netclientslaves"
bl_label = "Client Slaves"
@rnaOperator
def poll(self, context):
return True
def execute(self, context):
netsettings = context.scene.network_render
conn = clientConnection(netsettings.server_address, netsettings.server_port, self.report)
if conn:
conn.request("GET", "/slaves")
response = conn.getresponse()
print( response.status, response.reason )
slaves = (netrender.model.RenderSlave.materialize(s) for s in eval(str(response.read(), encoding='utf8')))
while(len(netsettings.slaves) > 0):
netsettings.slaves.remove(0)
netrender.slaves = []
for s in slaves:
for i in range(len(netrender.blacklist)):
slave = netrender.blacklist[i]
if slave.id == s.id:
netrender.blacklist[i] = s
netsettings.slaves_blacklist[i].name = s.name
break
else:
netrender.slaves.append(s)
netsettings.slaves.add()
slave = netsettings.slaves[-1]
slave.name = s.name
return {'FINISHED'}
def invoke(self, context, event):
return self.execute(context)
@rnaType
class RENDER_OT_netclientcancel(bpy.types.Operator):
'''Cancel the selected network rendering job.'''
bl_idname = "render.netclientcancel"
bl_label = "Client Cancel"
def poll(self, context):
netsettings = context.scene.network_render
return netsettings.active_job_index >= 0 and len(netsettings.jobs) > 0
def execute(self, context):
netsettings = context.scene.network_render
conn = clientConnection(netsettings.server_address, netsettings.server_port, self.report)
if conn:
job = netrender.jobs[netsettings.active_job_index]
conn.request("POST", cancelURL(job.id))
response = conn.getresponse()
print( response.status, response.reason )
'''Cancel the selected network rendering job.'''
bl_idname = "render.netclientcancel"
bl_label = "Client Cancel"
netsettings.jobs.remove(netsettings.active_job_index)
return ('FINISHED',)
def invoke(self, context, event):
return self.execute(context)
@rnaOperator
def poll(self, context):
netsettings = context.scene.network_render
return netsettings.active_job_index >= 0 and len(netsettings.jobs) > 0
def execute(self, context):
netsettings = context.scene.network_render
conn = clientConnection(netsettings.server_address, netsettings.server_port, self.report)
if conn:
job = netrender.jobs[netsettings.active_job_index]
conn.request("POST", cancelURL(job.id))
response = conn.getresponse()
print( response.status, response.reason )
netsettings.jobs.remove(netsettings.active_job_index)
return {'FINISHED'}
def invoke(self, context, event):
return self.execute(context)
@rnaType
class RENDER_OT_netclientcancelall(bpy.types.Operator):
'''Cancel all running network rendering jobs.'''
bl_idname = "render.netclientcancelall"
bl_label = "Client Cancel All"
def poll(self, context):
return True
def execute(self, context):
netsettings = context.scene.network_render
conn = clientConnection(netsettings.server_address, netsettings.server_port, self.report)
if conn:
conn.request("POST", "/clear")
response = conn.getresponse()
print( response.status, response.reason )
while(len(netsettings.jobs) > 0):
netsettings.jobs.remove(0)
'''Cancel all running network rendering jobs.'''
bl_idname = "render.netclientcancelall"
bl_label = "Client Cancel All"
return ('FINISHED',)
def invoke(self, context, event):
return self.execute(context)
def poll(self, context):
return True
@rnaOperator
def execute(self, context):
netsettings = context.scene.network_render
conn = clientConnection(netsettings.server_address, netsettings.server_port, self.report)
if conn:
conn.request("POST", "/clear")
response = conn.getresponse()
print( response.status, response.reason )
while(len(netsettings.jobs) > 0):
netsettings.jobs.remove(0)
return {'FINISHED'}
def invoke(self, context, event):
return self.execute(context)
@rnaType
class netclientdownload(bpy.types.Operator):
'''Download render results from the network'''
bl_idname = "render.netclientdownload"
bl_label = "Client Download"
def poll(self, context):
netsettings = context.scene.network_render
return netsettings.active_job_index >= 0 and len(netsettings.jobs) > 0
def execute(self, context):
netsettings = context.scene.network_render
rd = context.scene.render_data
conn = clientConnection(netsettings.server_address, netsettings.server_port, self.report)
if conn:
job = netrender.jobs[netsettings.active_job_index]
for frame in job.frames:
client.requestResult(conn, job.id, frame.number)
response = conn.getresponse()
if response.status != http.client.OK:
print("missing", frame.number)
continue
print("got back", frame.number)
f = open(netsettings.path + "%06d" % frame.number + ".exr", "wb")
buf = response.read(1024)
while buf:
f.write(buf)
buf = response.read(1024)
f.close()
conn.close()
return ('FINISHED',)
def invoke(self, context, event):
return self.execute(context)
'''Download render results from the network'''
bl_idname = "render.netclientdownload"
bl_label = "Client Download"
@rnaOperator
def poll(self, context):
netsettings = context.scene.network_render
return netsettings.active_job_index >= 0 and len(netsettings.jobs) > 0
def execute(self, context):
netsettings = context.scene.network_render
rd = context.scene.render_data
conn = clientConnection(netsettings.server_address, netsettings.server_port, self.report)
if conn:
job = netrender.jobs[netsettings.active_job_index]
for frame in job.frames:
client.requestResult(conn, job.id, frame.number)
response = conn.getresponse()
if response.status != http.client.OK:
print("missing", frame.number)
continue
print("got back", frame.number)
f = open(netsettings.path + "%06d" % frame.number + ".exr", "wb")
buf = response.read(1024)
while buf:
f.write(buf)
buf = response.read(1024)
f.close()
conn.close()
return {'FINISHED'}
def invoke(self, context, event):
return self.execute(context)
@rnaType
class netclientscan(bpy.types.Operator):
'''Operator documentation text, will be used for the operator tooltip and python docs.'''
bl_idname = "render.netclientscan"
bl_label = "Client Scan"
def poll(self, context):
return True
def execute(self, context):
address, port = clientScan(self.report)
__slots__ = []
'''Operator documentation text, will be used for the operator tooltip and python docs.'''
bl_idname = "render.netclientscan"
bl_label = "Client Scan"
if address:
scene = context.scene
netsettings = scene.network_render
netsettings.server_address = address
netsettings.server_port = port
return ('FINISHED',)
def poll(self, context):
return True
def invoke(self, context, event):
return self.execute(context)
def execute(self, context):
address, port = clientScan(self.report)
@rnaOperator
if address:
scene = context.scene
netsettings = scene.network_render
netsettings.server_address = address
netsettings.server_port = port
return {'FINISHED'}
def invoke(self, context, event):
print(dir(self))
return self.execute(context)
@rnaType
class netclientweb(bpy.types.Operator):
'''Open new window with information about running rendering jobs'''
bl_idname = "render.netclientweb"
bl_label = "Open Master Monitor"
def poll(self, context):
return True
def execute(self, context):
netsettings = context.scene.network_render
# open connection to make sure server exists
conn = clientConnection(netsettings.server_address, netsettings.server_port, self.report)
if conn:
conn.close()
webbrowser.open("http://%s:%i" % (netsettings.server_address, netsettings.server_port))
return ('FINISHED',)
def invoke(self, context, event):
return self.execute(context)
'''Open new window with information about running rendering jobs'''
bl_idname = "render.netclientweb"
bl_label = "Open Master Monitor"
def poll(self, context):
netsettings = context.scene.network_render
return netsettings.server_address != "[default]"
def execute(self, context):
netsettings = context.scene.network_render
# open connection to make sure server exists
conn = clientConnection(netsettings.server_address, netsettings.server_port, self.report)
if conn:
conn.close()
webbrowser.open("http://%s:%i" % (netsettings.server_address, netsettings.server_port))
return {'FINISHED'}
def invoke(self, context, event):
return self.execute(context)

View File

@@ -4,12 +4,12 @@
# 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.
@@ -30,218 +30,218 @@ MAX_TIMEOUT = 10
INCREMENT_TIMEOUT = 1
if platform.system() == 'Windows' and platform.version() >= '5': # Error mode is only available on Win2k or higher, that's version 5
import ctypes
def SetErrorMode():
val = ctypes.windll.kernel32.SetErrorMode(0x0002)
ctypes.windll.kernel32.SetErrorMode(val | 0x0002)
return val
def RestoreErrorMode(val):
ctypes.windll.kernel32.SetErrorMode(val)
import ctypes
def SetErrorMode():
val = ctypes.windll.kernel32.SetErrorMode(0x0002)
ctypes.windll.kernel32.SetErrorMode(val | 0x0002)
return val
def RestoreErrorMode(val):
ctypes.windll.kernel32.SetErrorMode(val)
else:
def SetErrorMode():
return 0
def RestoreErrorMode(val):
pass
def SetErrorMode():
return 0
def RestoreErrorMode(val):
pass
def slave_Info():
sysname, nodename, release, version, machine, processor = platform.uname()
slave = netrender.model.RenderSlave()
slave.name = nodename
slave.stats = sysname + " " + release + " " + machine + " " + processor
return slave
sysname, nodename, release, version, machine, processor = platform.uname()
slave = netrender.model.RenderSlave()
slave.name = nodename
slave.stats = sysname + " " + release + " " + machine + " " + processor
return slave
def testCancel(conn, job_id, frame_number):
conn.request("HEAD", "/status", headers={"job-id":job_id, "job-frame": str(frame_number)})
conn.request("HEAD", "/status", headers={"job-id":job_id, "job-frame": str(frame_number)})
# cancelled if job isn't found anymore
if conn.getresponse().status == http.client.NO_CONTENT:
return True
else:
return False
# cancelled if job isn't found anymore
if conn.getresponse().status == http.client.NO_CONTENT:
return True
else:
return False
def testFile(conn, job_id, slave_id, file_index, JOB_PREFIX, file_path, main_path = None):
job_full_path = prefixPath(JOB_PREFIX, file_path, main_path)
if not os.path.exists(job_full_path):
temp_path = JOB_PREFIX + "slave.temp.blend"
conn.request("GET", fileURL(job_id, file_index), headers={"slave-id":slave_id})
response = conn.getresponse()
if response.status != http.client.OK:
return None # file for job not returned by server, need to return an error code to server
f = open(temp_path, "wb")
buf = response.read(1024)
while buf:
f.write(buf)
buf = response.read(1024)
f.close()
os.renames(temp_path, job_full_path)
return job_full_path
job_full_path = prefixPath(JOB_PREFIX, file_path, main_path)
if not os.path.exists(job_full_path):
temp_path = JOB_PREFIX + "slave.temp.blend"
conn.request("GET", fileURL(job_id, file_index), headers={"slave-id":slave_id})
response = conn.getresponse()
if response.status != http.client.OK:
return None # file for job not returned by server, need to return an error code to server
f = open(temp_path, "wb")
buf = response.read(1024)
while buf:
f.write(buf)
buf = response.read(1024)
f.close()
os.renames(temp_path, job_full_path)
return job_full_path
def render_slave(engine, netsettings):
timeout = 1
engine.update_stats("", "Network render node initiation")
conn = clientConnection(netsettings.server_address, netsettings.server_port)
if conn:
conn.request("POST", "/slave", repr(slave_Info().serialize()))
response = conn.getresponse()
slave_id = response.getheader("slave-id")
NODE_PREFIX = netsettings.path + "slave_" + slave_id + os.sep
if not os.path.exists(NODE_PREFIX):
os.mkdir(NODE_PREFIX)
while not engine.test_break():
conn.request("GET", "/job", headers={"slave-id":slave_id})
response = conn.getresponse()
if response.status == http.client.OK:
timeout = 1 # reset timeout on new job
job = netrender.model.RenderJob.materialize(eval(str(response.read(), encoding='utf8')))
JOB_PREFIX = NODE_PREFIX + "job_" + job.id + os.sep
if not os.path.exists(JOB_PREFIX):
os.mkdir(JOB_PREFIX)
if job.type == netrender.model.JOB_BLENDER:
job_path = job.files[0].filepath # path of main file
main_path, main_file = os.path.split(job_path)
job_full_path = testFile(conn, job.id, slave_id, 0, JOB_PREFIX, job_path)
print("Fullpath", job_full_path)
print("File:", main_file, "and %i other files" % (len(job.files) - 1,))
engine.update_stats("", "Render File "+ main_file+ " for job "+ job.id)
for rfile in job.files[1:]:
print("\t", rfile.filepath)
testFile(conn, job.id, slave_id, rfile.index, JOB_PREFIX, rfile.filepath, main_path)
timeout = 1
# announce log to master
logfile = netrender.model.LogFile(job.id, slave_id, [frame.number for frame in job.frames])
conn.request("POST", "/log", bytes(repr(logfile.serialize()), encoding='utf8'))
response = conn.getresponse()
first_frame = job.frames[0].number
# start render
start_t = time.time()
if job.type == netrender.model.JOB_BLENDER:
frame_args = []
for frame in job.frames:
print("frame", frame.number)
frame_args += ["-f", str(frame.number)]
val = SetErrorMode()
process = subprocess.Popen([BLENDER_PATH, "-b", "-noaudio", job_full_path, "-o", JOB_PREFIX + "######", "-E", "BLENDER_RENDER", "-F", "MULTILAYER"] + frame_args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
RestoreErrorMode(val)
elif job.type == netrender.model.JOB_PROCESS:
command = job.frames[0].command
val = SetErrorMode()
process = subprocess.Popen(command.split(" "), stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
RestoreErrorMode(val)
headers = {"slave-id":slave_id}
cancelled = False
stdout = bytes()
run_t = time.time()
while process.poll() == None and not cancelled:
stdout += process.stdout.read(32)
current_t = time.time()
cancelled = engine.test_break()
if current_t - run_t > CANCEL_POLL_SPEED:
# update logs if needed
if stdout:
# (only need to update on one frame, they are linked
conn.request("PUT", logURL(job.id, first_frame), stdout, headers=headers)
response = conn.getresponse()
stdout = bytes()
run_t = current_t
if testCancel(conn, job.id, first_frame):
cancelled = True
# read leftovers if needed
stdout += process.stdout.read()
if cancelled:
# kill process if needed
if process.poll() == None:
process.terminate()
continue # to next frame
total_t = time.time() - start_t
avg_t = total_t / len(job.frames)
status = process.returncode
print("status", status)
# flush the rest of the logs
if stdout:
# (only need to update on one frame, they are linked
conn.request("PUT", logURL(job.id, first_frame), stdout, headers=headers)
if conn.getresponse().status == http.client.NO_CONTENT:
continue
headers = {"job-id":job.id, "slave-id":slave_id, "job-time":str(avg_t)}
if status == 0: # non zero status is error
headers["job-result"] = str(DONE)
for frame in job.frames:
headers["job-frame"] = str(frame.number)
if job.type == netrender.model.JOB_BLENDER:
# send image back to server
f = open(JOB_PREFIX + "%06d" % frame.number + ".exr", 'rb')
conn.request("PUT", "/render", f, headers=headers)
f.close()
if conn.getresponse().status == http.client.NO_CONTENT:
continue
elif job.type == netrender.model.JOB_PROCESS:
conn.request("PUT", "/render", headers=headers)
if conn.getresponse().status == http.client.NO_CONTENT:
continue
else:
headers["job-result"] = str(ERROR)
for frame in job.frames:
headers["job-frame"] = str(frame.number)
# send error result back to server
conn.request("PUT", "/render", headers=headers)
if conn.getresponse().status == http.client.NO_CONTENT:
continue
else:
if timeout < MAX_TIMEOUT:
timeout += INCREMENT_TIMEOUT
for i in range(timeout):
time.sleep(1)
if engine.test_break():
conn.close()
return
conn.close()
engine.update_stats("", "Network render node initiation")
conn = clientConnection(netsettings.server_address, netsettings.server_port)
if conn:
conn.request("POST", "/slave", repr(slave_Info().serialize()))
response = conn.getresponse()
slave_id = response.getheader("slave-id")
NODE_PREFIX = netsettings.path + "slave_" + slave_id + os.sep
if not os.path.exists(NODE_PREFIX):
os.mkdir(NODE_PREFIX)
while not engine.test_break():
conn.request("GET", "/job", headers={"slave-id":slave_id})
response = conn.getresponse()
if response.status == http.client.OK:
timeout = 1 # reset timeout on new job
job = netrender.model.RenderJob.materialize(eval(str(response.read(), encoding='utf8')))
JOB_PREFIX = NODE_PREFIX + "job_" + job.id + os.sep
if not os.path.exists(JOB_PREFIX):
os.mkdir(JOB_PREFIX)
if job.type == netrender.model.JOB_BLENDER:
job_path = job.files[0].filepath # path of main file
main_path, main_file = os.path.split(job_path)
job_full_path = testFile(conn, job.id, slave_id, 0, JOB_PREFIX, job_path)
print("Fullpath", job_full_path)
print("File:", main_file, "and %i other files" % (len(job.files) - 1,))
engine.update_stats("", "Render File "+ main_file+ " for job "+ job.id)
for rfile in job.files[1:]:
print("\t", rfile.filepath)
testFile(conn, job.id, slave_id, rfile.index, JOB_PREFIX, rfile.filepath, main_path)
# announce log to master
logfile = netrender.model.LogFile(job.id, slave_id, [frame.number for frame in job.frames])
conn.request("POST", "/log", bytes(repr(logfile.serialize()), encoding='utf8'))
response = conn.getresponse()
first_frame = job.frames[0].number
# start render
start_t = time.time()
if job.type == netrender.model.JOB_BLENDER:
frame_args = []
for frame in job.frames:
print("frame", frame.number)
frame_args += ["-f", str(frame.number)]
val = SetErrorMode()
process = subprocess.Popen([BLENDER_PATH, "-b", "-noaudio", job_full_path, "-o", JOB_PREFIX + "######", "-E", "BLENDER_RENDER", "-F", "MULTILAYER"] + frame_args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
RestoreErrorMode(val)
elif job.type == netrender.model.JOB_PROCESS:
command = job.frames[0].command
val = SetErrorMode()
process = subprocess.Popen(command.split(" "), stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
RestoreErrorMode(val)
headers = {"slave-id":slave_id}
cancelled = False
stdout = bytes()
run_t = time.time()
while process.poll() == None and not cancelled:
stdout += process.stdout.read(32)
current_t = time.time()
cancelled = engine.test_break()
if current_t - run_t > CANCEL_POLL_SPEED:
# update logs if needed
if stdout:
# (only need to update on one frame, they are linked
conn.request("PUT", logURL(job.id, first_frame), stdout, headers=headers)
response = conn.getresponse()
stdout = bytes()
run_t = current_t
if testCancel(conn, job.id, first_frame):
cancelled = True
# read leftovers if needed
stdout += process.stdout.read()
if cancelled:
# kill process if needed
if process.poll() == None:
process.terminate()
continue # to next frame
total_t = time.time() - start_t
avg_t = total_t / len(job.frames)
status = process.returncode
print("status", status)
# flush the rest of the logs
if stdout:
# (only need to update on one frame, they are linked
conn.request("PUT", logURL(job.id, first_frame), stdout, headers=headers)
if conn.getresponse().status == http.client.NO_CONTENT:
continue
headers = {"job-id":job.id, "slave-id":slave_id, "job-time":str(avg_t)}
if status == 0: # non zero status is error
headers["job-result"] = str(DONE)
for frame in job.frames:
headers["job-frame"] = str(frame.number)
if job.type == netrender.model.JOB_BLENDER:
# send image back to server
f = open(JOB_PREFIX + "%06d" % frame.number + ".exr", 'rb')
conn.request("PUT", "/render", f, headers=headers)
f.close()
if conn.getresponse().status == http.client.NO_CONTENT:
continue
elif job.type == netrender.model.JOB_PROCESS:
conn.request("PUT", "/render", headers=headers)
if conn.getresponse().status == http.client.NO_CONTENT:
continue
else:
headers["job-result"] = str(ERROR)
for frame in job.frames:
headers["job-frame"] = str(frame.number)
# send error result back to server
conn.request("PUT", "/render", headers=headers)
if conn.getresponse().status == http.client.NO_CONTENT:
continue
else:
if timeout < MAX_TIMEOUT:
timeout += INCREMENT_TIMEOUT
for i in range(timeout):
time.sleep(1)
if engine.test_break():
conn.close()
return
conn.close()
if __name__ == "__main__":
pass
pass

View File

@@ -4,12 +4,12 @@
# 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.
@@ -37,318 +37,319 @@ DONE = 2
ERROR = 3
class RenderButtonsPanel(bpy.types.Panel):
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "render"
# COMPAT_ENGINES must be defined in each subclass, external engines can add themselves here
def poll(self, context):
rd = context.scene.render_data
return (rd.use_game_engine==False) and (rd.engine in self.COMPAT_ENGINES)
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "render"
# COMPAT_ENGINES must be defined in each subclass, external engines can add themselves here
def poll(self, context):
rd = context.scene.render_data
return (rd.use_game_engine==False) and (rd.engine in self.COMPAT_ENGINES)
# Setting panel, use in the scene for now.
@rnaType
class RENDER_PT_network_settings(RenderButtonsPanel):
bl_label = "Network Settings"
COMPAT_ENGINES = {'NET_RENDER'}
bl_label = "Network Settings"
COMPAT_ENGINES = {'NET_RENDER'}
def draw(self, context):
layout = self.layout
def draw(self, context):
layout = self.layout
scene = context.scene
rd = scene.render_data
layout.active = True
split = layout.split()
col = split.column()
scene = context.scene
rd = scene.render_data
if scene.network_render.mode in ("RENDER_MASTER", "RENDER_SLAVE"):
col.operator("screen.render", text="Start", icon='PLAY').animation = True
layout.active = True
col.prop(scene.network_render, "mode")
col.prop(scene.network_render, "path")
col.prop(scene.network_render, "server_address")
col.prop(scene.network_render, "server_port")
if scene.network_render.mode == "RENDER_MASTER":
col.prop(scene.network_render, "server_broadcast")
else:
col.operator("render.netclientscan", icon='FILE_REFRESH', text="")
split = layout.split()
col = split.column()
if scene.network_render.mode in ("RENDER_MASTER", "RENDER_SLAVE"):
col.operator("screen.render", text="Start", icon='PLAY').animation = True
col.prop(scene.network_render, "mode")
col.prop(scene.network_render, "path")
col.prop(scene.network_render, "server_address")
col.prop(scene.network_render, "server_port")
if scene.network_render.mode == "RENDER_MASTER":
col.prop(scene.network_render, "server_broadcast")
else:
col.operator("render.netclientscan", icon='FILE_REFRESH', text="")
col.operator("render.netclientweb", icon='QUESTION')
@rnaType
class RENDER_PT_network_job(RenderButtonsPanel):
bl_label = "Job Settings"
COMPAT_ENGINES = {'NET_RENDER'}
def poll(self, context):
scene = context.scene
return (super().poll(context)
and scene.network_render.mode == "RENDER_CLIENT")
bl_label = "Job Settings"
COMPAT_ENGINES = {'NET_RENDER'}
def draw(self, context):
layout = self.layout
def poll(self, context):
scene = context.scene
return (super().poll(context)
and scene.network_render.mode == "RENDER_CLIENT")
scene = context.scene
rd = scene.render_data
layout.active = True
split = layout.split()
col = split.column()
if scene.network_render.server_address != "[default]":
col.operator("render.netclientanim", icon='RENDER_ANIMATION')
col.operator("render.netclientsend", icon='FILE_BLEND')
if scene.network_render.job_id:
col.operator("screen.render", text="Get Results", icon='RENDER_ANIMATION').animation = True
col.operator("render.netclientweb", icon='QUESTION')
col.prop(scene.network_render, "job_name")
col.prop(scene.network_render, "job_category")
row = col.row()
row.prop(scene.network_render, "priority")
row.prop(scene.network_render, "chunks")
def draw(self, context):
layout = self.layout
scene = context.scene
rd = scene.render_data
layout.active = True
split = layout.split()
col = split.column()
if scene.network_render.server_address != "[default]":
col.operator("render.netclientanim", icon='RENDER_ANIMATION')
col.operator("render.netclientsend", icon='FILE_BLEND')
if scene.network_render.job_id:
col.operator("screen.render", text="Get Results", icon='RENDER_ANIMATION').animation = True
col.prop(scene.network_render, "job_name")
col.prop(scene.network_render, "job_category")
row = col.row()
row.prop(scene.network_render, "priority")
row.prop(scene.network_render, "chunks")
@rnaType
class RENDER_PT_network_slaves(RenderButtonsPanel):
bl_label = "Slaves Status"
COMPAT_ENGINES = {'NET_RENDER'}
def poll(self, context):
scene = context.scene
return (super().poll(context)
and scene.network_render.mode == "RENDER_CLIENT"
and scene.network_render.server_address != "[default]")
bl_label = "Slaves Status"
COMPAT_ENGINES = {'NET_RENDER'}
def draw(self, context):
layout = self.layout
scene = context.scene
netsettings = scene.network_render
def poll(self, context):
scene = context.scene
return (super().poll(context)
and scene.network_render.mode == "RENDER_CLIENT"
and scene.network_render.server_address != "[default]")
row = layout.row()
row.template_list(netsettings, "slaves", netsettings, "active_slave_index", rows=2)
def draw(self, context):
layout = self.layout
sub = row.column(align=True)
sub.operator("render.netclientslaves", icon='FILE_REFRESH', text="")
sub.operator("render.netclientblacklistslave", icon='ZOOMOUT', text="")
if len(netrender.slaves) == 0 and len(netsettings.slaves) > 0:
while(len(netsettings.slaves) > 0):
netsettings.slaves.remove(0)
if netsettings.active_slave_index >= 0 and len(netsettings.slaves) > 0:
layout.separator()
slave = netrender.slaves[netsettings.active_slave_index]
scene = context.scene
netsettings = scene.network_render
layout.label(text="Name: " + slave.name)
layout.label(text="Address: " + slave.address[0])
layout.label(text="Seen: " + time.ctime(slave.last_seen))
layout.label(text="Stats: " + slave.stats)
row = layout.row()
row.template_list(netsettings, "slaves", netsettings, "active_slave_index", rows=2)
sub = row.column(align=True)
sub.operator("render.netclientslaves", icon='FILE_REFRESH', text="")
sub.operator("render.netclientblacklistslave", icon='ZOOMOUT', text="")
if len(netrender.slaves) == 0 and len(netsettings.slaves) > 0:
while(len(netsettings.slaves) > 0):
netsettings.slaves.remove(0)
if netsettings.active_slave_index >= 0 and len(netsettings.slaves) > 0:
layout.separator()
slave = netrender.slaves[netsettings.active_slave_index]
layout.label(text="Name: " + slave.name)
layout.label(text="Address: " + slave.address[0])
layout.label(text="Seen: " + time.ctime(slave.last_seen))
layout.label(text="Stats: " + slave.stats)
@rnaType
class RENDER_PT_network_slaves_blacklist(RenderButtonsPanel):
bl_label = "Slaves Blacklist"
COMPAT_ENGINES = {'NET_RENDER'}
def poll(self, context):
scene = context.scene
return (super().poll(context)
and scene.network_render.mode == "RENDER_CLIENT"
and scene.network_render.server_address != "[default]")
def draw(self, context):
layout = self.layout
scene = context.scene
netsettings = scene.network_render
bl_label = "Slaves Blacklist"
COMPAT_ENGINES = {'NET_RENDER'}
row = layout.row()
row.template_list(netsettings, "slaves_blacklist", netsettings, "active_blacklisted_slave_index", rows=2)
def poll(self, context):
scene = context.scene
return (super().poll(context)
and scene.network_render.mode == "RENDER_CLIENT"
and scene.network_render.server_address != "[default]")
sub = row.column(align=True)
sub.operator("render.netclientwhitelistslave", icon='ZOOMOUT', text="")
def draw(self, context):
layout = self.layout
if len(netrender.blacklist) == 0 and len(netsettings.slaves_blacklist) > 0:
while(len(netsettings.slaves_blacklist) > 0):
netsettings.slaves_blacklist.remove(0)
if netsettings.active_blacklisted_slave_index >= 0 and len(netsettings.slaves_blacklist) > 0:
layout.separator()
slave = netrender.blacklist[netsettings.active_blacklisted_slave_index]
scene = context.scene
netsettings = scene.network_render
layout.label(text="Name: " + slave.name)
layout.label(text="Address: " + slave.address[0])
layout.label(text="Seen: " + time.ctime(slave.last_seen))
layout.label(text="Stats: " + slave.stats)
row = layout.row()
row.template_list(netsettings, "slaves_blacklist", netsettings, "active_blacklisted_slave_index", rows=2)
sub = row.column(align=True)
sub.operator("render.netclientwhitelistslave", icon='ZOOMOUT', text="")
if len(netrender.blacklist) == 0 and len(netsettings.slaves_blacklist) > 0:
while(len(netsettings.slaves_blacklist) > 0):
netsettings.slaves_blacklist.remove(0)
if netsettings.active_blacklisted_slave_index >= 0 and len(netsettings.slaves_blacklist) > 0:
layout.separator()
slave = netrender.blacklist[netsettings.active_blacklisted_slave_index]
layout.label(text="Name: " + slave.name)
layout.label(text="Address: " + slave.address[0])
layout.label(text="Seen: " + time.ctime(slave.last_seen))
layout.label(text="Stats: " + slave.stats)
@rnaType
class RENDER_PT_network_jobs(RenderButtonsPanel):
bl_label = "Jobs"
COMPAT_ENGINES = {'NET_RENDER'}
def poll(self, context):
scene = context.scene
return (super().poll(context)
and scene.network_render.mode == "RENDER_CLIENT"
and scene.network_render.server_address != "[default]")
def draw(self, context):
layout = self.layout
scene = context.scene
netsettings = scene.network_render
bl_label = "Jobs"
COMPAT_ENGINES = {'NET_RENDER'}
row = layout.row()
row.template_list(netsettings, "jobs", netsettings, "active_job_index", rows=2)
def poll(self, context):
scene = context.scene
return (super().poll(context)
and scene.network_render.mode == "RENDER_CLIENT"
and scene.network_render.server_address != "[default]")
sub = row.column(align=True)
sub.operator("render.netclientstatus", icon='FILE_REFRESH', text="")
sub.operator("render.netclientcancel", icon='ZOOMOUT', text="")
sub.operator("render.netclientcancelall", icon='PANEL_CLOSE', text="")
sub.operator("render.netclientdownload", icon='RENDER_ANIMATION', text="")
def draw(self, context):
layout = self.layout
if len(netrender.jobs) == 0 and len(netsettings.jobs) > 0:
while(len(netsettings.jobs) > 0):
netsettings.jobs.remove(0)
if netsettings.active_job_index >= 0 and len(netsettings.jobs) > 0:
layout.separator()
job = netrender.jobs[netsettings.active_job_index]
scene = context.scene
netsettings = scene.network_render
layout.label(text="Name: %s" % job.name)
layout.label(text="Length: %04i" % len(job))
layout.label(text="Done: %04i" % job.results[DONE])
layout.label(text="Error: %04i" % job.results[ERROR])
row = layout.row()
row.template_list(netsettings, "jobs", netsettings, "active_job_index", rows=2)
sub = row.column(align=True)
sub.operator("render.netclientstatus", icon='FILE_REFRESH', text="")
sub.operator("render.netclientcancel", icon='ZOOMOUT', text="")
sub.operator("render.netclientcancelall", icon='PANEL_CLOSE', text="")
sub.operator("render.netclientdownload", icon='RENDER_ANIMATION', text="")
if len(netrender.jobs) == 0 and len(netsettings.jobs) > 0:
while(len(netsettings.jobs) > 0):
netsettings.jobs.remove(0)
if netsettings.active_job_index >= 0 and len(netsettings.jobs) > 0:
layout.separator()
job = netrender.jobs[netsettings.active_job_index]
layout.label(text="Name: %s" % job.name)
layout.label(text="Length: %04i" % len(job))
layout.label(text="Done: %04i" % job.results[DONE])
layout.label(text="Error: %04i" % job.results[ERROR])
@rnaType
class NetRenderSettings(bpy.types.IDPropertyGroup):
pass
pass
@rnaType
class NetRenderSlave(bpy.types.IDPropertyGroup):
pass
pass
@rnaType
class NetRenderJob(bpy.types.IDPropertyGroup):
pass
pass
bpy.types.Scene.PointerProperty(attr="network_render", type=NetRenderSettings, name="Network Render", description="Network Render Settings")
NetRenderSettings.StringProperty( attr="server_address",
name="Server address",
description="IP or name of the master render server",
maxlen = 128,
default = "[default]")
name="Server address",
description="IP or name of the master render server",
maxlen = 128,
default = "[default]")
NetRenderSettings.IntProperty( attr="server_port",
name="Server port",
description="port of the master render server",
default = 8000,
min=1,
max=65535)
name="Server port",
description="port of the master render server",
default = 8000,
min=1,
max=65535)
NetRenderSettings.BoolProperty( attr="server_broadcast",
name="Broadcast server address",
description="broadcast server address on local network",
default = True)
name="Broadcast server address",
description="broadcast server address on local network",
default = True)
default_path = os.environ.get("TEMP", None)
if not default_path:
if os.name == 'nt':
default_path = "c:/tmp/"
else:
default_path = "/tmp/"
if os.name == 'nt':
default_path = "c:/tmp/"
else:
default_path = "/tmp/"
elif not default_path.endswith(os.sep):
default_path += os.sep
default_path += os.sep
NetRenderSettings.StringProperty( attr="path",
name="Path",
description="Path for temporary files",
maxlen = 128,
default = default_path)
name="Path",
description="Path for temporary files",
maxlen = 128,
default = default_path)
NetRenderSettings.StringProperty( attr="job_name",
name="Job name",
description="Name of the job",
maxlen = 128,
default = "[default]")
name="Job name",
description="Name of the job",
maxlen = 128,
default = "[default]")
NetRenderSettings.StringProperty( attr="job_category",
name="Job category",
description="Category of the job",
maxlen = 128,
default = "")
name="Job category",
description="Category of the job",
maxlen = 128,
default = "")
NetRenderSettings.IntProperty( attr="chunks",
name="Chunks",
description="Number of frame to dispatch to each slave in one chunk",
default = 5,
min=1,
max=65535)
name="Chunks",
description="Number of frame to dispatch to each slave in one chunk",
default = 5,
min=1,
max=65535)
NetRenderSettings.IntProperty( attr="priority",
name="Priority",
description="Priority of the job",
default = 1,
min=1,
max=10)
name="Priority",
description="Priority of the job",
default = 1,
min=1,
max=10)
NetRenderSettings.StringProperty( attr="job_id",
name="Network job id",
description="id of the last sent render job",
maxlen = 64,
default = "")
name="Network job id",
description="id of the last sent render job",
maxlen = 64,
default = "")
NetRenderSettings.IntProperty( attr="active_slave_index",
name="Index of the active slave",
description="",
default = -1,
min= -1,
max=65535)
name="Index of the active slave",
description="",
default = -1,
min= -1,
max=65535)
NetRenderSettings.IntProperty( attr="active_blacklisted_slave_index",
name="Index of the active slave",
description="",
default = -1,
min= -1,
max=65535)
name="Index of the active slave",
description="",
default = -1,
min= -1,
max=65535)
NetRenderSettings.IntProperty( attr="active_job_index",
name="Index of the active job",
description="",
default = -1,
min= -1,
max=65535)
name="Index of the active job",
description="",
default = -1,
min= -1,
max=65535)
NetRenderSettings.EnumProperty(attr="mode",
items=(
("RENDER_CLIENT", "Client", "Act as render client"),
("RENDER_MASTER", "Master", "Act as render master"),
("RENDER_SLAVE", "Slave", "Act as render slave"),
),
name="Network mode",
description="Mode of operation of this instance",
default="RENDER_CLIENT")
items=(
("RENDER_CLIENT", "Client", "Act as render client"),
("RENDER_MASTER", "Master", "Act as render master"),
("RENDER_SLAVE", "Slave", "Act as render slave"),
),
name="Network mode",
description="Mode of operation of this instance",
default="RENDER_CLIENT")
NetRenderSettings.CollectionProperty(attr="slaves", type=NetRenderSlave, name="Slaves", description="")
NetRenderSettings.CollectionProperty(attr="slaves_blacklist", type=NetRenderSlave, name="Slaves Blacklist", description="")
NetRenderSettings.CollectionProperty(attr="jobs", type=NetRenderJob, name="Job List", description="")
NetRenderSlave.StringProperty( attr="name",
name="Name of the slave",
description="",
maxlen = 64,
default = "")
name="Name of the slave",
description="",
maxlen = 64,
default = "")
NetRenderJob.StringProperty( attr="name",
name="Name of the job",
description="",
maxlen = 128,
default = "")
name="Name of the job",
description="",
maxlen = 128,
default = "")

View File

@@ -4,12 +4,12 @@
# 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.
@@ -51,26 +51,22 @@ DONE = 2
ERROR = 3
FRAME_STATUS_TEXT = {
QUEUED: "Queued",
DISPATCHED: "Dispatched",
DONE: "Done",
ERROR: "Error"
}
QUEUED: "Queued",
DISPATCHED: "Dispatched",
DONE: "Done",
ERROR: "Error"
}
def rnaType(rna_type):
if bpy: bpy.types.register(rna_type)
return rna_type
def rnaOperator(rna_op):
if bpy: bpy.ops.add(rna_op)
return rna_op
if bpy: bpy.types.register(rna_type)
return rna_type
def reporting(report, message, errorType = None):
if errorType:
t = 'ERROR'
else:
t = 'INFO'
if report:
report(t, message)
return None
@@ -86,14 +82,14 @@ def clientScan(report = None):
s.settimeout(30)
s.bind(('', 8000))
buf, address = s.recvfrom(64)
address = address[0]
port = int(str(buf, encoding='utf8'))
reporting(report, "Master server found")
return (address, port)
except socket.timeout:
reporting(report, "No master server on network", IOError)
@@ -109,10 +105,10 @@ def clientConnection(address, port, report = None):
address, port = clientScan()
if address == "":
return None
try:
try:
conn = http.client.HTTPConnection(address, port)
if conn:
if clientVerifyVersion(conn):
return conn
@@ -127,21 +123,21 @@ def clientConnection(address, port, report = None):
raise
def clientVerifyVersion(conn):
conn.request("GET", "/version")
response = conn.getresponse()
if response.status != http.client.OK:
conn.close()
return False
server_version = response.read()
if server_version != VERSION:
print("Incorrect server version!")
print("expected", str(VERSION, encoding='utf8'), "received", str(server_version, encoding='utf8'))
return False
return True
conn.request("GET", "/version")
response = conn.getresponse()
if response.status != http.client.OK:
conn.close()
return False
server_version = response.read()
if server_version != VERSION:
print("Incorrect server version!")
print("expected", str(VERSION, encoding='utf8'), "received", str(server_version, encoding='utf8'))
return False
return True
def fileURL(job_id, file_index):
return "/file_%s_%i" % (job_id, file_index)
@@ -156,20 +152,20 @@ def cancelURL(job_id):
return "/cancel_%s" % (job_id)
def prefixPath(prefix_directory, file_path, prefix_path):
if os.path.isabs(file_path):
# if an absolute path, make sure path exists, if it doesn't, use relative local path
full_path = file_path
if not os.path.exists(full_path):
p, n = os.path.split(full_path)
if prefix_path and p.startswith(prefix_path):
directory = prefix_directory + p[len(prefix_path):]
full_path = directory + os.sep + n
if not os.path.exists(directory):
os.mkdir(directory)
else:
full_path = prefix_directory + n
else:
full_path = prefix_directory + file_path
return full_path
if os.path.isabs(file_path):
# if an absolute path, make sure path exists, if it doesn't, use relative local path
full_path = file_path
if not os.path.exists(full_path):
p, n = os.path.split(full_path)
if prefix_path and p.startswith(prefix_path):
directory = prefix_directory + p[len(prefix_path):]
full_path = directory + os.sep + n
if not os.path.exists(directory):
os.mkdir(directory)
else:
full_path = prefix_directory + n
else:
full_path = prefix_directory + file_path
return full_path

View File

@@ -85,7 +85,6 @@ def _main():
# a bit nasty but this prevents help() and input() from locking blender
# Ideally we could have some way for the console to replace sys.stdin but
# python would lock blender while waiting for a return value, not easy :|
import sys
sys.stdin = None
# if "-d" in sys.argv: # Enable this to measure startup speed
@@ -100,4 +99,10 @@ def _main():
else:
load_scripts()
# constants
version = _bpy._VERSION
version_string = _bpy._VERSION_STR
home = _bpy._HOME
_main()

View File

@@ -21,7 +21,7 @@
# for slightly faster access
from _bpy import ops as ops_module
op_add = ops_module.add
# op_add = ops_module.add
op_remove = ops_module.remove
op_add_macro = ops_module.add_macro
op_dir = ops_module.dir

View File

@@ -42,25 +42,27 @@ class Object(bpy_types.ID):
@property
def children(self):
"""All the children of this object"""
import bpy
return [child for child in bpy.data.objects if child.parent == self]
class _GenericBone:
'''
"""
functions for bones, common between Armature/Pose/Edit bones.
internal subclassing use only.
'''
"""
__slots__ = ()
def translate(self, vec):
"""Utility function to add *vec* to the head and tail of this bone."""
self.head += vec
self.tail += vec
def parent_index(self, parent_test):
'''
"""
The same as 'bone in other_bone.parent_recursive' but saved generating a list.
'''
"""
# use the name so different types can be tested.
name = parent_test.name
@@ -76,11 +78,13 @@ class _GenericBone:
@property
def basename(self):
"""The name of this bone before any '.' character"""
#return self.name.rsplit(".", 1)[0]
return self.name.split(".")[0]
@property
def parent_recursive(self):
"""A list of parents, starting with the immediate parent"""
parent_list = []
parent = self.parent
@@ -94,23 +98,26 @@ class _GenericBone:
@property
def length(self):
"""The distance from head to tail, when set the head is moved to fit the length."""
return self.vector.length
@length.setter
def length(self, value):
"""The distance from head to tail"""
self.tail = self.head + ((self.tail - self.head).normalize() * value)
@property
def vector(self):
"""The direction this bone is pointing. Utility function for (tail - head)"""
return (self.tail - self.head)
@property
def children(self):
"""A list of all the bones children."""
return [child for child in self._other_bones if child.parent == self]
@property
def children_recursive(self):
"""a list of all children from this bone."""
bones_children = []
for bone in self._other_bones:
index = bone.parent_index(self)
@@ -123,10 +130,11 @@ class _GenericBone:
@property
def children_recursive_basename(self):
'''
"""
Returns a chain of children with the same base name as this bone
Only direct chains are supported, forks caused by multiple children with matching basenames will.
'''
Only direct chains are supported, forks caused by multiple children with matching basenames will
terminate the function and not be returned.
"""
basename = self.basename
chain = []
@@ -177,10 +185,10 @@ class EditBone(StructRNA, _GenericBone):
__slots__ = ()
def align_orientation(self, other):
'''
"""
Align this bone to another by moving its tail and settings its roll
the length of the other bone is not used.
'''
"""
vec = other.vector.normalize() * self.length
self.tail = self.head + vec
self.roll = other.roll
@@ -196,10 +204,10 @@ class Mesh(bpy_types.ID):
__slots__ = ()
def from_pydata(self, verts, edges, faces):
'''
"""
Make a mesh from a list of verts/edges/faces
Until we have a nicer way to make geometry, use this.
'''
"""
self.add_geometry(len(verts), len(edges), len(faces))
verts_flat = [f for v in verts for f in v]
@@ -244,7 +252,7 @@ class Mesh(bpy_types.ID):
return [edge_face_count_dict.get(ed.key, 0) for ed in mesh.edges]
def edge_loops(self, faces=None, seams=()):
'''
"""
Edge loops defined by faces
Takes me.faces or a list of faces and returns the edge loops
@@ -255,12 +263,12 @@ class Mesh(bpy_types.ID):
[ [(0,1), (4, 8), (3,8)], ...]
optionaly, seams are edge keys that will be removed
'''
"""
OTHER_INDEX = 2,3,0,1 # opposite face index
OTHER_INDEX = 2, 3, 0, 1 # opposite face index
if faces is None:
faces= self.faces
faces = self.faces
edges = {}
@@ -278,7 +286,7 @@ class Mesh(bpy_types.ID):
edge_loops = []
for edkey, ed_adj in edges.items():
if 0 <len(ed_adj) < 3: # 1 or 2
if 0 < len(ed_adj) < 3: # 1 or 2
# Seek the first edge
context_loop = [edkey, ed_adj[0]]
edge_loops.append(context_loop)
@@ -296,7 +304,7 @@ class Mesh(bpy_types.ID):
ed_adj = edges[context_loop[-1]]
if len(ed_adj) != 2:
if other_dir and flipped==False: # the original edge had 2 other edges
if other_dir and flipped == False: # the original edge had 2 other edges
flipped = True # only flip the list once
context_loop.reverse()
ed_adj[:] = []
@@ -311,7 +319,7 @@ class Mesh(bpy_types.ID):
break
i = ed_adj.index(context_loop[-2])
context_loop.append( ed_adj[ not i] )
context_loop.append(ed_adj[not i])
# Dont look at this again
ed_adj[:] = []
@@ -372,6 +380,33 @@ class Macro(StructRNA, metaclass=OrderedMeta):
class Menu(StructRNA):
__slots__ = ()
@classmethod
def _dyn_menu_initialize(cls):
draw_funcs = getattr(cls.draw, "_draw_funcs", None)
if draw_funcs is None:
def draw_ls(*args):
for func in draw_ls._draw_funcs:
func(*args)
draw_funcs = draw_ls._draw_funcs = [cls.draw]
cls.draw = draw_ls
return draw_funcs
@classmethod
def append(cls, draw_func):
"""Prepend an draw function to this menu, takes the same arguments as the menus draw function."""
draw_funcs = cls._dyn_menu_initialize()
draw_funcs.append(draw_func)
@classmethod
def prepend(cls, draw_func):
"""Prepend a draw function to this menu, takes the same arguments as the menus draw function."""
draw_funcs = cls._dyn_menu_initialize()
draw_funcs.insert(0, draw_func)
def path_menu(self, searchpaths, operator):
layout = self.layout
# hard coded to set the operators 'path' to the filename.
@@ -396,9 +431,9 @@ class Menu(StructRNA):
layout.operator(operator, text=bpy.utils.display_name(f)).path = path
def draw_preset(self, context):
'''Define these on the subclass
"""Define these on the subclass
- preset_operator
- preset_subdir
'''
"""
import bpy
self.path_menu(bpy.utils.preset_paths(self.preset_subdir), self.preset_operator)

View File

@@ -1,118 +0,0 @@
# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
import bpy
def collect_baseclasses(_class, bases):
if _class is type or _class is object:
return bases
bases.append(_class)
for _superclass in _class.__bases__:
collect_baseclasses(_superclass, bases)
return bases
def collect_subclasses(_class, subs):
if _class is type or _class is object:
return subs
subs.append(_class)
for _subclass in _class.__subclasses__():
collect_subclasses(_subclass, subs)
return subs
class DynMenu(bpy.types.Menu):
def draw(self, context):
'''
This is a draw function that is used to call all subclasses draw functions
starting from the registered classes draw function and working down.
DynMenu.setup() must be called first.
Sort/group classes could be nice
'''
subclass_ls = []
collect_subclasses(self.__class__, subclass_ls)
# print(subclass_ls)
for subclass in subclass_ls:
# print("drawwing", subclass) # , dir(subclass))
subclass.internal_draw(self, context)
# print("subclass.internal_draw", subclass.internal_draw)
def setup(menu_class):
'''
Setup subclasses (not needed when self.add() is used)
'''
bases = collect_baseclasses(menu_class, [])
# Incase 'DynMenu' isnt last
while bases[-1] is not DynMenu:
bases.pop()
bases.pop() # remove 'DynMenu'
root_class = bases[-1] # this is the registered class
for subclass in collect_subclasses(root_class, []):
#print(subclass)
draw = getattr(subclass, 'draw', None)
if draw and not hasattr(subclass, 'internal_draw'):
# print("replace", subclass, draw)
try:
del subclass.draw
except:
pass
subclass.internal_draw = draw
root_class.draw = DynMenu.draw
def add(menu_class, func):
'''
Add a single function directly without having to make a class
important that the returned value should be stored in the module that called it.
'''
newclass = type('<menuclass>', (menu_class,), {})
newclass.internal_draw = func
setup(menu_class)
return newclass
'''
# so we dont need to import this module
DynMenu.setup = setup
DynMenu.add = add
# Only so we can access as bpy.types.
# dont ever use this directly!
bpy.types.register(DynMenu)
'''

View File

@@ -19,9 +19,8 @@
# <pep8 compliant>
import bpy
from rigify import RigifyError, get_layer_dict
from rigify_utils import bone_class_instance, copy_bone_simple, blend_bone_list, get_side_name, get_base_name, add_pole_target_bone
from rna_prop_ui import rna_idprop_ui_prop_get
from rigify import RigifyError
from rigify_utils import bone_class_instance, copy_bone_simple, add_pole_target_bone
from Mathutils import Vector
METARIG_NAMES = "hips", "thigh", "shin", "foot", "toe"

View File

@@ -90,6 +90,7 @@ def metarig_template():
pbone = obj.pose.bones['rib_cage']
pbone['type'] = 'spine_pivot_flex'
def metarig_definition(obj, orig_bone_name):
'''
The bone given is the second in a chain.

View File

@@ -16,13 +16,37 @@
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
# classes for extracting info from blenders internal classes
import bpy
# use to strip python paths
script_paths = bpy.utils.script_paths()
def range_str(val):
if val < -10000000:
return '-inf'
elif val > 10000000:
return 'inf'
elif type(val) == float:
return '%g' % val
else:
return str(val)
def float_as_string(f):
val_str = "%g" % f
if '.' not in val_str and '-' not in val_str: # value could be 1e-05
val_str += '.0'
return val_str
class InfoStructRNA:
global_lookup = {}
def __init__(self, rna_type):
self.bl_rna = rna_type
@@ -43,18 +67,53 @@ class InfoStructRNA:
def build(self):
rna_type = self.bl_rna
parent_id = self.identifier
self.properties[:] = [GetInfoPropertyRNA(rna_prop, parent_id) for rna_prop in rna_type.properties.values()]
self.properties[:] = [GetInfoPropertyRNA(rna_prop, parent_id) for rna_id, rna_prop in rna_type.properties.items() if rna_id != "rna_type"]
self.functions[:] = [GetInfoFunctionRNA(rna_prop, parent_id) for rna_prop in rna_type.functions.values()]
def getNestedProperties(self, ls = None):
def get_bases(self):
bases = []
item = self
while item:
item = item.base
if item:
bases.append(item)
return bases
def get_nested_properties(self, ls=None):
if not ls:
ls = self.properties[:]
if self.nested:
self.nested.getNestedProperties(ls)
self.nested.get_nested_properties(ls)
return ls
def _get_py_visible_attrs(self):
attrs = []
py_class = getattr(bpy.types, self.identifier)
for attr_str in dir(py_class):
if attr_str.startswith("_"):
continue
attrs.append((attr_str, getattr(py_class, attr_str)))
return attrs
def get_py_properties(self):
properties = []
for identifier, attr in self._get_py_visible_attrs():
if type(attr) is property:
properties.append((identifier, attr))
return properties
def get_py_functions(self):
import types
functions = []
for identifier, attr in self._get_py_visible_attrs():
if type(attr) in (types.FunctionType, types.MethodType):
functions.append((identifier, attr))
return functions
def __repr__(self):
txt = ''
@@ -74,44 +133,137 @@ class InfoStructRNA:
class InfoPropertyRNA:
global_lookup = {}
def __init__(self, rna_prop):
self.bl_prop = rna_prop
self.identifier = rna_prop.identifier
self.name = rna_prop.name
self.description = rna_prop.description.strip()
self.default_str = "<UNKNOWN>"
def build(self):
rna_prop = self.bl_prop
self.enum_items = []
self.min = -1
self.max = -1
self.min = getattr(rna_prop, "hard_min", -1)
self.max = getattr(rna_prop, "hard_max", -1)
self.array_length = getattr(rna_prop, "array_length", 0)
self.collection_type = GetInfoStructRNA(rna_prop.srna)
self.is_required = rna_prop.is_required
self.is_readonly = rna_prop.is_readonly
self.is_never_none = rna_prop.is_never_none
self.type = rna_prop.type.lower()
self.fixed_type = GetInfoStructRNA(rna_prop.fixed_type) # valid for pointer/collections
fixed_type = getattr(rna_prop, "fixed_type", "")
if fixed_type:
self.fixed_type = GetInfoStructRNA(fixed_type) # valid for pointer/collections
else:
self.fixed_type = None
if self.type == "enum":
self.enum_items[:] = rna_prop.items.keys()
if self.array_length:
self.default = tuple(getattr(rna_prop, "default_array", ()))
self.default_str = ''
# special case for floats
if len(self.default) > 0:
if type(self.default[0]) is float:
self.default_str = "(%s)" % ", ".join([float_as_string(f) for f in self.default])
if not self.default_str:
self.default_str = str(self.default)
else:
self.default = getattr(rna_prop, "default", "")
if type(self.default) is float:
self.default_str = float_as_string(self.default)
else:
self.default_str = str(self.default)
self.srna = GetInfoStructRNA(rna_prop.srna) # valid for pointer/collections
def get_default_string(self):
# pointer has no default, just set as None
if self.type == "pointer":
return "None"
elif self.type == "string":
return '"' + self.default_str + '"'
elif self.type == "enum":
if self.default_str:
return "'" + self.default_str + "'"
else:
return ""
return self.default_str
def get_arg_default(self, force=True):
default = self.get_default_string()
if default and (force or self.is_required == False):
return "%s=%s" % (self.identifier, default)
return self.identifier
def get_type_description(self, as_arg=False, class_fmt="%s"):
type_str = ""
if self.fixed_type is None:
type_str += self.type
if self.array_length:
type_str += " array of %d items" % (self.array_length)
if self.type in ("float", "int"):
type_str += " in [%s, %s]" % (range_str(self.min), range_str(self.max))
elif self.type == "enum":
type_str += " in [%s]" % ', '.join([("'%s'" % s) for s in self.enum_items])
else:
if self.type == "collection":
if self.collection_type:
collection_str = (class_fmt % self.collection_type.identifier) + " collection of "
else:
collection_str = "Collection of "
else:
collection_str = ""
type_str += collection_str + (class_fmt % self.fixed_type.identifier)
if as_arg:
if not self.is_required:
type_str += ", (optional)"
else: # readonly is only useful for selfs, not args
if self.is_readonly:
type_str += ", (readonly)"
if self.is_never_none:
type_str += ", (never None)"
return type_str
def __repr__(self):
txt = ''
txt += ' * ' + self.identifier + ': ' + self.description
return txt
class InfoFunctionRNA:
global_lookup = {}
def __init__(self, rna_func):
self.bl_func = rna_func
self.identifier = rna_func.identifier
# self.name = rna_func.name # functions have no name!
self.description = rna_func.description.strip()
self.args = [] # todo
self.return_value = None # todo
self.args = []
self.return_value = None
def build(self):
rna_prop = self.bl_prop
pass
rna_func = self.bl_func
parent_id = rna_func
for rna_prop in rna_func.parameters.values():
prop = GetInfoPropertyRNA(rna_prop, parent_id)
if rna_prop.use_return:
self.return_value = prop
else:
self.args.append(prop)
def __repr__(self):
txt = ''
@@ -123,6 +275,56 @@ class InfoFunctionRNA:
return txt
class InfoOperatorRNA:
global_lookup = {}
def __init__(self, rna_op):
self.bl_op = rna_op
self.identifier = rna_op.identifier
mod, name = self.identifier.split("_OT_", 1)
self.module_name = mod.lower()
self.func_name = name
# self.name = rna_func.name # functions have no name!
self.description = rna_op.description.strip()
self.args = []
def build(self):
rna_op = self.bl_op
parent_id = self.identifier
for rna_id, rna_prop in rna_op.properties.items():
if rna_id == "rna_type":
continue
prop = GetInfoPropertyRNA(rna_prop, parent_id)
self.args.append(prop)
def get_location(self):
op_class = getattr(bpy.types, self.identifier)
op_func = getattr(op_class, "execute", None)
if op_func is None:
op_func = getattr(op_class, "invoke", None)
if op_func is None:
op_func = getattr(op_class, "poll", None)
if op_func:
op_code = op_func.__code__
source_path = op_code.co_filename
# clear the prefix
for p in script_paths:
source_path = source_path.split(p)[-1]
if source_path[0] in "/\\":
source_path = source_path[1:]
return source_path, op_code.co_firstlineno
else:
return None, None
def _GetInfoRNA(bl_rna, cls, parent_id=''):
if bl_rna == None:
@@ -139,21 +341,27 @@ def _GetInfoRNA(bl_rna, cls, parent_id=''):
def GetInfoStructRNA(bl_rna):
return _GetInfoRNA(bl_rna, InfoStructRNA)
def GetInfoPropertyRNA(bl_rna, parent_id):
return _GetInfoRNA(bl_rna, InfoPropertyRNA, parent_id)
def GetInfoFunctionRNA(bl_rna, parent_id):
return _GetInfoRNA(bl_rna, InfoFunctionRNA, parent_id)
def GetInfoOperatorRNA(bl_rna):
return _GetInfoRNA(bl_rna, InfoOperatorRNA)
def BuildRNAInfo():
# Use for faster lookups
# use rna_struct.identifier as the key for each dict
rna_struct_dict = {} # store identifier:rna lookups
rna_full_path_dict = {} # store the result of full_rna_struct_path(rna_struct)
rna_children_dict = {} # store all rna_structs nested from here
rna_references_dict = {} # store a list of rna path strings that reference this type
rna_functions_dict = {} # store all functions directly in this type (not inherited)
rna_struct_dict = {} # store identifier:rna lookups
rna_full_path_dict = {} # store the result of full_rna_struct_path(rna_struct)
rna_children_dict = {} # store all rna_structs nested from here
rna_references_dict = {} # store a list of rna path strings that reference this type
rna_functions_dict = {} # store all functions directly in this type (not inherited)
rna_words = set()
def rna_id_ignore(rna_id):
@@ -166,7 +374,8 @@ def BuildRNAInfo():
return True
if "_PT_" in rna_id:
return True
if "_HT_" in rna_id:
return True
return False
def full_rna_struct_path(rna_struct):
@@ -181,8 +390,10 @@ def BuildRNAInfo():
# def write_func(rna_func, ident):
def base_id(rna_struct):
try: return rna_struct.base.identifier
except: return '' # invalid id
try:
return rna_struct.base.identifier
except:
return "" # invalid id
#structs = [(base_id(rna_struct), rna_struct.identifier, rna_struct) for rna_struct in bpy.doc.structs.values()]
'''
@@ -194,8 +405,7 @@ def BuildRNAInfo():
for rna_type_name in dir(bpy.types):
rna_type = getattr(bpy.types, rna_type_name)
try: rna_struct = rna_type.bl_rna
except: rna_struct = None
rna_struct = getattr(rna_type, "bl_rna", None)
if rna_struct:
#if not rna_type_name.startswith('__'):
@@ -203,7 +413,7 @@ def BuildRNAInfo():
identifier = rna_struct.identifier
if not rna_id_ignore(identifier):
structs.append( (base_id(rna_struct), identifier, rna_struct) )
structs.append((base_id(rna_struct), identifier, rna_struct))
# Simple lookup
rna_struct_dict[identifier] = rna_struct
@@ -212,12 +422,12 @@ def BuildRNAInfo():
rna_full_path_dict[identifier] = full_rna_struct_path(rna_struct)
# Store a list of functions, remove inherited later
rna_functions_dict[identifier]= list(rna_struct.functions)
rna_functions_dict[identifier] = list(rna_struct.functions)
# fill in these later
rna_children_dict[identifier]= []
rna_references_dict[identifier]= []
rna_children_dict[identifier] = []
rna_references_dict[identifier] = []
else:
@@ -247,11 +457,11 @@ def BuildRNAInfo():
data = structs.pop(i)
ok = False
while i < len(structs):
if structs[i][1]==rna_base:
structs.insert(i+1, data) # insert after the item we depend on.
if structs[i][1] == rna_base:
structs.insert(i + 1, data) # insert after the item we depend on.
ok = True
break
i+=1
i += 1
if not ok:
print('Dependancy "%s" could not be found for "%s"' % (identifier, rna_base))
@@ -269,37 +479,40 @@ def BuildRNAInfo():
rna_base_func_keys = [f.identifier for f in rna_struct_dict[rna_base].functions]
else:
rna_base_prop_keys = []
rna_base_func_keys= []
rna_base_func_keys = []
# rna_struct_path = full_rna_struct_path(rna_struct)
rna_struct_path = rna_full_path_dict[identifier]
for rna_prop_identifier, rna_prop in rna_struct.properties.items():
if rna_prop_identifier=='RNA': continue
if rna_id_ignore(rna_prop_identifier): continue
if rna_prop_identifier in rna_base_prop_keys: continue
if rna_prop_identifier == 'RNA' or \
rna_id_ignore(rna_prop_identifier) or \
rna_prop_identifier in rna_base_prop_keys:
continue
for rna_prop_ptr in (getattr(rna_prop, "fixed_type", None), getattr(rna_prop, "srna", None)):
# Does this property point to me?
if rna_prop_ptr:
rna_references_dict[rna_prop_ptr.identifier].append( "%s.%s" % (rna_struct_path, rna_prop_identifier) )
rna_references_dict[rna_prop_ptr.identifier].append("%s.%s" % (rna_struct_path, rna_prop_identifier))
for rna_func in rna_struct.functions:
for rna_prop_identifier, rna_prop in rna_func.parameters.items():
if rna_prop_identifier=='RNA': continue
if rna_id_ignore(rna_prop_identifier): continue
if rna_prop_identifier in rna_base_func_keys: continue
if rna_prop_identifier == 'RNA' or \
rna_id_ignore(rna_prop_identifier) or \
rna_prop_identifier in rna_base_func_keys:
continue
try: rna_prop_ptr = rna_prop.fixed_type
except: rna_prop_ptr = None
try:
rna_prop_ptr = rna_prop.fixed_type
except:
rna_prop_ptr = None
# Does this property point to me?
if rna_prop_ptr:
rna_references_dict[rna_prop_ptr.identifier].append( "%s.%s" % (rna_struct_path, rna_func.identifier) )
rna_references_dict[rna_prop_ptr.identifier].append("%s.%s" % (rna_struct_path, rna_func.identifier))
# Store nested children
@@ -309,11 +522,11 @@ def BuildRNAInfo():
if rna_base:
rna_funcs = rna_functions_dict[identifier]
rna_funcs = rna_functions_dict[identifier]
if rna_funcs:
# Remove inherited functions if we have any
rna_base_funcs = rna_functions_dict__copy[rna_base]
rna_funcs[:] = [f for f in rna_funcs if f not in rna_base_funcs]
rna_base_funcs = rna_functions_dict__copy[rna_base]
rna_funcs[:] = [f for f in rna_funcs if f not in rna_base_funcs]
rna_functions_dict__copy.clear()
del rna_functions_dict__copy
@@ -329,7 +542,7 @@ def BuildRNAInfo():
# continue
#write_struct(rna_struct, '')
info_struct= GetInfoStructRNA(rna_struct)
info_struct = GetInfoStructRNA(rna_struct)
if rna_base:
info_struct.base = GetInfoStructRNA(rna_struct_dict[rna_base])
info_struct.nested = GetInfoStructRNA(rna_struct.nested)
@@ -347,9 +560,42 @@ def BuildRNAInfo():
for rna_info in InfoStructRNA.global_lookup.values():
rna_info.build()
for prop in rna_info.properties:
prop.build()
for func in rna_info.functions:
func.build()
for prop in func.args:
prop.build()
if func.return_value:
func.return_value.build()
for rna_info in InfoStructRNA.global_lookup.values():
print(rna_info)
# now for operators
op_mods = dir(bpy.ops)
return InfoStructRNA.global_lookup, InfoFunctionRNA.global_lookup, InfoPropertyRNA.global_lookup
for op_mod_name in sorted(op_mods):
if op_mod_name.startswith('__') or op_mod_name in ("add", "remove"):
continue
op_mod = getattr(bpy.ops, op_mod_name)
operators = dir(op_mod)
for op in sorted(operators):
try:
rna_prop = getattr(op_mod, op).get_rna()
except AttributeError:
rna_prop = None
except TypeError:
rna_prop = None
if rna_prop:
GetInfoOperatorRNA(rna_prop.bl_rna)
for rna_info in InfoOperatorRNA.global_lookup.values():
rna_info.build()
for rna_prop in rna_info.args:
rna_prop.build()
#for rna_info in InfoStructRNA.global_lookup.values():
# print(rna_info)
return InfoStructRNA.global_lookup, InfoFunctionRNA.global_lookup, InfoOperatorRNA.global_lookup, InfoPropertyRNA.global_lookup

View File

@@ -143,7 +143,7 @@ rna_max = FloatProperty(name="Max", default=1.0, precision=3)
class WM_OT_properties_edit(bpy.types.Operator):
'''Internal use (edit a property path)'''
bl_idname = "wm.properties_edit"
bl_label = "Edit Property!"
bl_label = "Edit Property"
path = rna_path
property = rna_property
@@ -196,7 +196,7 @@ class WM_OT_properties_edit(bpy.types.Operator):
prop_ui['description'] = self.properties.description
return ('FINISHED',)
return {'FINISHED'}
def invoke(self, context, event):
@@ -216,7 +216,7 @@ class WM_OT_properties_edit(bpy.types.Operator):
#return wm.invoke_props_popup(self, event)
wm.invoke_props_popup(self, event)
return ('RUNNING_MODAL',)
return {'RUNNING_MODAL'}
class WM_OT_properties_add(bpy.types.Operator):
@@ -242,7 +242,7 @@ class WM_OT_properties_add(bpy.types.Operator):
property = unique_name(item.keys())
item[property] = 1.0
return ('FINISHED',)
return {'FINISHED'}
class WM_OT_properties_remove(bpy.types.Operator):
@@ -256,4 +256,4 @@ class WM_OT_properties_remove(bpy.types.Operator):
def execute(self, context):
item = eval("context.%s" % self.properties.path)
del item[self.properties.property]
return ('FINISHED',)
return {'FINISHED'}

View File

@@ -23,6 +23,7 @@ from math import cos, sin, pi
# could this be stored elsewhere?
def metarig_template():
# generated by rigify.write_meta_rig
bpy.ops.object.mode_set(mode='EDIT')
@@ -607,17 +608,16 @@ class AddHuman(bpy.types.Operator):
bones.remove(bones[0])
metarig_template()
bpy.ops.object.mode_set(mode=mode_orig)
return ('FINISHED',)
return {'FINISHED'}
# Register the operator
bpy.ops.add(AddHuman)
bpy.types.register(AddHuman)
# Add to a menu
import dynamic_menu
menu_func = (lambda self, context: self.layout.operator(AddHuman.bl_idname,
icon='OUTLINER_OB_ARMATURE', text="Human (Meta-Rig)"))
menu_func = (lambda self, context: self.layout.operator(AddHuman.bl_idname, icon='OUTLINER_OB_ARMATURE', text="Human (Meta-Rig)"))
menu_item = dynamic_menu.add(bpy.types.INFO_MT_armature_add, menu_func)
bpy.types.INFO_MT_armature_add.append(menu_func)
if __name__ == "__main__":
bpy.ops.mesh.armature_human_advanced_add()

View File

@@ -122,18 +122,16 @@ class AddTorus(bpy.types.Operator):
ob_new.location = tuple(context.scene.cursor_location)
return ('FINISHED',)
return {'FINISHED'}
# Register the operator
bpy.ops.add(AddTorus)
# Add to a menu
import dynamic_menu
bpy.types.register(AddTorus)
# Add to the menu
menu_func = (lambda self, context: self.layout.operator(AddTorus.bl_idname,
text="Torus", icon='MESH_DONUT'))
menu_item = dynamic_menu.add(bpy.types.INFO_MT_mesh_add, menu_func)
bpy.types.INFO_MT_mesh_add.append(menu_func)
if __name__ == "__main__":
bpy.ops.mesh.primitive_torus_add()

View File

@@ -79,10 +79,10 @@ def execute(context):
try:
line = sc.history[-1].line
except:
return ('CANCELLED',)
return {'CANCELLED'}
if sc.console_type != 'PYTHON':
return ('CANCELLED',)
return {'CANCELLED'}
console, stdout, stderr = get_console(hash(context.region))
@@ -136,7 +136,7 @@ def execute(context):
if output_err:
add_scrollback(output_err, 'ERROR')
return ('FINISHED',)
return {'FINISHED'}
def autocomplete(context):
@@ -150,10 +150,10 @@ def autocomplete(context):
line = current_line.line
if not console:
return ('CANCELLED',)
return {'CANCELLED'}
if sc.console_type != 'PYTHON':
return ('CANCELLED',)
return {'CANCELLED'}
# This function isnt aware of the text editor or being an operator
# just does the autocomp then copy its results back
@@ -172,7 +172,7 @@ def autocomplete(context):
context.area.tag_redraw()
return ('FINISHED',)
return {'FINISHED'}
def banner(context):
@@ -195,4 +195,4 @@ def banner(context):
console = get_console(hash(context.region))[0]
console.locals["C"] = bpy.context
return ('FINISHED',)
return {'FINISHED'}

View File

@@ -49,7 +49,7 @@ def execute(context):
try:
line = sc.history[-1].line
except:
return ('CANCELLED',)
return {'CANCELLED'}
bpy.ops.console.scrollback_append(text=sc.prompt + line, type='INPUT')
@@ -60,13 +60,13 @@ def execute(context):
remove_duplicates=True)
sc.prompt = os.getcwd() + PROMPT
return ('FINISHED',)
return {'FINISHED'}
def autocomplete(context):
# sc = context.space_data
# TODO
return ('CANCELLED',)
return {'CANCELLED'}
def banner(context):
@@ -75,4 +75,4 @@ def banner(context):
shell_run("bash --version")
sc.prompt = os.getcwd() + PROMPT
return ('FINISHED',)
return {'FINISHED'}

View File

@@ -65,11 +65,11 @@ class MeshSelectInteriorFaces(bpy.types.Operator):
def execute(self, context):
main(context)
return ('FINISHED',)
return {'FINISHED'}
# Register the operator
bpy.ops.add(MeshSelectInteriorFaces)
bpy.types.register(MeshSelectInteriorFaces)
if __name__ == "__main__":
bpy.ops.mesh.faces_select_interior()

View File

@@ -249,17 +249,16 @@ def mesh_faces_extend(me, faces, mat_idx = 0):
def getSelectedEdges(context, me, ob):
MESH_MODE= context.scene.tool_settings.mesh_selection_mode
MESH_MODE = tuple(context.tool_settings.mesh_selection_mode)
context.tool_settings.mesh_selection_mode = False, True, False
if MESH_MODE in ('EDGE', 'VERTEX'):
context.scene.tool_settings.mesh_selection_mode = 'EDGE'
if not MESH_MODE[2]:
edges= [ ed for ed in me.edges if ed.selected ]
# print len(edges), len(me.edges)
context.scene.tool_settings.mesh_selection_mode = MESH_MODE
return edges
if MESH_MODE == 'FACE':
context.scene.tool_settings.mesh_selection_mode = 'EDGE'
else:
# value is [edge, face_sel_user_in]
edge_dict= dict((ed.key, [ed, 0]) for ed in me.edges)
@@ -268,7 +267,7 @@ def getSelectedEdges(context, me, ob):
for edkey in f.edge_keys:
edge_dict[edkey][1] += 1
context.scene.tool_settings.mesh_selection_mode = MESH_MODE
context.tool_settings.mesh_selection_mode = MESH_MODE
return [ ed_data[0] for ed_data in edge_dict.values() if ed_data[1] == 1 ]
@@ -644,15 +643,14 @@ class MESH_OT_skin(bpy.types.Operator):
def execute(self, context):
main(context)
return ('FINISHED',)
return {'FINISHED'}
# Register the operator
bpy.ops.add(MESH_OT_skin)
bpy.types.register(MESH_OT_skin)
# Add to a menu
import dynamic_menu
menu_item = dynamic_menu.add(bpy.types.VIEW3D_MT_edit_mesh_faces, (lambda self, context: self.layout.operator("mesh.skin", text="Bridge Faces")) )
bpy.types.VIEW3D_MT_edit_mesh_faces.append((lambda self, context: self.layout.operator("mesh.skin", text="Bridge Faces")))
if __name__ == "__main__":
bpy.ops.mesh.skin()

View File

@@ -57,13 +57,13 @@ class SelectPattern(bpy.types.Operator):
elif not self.properties.extend:
item.selected = False
return ('FINISHED',)
return {'FINISHED'}
def invoke(self, context, event):
wm = context.manager
# return wm.invoke_props_popup(self, event)
wm.invoke_props_popup(self, event)
return ('RUNNING_MODAL',)
return {'RUNNING_MODAL'}
def draw(self, context):
layout = self.layout
@@ -84,27 +84,45 @@ class SubdivisionSet(bpy.types.Operator):
bl_undo = True
level = IntProperty(name="Level",
default=1, min=0, max=100, soft_min=0, soft_max=6)
default=1, min=-100, max=100, soft_min=-6, soft_max=6)
relative = BoolProperty(name="Relative", description="Apply the subsurf level as an offset relative to the current level", default=False)
def poll(self, context):
ob = context.active_object
return (ob and ob.type == 'MESH')
obs = context.selected_editable_objects
return (obs is not None)
def execute(self, context):
level = self.properties.level
relative = self.properties.relative
if relative and level == 0:
return {'CANCELLED'} # nothing to do
def set_object_subd(obj):
for mod in obj.modifiers:
if mod.type == 'MULTIRES':
if level < mod.total_levels:
if obj.mode == 'SCULPT' and mod.sculpt_levels != level:
mod.sculpt_levels = level
elif obj.mode == 'OBJECT' and mod.levels != level:
mod.levels = level
if level <= mod.total_levels:
if obj.mode == 'SCULPT':
if relative:
mod.sculpt_levels += level
else:
if mod.sculpt_levels != level:
mod.sculpt_levels = level
elif obj.mode == 'OBJECT':
if relative:
mod.levels += level
else:
if mod.levels != level:
mod.levels = level
return
elif mod.type == 'SUBSURF':
if mod.levels != level:
mod.levels = level
if relative:
mod.levels += level
else:
if mod.levels != level:
mod.levels = level
return
# adda new modifier
@@ -114,7 +132,7 @@ class SubdivisionSet(bpy.types.Operator):
for obj in context.selected_editable_objects:
set_object_subd(obj)
return ('FINISHED',)
return {'FINISHED'}
class Retopo(bpy.types.Operator):
@@ -128,9 +146,175 @@ class Retopo(bpy.types.Operator):
def execute(self, context):
import retopo
retopo.main()
return ('FINISHED',)
return {'FINISHED'}
bpy.ops.add(SelectPattern)
bpy.ops.add(SubdivisionSet)
bpy.ops.add(Retopo)
class ShapeTransfer(bpy.types.Operator):
'''Copy the active objects current shape to other selected objects with the same number of verts'''
bl_idname = "object.shape_key_transfer"
bl_label = "Transfer Shape Key"
bl_register = True
bl_undo = True
mode = EnumProperty(items=(
('OFFSET', "Offset", "Apply the relative positional offset"),
('RELATIVE_FACE', "Relative Face", "Calculate the geometricly relative position (using faces)."),
('RELATIVE_EDGE', "Relative Edge", "Calculate the geometricly relative position (using edges).")),
name="Transformation Mode",
description="Method to apply relative shape positions to the new shape",
default='OFFSET')
use_clamp = BoolProperty(name="Clamp Offset",
description="Clamp the transformation to the distance each vertex moves in the original shape.",
default=False)
def _main(self, ob_act, objects, mode='OFFSET', use_clamp=False):
def me_nos(verts):
return [v.normal.copy() for v in verts]
def me_cos(verts):
return [v.co.copy() for v in verts]
def ob_add_shape(ob):
me = ob.data
ob.add_shape_key(from_mix=False)
if len(me.shape_keys.keys) == 1:
ob.add_shape_key(from_mix=False) # we need a rest
ob.active_shape_key_index = len(me.shape_keys.keys) - 1
ob.shape_key_lock = True
from Geometry import BarycentricTransform
from Mathutils import Vector
if use_clamp and mode == 'OFFSET':
use_clamp = False
me = ob_act.data
orig_shape_coords = me_cos(ob_act.active_shape_key.data)
orig_normals = me_nos(me.verts)
orig_coords = me_cos(me.verts)
for ob_other in objects:
me_other = ob_other.data
if len(me_other.verts) != len(me.verts):
self.report({'WARNING'}, "Skipping '%s', vertex count differs" % ob_other.name)
continue
target_normals = me_nos(me_other.verts)
target_coords = me_cos(me_other.verts)
ob_add_shape(ob_other)
# editing the final coords, only list that stores wrapped coords
target_shape_coords = [v.co for v in ob_other.active_shape_key.data]
median_coords = [[] for i in range(len(me.verts))]
# Method 1, edge
if mode == 'OFFSET':
for i, vert_cos in enumerate(median_coords):
vert_cos.append(target_coords[i] + (orig_shape_coords[i] - orig_coords[i]))
elif mode == 'RELATIVE_FACE':
for face in me.faces:
i1, i2, i3, i4 = face.verts_raw
if i4 != 0:
pt = BarycentricTransform(orig_shape_coords[i1],
orig_coords[i4], orig_coords[i1], orig_coords[i2],
target_coords[i4], target_coords[i1], target_coords[i2])
median_coords[i1].append(pt)
pt = BarycentricTransform(orig_shape_coords[i2],
orig_coords[i1], orig_coords[i2], orig_coords[i3],
target_coords[i1], target_coords[i2], target_coords[i3])
median_coords[i2].append(pt)
pt = BarycentricTransform(orig_shape_coords[i3],
orig_coords[i2], orig_coords[i3], orig_coords[i4],
target_coords[i2], target_coords[i3], target_coords[i4])
median_coords[i3].append(pt)
pt = BarycentricTransform(orig_shape_coords[i4],
orig_coords[i3], orig_coords[i4], orig_coords[i1],
target_coords[i3], target_coords[i4], target_coords[i1])
median_coords[i4].append(pt)
else:
pt = BarycentricTransform(orig_shape_coords[i1],
orig_coords[i3], orig_coords[i1], orig_coords[i2],
target_coords[i3], target_coords[i1], target_coords[i2])
median_coords[i1].append(pt)
pt = BarycentricTransform(orig_shape_coords[i2],
orig_coords[i1], orig_coords[i2], orig_coords[i3],
target_coords[i1], target_coords[i2], target_coords[i3])
median_coords[i2].append(pt)
pt = BarycentricTransform(orig_shape_coords[i3],
orig_coords[i2], orig_coords[i3], orig_coords[i1],
target_coords[i2], target_coords[i3], target_coords[i1])
median_coords[i3].append(pt)
elif mode == 'RELATIVE_EDGE':
for ed in me.edges:
i1, i2 = ed.verts
v1, v2 = orig_coords[i1], orig_coords[i2]
edge_length = (v1 - v2).length
n1loc = v1 + orig_normals[i1] * edge_length
n2loc = v2 + orig_normals[i2] * edge_length
# now get the target nloc's
v1_to, v2_to = target_coords[i1], target_coords[i2]
edlen_to = (v1_to - v2_to).length
n1loc_to = v1_to + target_normals[i1] * edlen_to
n2loc_to = v2_to + target_normals[i2] * edlen_to
pt = BarycentricTransform(orig_shape_coords[i1],
v2, v1, n1loc,
v2_to, v1_to, n1loc_to)
median_coords[i1].append(pt)
pt = BarycentricTransform(orig_shape_coords[i2],
v1, v2, n2loc,
v1_to, v2_to, n2loc_to)
median_coords[i2].append(pt)
# apply the offsets to the new shape
from functools import reduce
VectorAdd = Vector.__add__
for i, vert_cos in enumerate(median_coords):
if vert_cos:
co = reduce(VectorAdd, vert_cos) / len(vert_cos)
if use_clamp:
# clamp to the same movement as the original
# breaks copy between different scaled meshes.
len_from = (orig_shape_coords[i] - orig_coords[i]).length
ofs = co - target_coords[i]
ofs.length = len_from
co = target_coords[i] + ofs
target_shape_coords[i][:] = co
return {'FINISHED'}
def poll(self, context):
obj = context.active_object
return (obj and obj.mode != 'EDIT')
def execute(self, context):
C = bpy.context
ob_act = C.active_object
objects = [ob for ob in C.selected_editable_objects if ob != ob_act]
return self._main(ob_act, objects, self.properties.mode, self.properties.use_clamp)
bpy.types.register(SelectPattern)
bpy.types.register(SubdivisionSet)
bpy.types.register(Retopo)
bpy.types.register(ShapeTransfer)

View File

@@ -40,7 +40,7 @@ class AddPresetBase(bpy.types.Operator):
def execute(self, context):
if not self.properties.name:
return ('FINISHED',)
return {'FINISHED'}
filename = self._as_filename(self.properties.name) + ".py"
@@ -53,7 +53,7 @@ class AddPresetBase(bpy.types.Operator):
file_preset.close()
return ('FINISHED',)
return {'FINISHED'}
def invoke(self, context, event):
wm = context.manager
@@ -61,7 +61,7 @@ class AddPresetBase(bpy.types.Operator):
#return wm.invoke_props_popup(self, event)
wm.invoke_props_popup(self, event)
return ('RUNNING_MODAL',)
return {'RUNNING_MODAL'}
class AddPresetRender(AddPresetBase):
@@ -125,6 +125,6 @@ class AddPresetCloth(AddPresetBase):
preset_subdir = "cloth"
bpy.ops.add(AddPresetRender)
bpy.ops.add(AddPresetSSS)
bpy.ops.add(AddPresetCloth)
bpy.types.register(AddPresetRender)
bpy.types.register(AddPresetSSS)
bpy.types.register(AddPresetCloth)

View File

@@ -17,37 +17,40 @@
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
# <pep8 compliant>
# History
#
# Originally written by Matt Ebb
import bpy
import subprocess, os, platform
import subprocess
import os
import platform
# from BKE_add_image_extension()
img_format_exts = {
'IRIS':'.rgb',
'RADHDR':'.hdr',
'PNG':'png',
'TARGA':'tga',
'RAWTARGA':'tga',
'BMP':'bmp',
'TIFF':'tif',
'OPENEXR':'exr',
'MULTILAYER':'exr',
'CINEON':'cin',
'DPX':'dpx',
'JPEG':'jpg',
'JPEG2000':'jp2',
'QUICKTIME_QTKIT':'mov',
'QUICKTIME_CARBON':'mov',
'AVIRAW':'avi',
'AVIJPEG':'avi',
'AVICODEC':'avi',
'XVID':'avi',
'THEORA':'ogg',
'IRIS': '.rgb',
'RADHDR': '.hdr',
'PNG': 'png',
'TARGA': 'tga',
'RAWTARGA': 'tga',
'BMP': 'bmp',
'TIFF': 'tif',
'OPENEXR': 'exr',
'MULTILAYER': 'exr',
'CINEON': 'cin',
'DPX': 'dpx',
'JPEG': 'jpg',
'JPEG2000': 'jp2',
'QUICKTIME_QTKIT': 'mov',
'QUICKTIME_CARBON': 'mov',
'AVIRAW': 'avi',
'AVIJPEG': 'avi',
'AVICODEC': 'avi',
'XVID': 'avi',
'THEORA': 'ogg',
}
movie_formats = ('QUICKTIME_QTKIT',
@@ -56,8 +59,8 @@ movie_formats = ('QUICKTIME_QTKIT',
'AVIJPEG',
'AVICODEC',
'XVID',
'THEORA'
)
'THEORA')
def guess_player_path(preset):
if preset == 'BLENDER24':
@@ -146,4 +149,4 @@ class PlayRenderedAnim(bpy.types.Operator):
return('FINISHED',)
bpy.ops.add(PlayRenderedAnim)
bpy.types.register(PlayRenderedAnim)

View File

@@ -257,16 +257,13 @@ class FollowActiveQuads(bpy.types.Operator):
def execute(self, context):
main(context, self)
return ('FINISHED',)
return {'FINISHED'}
bpy.ops.add(FollowActiveQuads)
bpy.types.register(FollowActiveQuads)
# Add to a menu
import dynamic_menu
menu_func = (lambda self, context: self.layout.operator(FollowActiveQuads.bl_idname))
menu_item = dynamic_menu.add(bpy.types.VIEW3D_MT_uv_map, menu_func)
bpy.types.VIEW3D_MT_uv_map.append(menu_func)
if __name__ == '__main__':
bpy.ops.uv.follow_active_quads()

View File

@@ -1109,6 +1109,8 @@ def main(context, island_margin, projection_limit):
"""
from bpy.props import *
class SmartProject(bpy.types.Operator):
'''This script projection unwraps the selected faces of a mesh. it operates on all selected mesh objects, and can be used unwrap selected faces, or all faces.'''
bl_idname = "uv.smart_project"
@@ -1130,18 +1132,15 @@ class SmartProject(bpy.types.Operator):
def execute(self, context):
main(context, self.properties.island_margin, self.properties.angle_limit)
return ('FINISHED',)
return {'FINISHED'}
bpy.ops.add(SmartProject)
bpy.types.register(SmartProject)
# Add to a menu
import dynamic_menu
menu_func = (lambda self, context: self.layout.operator(SmartProject.bl_idname,
text="Smart Project"))
menu_item = dynamic_menu.add(bpy.types.VIEW3D_MT_uv_map, menu_func)
bpy.types.VIEW3D_MT_uv_map.append(menu_func)
if __name__ == '__main__':
bpy.ops.uv.smart_project()

View File

@@ -158,24 +158,23 @@ class VertexPaintDirt(bpy.types.Operator):
dirt_only = BoolProperty(name="Dirt Only", description="Dont calculate cleans for convex areas", default=False)
def execute(self, context):
sce = context.scene
ob = context.object
obj = context.object
if not ob or ob.type != 'MESH':
if not obj or obj.type != 'MESH':
print('Error, no active mesh object, aborting.')
return('CANCELLED',)
me = ob.data
mesh = obj.data
t = time.time()
applyVertexDirt(me, self.properties.blur_iterations, self.properties.blur_strength, math.radians(self.properties.dirt_angle), math.radians(self.properties.clean_angle), self.properties.dirt_only)
applyVertexDirt(mesh, self.properties.blur_iterations, self.properties.blur_strength, math.radians(self.properties.dirt_angle), math.radians(self.properties.clean_angle), self.properties.dirt_only)
print('Dirt calculated in %.6f' % (time.time() - t))
return('FINISHED',)
bpy.ops.add(VertexPaintDirt)
bpy.types.register(VertexPaintDirt)
if __name__ == "__main__":
bpy.ops.mesh.vertex_paint_dirt()

View File

@@ -34,7 +34,7 @@ class MESH_OT_delete_edgeloop(bpy.types.Operator):
bpy.ops.mesh.select_more()
bpy.ops.mesh.remove_doubles()
return ('FINISHED',)
return {'FINISHED'}
rna_path_prop = StringProperty(name="Context Attributes",
description="rna context string", maxlen=1024, default="")
@@ -60,15 +60,16 @@ def context_path_validate(context, path):
def execute_context_assign(self, context):
if context_path_validate(context, self.properties.path) is Ellipsis:
return ('PASS_THROUGH',)
return {'PASS_THROUGH'}
exec("context.%s=self.properties.value" % self.properties.path)
return ('FINISHED',)
return {'FINISHED'}
class WM_OT_context_set_boolean(bpy.types.Operator):
'''Set a context value.'''
bl_idname = "wm.context_set_boolean"
bl_label = "Context Set"
bl_label = "Context Set Boolean"
bl_undo = True
path = rna_path_prop
value = BoolProperty(name="Value",
@@ -81,6 +82,7 @@ class WM_OT_context_set_int(bpy.types.Operator): # same as enum
'''Set a context value.'''
bl_idname = "wm.context_set_int"
bl_label = "Context Set"
bl_undo = True
path = rna_path_prop
value = IntProperty(name="Value", description="Assign value", default=0)
@@ -91,7 +93,8 @@ class WM_OT_context_set_int(bpy.types.Operator): # same as enum
class WM_OT_context_set_float(bpy.types.Operator): # same as enum
'''Set a context value.'''
bl_idname = "wm.context_set_float"
bl_label = "Context Set"
bl_label = "Context Set Float"
bl_undo = True
path = rna_path_prop
value = FloatProperty(name="Value",
@@ -103,7 +106,8 @@ class WM_OT_context_set_float(bpy.types.Operator): # same as enum
class WM_OT_context_set_string(bpy.types.Operator): # same as enum
'''Set a context value.'''
bl_idname = "wm.context_set_string"
bl_label = "Context Set"
bl_label = "Context Set String"
bl_undo = True
path = rna_path_prop
value = StringProperty(name="Value",
@@ -115,7 +119,8 @@ class WM_OT_context_set_string(bpy.types.Operator): # same as enum
class WM_OT_context_set_enum(bpy.types.Operator):
'''Set a context value.'''
bl_idname = "wm.context_set_enum"
bl_label = "Context Set"
bl_label = "Context Set Enum"
bl_undo = True
path = rna_path_prop
value = StringProperty(name="Value",
@@ -125,27 +130,48 @@ class WM_OT_context_set_enum(bpy.types.Operator):
execute = execute_context_assign
class WM_OT_context_set_value(bpy.types.Operator):
'''Set a context value.'''
bl_idname = "wm.context_set_value"
bl_label = "Context Set Value"
bl_undo = True
path = rna_path_prop
value = StringProperty(name="Value",
description="Assignment value (as a string)",
maxlen=1024, default="")
def execute(self, context):
if context_path_validate(context, self.properties.path) is Ellipsis:
return {'PASS_THROUGH'}
exec("context.%s=%s" % (self.properties.path, self.properties.value))
return {'FINISHED'}
class WM_OT_context_toggle(bpy.types.Operator):
'''Toggle a context value.'''
bl_idname = "wm.context_toggle"
bl_label = "Context Toggle"
bl_undo = True
path = rna_path_prop
def execute(self, context):
if context_path_validate(context, self.properties.path) is Ellipsis:
return ('PASS_THROUGH',)
return {'PASS_THROUGH'}
exec("context.%s=not (context.%s)" %
(self.properties.path, self.properties.path))
return ('FINISHED',)
return {'FINISHED'}
class WM_OT_context_toggle_enum(bpy.types.Operator):
'''Toggle a context value.'''
bl_idname = "wm.context_toggle_enum"
bl_label = "Context Toggle Values"
bl_undo = True
path = rna_path_prop
value_1 = StringProperty(name="Value", \
@@ -157,14 +183,14 @@ class WM_OT_context_toggle_enum(bpy.types.Operator):
def execute(self, context):
if context_path_validate(context, self.properties.path) is Ellipsis:
return ('PASS_THROUGH',)
return {'PASS_THROUGH'}
exec("context.%s = ['%s', '%s'][context.%s!='%s']" % \
(self.properties.path, self.properties.value_1,\
self.properties.value_2, self.properties.path,
self.properties.value_2))
return ('FINISHED',)
return {'FINISHED'}
class WM_OT_context_cycle_int(bpy.types.Operator):
@@ -172,6 +198,8 @@ class WM_OT_context_cycle_int(bpy.types.Operator):
vertex keys, groups' etc.'''
bl_idname = "wm.context_cycle_int"
bl_label = "Context Int Cycle"
bl_undo = True
path = rna_path_prop
reverse = rna_reverse_prop
@@ -179,7 +207,7 @@ class WM_OT_context_cycle_int(bpy.types.Operator):
value = context_path_validate(context, self.properties.path)
if value is Ellipsis:
return ('PASS_THROUGH',)
return {'PASS_THROUGH'}
self.properties.value = value
if self.properties.reverse:
@@ -196,13 +224,14 @@ class WM_OT_context_cycle_int(bpy.types.Operator):
self.properties.value = - (1 << 32)
execute_context_assign(self, context)
return ('FINISHED',)
return {'FINISHED'}
class WM_OT_context_cycle_enum(bpy.types.Operator):
'''Toggle a context value.'''
bl_idname = "wm.context_cycle_enum"
bl_label = "Context Enum Cycle"
bl_undo = True
path = rna_path_prop
reverse = rna_reverse_prop
@@ -211,7 +240,7 @@ class WM_OT_context_cycle_enum(bpy.types.Operator):
value = context_path_validate(context, self.properties.path)
if value is Ellipsis:
return ('PASS_THROUGH',)
return {'PASS_THROUGH'}
orig_value = value
@@ -247,7 +276,7 @@ class WM_OT_context_cycle_enum(bpy.types.Operator):
# set the new value
exec("context.%s=advance_enum" % self.properties.path)
return ('FINISHED',)
return {'FINISHED'}
doc_id = StringProperty(name="Doc ID",
description="", maxlen=1024, default="", hidden=True)
@@ -275,26 +304,26 @@ class WM_OT_doc_view(bpy.types.Operator):
def execute(self, context):
id_split = self.properties.doc_id.split('.')
if len(id_split) == 1: # rna, class
url = '%s/bpy.types.%s-class.html' % (self._prefix, id_split[0])
url = '%s/bpy.types.%s.html' % (self._prefix, id_split[0])
elif len(id_split) == 2: # rna, class.prop
class_name, class_prop = id_split
if hasattr(bpy.types, class_name.upper() + '_OT_' + class_prop):
url = '%s/bpy.ops.%s-module.html#%s' % \
(self._prefix, class_name, class_prop)
url = '%s/bpy.ops.%s.html#bpy.ops.%s.%s' % \
(self._prefix, class_name, class_name, class_prop)
else:
# It so happens that epydoc nests these
class_name_full = self._nested_class_string(class_name)
url = '%s/bpy.types.%s-class.html#%s' % \
(self._prefix, class_name_full, class_prop)
# It so happens that epydoc nests these, not sphinx
# class_name_full = self._nested_class_string(class_name)
url = '%s/bpy.types.%s.html#bpy.types.%s.%s' % \
(self._prefix, class_name, class_name, class_prop)
else:
return ('PASS_THROUGH',)
return {'PASS_THROUGH'}
import webbrowser
webbrowser.open(url)
return ('FINISHED',)
return {'FINISHED'}
class WM_OT_doc_edit(bpy.types.Operator):
@@ -325,7 +354,7 @@ class WM_OT_doc_edit(bpy.types.Operator):
class_name, class_prop = doc_id.split('.')
if not doc_new:
return ('RUNNING_MODAL',)
return {'RUNNING_MODAL'}
# check if this is an operator
op_name = class_name.upper() + '_OT_' + class_prop
@@ -338,7 +367,7 @@ class WM_OT_doc_edit(bpy.types.Operator):
rna = op_class.bl_rna
doc_orig = rna.description
if doc_orig == doc_new:
return ('RUNNING_MODAL',)
return {'RUNNING_MODAL'}
print("op - old:'%s' -> new:'%s'" % (doc_orig, doc_new))
upload["title"] = 'OPERATOR %s:%s' % (doc_id, doc_orig)
@@ -350,7 +379,7 @@ class WM_OT_doc_edit(bpy.types.Operator):
rna = getattr(bpy.types, class_name).bl_rna
doc_orig = rna.properties[class_prop].description
if doc_orig == doc_new:
return ('RUNNING_MODAL',)
return {'RUNNING_MODAL'}
print("rna - old:'%s' -> new:'%s'" % (doc_orig, doc_new))
upload["title"] = 'RNA %s:%s' % (doc_id, doc_orig)
@@ -359,7 +388,7 @@ class WM_OT_doc_edit(bpy.types.Operator):
self._send_xmlrpc(upload)
return ('FINISHED',)
return {'FINISHED'}
def invoke(self, context, event):
wm = context.manager
@@ -374,28 +403,29 @@ class WM_OT_reload_scripts(bpy.types.Operator):
def execute(self, context):
MOD = type(bpy)
bpy.load_scripts(True)
return ('FINISHED',)
return {'FINISHED'}
bpy.ops.add(MESH_OT_delete_edgeloop)
bpy.types.register(MESH_OT_delete_edgeloop)
bpy.ops.add(WM_OT_context_set_boolean)
bpy.ops.add(WM_OT_context_set_int)
bpy.ops.add(WM_OT_context_set_float)
bpy.ops.add(WM_OT_context_set_string)
bpy.ops.add(WM_OT_context_set_enum)
bpy.ops.add(WM_OT_context_toggle)
bpy.ops.add(WM_OT_context_toggle_enum)
bpy.ops.add(WM_OT_context_cycle_enum)
bpy.ops.add(WM_OT_context_cycle_int)
bpy.types.register(WM_OT_context_set_boolean)
bpy.types.register(WM_OT_context_set_int)
bpy.types.register(WM_OT_context_set_float)
bpy.types.register(WM_OT_context_set_string)
bpy.types.register(WM_OT_context_set_enum)
bpy.types.register(WM_OT_context_set_value)
bpy.types.register(WM_OT_context_toggle)
bpy.types.register(WM_OT_context_toggle_enum)
bpy.types.register(WM_OT_context_cycle_enum)
bpy.types.register(WM_OT_context_cycle_int)
bpy.ops.add(WM_OT_doc_view)
bpy.ops.add(WM_OT_doc_edit)
bpy.types.register(WM_OT_doc_view)
bpy.types.register(WM_OT_doc_edit)
bpy.ops.add(WM_OT_reload_scripts)
bpy.types.register(WM_OT_reload_scripts)
# experemental!
import rna_prop_ui
bpy.ops.add(rna_prop_ui.WM_OT_properties_edit)
bpy.ops.add(rna_prop_ui.WM_OT_properties_add)
bpy.ops.add(rna_prop_ui.WM_OT_properties_remove)
bpy.types.register(rna_prop_ui.WM_OT_properties_edit)
bpy.types.register(rna_prop_ui.WM_OT_properties_add)
bpy.types.register(rna_prop_ui.WM_OT_properties_remove)

View File

@@ -4,4 +4,4 @@ bpy.context.scene.render_data.resolution_percentage = 100
bpy.context.scene.render_data.pixel_aspect_x = 1
bpy.context.scene.render_data.pixel_aspect_y = 1
bpy.context.scene.render_data.fps = 24
bpy.context.scene.render_data.fps_base = 1
bpy.context.scene.render_data.fps_base = 1

View File

@@ -4,4 +4,4 @@ bpy.context.scene.render_data.resolution_percentage = 100
bpy.context.scene.render_data.pixel_aspect_x = 1
bpy.context.scene.render_data.pixel_aspect_y = 1
bpy.context.scene.render_data.fps = 24
bpy.context.scene.render_data.fps_base = 1
bpy.context.scene.render_data.fps_base = 1

View File

@@ -4,4 +4,4 @@ bpy.context.scene.render_data.resolution_percentage = 100
bpy.context.scene.render_data.pixel_aspect_x = 54
bpy.context.scene.render_data.pixel_aspect_y = 51
bpy.context.scene.render_data.fps = 25
bpy.context.scene.render_data.fps_base = 1
bpy.context.scene.render_data.fps_base = 1

View File

@@ -4,4 +4,4 @@ bpy.context.scene.render_data.resolution_percentage = 100
bpy.context.scene.render_data.pixel_aspect_x = 64
bpy.context.scene.render_data.pixel_aspect_y = 45
bpy.context.scene.render_data.fps = 25
bpy.context.scene.render_data.fps_base = 1
bpy.context.scene.render_data.fps_base = 1

View File

@@ -30,7 +30,7 @@ class ExportSomeData(bpy.types.Operator):
write_some_data(self.properties.path, context, self.properties.use_setting)
return ('FINISHED',)
return {'FINISHED'}
def invoke(self, context, event):
wm = context.manager
@@ -38,7 +38,7 @@ class ExportSomeData(bpy.types.Operator):
if True:
# File selector
wm.add_fileselect(self) # will run self.execute()
return ('RUNNING_MODAL',)
return {'RUNNING_MODAL'}
elif 0:
# Redo popup
return wm.invoke_props_popup(self, event) #
@@ -46,13 +46,11 @@ class ExportSomeData(bpy.types.Operator):
return self.execute(context)
bpy.ops.add(ExportSomeData)
bpy.types.register(ExportSomeData)
# Only needed if you want to add into a dynamic menu
import dynamic_menu
menu_func = lambda self, context: self.layout.operator("export.some_data", text="Example Exporter...")
menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_export, menu_func)
bpy.types.INFO_MT_file_export.append(menu_func)
# Use for running this script directly
if __name__ == "__main__":
bpy.ops.export.some_data(path="/tmp/test.ply")

View File

@@ -13,9 +13,9 @@ class SimpleOperator(bpy.types.Operator):
def execute(self, context):
main(context)
return ('FINISHED',)
return {'FINISHED'}
bpy.ops.add(SimpleOperator)
bpy.types.register(SimpleOperator)
if __name__ == "__main__":
bpy.ops.object.simple_operator()

View File

@@ -254,7 +254,7 @@ class DATA_PT_iksolver_itasc(DataButtonsPanel):
row = layout.row()
row.prop(ob.pose, "ik_solver")
if itasc:
layout.prop(itasc, "mode", expand=True)
simulation = (itasc.mode == 'SIMULATION')

View File

@@ -138,7 +138,7 @@ class Reload(bpy.types.Operator):
def execute(self, context):
DATA_PT_template.templates[:] = metarig_templates()
return ('FINISHED',)
return {'FINISHED'}
def rigify_report_exception(operator, exception):
@@ -180,7 +180,7 @@ class Generate(bpy.types.Operator):
except rigify.RigifyError as rig_exception:
rigify_report_exception(self, rig_exception)
return ('FINISHED',)
return {'FINISHED'}
class Validate(bpy.types.Operator):
@@ -196,7 +196,7 @@ class Validate(bpy.types.Operator):
rigify.validate_rig(context, context.object)
except rigify.RigifyError as rig_exception:
rigify_report_exception(self, rig_exception)
return ('FINISHED',)
return {'FINISHED'}
class Sample(bpy.types.Operator):
@@ -219,7 +219,7 @@ class Sample(bpy.types.Operator):
if obj_gen:
obj_gen.location.x = i * 1.0
return ('FINISHED',)
return {'FINISHED'}
class Graph(bpy.types.Operator):
@@ -244,7 +244,7 @@ class Graph(bpy.types.Operator):
os.system("dot -Tpng %s > %s; gnome-open %s &" % (path_dot, path_png, path_png))
#os.system("python /b/xdot.py '%s' &" % path_dot)
return ('FINISHED',)
return {'FINISHED'}
class AsScript(bpy.types.Operator):
@@ -267,7 +267,7 @@ class AsScript(bpy.types.Operator):
file.write(code)
file.close()
return ('FINISHED',)
return {'FINISHED'}
def invoke(self, context, event):
import os
@@ -275,7 +275,7 @@ class AsScript(bpy.types.Operator):
self.properties.path = os.path.splitext(bpy.data.filename)[0] + "-" + bpy.utils.clean_name(obj.name) + ".py"
wm = context.manager
wm.add_fileselect(self)
return ('RUNNING_MODAL',)
return {'RUNNING_MODAL'}
# operators that use the GUI
@@ -294,7 +294,7 @@ class ActiveAssign(bpy.types.Operator):
pose_templates = scene.pose_templates
template_name = DATA_PT_template.templates[pose_templates.active_template_index]
context.active_pose_bone["type"] = template_name
return ('FINISHED',)
return {'FINISHED'}
class ActiveClear(bpy.types.Operator):
@@ -310,14 +310,10 @@ class ActiveClear(bpy.types.Operator):
def execute(self, context):
scene = context.scene
del context.active_pose_bone["type"]
return ('FINISHED',)
return {'FINISHED'}
import space_info
import dynamic_menu
class INFO_MT_armature_metarig_add(dynamic_menu.DynMenu):
class INFO_MT_armature_metarig_add(bpy.types.Menu):
bl_idname = "INFO_MT_armature_metarig_add"
bl_label = "Meta-Rig"
@@ -336,18 +332,19 @@ bpy.types.register(DATA_PT_template)
bpy.types.register(PoseTemplateSettings)
bpy.types.register(PoseTemplate)
bpy.ops.add(Reload)
bpy.ops.add(Generate)
bpy.ops.add(Validate)
bpy.ops.add(Sample)
bpy.ops.add(Graph)
bpy.ops.add(AsScript)
bpy.types.register(Reload)
bpy.types.register(Generate)
bpy.types.register(Validate)
bpy.types.register(Sample)
bpy.types.register(Graph)
bpy.types.register(AsScript)
bpy.ops.add(ActiveAssign)
bpy.ops.add(ActiveClear)
bpy.types.register(ActiveAssign)
bpy.types.register(ActiveClear)
bpy.types.register(INFO_MT_armature_metarig_add)
import space_info
menu_func = (lambda self, context: self.layout.menu("INFO_MT_armature_metarig_add", icon='OUTLINER_OB_ARMATURE'))
menu_item = dynamic_menu.add(bpy.types.INFO_MT_armature_add, menu_func)
space_info.INFO_MT_armature_add.append(menu_func)

View File

@@ -602,16 +602,24 @@ class DATA_PT_modifiers(DataButtonsPanel):
layout.label(text="See Soft Body panel.")
def SOLIDIFY(self, layout, ob, md, wide_ui):
layout.prop(md, "offset")
split = layout.split()
col = split.column()
col.prop(md, "offset")
col.label(text="Crease:")
col.prop(md, "edge_crease_inner",text="Inner")
col.prop(md, "edge_crease_outer", text="Outer")
col.prop(md, "edge_crease_rim", text="Rim")
if wide_ui:
col = split.column()
col.label()
col.prop(md, "use_rim")
col.prop(md, "use_even_offset")
col.prop(md, "use_quality_normals")
col.prop(md, "edge_crease_inner")
col.prop(md, "edge_crease_outer")
col.prop(md, "edge_crease_rim")
# col = layout.column()
# col.label(text="Vertex Group:")
# col.prop_object(md, "vertex_group", ob, "vertex_groups", text="")
@@ -638,14 +646,15 @@ class DATA_PT_modifiers(DataButtonsPanel):
def UV_PROJECT(self, layout, ob, md, wide_ui):
if ob.type == 'MESH':
split = layout.split()
col = split.column()
col.label(text="UV Layer:")
col.prop_object(md, "uv_layer", ob.data, "uv_textures", text="")
col.label(text="Image:")
col.prop(md, "image", text="")
if wide_ui:
col = split.column()
col.label(text="Image:")
col.prop(md, "image", text="")
col.label(text="UV Layer:")
col.prop_object(md, "uv_layer", ob.data, "uv_textures", text="")
split = layout.split()
col = split.column()
@@ -720,4 +729,4 @@ class DATA_PT_modifiers(DataButtonsPanel):
col.prop(md, "width", slider=True)
col.prop(md, "narrowness", slider=True)
bpy.types.register(DATA_PT_modifiers)
bpy.types.register(DATA_PT_modifiers)

View File

@@ -274,8 +274,7 @@ class RENDER_PT_game_stereo(RenderButtonsPanel):
# stereo:
if stereo_mode == 'STEREO':
layout.prop(gs, "stereo_mode")
# layout.label(text="To do: Focal Length") # to be done after 2.5alpha0 is out
# layout.label(text="To do: Eye Separation") # to be done after 2.5alpha0 is out
layout.prop(gs, "eye_separation")
# dome:
elif stereo_mode == 'DOME':

View File

@@ -264,6 +264,7 @@ class PHYSICS_PT_softbody_solver(PhysicButtonsPanel):
layout.label(text="Diagnostics:")
layout.prop(softbody, "diagnose")
layout.prop(softbody, "estimate_matrix")
class PHYSICS_PT_softbody_field_weights(PhysicButtonsPanel):

View File

@@ -581,8 +581,42 @@ class RENDER_PT_stamp(RenderButtonsPanel):
sub.prop(rd, "stamp_note_text", text="")
bpy.types.register(RENDER_MT_presets)
class RENDER_PT_bake(RenderButtonsPanel):
bl_label = "Bake"
bl_default_closed = True
COMPAT_ENGINES = {'BLENDER_RENDER'}
def draw(self, context):
layout = self.layout
rd = context.scene.render_data
wide_ui = context.region.width > narrowui
row = layout.row()
row.operator("object.bake_image", icon='RENDER_STILL')
row.prop(rd, "bake_type", text="")
col = layout.column()
col.active = (rd.bake_type == 'NORMALS')
col.prop(rd, "bake_normal_space")
# col.prop(rd, "bake_aa_mode")
# col.prop(rd, "bake_enable_aa")
col = layout.column()
row = col.row(align=True)
row.prop(rd, "bake_active")
row.prop(rd, "bake_normalized")
row = col.row(align=True)
row.prop(rd, "bake_clear")
row.prop(rd, "bake_margin")
row = col.row(align=True)
row.prop(rd, "bake_distance")
row.prop(rd, "bake_bias")
bpy.types.register(RENDER_MT_presets)
bpy.types.register(RENDER_PT_render)
bpy.types.register(RENDER_PT_layers)
bpy.types.register(RENDER_PT_dimensions)
@@ -593,3 +627,4 @@ bpy.types.register(RENDER_PT_encoding)
bpy.types.register(RENDER_PT_performance)
bpy.types.register(RENDER_PT_post_processing)
bpy.types.register(RENDER_PT_stamp)
bpy.types.register(RENDER_PT_bake)

View File

@@ -131,7 +131,7 @@ class ConsoleExec(bpy.types.Operator):
return execute(context)
else:
print("Error: bpy.ops.console.execute_" + sc.language + " - not found")
return ('FINISHED',)
return {'FINISHED'}
class ConsoleAutocomplete(bpy.types.Operator):
@@ -153,11 +153,13 @@ class ConsoleAutocomplete(bpy.types.Operator):
return autocomplete(context)
else:
print("Error: bpy.ops.console.autocomplete_" + sc.language + " - not found")
return ('FINISHED',)
return {'FINISHED'}
class ConsoleBanner(bpy.types.Operator):
'''Print a message whem the terminal initializes'''
bl_idname = "console.banner"
bl_label = "Console Banner"
def execute(self, context):
sc = context.space_data
@@ -173,12 +175,13 @@ class ConsoleBanner(bpy.types.Operator):
return banner(context)
else:
print("Error: bpy.ops.console.banner_" + sc.language + " - not found")
return ('FINISHED',)
return {'FINISHED'}
class ConsoleLanguage(bpy.types.Operator):
'''Set the current language for this console'''
bl_idname = "console.language"
bl_label = "Console Language"
language = StringProperty(name="Language", maxlen=32, default="")
def execute(self, context):
@@ -193,7 +196,7 @@ class ConsoleLanguage(bpy.types.Operator):
bpy.ops.console.history_append(text="", current_character=0,
remove_duplicates=True)
return ('FINISHED',)
return {'FINISHED'}
bpy.types.register(CONSOLE_HT_header)
@@ -202,9 +205,9 @@ bpy.types.register(CONSOLE_MT_report)
bpy.types.register(CONSOLE_MT_language)
# Stubs that call the language operators
bpy.ops.add(ConsoleExec)
bpy.ops.add(ConsoleAutocomplete)
bpy.ops.add(ConsoleBanner)
bpy.types.register(ConsoleExec)
bpy.types.register(ConsoleAutocomplete)
bpy.types.register(ConsoleBanner)
# Set the language and call the banner
bpy.ops.add(ConsoleLanguage)
bpy.types.register(ConsoleLanguage)

View File

@@ -19,9 +19,6 @@
# <pep8 compliant>
import bpy
import dynamic_menu
# reload(dynamic_menu)
class INFO_HT_header(bpy.types.Header):
bl_space_type = 'INFO'
@@ -79,7 +76,7 @@ class INFO_MT_file(bpy.types.Menu):
layout.operator("wm.read_homefile", text="New", icon='NEW')
layout.operator_context = 'INVOKE_AREA'
layout.operator("wm.open_mainfile", text="Open...", icon='FILE_FOLDER')
layout.operator_menu_enum("wm.open_recentfile", "file", text="Open Recent")
layout.menu("INFO_MT_file_open_recent")
layout.operator("wm.recover_last_session")
layout.operator("wm.recover_auto_save", text="Recover Auto Save...")
@@ -115,21 +112,22 @@ class INFO_MT_file(bpy.types.Menu):
layout.operator_context = 'EXEC_AREA'
layout.operator("wm.exit_blender", text="Quit", icon='QUIT')
# test for expanding menus
'''
class INFO_MT_file_more(INFO_MT_file):
bl_label = "File"
class INFO_MT_file_open_recent(bpy.types.Menu):
bl_idname = "INFO_MT_file_open_recent"
bl_label = "Open Recent..."
def draw(self, context):
import os
layout = self.layout
layout.operator_context = 'EXEC_AREA'
file = open(os.path.join(bpy.home, ".Blog"), "rU")
for line in file:
line = line.rstrip()
layout.operator("wm.open_mainfile", text=line, icon='FILE_BLEND').path = line
file.close()
layout.operator("wm.read_homefile", text="TESTING ")
dynamic_menu.setup(INFO_MT_file_more)
'''
class INFO_MT_file_import(dynamic_menu.DynMenu):
class INFO_MT_file_import(bpy.types.Menu):
bl_idname = "INFO_MT_file_import"
bl_label = "Import"
@@ -138,7 +136,7 @@ class INFO_MT_file_import(dynamic_menu.DynMenu):
self.layout.operator("wm.collada_import", text="COLLADA (.dae)...")
class INFO_MT_file_export(dynamic_menu.DynMenu):
class INFO_MT_file_export(bpy.types.Menu):
bl_idname = "INFO_MT_file_export"
bl_label = "Export"
@@ -164,9 +162,9 @@ class INFO_MT_file_external_data(bpy.types.Menu):
layout.operator("file.find_missing_files")
class INFO_MT_mesh_add(dynamic_menu.DynMenu):
class INFO_MT_mesh_add(bpy.types.Menu):
bl_idname = "INFO_MT_mesh_add"
bl_label = "Mesh"
bl_label = "Add Mesh"
def draw(self, context):
layout = self.layout
@@ -183,7 +181,7 @@ class INFO_MT_mesh_add(dynamic_menu.DynMenu):
layout.operator("mesh.primitive_monkey_add", icon='MESH_MONKEY', text="Monkey")
class INFO_MT_armature_add(dynamic_menu.DynMenu):
class INFO_MT_armature_add(bpy.types.Menu):
bl_idname = "INFO_MT_armature_add"
bl_label = "Armature"
@@ -290,6 +288,7 @@ class INFO_MT_help(bpy.types.Menu):
bpy.types.register(INFO_HT_header)
bpy.types.register(INFO_MT_file)
bpy.types.register(INFO_MT_file_open_recent)
bpy.types.register(INFO_MT_file_import)
bpy.types.register(INFO_MT_file_export)
bpy.types.register(INFO_MT_file_external_data)
@@ -308,7 +307,7 @@ class HelpOperator(bpy.types.Operator):
def execute(self, context):
import webbrowser
webbrowser.open(self._url)
return ('FINISHED',)
return {'FINISHED'}
class HELP_OT_manual(HelpOperator):
@@ -391,14 +390,14 @@ class HELP_OT_operator_cheat_sheet(bpy.types.Operator):
textblock.write('\n'.join(op_strings))
textblock.name = "OperatorList.txt"
print("See OperatorList.txt textblock")
return ('FINISHED',)
return {'FINISHED'}
bpy.ops.add(HELP_OT_manual)
bpy.ops.add(HELP_OT_release_logs)
bpy.ops.add(HELP_OT_blender_website)
bpy.ops.add(HELP_OT_blender_eshop)
bpy.ops.add(HELP_OT_developer_community)
bpy.ops.add(HELP_OT_user_community)
bpy.ops.add(HELP_OT_report_bug)
bpy.ops.add(HELP_OT_python_api)
bpy.ops.add(HELP_OT_operator_cheat_sheet)
bpy.types.register(HELP_OT_manual)
bpy.types.register(HELP_OT_release_logs)
bpy.types.register(HELP_OT_blender_website)
bpy.types.register(HELP_OT_blender_eshop)
bpy.types.register(HELP_OT_developer_community)
bpy.types.register(HELP_OT_user_community)
bpy.types.register(HELP_OT_report_bug)
bpy.types.register(HELP_OT_python_api)
bpy.types.register(HELP_OT_operator_cheat_sheet)

View File

@@ -102,6 +102,7 @@ class TIME_MT_view(bpy.types.Menu):
layout.operator("marker.camera_bind")
class TIME_MT_frame(bpy.types.Menu):
bl_label = "Frame"

View File

@@ -21,71 +21,79 @@ import bpy
KM_HIERARCHY = [
('Window', 'EMPTY', 'WINDOW', []), # file save, window change, exit
('Screen Editing', 'EMPTY', 'WINDOW', []), # resizing, action corners
('Screen', 'EMPTY', 'WINDOW', []), # full screen, undo, screenshot
('Screen', 'EMPTY', 'WINDOW', [ # full screen, undo, screenshot
('Screen Editing', 'EMPTY', 'WINDOW', []), # resizing, action corners
]),
('View2D', 'EMPTY', 'WINDOW', []), # view 2d navigation (per region)
('Frames', 'EMPTY', 'WINDOW', []), # frame navigation (per region)
('View2D Buttons List', 'EMPTY', 'WINDOW', []), # view 2d with buttons navigation
('Header', 'EMPTY', 'WINDOW', []), # header stuff (per region)
('Markers', 'EMPTY', 'WINDOW', []), # markers (per region)
('Animation', 'EMPTY', 'WINDOW', []), # frame change on click, preview range (per region)
('Grease Pencil', 'EMPTY', 'WINDOW', []), # grease pencil stuff (per region)
('View2D Buttons List', 'EMPTY', 'WINDOW', []), # view 2d with buttons navigation
('Animation_Channels', 'EMPTY', 'WINDOW', []),
('Buttons Generic', 'PROPERTIES', 'WINDOW', []), # align context menu
('TimeLine', 'TIMELINE', 'WINDOW', []),
('Outliner', 'OUTLINER', 'WINDOW', []),
('View3D', 'VIEW_3D', 'WINDOW', [ # view 3d navigation and generic stuff (select, transform)
('Pose', 'EMPTY', 'WINDOW', []),
('3D View', 'VIEW_3D', 'WINDOW', [ # view 3d navigation and generic stuff (select, transform)
('Object Mode', 'EMPTY', 'WINDOW', []),
('Vertex Paint', 'EMPTY', 'WINDOW', []),
('Weight Paint', 'EMPTY', 'WINDOW', []),
('Face Mask', 'EMPTY', 'WINDOW', []),
('Sculpt', 'EMPTY', 'WINDOW', []),
('EditMesh', 'EMPTY', 'WINDOW', []),
('Mesh', 'EMPTY', 'WINDOW', []),
('Curve', 'EMPTY', 'WINDOW', []),
('Armature', 'EMPTY', 'WINDOW', []),
('Metaball', 'EMPTY', 'WINDOW', []),
('Lattice', 'EMPTY', 'WINDOW', []),
('Armature_Sketch', 'EMPTY', 'WINDOW', []),
('Particle', 'EMPTY', 'WINDOW', []),
('Font', 'EMPTY', 'WINDOW', []),
('Object Non-modal', 'EMPTY', 'WINDOW', []), # mode change
('Pose', 'EMPTY', 'WINDOW', []),
('Vertex Paint', 'EMPTY', 'WINDOW', []),
('Weight Paint', 'EMPTY', 'WINDOW', []),
('Face Mask', 'EMPTY', 'WINDOW', []),
('Image Paint', 'EMPTY', 'WINDOW', []), # image and view3d
('View3D Generic', 'VIEW_3D', 'WINDOW', []) # toolbar and properties
('Sculpt', 'EMPTY', 'WINDOW', []),
('Armature Sketch', 'EMPTY', 'WINDOW', []),
('Particle', 'EMPTY', 'WINDOW', []),
('Object Non-modal', 'EMPTY', 'WINDOW', []), # mode change
('3D View Generic', 'VIEW_3D', 'WINDOW', []) # toolbar and properties
]),
('GraphEdit Keys', 'GRAPH_EDITOR', 'WINDOW', [
('GraphEdit Generic', 'GRAPH_EDITOR', 'WINDOW', [])
('Frames', 'EMPTY', 'WINDOW', []), # frame navigation (per region)
('Markers', 'EMPTY', 'WINDOW', []), # markers (per region)
('Animation', 'EMPTY', 'WINDOW', []), # frame change on click, preview range (per region)
('Animation Channels', 'EMPTY', 'WINDOW', []),
('Graph Editor', 'GRAPH_EDITOR', 'WINDOW', [
('Graph Editor Generic', 'GRAPH_EDITOR', 'WINDOW', [])
]),
('Dopesheet', 'DOPESHEET_EDITOR', 'WINDOW', []),
('NLA Editor', 'NLA_EDITOR', 'WINDOW', [
('NLA Channels', 'NLA_EDITOR', 'WINDOW', []),
('NLA Generic', 'NLA_EDITOR', 'WINDOW', [])
]),
('Image', 'IMAGE_EDITOR', 'WINDOW', [
('UVEdit', 'EMPTY', 'WINDOW', []), # image (reverse order, UVEdit before Image
('UV Editor', 'EMPTY', 'WINDOW', []), # image (reverse order, UVEdit before Image
('Image Paint', 'EMPTY', 'WINDOW', []), # image and view3d
('Image Generic', 'IMAGE_EDITOR', 'WINDOW', [])
]),
('Node Generic', 'NODE_EDITOR', 'WINDOW', [
('Node', 'NODE_EDITOR', 'WINDOW', [])
('Timeline', 'TIMELINE', 'WINDOW', []),
('Outliner', 'OUTLINER', 'WINDOW', []),
('Node Editor', 'NODE_EDITOR', 'WINDOW', [
('Node Generic', 'NODE_EDITOR', 'WINDOW', [])
]),
('File', 'FILE_BROWSER', 'WINDOW', [
('FileMain', 'FILE_BROWSER', 'WINDOW', []),
('FileButtons', 'FILE_BROWSER', 'WINDOW', [])
]),
('Action_Keys', 'DOPESHEET_EDITOR', 'WINDOW', []),
('NLA Generic', 'NLA_EDITOR', 'WINDOW', [
('NLA Channels', 'NLA_EDITOR', 'WINDOW', []),
('NLA Data', 'NLA_EDITOR', 'WINDOW', [])
('Sequencer', 'SEQUENCE_EDITOR', 'WINDOW', []),
('Logic Editor', 'LOGIC_EDITOR', 'WINDOW', []),
('File Browser', 'FILE_BROWSER', 'WINDOW', [
('File Browser Main', 'FILE_BROWSER', 'WINDOW', []),
('File Browser Buttons', 'FILE_BROWSER', 'WINDOW', [])
]),
('Property Editor', 'PROPERTIES', 'WINDOW', []), # align context menu
('Script', 'SCRIPTS_WINDOW', 'WINDOW', []),
('Text', 'TEXT_EDITOR', 'WINDOW', []),
('Sequencer', 'SEQUENCE_EDITOR', 'WINDOW', []),
('Logic Generic', 'LOGIC_EDITOR', 'WINDOW', []),
('Console', 'CONSOLE', 'WINDOW', []),
('View3D Gesture Circle', 'EMPTY', 'WINDOW', []),
('Gesture Border', 'EMPTY', 'WINDOW', []),
('Standard Modal Map', 'EMPTY', 'WINDOW', []),
@@ -503,8 +511,6 @@ class USERPREF_PT_system(bpy.types.Panel):
sub.template_color_ramp(system, "weight_color_range", expand=True)
class USERPREF_PT_theme(bpy.types.Panel):
bl_space_type = 'USER_PREFERENCES'
bl_label = "Themes"
@@ -1254,10 +1260,10 @@ class USERPREF_PT_input(bpy.types.Panel):
userpref = context.user_preferences
return (userpref.active_section == 'INPUT')
def draw_entry(self, kc, entry, col, level = 0):
def draw_entry(self, kc, entry, col, level=0):
idname, spaceid, regionid, children = entry
km = kc.find_keymap(idname, space_type = spaceid, region_type = regionid)
km = kc.find_keymap(idname, space_type=spaceid, region_type=regionid)
if km:
self.draw_km(kc, km, children, col, level)
@@ -1266,9 +1272,9 @@ class USERPREF_PT_input(bpy.types.Panel):
indentpx = 16
if level == 0:
level = 0.0001 # Tweak so that a percentage of 0 won't split by half
indent = level*indentpx / bpy.context.region.width
indent = level * indentpx / bpy.context.region.width
split=layout.split(percentage=indent)
split = layout.split(percentage=indent)
col = split.column()
col = split.column()
return col
@@ -1309,7 +1315,7 @@ class USERPREF_PT_input(bpy.types.Panel):
self.draw_kmi(kc, km, kmi, col, level + 1)
# "Add New" at end of keymap item list
col = self.indented_layout(col, level+1)
col = self.indented_layout(col, level + 1)
subcol = col.split(percentage=0.2).column()
subcol.active = km.user_defined
subcol.operator("wm.keyitem_add", text="Add New", icon='ZOOMIN')
@@ -1324,7 +1330,6 @@ class USERPREF_PT_input(bpy.types.Panel):
for entry in children:
self.draw_entry(kc, entry, col, level + 1)
def draw_kmi(self, kc, km, kmi, layout, level):
layout.set_context_pointer("keyitem", kmi)
@@ -1475,8 +1480,9 @@ class USERPREF_PT_input(bpy.types.Panel):
if len(filtered_items) != 0:
km = km.active()
layout.set_context_pointer("keymap", km)
col = layout.column()
col.set_context_pointer("keymap", km)
row = col.row()
row.label(text=km.name, icon="DOT")
@@ -1491,6 +1497,12 @@ class USERPREF_PT_input(bpy.types.Panel):
for kmi in filtered_items:
self.draw_kmi(kc, km, kmi, col, 1)
# "Add New" at end of keymap item list
col = self.indented_layout(layout, 1)
subcol = col.split(percentage=0.2).column()
subcol.active = km.user_defined
subcol.operator("wm.keyitem_add", text="Add New", icon='ZOOMIN')
def draw_hierarchy(self, defkc, layout):
for entry in KM_HIERARCHY:
self.draw_entry(defkc, entry, layout)
@@ -1540,13 +1552,15 @@ bpy.types.register(USERPREF_PT_input)
from bpy.props import *
class WM_OT_keyconfig_test(bpy.types.Operator):
"Test keyconfig for conflicts."
bl_idname = "wm.keyconfig_test"
bl_label = "Test Key Configuration for Conflicts"
def testEntry(self, kc, entry, src = None, parent = None):
def testEntry(self, kc, entry, src=None, parent=None):
result = False
def kmistr(kmi):
if km.modal:
s = ["kmi = km.add_modal_item(\'%s\', \'%s\', \'%s\'" % (kmi.propvalue, kmi.type, kmi.value)]
@@ -1566,9 +1580,9 @@ class WM_OT_keyconfig_test(bpy.types.Operator):
s.append(", oskey=True")
if kmi.key_modifier and kmi.key_modifier != 'NONE':
s.append(", key_modifier=\'%s\'" % kmi.key_modifier)
s.append(")\n")
props = kmi.properties
if props is not None:
@@ -1578,16 +1592,16 @@ class WM_OT_keyconfig_test(bpy.types.Operator):
value = _string_value(value)
if value != "":
s.append("kmi.properties.%s = %s\n" % (pname, value))
return "".join(s).strip()
idname, spaceid, regionid, children = entry
km = kc.find_keymap(idname, space_type = spaceid, region_type = regionid)
km = kc.find_keymap(idname, space_type=spaceid, region_type=regionid)
if km:
km = km.active()
if src:
for item in km.items:
if src.compare(item):
@@ -1597,14 +1611,14 @@ class WM_OT_keyconfig_test(bpy.types.Operator):
print(km.name)
print(kmistr(item))
result = True
for child in children:
if self.testEntry(kc, child, src, parent):
result = True
else:
for i in range(len(km.items)):
src = km.items[i]
for child in children:
if self.testEntry(kc, child, src, km):
result = True
@@ -1617,28 +1631,29 @@ class WM_OT_keyconfig_test(bpy.types.Operator):
print(kmistr(src))
print(kmistr(item))
result = True
for child in children:
if self.testEntry(kc, child):
result = True
return result
def testConfig(self, kc):
result = False
for entry in KM_HIERARCHY:
if self.testEntry(kc, entry):
result = True
return result
def execute(self, context):
wm = context.manager
kc = wm.default_keyconfig
if self.testConfig(kc):
print("CONFLICT")
return ('FINISHED',)
return {'FINISHED'}
def _string_value(value):
result = ""
@@ -1666,7 +1681,8 @@ def _string_value(value):
print("Export key configuration: can't write ", value)
return result
class WM_OT_keyconfig_export(bpy.types.Operator):
"Export key configuration to a python script."
bl_idname = "wm.keyconfig_export"
@@ -1728,12 +1744,12 @@ class WM_OT_keyconfig_export(bpy.types.Operator):
f.close()
return ('FINISHED',)
return {'FINISHED'}
def invoke(self, context, event):
wm = context.manager
wm.add_fileselect(self)
return ('RUNNING_MODAL',)
return {'RUNNING_MODAL'}
class WM_OT_keymap_edit(bpy.types.Operator):
@@ -1745,7 +1761,7 @@ class WM_OT_keymap_edit(bpy.types.Operator):
wm = context.manager
km = context.keymap
km.copy_to_user()
return ('FINISHED',)
return {'FINISHED'}
class WM_OT_keymap_restore(bpy.types.Operator):
@@ -1765,7 +1781,8 @@ class WM_OT_keymap_restore(bpy.types.Operator):
km = context.keymap
km.restore_to_default()
return ('FINISHED',)
return {'FINISHED'}
class WM_OT_keyitem_restore(bpy.types.Operator):
"Restore key map item."
@@ -1784,8 +1801,9 @@ class WM_OT_keyitem_restore(bpy.types.Operator):
km.restore_item_to_default(kmi)
return ('FINISHED',)
return {'FINISHED'}
class WM_OT_keyitem_add(bpy.types.Operator):
"Add key map item."
bl_idname = "wm.keyitem_add"
@@ -1794,11 +1812,20 @@ class WM_OT_keyitem_add(bpy.types.Operator):
def execute(self, context):
wm = context.manager
km = context.keymap
kc = wm.default_keyconfig
if km.modal:
km.add_modal_item("", 'A', 'PRESS') # kmi
else:
km.add_item("", 'A', 'PRESS') # kmi
return ('FINISHED',)
km.add_item("none", 'A', 'PRESS') # kmi
# clear filter and expand keymap so we can see the newly added item
if kc.filter != '':
kc.filter = ''
km.items_expanded = True
km.children_expanded = True
return {'FINISHED'}
class WM_OT_keyitem_remove(bpy.types.Operator):
@@ -1811,12 +1838,12 @@ class WM_OT_keyitem_remove(bpy.types.Operator):
kmi = context.keyitem
km = context.keymap
km.remove_item(kmi)
return ('FINISHED',)
return {'FINISHED'}
bpy.ops.add(WM_OT_keyconfig_export)
bpy.ops.add(WM_OT_keyconfig_test)
bpy.ops.add(WM_OT_keymap_edit)
bpy.ops.add(WM_OT_keymap_restore)
bpy.ops.add(WM_OT_keyitem_add)
bpy.ops.add(WM_OT_keyitem_remove)
bpy.ops.add(WM_OT_keyitem_restore)
bpy.types.register(WM_OT_keyconfig_export)
bpy.types.register(WM_OT_keyconfig_test)
bpy.types.register(WM_OT_keymap_edit)
bpy.types.register(WM_OT_keymap_restore)
bpy.types.register(WM_OT_keyitem_add)
bpy.types.register(WM_OT_keyitem_remove)
bpy.types.register(WM_OT_keyitem_restore)

View File

@@ -18,7 +18,6 @@
# <pep8 compliant>
import bpy
import dynamic_menu
class VIEW3D_HT_header(bpy.types.Header):
@@ -205,7 +204,7 @@ class VIEW3D_MT_snap(bpy.types.Menu):
layout.operator("view3d.snap_cursor_to_active", text="Cursor to Active")
class VIEW3D_MT_uv_map(dynamic_menu.DynMenu):
class VIEW3D_MT_uv_map(bpy.types.Menu):
bl_label = "UV Mapping"
def draw(self, context):
@@ -456,6 +455,7 @@ class VIEW3D_MT_select_edit_mesh(bpy.types.Menu):
layout.separator()
layout.operator("mesh.select_random", text="Random...")
layout.operator("mesh.select_nth", text="Select Nth...")
layout.operator("mesh.edges_select_sharp", text="Sharp Edges")
layout.operator("mesh.faces_select_linked_flat", text="Linked Flat Faces")
layout.operator("mesh.faces_select_interior", text="Interior Faces")
@@ -902,6 +902,24 @@ class VIEW3D_MT_particle(bpy.types.Menu):
layout.menu("VIEW3D_MT_particle_showhide")
class VIEW3D_MT_particle_specials(bpy.types.Menu):
bl_label = "Specials"
def draw(self, context):
layout = self.layout
particle_edit = context.tool_settings.particle_edit
layout.operator("particle.rekey")
layout.separator()
if particle_edit.selection_mode == 'POINT':
layout.operator("particle.subdivide")
layout.operator("particle.select_first")
layout.operator("particle.select_last")
layout.operator("particle.remove_doubles")
class VIEW3D_MT_particle_showhide(VIEW3D_MT_showhide):
_operator_name = "particle"
@@ -1121,6 +1139,27 @@ class VIEW3D_MT_edit_mesh_specials(bpy.types.Menu):
layout.operator("mesh.select_vertex_path")
class VIEW3D_MT_edit_mesh_selection_mode(bpy.types.Menu):
bl_label = "Mesh Select Mode"
def draw(self, context):
layout = self.layout
layout.operator_context = 'INVOKE_REGION_WIN'
prop = layout.operator("wm.context_set_value", text="Vertex", icon='VERTEXSEL')
prop.value = "(True, False, False)"
prop.path = "tool_settings.mesh_selection_mode"
prop = layout.operator("wm.context_set_value", text="Edge", icon='EDGESEL')
prop.value = "(False, True, False)"
prop.path = "tool_settings.mesh_selection_mode"
prop = layout.operator("wm.context_set_value", text="Face", icon='FACESEL')
prop.value = "(False, False, True)"
prop.path = "tool_settings.mesh_selection_mode"
class VIEW3D_MT_edit_mesh_vertices(bpy.types.Menu):
bl_label = "Vertices"
@@ -1190,7 +1229,7 @@ class VIEW3D_MT_edit_mesh_edges(bpy.types.Menu):
layout.operator("mesh.region_to_loop")
class VIEW3D_MT_edit_mesh_faces(dynamic_menu.DynMenu):
class VIEW3D_MT_edit_mesh_faces(bpy.types.Menu):
bl_label = "Faces"
bl_idname = "VIEW3D_MT_edit_mesh_faces"
@@ -1323,6 +1362,20 @@ class VIEW3D_MT_edit_curve_segments(bpy.types.Menu):
layout.operator("curve.switch_direction")
class VIEW3D_MT_edit_curve_specials(bpy.types.Menu):
bl_label = "Specials"
def draw(self, context):
layout = self.layout
layout.operator("curve.subdivide")
layout.operator("curve.switch_direction")
layout.operator("curve.spline_weight_set")
layout.operator("curve.radius_set")
layout.operator("curve.smooth")
layout.operator("curve.smooth_radius")
class VIEW3D_MT_edit_curve_showhide(VIEW3D_MT_showhide):
_operator_name = "curve"
@@ -1901,7 +1954,8 @@ bpy.types.register(VIEW3D_MT_sculpt) # Sculpt Menu
bpy.types.register(VIEW3D_MT_paint_vertex)
bpy.types.register(VIEW3D_MT_particle) # Particle Menu
bpy.types.register(VIEW3D_MT_particle)# Particle Menu
bpy.types.register(VIEW3D_MT_particle_specials)
bpy.types.register(VIEW3D_MT_particle_showhide)
bpy.types.register(VIEW3D_MT_pose) # POSE Menu
@@ -1915,6 +1969,7 @@ bpy.types.register(VIEW3D_MT_pose_showhide)
bpy.types.register(VIEW3D_MT_edit_mesh)
bpy.types.register(VIEW3D_MT_edit_mesh_specials) # Only as a menu for keybindings
bpy.types.register(VIEW3D_MT_edit_mesh_selection_mode) # Only as a menu for keybindings
bpy.types.register(VIEW3D_MT_edit_mesh_vertices)
bpy.types.register(VIEW3D_MT_edit_mesh_edges)
bpy.types.register(VIEW3D_MT_edit_mesh_faces)
@@ -1924,6 +1979,7 @@ bpy.types.register(VIEW3D_MT_edit_mesh_showhide)
bpy.types.register(VIEW3D_MT_edit_curve)
bpy.types.register(VIEW3D_MT_edit_curve_ctrlpoints)
bpy.types.register(VIEW3D_MT_edit_curve_segments)
bpy.types.register(VIEW3D_MT_edit_curve_specials)
bpy.types.register(VIEW3D_MT_edit_curve_showhide)
bpy.types.register(VIEW3D_MT_edit_surface)

View File

@@ -498,7 +498,15 @@ class VIEW3D_PT_tools_brush(PaintPanel):
if not context.particle_edit_object:
col = layout.split().column()
row = col.row()
row.template_list(settings, "brushes", settings, "active_brush_index", rows=2)
if context.sculpt_object and brush:
defaulttools = 8
elif context.texture_paint_object and brush:
defaulttools = 4
else:
defaulttools = 2
row.template_list(settings, "brushes", settings, "active_brush_index", rows=2, maxrows=defaulttools)
col.template_ID(settings, "brush", new="brush.add")
@@ -531,8 +539,6 @@ class VIEW3D_PT_tools_brush(PaintPanel):
elif context.sculpt_object and brush:
col = layout.column()
col.separator()
col.prop(brush, "sculpt_tool", expand=True)
col.separator()
row = col.row(align=True)
row.prop(brush, "size", slider=True)
@@ -563,12 +569,6 @@ class VIEW3D_PT_tools_brush(PaintPanel):
# Texture Paint Mode #
elif context.texture_paint_object and brush:
col = layout.column(align=True)
col.prop_enum(settings, "tool", 'DRAW')
col.prop_enum(settings, "tool", 'SOFTEN')
col.prop_enum(settings, "tool", 'CLONE')
col.prop_enum(settings, "tool", 'SMEAR')
col = layout.column()
col.prop(brush, "color", text="")
@@ -624,6 +624,33 @@ class VIEW3D_PT_tools_brush(PaintPanel):
#row.prop(brush, "jitter", slider=True)
#row.prop(brush, "use_jitter_pressure", toggle=True, text="")
class VIEW3D_PT_tools_brush_tool(PaintPanel):
bl_label = "Tool"
bl_default_closed = True
def poll(self, context):
settings = self.paint_settings(context)
return (settings and settings.brush and (context.sculpt_object or
context.texture_paint_object))
def draw(self, context):
layout = self.layout
settings = self.paint_settings(context)
brush = settings.brush
texture_paint = context.texture_paint_object
sculpt = context.sculpt_object
col = layout.column(align=True)
if context.sculpt_object:
col.prop(brush, "sculpt_tool", expand=True)
elif context.texture_paint_object:
col.prop_enum(settings, "tool", 'DRAW')
col.prop_enum(settings, "tool", 'SOFTEN')
col.prop_enum(settings, "tool", 'CLONE')
col.prop_enum(settings, "tool", 'SMEAR')
class VIEW3D_PT_tools_brush_stroke(PaintPanel):
bl_label = "Stroke"
@@ -690,7 +717,7 @@ class VIEW3D_PT_sculpt_options(PaintPanel):
bl_label = "Options"
def poll(self, context):
return context.sculpt_object
return (context.sculpt_object and context.tool_settings.sculpt)
def draw(self, context):
layout = self.layout
@@ -826,24 +853,50 @@ class VIEW3D_PT_tools_projectpaint(View3DPanel):
col.active = (ipaint.use_normal_falloff and use_projection)
col.prop(ipaint, "normal_angle", text="")
split = layout.split(percentage=0.7)
col = layout.column(align=False)
row = col.row()
row.active = (use_projection)
row.prop(ipaint, "use_stencil_layer", text="Stencil")
col = split.column(align=False)
col.active = (use_projection)
col.prop(ipaint, "use_stencil_layer")
col = split.column(align=False)
col.active = (use_projection and ipaint.use_stencil_layer)
col.prop(ipaint, "invert_stencil", text="Inv")
row2 = row.row(align=False)
row2.active = (use_projection and ipaint.use_stencil_layer)
row2.menu("VIEW3D_MT_tools_projectpaint_stencil", text=context.active_object.data.uv_texture_stencil.name)
row2.prop(ipaint, "invert_stencil", text="", icon='IMAGE_ALPHA')
col = layout.column()
sub = col.column()
sub.active = (settings.tool == 'CLONE')
sub.prop(ipaint, "use_clone_layer")
row = sub.row()
row.active = (settings.tool == 'CLONE')
row.prop(ipaint, "use_clone_layer", text="Clone")
row.menu("VIEW3D_MT_tools_projectpaint_clone", text=context.active_object.data.uv_texture_clone.name)
sub = col.column()
sub.prop(ipaint, "seam_bleed")
class VIEW3D_MT_tools_projectpaint_clone(bpy.types.Menu):
bl_label = "Clone Layer"
def draw(self, context):
layout = self.layout
for i, tex in enumerate(context.active_object.data.uv_textures):
prop = layout.operator("wm.context_set_int", text=tex.name)
prop.path = "active_object.data.uv_texture_clone_index"
prop.value = i
class VIEW3D_MT_tools_projectpaint_stencil(bpy.types.Menu):
bl_label = "Mask Layer"
def draw(self, context):
layout = self.layout
for i, tex in enumerate(context.active_object.data.uv_textures):
prop = layout.operator("wm.context_set_int", text=tex.name)
prop.path = "active_object.data.uv_texture_stencil_index"
prop.value = i
bpy.types.register(VIEW3D_MT_tools_projectpaint_clone)
bpy.types.register(VIEW3D_MT_tools_projectpaint_stencil)
class VIEW3D_PT_tools_particlemode(View3DPanel):
'''default tools for particle mode'''
@@ -922,6 +975,7 @@ bpy.types.register(VIEW3D_PT_tools_latticeedit)
bpy.types.register(VIEW3D_PT_tools_posemode)
bpy.types.register(VIEW3D_PT_tools_posemode_options)
bpy.types.register(VIEW3D_PT_tools_brush)
bpy.types.register(VIEW3D_PT_tools_brush_tool)
bpy.types.register(VIEW3D_PT_tools_brush_stroke)
bpy.types.register(VIEW3D_PT_tools_brush_curve)
bpy.types.register(VIEW3D_PT_sculpt_options)

View File

@@ -16,8 +16,6 @@
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
import unittest
import random

View File

@@ -137,6 +137,10 @@ ifeq ($(WITH_SNDFILE),true)
COMLIB += $(NAN_AUDASPACE)/lib/$(DEBUG_DIR)libaud_sndfile.a
endif
ifeq ($(WITH_FFTW3),true)
COMLIB += $(NAN_AUDASPACE)/lib/$(DEBUG_DIR)libaud_fftw.a
endif
ifneq ($(NAN_NO_KETSJI),true)
COMLIB += $(OCGDIR)/gameengine/bloutines/$(DEBUG_DIR)libbloutines.a
COMLIB += $(OCGDIR)/gameengine/blconverter/$(DEBUG_DIR)libblconverter.a

View File

@@ -182,11 +182,11 @@ AviError AVI_print_error (AviError in_error) {
return in_error;
}
/*
void AVI_set_debug (int mode) {
AVI_DEBUG= mode;
}
*/
/*
int AVI_is_avi (char *name) {
FILE *fp;

View File

@@ -198,11 +198,11 @@ int CustomData_get_named_layer_index(const struct CustomData *data, int type, ch
int CustomData_get_active_layer_index(const struct CustomData *data, int type);
int CustomData_get_render_layer_index(const struct CustomData *data, int type);
int CustomData_get_clone_layer_index(const struct CustomData *data, int type);
int CustomData_get_mask_layer_index(const struct CustomData *data, int type);
int CustomData_get_stencil_layer_index(const struct CustomData *data, int type);
int CustomData_get_active_layer(const struct CustomData *data, int type);
int CustomData_get_render_layer(const struct CustomData *data, int type);
int CustomData_get_clone_layer(const struct CustomData *data, int type);
int CustomData_get_mask_layer(const struct CustomData *data, int type);
int CustomData_get_stencil_layer(const struct CustomData *data, int type);
/* copies the data from source to the data element at index in the first
* layer of type
@@ -231,13 +231,13 @@ void *CustomData_set_layer_n(const struct CustomData *data, int type, int n, voi
void CustomData_set_layer_active(struct CustomData *data, int type, int n);
void CustomData_set_layer_render(struct CustomData *data, int type, int n);
void CustomData_set_layer_clone(struct CustomData *data, int type, int n);
void CustomData_set_layer_mask(struct CustomData *data, int type, int n);
void CustomData_set_layer_stencil(struct CustomData *data, int type, int n);
/* same as above but works with an index from CustomData_get_layer_index */
void CustomData_set_layer_active_index(struct CustomData *data, int type, int n);
void CustomData_set_layer_render_index(struct CustomData *data, int type, int n);
void CustomData_set_layer_clone_index(struct CustomData *data, int type, int n);
void CustomData_set_layer_mask_index(struct CustomData *data, int type, int n);
void CustomData_set_layer_stencil_index(struct CustomData *data, int type, int n);
/* adds flag to the layer flags */
void CustomData_set_layer_flag(struct CustomData *data, int type, int flag);

View File

@@ -158,7 +158,12 @@ void copy_fcurves(ListBase *dst, ListBase *src);
struct FCurve *list_find_fcurve(ListBase *list, const char rna_path[], const int array_index);
/* high level function to get an fcurve from C without having the rna */
struct FCurve *id_data_find_fcurve(ID* id, void *data, struct StructRNA *type, char *prop_name, int index);
struct FCurve *id_data_find_fcurve(ID *id, void *data, struct StructRNA *type, char *prop_name, int index);
/* Get list of LinkData's containing pointers to the F-Curves which control the types of data indicated
* e.g. numMatches = list_find_data_fcurves(matches, &act->curves, "pose.bones[", "MyFancyBone");
*/
int list_find_data_fcurves(ListBase *dst, ListBase *src, const char *dataPrefix, const char *dataName);
/* Binary search algorithm for finding where to 'insert' BezTriple with given frame number.
* Returns the index to insert at (data already at that index will be offset if replace is 0)

View File

@@ -59,7 +59,7 @@ void key_curve_normal_weights(float t, float *data, int type);
float *do_ob_key(struct Scene *scene, struct Object *ob);
struct Key *ob_get_key(struct Object *ob);
struct KeyBlock *add_keyblock(struct Scene *scene, struct Key *key);
struct KeyBlock *add_keyblock(struct Key *key, char *name);
struct KeyBlock *ob_get_keyblock(struct Object *ob);
struct KeyBlock *ob_get_reference_keyblock(struct Object *ob);
struct KeyBlock *key_get_keyblock(struct Key *key, int index);
@@ -68,6 +68,14 @@ char *key_get_curValue_rnaPath(struct Key *key, struct KeyBlock *kb);
// needed for the GE
void do_rel_key(int start, int end, int tot, char *basispoin, struct Key *key, struct KeyBlock *actkb, int mode);
/* conversion functions */
void key_to_mesh(struct KeyBlock *kb, struct Mesh *me);
void mesh_to_key(struct Mesh *me, struct KeyBlock *kb);
void key_to_latt(struct KeyBlock *kb, struct Lattice *lt);
void latt_to_key(struct Lattice *lt, struct KeyBlock *kb);
void key_to_curve(struct KeyBlock *kb, struct Curve *cu, struct ListBase *nurb);
void curve_to_key(struct Curve *cu, struct KeyBlock *kb, struct ListBase *nurb);
#ifdef __cplusplus
};
#endif

View File

@@ -120,6 +120,7 @@ int give_obdata_texspace(struct Object *ob, short **texflag, float **loc, float
int object_insert_ptcache(struct Object *ob);
// void object_delete_ptcache(struct Object *ob, int index);
struct KeyBlock *object_insert_shape_key(struct Scene *scene, struct Object *ob, char *name, int from_mix);
#ifdef __cplusplus

View File

@@ -55,7 +55,7 @@ struct uiMenuItem;
ED_spacetypes_init() in editors/area/spacetypes.c */
/* an editor in Blender is a combined ScrArea + SpaceType + SpaceData */
#define BKE_ST_MAXNAME 32
#define BKE_ST_MAXNAME 64
typedef struct SpaceType {
struct SpaceType *next, *prev;
@@ -220,8 +220,6 @@ const struct ListBase *BKE_spacetypes_list(void);
void BKE_spacetype_register(struct SpaceType *st);
void BKE_spacetypes_free(void); /* only for quitting blender */
// MenuType *BKE_spacemenu_find(const char *idname, int spacetype);
/* spacedata */
void BKE_spacedata_freelist(ListBase *lb);
void BKE_spacedata_copylist(ListBase *lb1, ListBase *lb2);

View File

@@ -195,7 +195,7 @@ void free_imbuf_seq(struct Scene *scene, struct ListBase * seqbasep, int check_m
void seq_update_sound(struct Sequence *seq);
void seq_update_muting(struct Editing *ed);
void seqbase_sound_reload(Scene *scene, ListBase *seqbase);
void clear_scene_in_allseqs(struct Scene *sce);
struct Sequence *get_seq_by_name(struct ListBase *seqbase, const char *name, int recursive);

View File

@@ -37,17 +37,19 @@ extern "C" {
/* generic blender movie support, could move to own module */
struct RenderData;
struct ReportList;
struct Scene;
void start_avi(struct Scene *scene, struct RenderData *rd, int rectx, int recty);
int start_avi(struct Scene *scene, struct RenderData *rd, int rectx, int recty, struct ReportList *reports);
void end_avi(void);
void append_avi(struct RenderData *rd, int frame, int *pixels, int rectx, int recty);
int append_avi(struct RenderData *rd, int frame, int *pixels, int rectx, int recty, struct ReportList *reports);
void makeavistring (struct RenderData *rd, char *string);
typedef struct bMovieHandle {
void (*start_movie)(struct Scene *scene, struct RenderData *rd, int rectx, int recty);
void (*append_movie)(struct RenderData *rd, int frame, int *pixels, int rectx, int recty);
int (*start_movie)(struct Scene *scene, struct RenderData *rd, int rectx, int recty, struct ReportList *reports);
int (*append_movie)(struct RenderData *rd, int frame, int *pixels, int rectx, int recty, struct ReportList *reports);
void (*end_movie)(void);
int (*get_next_frame)(struct RenderData *rd); /* optional */
int (*get_next_frame)(struct RenderData *rd, struct ReportList *reports); /* optional */
} bMovieHandle;
bMovieHandle *BKE_get_movie_handle(int imtype);

View File

@@ -57,11 +57,12 @@ extern "C" {
struct IDProperty;
struct RenderData;
struct ReportList;
struct Scene;
extern void start_ffmpeg(struct Scene *scene, struct RenderData *rd, int rectx, int recty);
extern int start_ffmpeg(struct Scene *scene, struct RenderData *rd, int rectx, int recty, struct ReportList *reports);
extern void end_ffmpeg(void);
extern void append_ffmpeg(struct RenderData *rd, int frame, int *pixels, int rectx, int recty);
extern int append_ffmpeg(struct RenderData *rd, int frame, int *pixels, int rectx, int recty, struct ReportList *reports);
extern void ffmpeg_set_preset(struct RenderData *rd, int preset);
extern void ffmpeg_verify_image_type(struct RenderData *rd);

View File

@@ -33,12 +33,13 @@ extern "C" {
#endif
struct RenderData;
struct ReportList;
struct Scene;
extern void start_frameserver(struct Scene *scene, struct RenderData *rd, int rectx, int recty);
extern int start_frameserver(struct Scene *scene, struct RenderData *rd, int rectx, int recty, struct ReportList *reports);
extern void end_frameserver(void);
extern void append_frameserver(struct RenderData *rd, int frame, int *pixels, int rectx, int recty);
extern int frameserver_loop(struct RenderData *rd);
extern int append_frameserver(struct RenderData *rd, int frame, int *pixels, int rectx, int recty, struct ReportList *reports);
extern int frameserver_loop(struct RenderData *rd, struct ReportList *reports);
#ifdef __cplusplus
}

View File

@@ -379,19 +379,10 @@ bActionGroup *action_groups_find_named (bAction *act, const char name[])
/* usually used within a loop, so we got a N^2 slowdown */
bPoseChannel *get_pose_channel(const bPose *pose, const char *name)
{
bPoseChannel *chan;
if (ELEM(NULL, pose, name) || (name[0] == 0))
return NULL;
for (chan=pose->chanbase.first; chan; chan=chan->next) {
if (chan->name[0] == name[0]) {
if (!strcmp (chan->name, name))
return chan;
}
}
return NULL;
return BLI_findstring(&pose->chanbase, name, offsetof(bPoseChannel, name));
}
/* Use with care, not on Armature poses but for temporal ones */

View File

@@ -72,7 +72,7 @@ static short id_has_animdata (ID *id)
switch (GS(id->name)) {
/* has AnimData */
case ID_OB:
case ID_MB: case ID_CU: case ID_AR:
case ID_ME: case ID_MB: case ID_CU: case ID_AR:
case ID_KE:
case ID_PA:
case ID_MA: case ID_TE: case ID_NT:
@@ -1774,7 +1774,7 @@ void BKE_animsys_evaluate_all_animation (Main *main, float ctime)
EVAL_ANIM_IDS(main->armature.first, ADT_RECALC_ANIM);
/* meshes */
// TODO...
EVAL_ANIM_IDS(main->mesh.first, ADT_RECALC_ANIM);
/* particles */
EVAL_ANIM_IDS(main->particle.first, ADT_RECALC_ANIM);

View File

@@ -40,6 +40,8 @@
#include "DNA_scene_types.h"
#include "DNA_windowmanager_types.h"
#include "WM_types.h"
#include "RNA_access.h"
#include "BLI_math.h"
@@ -56,6 +58,8 @@
#include "BKE_texture.h"
#include "BKE_utildefines.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"

View File

@@ -1006,7 +1006,7 @@ int CustomData_get_clone_layer_index(const CustomData *data, int type)
return -1;
}
int CustomData_get_mask_layer_index(const CustomData *data, int type)
int CustomData_get_stencil_layer_index(const CustomData *data, int type)
{
int i;
@@ -1050,7 +1050,7 @@ int CustomData_get_clone_layer(const CustomData *data, int type)
return -1;
}
int CustomData_get_mask_layer(const CustomData *data, int type)
int CustomData_get_stencil_layer(const CustomData *data, int type)
{
int i;
@@ -1088,7 +1088,7 @@ void CustomData_set_layer_clone(CustomData *data, int type, int n)
data->layers[i].active_clone = n;
}
void CustomData_set_layer_mask(CustomData *data, int type, int n)
void CustomData_set_layer_stencil(CustomData *data, int type, int n)
{
int i;
@@ -1125,7 +1125,7 @@ void CustomData_set_layer_clone_index(CustomData *data, int type, int n)
data->layers[i].active_clone = n-i;
}
void CustomData_set_layer_mask_index(CustomData *data, int type, int n)
void CustomData_set_layer_stencil_index(CustomData *data, int type, int n)
{
int i;

Some files were not shown because too many files have changed in this diff Show More