diff options
487 files changed, 14462 insertions, 7880 deletions
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp index 7159f552829..5c645f82a45 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp @@ -412,31 +412,6 @@ void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTra // restore collisionObject->internalSetTemporaryCollisionShape(saveCollisionShape); } - } else { - if (collisionShape->isSoftBody()) { - btSoftBody* softBody = static_cast<btSoftBody*>(collisionObject); - btSoftBody::sRayCast softResult; - if (softBody->rayTest(rayFromTrans.getOrigin(), rayToTrans.getOrigin(), softResult)) - { - btCollisionWorld::LocalShapeInfo shapeInfo; - shapeInfo.m_shapePart = 0; - shapeInfo.m_triangleIndex = softResult.index; - // get the normal - btVector3 normal = softBody->m_faces[softResult.index].m_normal; - btVector3 rayDir = rayToTrans.getOrigin() - rayFromTrans.getOrigin(); - if (normal.dot(rayDir) > 0) { - // normal always point toward origin of the ray - normal = -normal; - } - btCollisionWorld::LocalRayResult rayResult - (collisionObject, - &shapeInfo, - normal, - softResult.fraction); - bool normalInWorldSpace = true; - resultCallback.addSingleResult(rayResult,normalInWorldSpace); - } - } } } } diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h index 87f7137a55b..24343938e5c 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h @@ -354,7 +354,7 @@ public: /// rayTest performs a raycast on all objects in the btCollisionWorld, and calls the resultCallback /// This allows for several queries: first hit, all hits, any hit, dependent on the value returned by the callback. - void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const; + virtual void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const; // convexTest performs a swept convex cast on all objects in the btCollisionWorld, and calls the resultCallback // This allows for several queries: first hit, all hits, any hit, dependent on the value return by the callback. diff --git a/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp b/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp index a0069b95145..982ec3e5eb3 100644 --- a/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp +++ b/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp @@ -22,6 +22,7 @@ subject to the following restrictions: #include "btSoftBodyHelpers.h" +//#define USE_BRUTEFORCE_RAYBROADPHASE 1 @@ -140,3 +141,140 @@ void btSoftRigidDynamicsWorld::debugDrawWorld() } } } + + +struct btSoftSingleRayCallback : public btBroadphaseRayCallback +{ + btVector3 m_rayFromWorld; + btVector3 m_rayToWorld; + btTransform m_rayFromTrans; + btTransform m_rayToTrans; + btVector3 m_hitNormal; + + const btSoftRigidDynamicsWorld* m_world; + btCollisionWorld::RayResultCallback& m_resultCallback; + + btSoftSingleRayCallback(const btVector3& rayFromWorld,const btVector3& rayToWorld,const btSoftRigidDynamicsWorld* world,btCollisionWorld::RayResultCallback& resultCallback) + :m_rayFromWorld(rayFromWorld), + m_rayToWorld(rayToWorld), + m_world(world), + m_resultCallback(resultCallback) + { + m_rayFromTrans.setIdentity(); + m_rayFromTrans.setOrigin(m_rayFromWorld); + m_rayToTrans.setIdentity(); + m_rayToTrans.setOrigin(m_rayToWorld); + + btVector3 rayDir = (rayToWorld-rayFromWorld); + + rayDir.normalize (); + ///what about division by zero? --> just set rayDirection[i] to INF/1e30 + m_rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[0]; + m_rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[1]; + m_rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[2]; + m_signs[0] = m_rayDirectionInverse[0] < 0.0; + m_signs[1] = m_rayDirectionInverse[1] < 0.0; + m_signs[2] = m_rayDirectionInverse[2] < 0.0; + + m_lambda_max = rayDir.dot(m_rayToWorld-m_rayFromWorld); + + } + + + + virtual bool process(const btBroadphaseProxy* proxy) + { + ///terminate further ray tests, once the closestHitFraction reached zero + if (m_resultCallback.m_closestHitFraction == btScalar(0.f)) + return false; + + btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject; + + //only perform raycast if filterMask matches + if(m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) + { + //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject(); + //btVector3 collisionObjectAabbMin,collisionObjectAabbMax; +#if 0 +#ifdef RECALCULATE_AABB + btVector3 collisionObjectAabbMin,collisionObjectAabbMax; + collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax); +#else + //getBroadphase()->getAabb(collisionObject->getBroadphaseHandle(),collisionObjectAabbMin,collisionObjectAabbMax); + const btVector3& collisionObjectAabbMin = collisionObject->getBroadphaseHandle()->m_aabbMin; + const btVector3& collisionObjectAabbMax = collisionObject->getBroadphaseHandle()->m_aabbMax; +#endif +#endif + //btScalar hitLambda = m_resultCallback.m_closestHitFraction; + //culling already done by broadphase + //if (btRayAabb(m_rayFromWorld,m_rayToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,m_hitNormal)) + { + m_world->rayTestSingle(m_rayFromTrans,m_rayToTrans, + collisionObject, + collisionObject->getCollisionShape(), + collisionObject->getWorldTransform(), + m_resultCallback); + } + } + return true; + } +}; + +void btSoftRigidDynamicsWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const +{ + BT_PROFILE("rayTest"); + /// use the broadphase to accelerate the search for objects, based on their aabb + /// and for each object with ray-aabb overlap, perform an exact ray test + btSoftSingleRayCallback rayCB(rayFromWorld,rayToWorld,this,resultCallback); + +#ifndef USE_BRUTEFORCE_RAYBROADPHASE + m_broadphasePairCache->rayTest(rayFromWorld,rayToWorld,rayCB); +#else + for (int i=0;i<this->getNumCollisionObjects();i++) + { + rayCB.process(m_collisionObjects[i]->getBroadphaseHandle()); + } +#endif //USE_BRUTEFORCE_RAYBROADPHASE + +} + + +void btSoftRigidDynamicsWorld::rayTestSingle(const btTransform& rayFromTrans,const btTransform& rayToTrans, + btCollisionObject* collisionObject, + const btCollisionShape* collisionShape, + const btTransform& colObjWorldTransform, + RayResultCallback& resultCallback) +{ + if (collisionShape->isSoftBody()) { + btSoftBody* softBody = btSoftBody::upcast(collisionObject); + if (softBody) { + btSoftBody::sRayCast softResult; + if (softBody->rayTest(rayFromTrans.getOrigin(), rayToTrans.getOrigin(), softResult)) + { + if (softResult.fraction<= resultCallback.m_closestHitFraction) + { + btCollisionWorld::LocalShapeInfo shapeInfo; + shapeInfo.m_shapePart = 0; + shapeInfo.m_triangleIndex = softResult.index; + // get the normal + btVector3 normal = softBody->m_faces[softResult.index].m_normal; + btVector3 rayDir = rayToTrans.getOrigin() - rayFromTrans.getOrigin(); + if (normal.dot(rayDir) > 0) { + // normal must always point toward origin of the ray + normal = -normal; + } + btCollisionWorld::LocalRayResult rayResult + (collisionObject, + &shapeInfo, + normal, + softResult.fraction); + bool normalInWorldSpace = true; + resultCallback.addSingleResult(rayResult,normalInWorldSpace); + } + } + } + } + else { + btCollisionWorld::rayTestSingle(rayFromTrans,rayToTrans,collisionObject,collisionShape,colObjWorldTransform,resultCallback); + } +} diff --git a/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.h b/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.h index edb848e2481..14220ee7564 100644 --- a/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.h +++ b/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.h @@ -77,6 +77,17 @@ public: return m_softBodies; } + virtual void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const; + + /// rayTestSingle performs a raycast call and calls the resultCallback. It is used internally by rayTest. + /// In a future implementation, we consider moving the ray test as a virtual method in btCollisionShape. + /// This allows more customization. + static void rayTestSingle(const btTransform& rayFromTrans,const btTransform& rayToTrans, + btCollisionObject* collisionObject, + const btCollisionShape* collisionShape, + const btTransform& colObjWorldTransform, + RayResultCallback& resultCallback); + }; #endif //BT_SOFT_RIGID_DYNAMICS_WORLD_H diff --git a/intern/audaspace/FX/AUD_AccumulatorFactory.cpp b/intern/audaspace/FX/AUD_AccumulatorFactory.cpp new file mode 100644 index 00000000000..20709c57ee5 --- /dev/null +++ b/intern/audaspace/FX/AUD_AccumulatorFactory.cpp @@ -0,0 +1,49 @@ +/* + * $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_AccumulatorFactory.h" +#include "AUD_AccumulatorReader.h" + +AUD_AccumulatorFactory::AUD_AccumulatorFactory(AUD_IFactory* factory, + bool additive) : + AUD_EffectFactory(factory), + m_additive(additive) {} + +AUD_AccumulatorFactory::AUD_AccumulatorFactory(bool additive) : + AUD_EffectFactory(0), + m_additive(additive) {} + +AUD_IReader* AUD_AccumulatorFactory::createReader() +{ + AUD_IReader* reader = getReader(); + + if(reader != 0) + { + reader = new AUD_AccumulatorReader(reader, m_additive); + AUD_NEW("reader") + } + + return reader; +} diff --git a/intern/audaspace/FX/AUD_AccumulatorFactory.h b/intern/audaspace/FX/AUD_AccumulatorFactory.h new file mode 100644 index 00000000000..e475a19ccf6 --- /dev/null +++ b/intern/audaspace/FX/AUD_AccumulatorFactory.h @@ -0,0 +1,59 @@ +/* + * $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_ACCUMULATORFACTORY +#define AUD_ACCUMULATORFACTORY + +#include "AUD_EffectFactory.h" + +/** + * This factory creates an accumulator reader. + */ +class AUD_AccumulatorFactory : public AUD_EffectFactory +{ +private: + /** + * Whether the accumulator is additive. + */ + bool m_additive; + +public: + /** + * Creates a new accumulator factory. + * \param factory The input factory. + * \param additive Whether the accumulator is additive. + */ + AUD_AccumulatorFactory(AUD_IFactory* factory, bool additive = false); + + /** + * Creates a new accumulator factory. + * \param additive Whether the accumulator is additive. + */ + AUD_AccumulatorFactory(bool additive = false); + + virtual AUD_IReader* createReader(); +}; + +#endif //AUD_ACCUMULATORFACTORY diff --git a/intern/audaspace/FX/AUD_AccumulatorReader.cpp b/intern/audaspace/FX/AUD_AccumulatorReader.cpp new file mode 100644 index 00000000000..67ab4157f9c --- /dev/null +++ b/intern/audaspace/FX/AUD_AccumulatorReader.cpp @@ -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 ***** + */ + +#include "AUD_AccumulatorReader.h" +#include "AUD_Buffer.h" + +#include <cstring> + +#define CC specs.channels + channel + +AUD_AccumulatorReader::AUD_AccumulatorReader(AUD_IReader* reader, + bool additive) : + AUD_EffectReader(reader), + m_additive(additive) +{ + AUD_Specs specs = reader->getSpecs(); + int samplesize = AUD_SAMPLE_SIZE(specs); + + m_buffer = new AUD_Buffer(); AUD_NEW("buffer") + + m_sums = new AUD_Buffer(samplesize); AUD_NEW("buffer") + memset(m_sums->getBuffer(), 0, samplesize); + + m_prevs = new AUD_Buffer(samplesize); AUD_NEW("buffer") + memset(m_prevs->getBuffer(), 0, samplesize); +} + +AUD_AccumulatorReader::~AUD_AccumulatorReader() +{ + delete m_buffer; AUD_DELETE("buffer") + delete m_sums; AUD_DELETE("buffer") + delete m_prevs; AUD_DELETE("buffer") +} + +void AUD_AccumulatorReader::read(int & length, sample_t* & buffer) +{ + sample_t* buf; + sample_t* sums; + sample_t* prevs; + sums = m_sums->getBuffer(); + prevs = m_prevs->getBuffer(); + + 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(); + + if(m_additive) + { + for(int channel = 0; channel < specs.channels; channel++) + { + for(int i = 0; i < length; i++) + { + if(buf[i * CC] > prevs[channel]) + sums[channel] += buf[i * CC] - prevs[channel]; + buffer[i * CC] = sums[channel] + buf[i * CC]; + prevs[channel] = buf[i * CC]; + } + } + } + else + { + for(int channel = 0; channel < specs.channels; channel++) + { + for(int i = 0; i < length * specs.channels; i++) + { + if(buf[i * CC] > prevs[channel]) + sums[channel] += buf[i * CC] - prevs[channel]; + buffer[i * CC] = sums[channel]; + prevs[channel] = buf[i * CC]; + } + } + } +} diff --git a/intern/audaspace/FX/AUD_AccumulatorReader.h b/intern/audaspace/FX/AUD_AccumulatorReader.h new file mode 100644 index 00000000000..8ad1dda30f6 --- /dev/null +++ b/intern/audaspace/FX/AUD_AccumulatorReader.h @@ -0,0 +1,75 @@ +/* + * $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_ACCUMULATORREADER +#define AUD_ACCUMULATORREADER + +#include "AUD_EffectReader.h" +class AUD_Buffer; + +/** + * This class represents an accumulator. + */ +class AUD_AccumulatorReader : public AUD_EffectReader +{ +private: + /** + * The playback buffer. + */ + AUD_Buffer *m_buffer; + + /** + * The sums of the specific channels. + */ + AUD_Buffer *m_sums; + + /** + * The previous results of the specific channels. + */ + AUD_Buffer *m_prevs; + + /** + * Whether the accumulator is additive. + */ + bool m_additive; + +public: + /** + * Creates a new accumulator reader. + * \param reader The reader to read from. + * \param additive Whether the accumulator is additive. + * \exception AUD_Exception Thrown if the reader specified is NULL. + */ + AUD_AccumulatorReader(AUD_IReader* reader, bool additive); + + /** + * Destroys the reader. + */ + virtual ~AUD_AccumulatorReader(); + + virtual void read(int & length, sample_t* & buffer); +}; + +#endif //AUD_ACCUMULATORREADER diff --git a/intern/audaspace/FX/AUD_ButterworthFactory.cpp b/intern/audaspace/FX/AUD_ButterworthFactory.cpp new file mode 100644 index 00000000000..fd0a53def7c --- /dev/null +++ b/intern/audaspace/FX/AUD_ButterworthFactory.cpp @@ -0,0 +1,49 @@ +/* + * $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_ButterworthFactory.h" +#include "AUD_ButterworthReader.h" + +AUD_ButterworthFactory::AUD_ButterworthFactory(AUD_IFactory* factory, + float frequency) : + AUD_EffectFactory(factory), + m_frequency(frequency) {} + +AUD_ButterworthFactory::AUD_ButterworthFactory(float frequency) : + AUD_EffectFactory(0), + m_frequency(frequency) {} + +AUD_IReader* AUD_ButterworthFactory::createReader() +{ + AUD_IReader* reader = getReader(); + + if(reader != 0) + { + reader = new AUD_ButterworthReader(reader, m_frequency); + AUD_NEW("reader") + } + + return reader; +} diff --git a/intern/audaspace/FX/AUD_ButterworthFactory.h b/intern/audaspace/FX/AUD_ButterworthFactory.h new file mode 100644 index 00000000000..69169531d70 --- /dev/null +++ b/intern/audaspace/FX/AUD_ButterworthFactory.h @@ -0,0 +1,59 @@ +/* + * $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_BUTTERWORTHFACTORY +#define AUD_BUTTERWORTHFACTORY + +#include "AUD_EffectFactory.h" + +/** + * This factory creates a butterworth filter reader. + */ +class AUD_ButterworthFactory : public AUD_EffectFactory +{ +private: + /** + * The attack value in seconds. + */ + float m_frequency; + +public: + /** + * Creates a new butterworth factory. + * \param factory The input factory. + * \param frequency The cutoff frequency. + */ + AUD_ButterworthFactory(AUD_IFactory* factory, float frequency); + + /** + * Creates a new butterworth factory. + * \param frequency The cutoff frequency. + */ + AUD_ButterworthFactory(float frequency); + + virtual AUD_IReader* createReader(); +}; + +#endif //AUD_BUTTERWORTHFACTORY diff --git a/intern/audaspace/FX/AUD_ButterworthReader.cpp b/intern/audaspace/FX/AUD_ButterworthReader.cpp new file mode 100644 index 00000000000..2129dfef798 --- /dev/null +++ b/intern/audaspace/FX/AUD_ButterworthReader.cpp @@ -0,0 +1,124 @@ +/* + * $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_ButterworthReader.h" +#include "AUD_Buffer.h" + +#include <cstring> +#include <cmath> + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +#define BWPB41 0.76536686473 +#define BWPB42 1.84775906502 +#define CC channels + channel + +AUD_ButterworthReader::AUD_ButterworthReader(AUD_IReader* reader, + float frequency) : + AUD_EffectReader(reader) +{ + AUD_Specs specs = reader->getSpecs(); + int samplesize = AUD_SAMPLE_SIZE(specs); + + m_buffer = new AUD_Buffer(); AUD_NEW("buffer") + + m_outvalues = new AUD_Buffer(samplesize * 5); AUD_NEW("buffer") + memset(m_outvalues->getBuffer(), 0, samplesize * 5); + + m_invalues = new AUD_Buffer(samplesize * 5); AUD_NEW("buffer") + memset(m_invalues->getBuffer(), 0, samplesize * 5); + + m_position = 0; + + // calculate coefficients + float omega = 2 * tan(frequency * M_PI / specs.rate); + float o2 = omega * omega; + float o4 = o2 * o2; + float x1 = o2 + 2 * BWPB41 * omega + 4; + float x2 = o2 + 2 * BWPB42 * omega + 4; + float y1 = o2 - 2 * BWPB41 * omega + 4; + float y2 = o2 - 2 * BWPB42 * omega + 4; + float o228 = 2 * o2 - 8; + float norm = x1 * x2; + m_coeff[0][0] = 0; + m_coeff[0][1] = (x1 + x2) * o228 / norm; + m_coeff[0][2] = (x1 * y2 + x2 * y1 + o228 * o228) / norm; + m_coeff[0][3] = (y1 + y2) * o228 / norm; + m_coeff[0][4] = y1 * y2 / norm; + m_coeff[1][4] = m_coeff[1][0] = o4 / norm; + m_coeff[1][3] = m_coeff[1][1] = 4 * o4 / norm; + m_coeff[1][2] = 6 * o4 / norm; +} + +AUD_ButterworthReader::~AUD_ButterworthReader() +{ + delete m_buffer; AUD_DELETE("buffer") + + delete m_outvalues; AUD_DELETE("buffer") + delete m_invalues; AUD_DELETE("buffer"); +} + +void AUD_ButterworthReader::read(int & length, sample_t* & buffer) +{ + sample_t* buf; + sample_t* outvalues; + sample_t* invalues; + + outvalues = m_outvalues->getBuffer(); + invalues = m_invalues->getBuffer(); + + 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(); + int channels = specs.channels; + + for(int channel = 0; channel < channels; channel++) + { + for(int i = 0; i < length; i++) + { + invalues[m_position * CC] = buf[i * CC]; + outvalues[m_position * CC] = 0; + + for(int j = 0; j < 4; j++) + { + outvalues[m_position * CC] += m_coeff[1][j] * + invalues[((m_position + j) % 5) * CC] - + m_coeff[0][j] * + outvalues[((m_position + j) % 5) * CC]; + } + + buffer[i * CC] = outvalues[m_position * CC]; + + m_position = (m_position + 4) % 5; + } + } +} diff --git a/intern/audaspace/FX/AUD_ButterworthReader.h b/intern/audaspace/FX/AUD_ButterworthReader.h new file mode 100644 index 00000000000..b1cbd4e3820 --- /dev/null +++ b/intern/audaspace/FX/AUD_ButterworthReader.h @@ -0,0 +1,83 @@ +/* + * $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_BUTTERWORTHREADER +#define AUD_BUTTERWORTHREADER + +#include "AUD_EffectReader.h" +class AUD_Buffer; + +/** + * This class represents a butterworth filter. + */ +class AUD_ButterworthReader : public AUD_EffectReader +{ +private: + /** + * The playback buffer. + */ + AUD_Buffer *m_buffer; + + /** + * The last out values buffer. + */ + AUD_Buffer *m_outvalues; + + /** + * The last in values buffer. + */ + AUD_Buffer *m_invalues; + + /** + * The position for buffer cycling. + */ + int m_position; + + /** + * Filter coefficients. + */ + float m_coeff[2][5]; + +public: + /** + * Creates a new butterworth reader. + * \param reader The reader to read from. + * \param attack The attack value in seconds. + * \param release The release value in seconds. + * \param threshold The threshold value. + * \param arthreshold The attack/release threshold value. + * \exception AUD_Exception Thrown if the reader specified is NULL. + */ + AUD_ButterworthReader(AUD_IReader* reader, float frequency); + + /** + * Destroys the reader. + */ + virtual ~AUD_ButterworthReader(); + + virtual void read(int & length, sample_t* & buffer); +}; + +#endif //AUD_BUTTERWORTHREADER diff --git a/intern/audaspace/FX/AUD_DelayReader.cpp b/intern/audaspace/FX/AUD_DelayReader.cpp index 38d3b893b5c..f2521f645aa 100644 --- a/intern/audaspace/FX/AUD_DelayReader.cpp +++ b/intern/audaspace/FX/AUD_DelayReader.cpp @@ -77,31 +77,26 @@ void AUD_DelayReader::read(int & length, sample_t* & buffer) { if(m_remdelay > 0) { - int samplesize = AUD_SAMPLE_SIZE(m_reader->getSpecs()); + AUD_Specs specs = m_reader->getSpecs(); + int samplesize = AUD_SAMPLE_SIZE(specs); - if(m_buffer->getSize() < length*samplesize) - m_buffer->resize(length*samplesize); + if(m_buffer->getSize() < length * samplesize) + m_buffer->resize(length * samplesize); if(length > m_remdelay) { - if(getSpecs().format == AUD_FORMAT_U8) - memset(m_buffer->getBuffer(), 0x80, m_remdelay*samplesize); - else - memset(m_buffer->getBuffer(), 0, m_remdelay*samplesize); + memset(m_buffer->getBuffer(), 0, m_remdelay * samplesize); int len = length - m_remdelay; m_reader->read(len, buffer); - memcpy(m_buffer->getBuffer()+m_remdelay*samplesize, - buffer, len*samplesize); + memcpy(m_buffer->getBuffer() + m_remdelay * specs.channels, + buffer, len * samplesize); if(len < length-m_remdelay) length = m_remdelay + len; m_remdelay = 0; } else { - if(getSpecs().format == AUD_FORMAT_U8) - memset(m_buffer->getBuffer(), 0x80, length*samplesize); - else - memset(m_buffer->getBuffer(), 0, length*samplesize); + memset(m_buffer->getBuffer(), 0, length * samplesize); m_remdelay -= length; } buffer = m_buffer->getBuffer(); diff --git a/intern/audaspace/FX/AUD_DoubleReader.cpp b/intern/audaspace/FX/AUD_DoubleReader.cpp index 8d3afbf2f1d..1e51a094427 100644 --- a/intern/audaspace/FX/AUD_DoubleReader.cpp +++ b/intern/audaspace/FX/AUD_DoubleReader.cpp @@ -137,15 +137,16 @@ void AUD_DoubleReader::read(int & length, sample_t* & buffer) m_reader1->read(len, buffer); if(len < length) { - int samplesize = AUD_SAMPLE_SIZE(m_reader1->getSpecs()); + AUD_Specs specs = m_reader1->getSpecs(); + int samplesize = AUD_SAMPLE_SIZE(specs); if(m_buffer->getSize() < length * samplesize) m_buffer->resize(length * samplesize); - memcpy(m_buffer->getBuffer(), buffer, len*samplesize); + memcpy(m_buffer->getBuffer(), buffer, len * samplesize); len = length - len; length -= len; m_reader2->read(len, buffer); - memcpy(m_buffer->getBuffer() + length*samplesize, - buffer, len*samplesize); + memcpy(m_buffer->getBuffer() + length * specs.channels, buffer, + len * samplesize); length += len; buffer = m_buffer->getBuffer(); m_finished1 = true; diff --git a/intern/audaspace/FX/AUD_EnvelopeFactory.cpp b/intern/audaspace/FX/AUD_EnvelopeFactory.cpp new file mode 100644 index 00000000000..c3b2c3f24fe --- /dev/null +++ b/intern/audaspace/FX/AUD_EnvelopeFactory.cpp @@ -0,0 +1,58 @@ +/* + * $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_EnvelopeFactory.h" +#include "AUD_EnvelopeReader.h" + +AUD_EnvelopeFactory::AUD_EnvelopeFactory(AUD_IFactory* factory, float attack, + float release, float threshold, + float arthreshold) : + AUD_EffectFactory(factory), + m_attack(attack), + m_release(release), + m_threshold(threshold), + m_arthreshold(arthreshold) {} + +AUD_EnvelopeFactory::AUD_EnvelopeFactory(float attack, float release, + float threshold, float arthreshold) : + AUD_EffectFactory(0), + m_attack(attack), + m_release(release), + m_threshold(threshold), + m_arthreshold(arthreshold) {} + +AUD_IReader* AUD_EnvelopeFactory::createReader() +{ + AUD_IReader* reader = getReader(); + + if(reader != 0) + { + reader = new AUD_EnvelopeReader(reader, m_attack, m_release, + m_threshold, m_arthreshold); + AUD_NEW("reader") + } + + return reader; +} diff --git a/intern/audaspace/FX/AUD_EnvelopeFactory.h b/intern/audaspace/FX/AUD_EnvelopeFactory.h new file mode 100644 index 00000000000..c79e5472e30 --- /dev/null +++ b/intern/audaspace/FX/AUD_EnvelopeFactory.h @@ -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 ***** + */ + +#ifndef AUD_ENVELOPEFACTORY +#define AUD_ENVELOPEFACTORY + +#include "AUD_EffectFactory.h" + +/** + * This factory creates an envelope follower reader. + */ +class AUD_EnvelopeFactory : public AUD_EffectFactory +{ +private: + /** + * The attack value in seconds. + */ + float m_attack; + + /** + * The release value in seconds. + */ + float m_release; + + /** + * The threshold value. + */ + float m_threshold; + + /** + * The attack/release threshold value. + */ + float m_arthreshold; + +public: + /** + * Creates a new envelope factory. + * \param factory The input factory. + * \param attack The attack value in seconds. + * \param release The release value in seconds. + * \param threshold The threshold value. + * \param arthreshold The attack/release threshold value. + */ + AUD_EnvelopeFactory(AUD_IFactory* factory, float attack, float release, + float threshold, float arthreshold); + + /** + * Creates a new envelope factory. + * \param attack The attack value in seconds. + * \param release The release value in seconds. + * \param threshold The threshold value. + * \param arthreshold The attack/release threshold value. + */ + AUD_EnvelopeFactory(float attack, float release, float threshold, + float arthreshold); + + virtual AUD_IReader* createReader(); +}; + +#endif //AUD_ENVELOPEFACTORY diff --git a/intern/audaspace/FX/AUD_EnvelopeReader.cpp b/intern/audaspace/FX/AUD_EnvelopeReader.cpp new file mode 100644 index 00000000000..71ccbfd6503 --- /dev/null +++ b/intern/audaspace/FX/AUD_EnvelopeReader.cpp @@ -0,0 +1,86 @@ +/* + * $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_EnvelopeReader.h" +#include "AUD_Buffer.h" + +#include <cstring> +#include <cmath> + +AUD_EnvelopeReader::AUD_EnvelopeReader(AUD_IReader* reader, float attack, + float release, float threshold, + float arthreshold) : + AUD_EffectReader(reader), + m_threshold(threshold) +{ + AUD_Specs specs = reader->getSpecs(); + int samplesize = AUD_SAMPLE_SIZE(specs); + + m_buffer = new AUD_Buffer(); AUD_NEW("buffer") + + m_envelopes = new AUD_Buffer(samplesize); + AUD_NEW("buffer") + memset(m_envelopes->getBuffer(), 0, samplesize); + + m_bAttack = pow(arthreshold, 1.0f/(specs.rate * attack)); + m_bRelease = pow(arthreshold, 1.0f/(specs.rate * release)); +} + +AUD_EnvelopeReader::~AUD_EnvelopeReader() +{ + delete m_buffer; AUD_DELETE("buffer") + delete m_envelopes; AUD_DELETE("buffer") +} + +void AUD_EnvelopeReader::read(int & length, sample_t* & buffer) +{ + sample_t* buf; + sample_t* envelopes; + envelopes = m_envelopes->getBuffer(); + + 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(); + + sample_t value; + + for(int channel = 0; channel < specs.channels; channel++) + { + for(int i = 0; i < length; i++) + { + value = fabs(buf[i * specs.channels + channel]); + if(value < m_threshold) + value = 0.0f; + + buffer[i * specs.channels + channel] = envelopes[channel] = + ((value > envelopes[channel]) ? m_bAttack : m_bRelease) * + (envelopes[channel] - value) + value; + } + } +} diff --git a/intern/audaspace/FX/AUD_EnvelopeReader.h b/intern/audaspace/FX/AUD_EnvelopeReader.h new file mode 100644 index 00000000000..ff9dd23d34c --- /dev/null +++ b/intern/audaspace/FX/AUD_EnvelopeReader.h @@ -0,0 +1,84 @@ +/* + * $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_ENVELOPEREADER +#define AUD_ENVELOPEREADER + +#include "AUD_EffectReader.h" +class AUD_Buffer; + +/** + * This class represents an envelope follower. + */ +class AUD_EnvelopeReader : public AUD_EffectReader +{ +private: + /** + * The playback buffer. + */ + AUD_Buffer *m_buffer; + + /** + * The last envelopes buffer. + */ + AUD_Buffer *m_envelopes; + + /** + * Attack b value. + */ + float m_bAttack; + + /** + * Release b value. + */ + float m_bRelease; + + /** + * Threshold value. + */ + float m_threshold; + +public: + /** + * Creates a new envelope reader. + * \param reader The reader to read from. + * \param attack The attack value in seconds. + * \param release The release value in seconds. + * \param threshold The threshold value. + * \param arthreshold The attack/release threshold value. + * \exception AUD_Exception Thrown if the reader specified is NULL. + */ + AUD_EnvelopeReader(AUD_IReader* reader, float attack, float release, + float threshold, float arthreshold); + + /** + * Destroys the reader. + */ + virtual ~AUD_EnvelopeReader(); + + virtual void read(int & length, sample_t* & buffer); +}; + +#endif //AUD_ENVELOPEREADER diff --git a/intern/audaspace/FX/AUD_FaderReader.cpp b/intern/audaspace/FX/AUD_FaderReader.cpp index d5096e7fae1..6c7ea6e0a01 100644 --- a/intern/audaspace/FX/AUD_FaderReader.cpp +++ b/intern/audaspace/FX/AUD_FaderReader.cpp @@ -35,35 +35,6 @@ AUD_FaderReader::AUD_FaderReader(AUD_IReader* reader, AUD_FadeType type, m_start(start), m_length(length) { - int bigendian = 1; - bigendian = (((char*)&bigendian)[0]) ? 0: 1; // 1 if Big Endian - - switch(m_reader->getSpecs().format) - { - case AUD_FORMAT_S16: - m_adjust = AUD_volume_adjust<int16_t>; - break; - case AUD_FORMAT_S32: - m_adjust = AUD_volume_adjust<int32_t>; - break; - case AUD_FORMAT_FLOAT32: - m_adjust = AUD_volume_adjust<float>; - break; - case AUD_FORMAT_FLOAT64: - m_adjust = AUD_volume_adjust<double>; - break; - case AUD_FORMAT_U8: - m_adjust = AUD_volume_adjust_u8; - break; - case AUD_FORMAT_S24: - m_adjust = bigendian ? AUD_volume_adjust_s24_be : - AUD_volume_adjust_s24_le; - break; - default: - delete m_reader; - AUD_THROW(AUD_ERROR_READER); - } - m_buffer = new AUD_Buffer(); AUD_NEW("buffer") } @@ -93,9 +64,7 @@ void AUD_FaderReader::read(int & length, sample_t* & buffer) if(m_type != AUD_FADE_OUT) { buffer = m_buffer->getBuffer(); - memset(buffer, - specs.format == AUD_FORMAT_U8 ? 0x80 : 0, - length * samplesize); + memset(buffer, 0, length * samplesize); } } else if(position / (float)specs.rate >= m_start+m_length) @@ -103,9 +72,7 @@ void AUD_FaderReader::read(int & length, sample_t* & buffer) if(m_type == AUD_FADE_OUT) { buffer = m_buffer->getBuffer(); - memset(buffer, - specs.format == AUD_FORMAT_U8 ? 0x80 : 0, - length * samplesize); + memset(buffer, 0, length * samplesize); } } else @@ -113,19 +80,21 @@ void AUD_FaderReader::read(int & length, sample_t* & buffer) sample_t* buf = m_buffer->getBuffer(); float volume; - for(int i = 0; i < length; i++) + for(int i = 0; i < length * specs.channels; i++) { - volume = (((position+i)/(float)specs.rate)-m_start) / m_length; - if(volume > 1.0f) - volume = 1.0f; - else if(volume < 0.0f) - volume = 0.0f; + if(i % specs.channels == 0) + { + volume = (((position+i)/(float)specs.rate)-m_start) / m_length; + if(volume > 1.0f) + volume = 1.0f; + else if(volume < 0.0f) + volume = 0.0f; - if(m_type == AUD_FADE_OUT) - volume = 1.0f - volume; + if(m_type == AUD_FADE_OUT) + volume = 1.0f - volume; + } - m_adjust(buf + i * samplesize, buffer + i * samplesize, - specs.channels, volume); + buf[i] = buffer[i] * volume; } buffer = buf; diff --git a/intern/audaspace/FX/AUD_FaderReader.h b/intern/audaspace/FX/AUD_FaderReader.h index 773643b2f5d..a75ac6e7a47 100644 --- a/intern/audaspace/FX/AUD_FaderReader.h +++ b/intern/audaspace/FX/AUD_FaderReader.h @@ -27,7 +27,6 @@ #define AUD_FADERREADER #include "AUD_EffectReader.h" -#include "AUD_ConverterFunctions.h" class AUD_Buffer; /** @@ -58,11 +57,6 @@ private: */ float m_length; - /** - * Volume adjustment function. - */ - AUD_volume_adjust_f m_adjust; - public: /** * Creates a new fader reader. diff --git a/intern/audaspace/FX/AUD_HighpassFactory.cpp b/intern/audaspace/FX/AUD_HighpassFactory.cpp new file mode 100644 index 00000000000..384d36beab7 --- /dev/null +++ b/intern/audaspace/FX/AUD_HighpassFactory.cpp @@ -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 ***** + */ + +#include "AUD_HighpassFactory.h" +#include "AUD_HighpassReader.h" + +AUD_HighpassFactory::AUD_HighpassFactory(AUD_IFactory* factory, float frequency, + float Q) : + AUD_EffectFactory(factory), + m_frequency(frequency), + m_Q(Q) {} + +AUD_HighpassFactory::AUD_HighpassFactory(float frequency, float Q) : + AUD_EffectFactory(0), + m_frequency(frequency), + m_Q(Q) {} + +AUD_IReader* AUD_HighpassFactory::createReader() +{ + AUD_IReader* reader = getReader(); + + if(reader != 0) + { + reader = new AUD_HighpassReader(reader, m_frequency, m_Q); + AUD_NEW("reader") + } + + return reader; +} diff --git a/intern/audaspace/FX/AUD_HighpassFactory.h b/intern/audaspace/FX/AUD_HighpassFactory.h new file mode 100644 index 00000000000..5e31053ed6c --- /dev/null +++ b/intern/audaspace/FX/AUD_HighpassFactory.h @@ -0,0 +1,66 @@ +/* + * $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_HIGHPASSFACTORY +#define AUD_HIGHPASSFACTORY + +#include "AUD_EffectFactory.h" + +/** + * This factory creates a highpass filter reader. + */ +class AUD_HighpassFactory : public AUD_EffectFactory +{ +private: + /** + * The attack value in seconds. + */ + float m_frequency; + + /** + * The Q factor. + */ + float m_Q; + +public: + /** + * Creates a new highpass factory. + * \param factory The input factory. + * \param frequency The cutoff frequency. + * \param Q The Q factor. + */ + AUD_HighpassFactory(AUD_IFactory* factory, float frequency, float Q = 1.0f); + + /** + * Creates a new highpass factory. + * \param frequency The cutoff frequency. + * \param Q The Q factor. + */ + AUD_HighpassFactory(float frequency, float Q = 1.0f); + + virtual AUD_IReader* createReader(); +}; + +#endif //AUD_HIGHPASSFACTORY diff --git a/intern/audaspace/FX/AUD_HighpassReader.cpp b/intern/audaspace/FX/AUD_HighpassReader.cpp new file mode 100644 index 00000000000..36b1bb8082e --- /dev/null +++ b/intern/audaspace/FX/AUD_HighpassReader.cpp @@ -0,0 +1,116 @@ +/* + * $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_HighpassReader.h" +#include "AUD_Buffer.h" + +#include <cstring> +#include <cmath> + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +#define CC channels + channel + +AUD_HighpassReader::AUD_HighpassReader(AUD_IReader* reader, float frequency, + float Q) : + AUD_EffectReader(reader) +{ + AUD_Specs specs = reader->getSpecs(); + int samplesize = AUD_SAMPLE_SIZE(specs); + + m_buffer = new AUD_Buffer(); AUD_NEW("buffer") + + m_outvalues = new AUD_Buffer(samplesize * AUD_HIGHPASS_ORDER); + AUD_NEW("buffer") + memset(m_outvalues->getBuffer(), 0, samplesize * AUD_HIGHPASS_ORDER); + + m_invalues = new AUD_Buffer(samplesize * AUD_HIGHPASS_ORDER); + AUD_NEW("buffer") + memset(m_invalues->getBuffer(), 0, samplesize * AUD_HIGHPASS_ORDER); + + m_position = 0; + + // calculate coefficients + float w0 = 2 * M_PI * frequency / specs.rate; + float alpha = sin(w0) / (2 * Q); + float norm = 1 + alpha; + m_coeff[0][0] = 0; + m_coeff[0][1] = -2 * cos(w0) / norm; + m_coeff[0][2] = (1 - alpha) / norm; + m_coeff[1][2] = m_coeff[1][0] = (1 + cos(w0)) / (2 * norm); + m_coeff[1][1] = (-1 - cos(w0)) / norm; +} + +AUD_HighpassReader::~AUD_HighpassReader() +{ + delete m_buffer; AUD_DELETE("buffer") + + delete m_outvalues; AUD_DELETE("buffer") + delete m_invalues; AUD_DELETE("buffer"); +} + +void AUD_HighpassReader::read(int & length, sample_t* & buffer) +{ + sample_t* buf; + sample_t* outvalues; + sample_t* invalues; + + outvalues = m_outvalues->getBuffer(); + invalues = m_invalues->getBuffer(); + + 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(); + int channels = specs.channels; + + for(int channel = 0; channel < channels; channel++) + { + for(int i = 0; i < length; i++) + { + invalues[m_position * CC] = buf[i * CC]; + outvalues[m_position * CC] = 0; + + for(int j = 0; j < AUD_HIGHPASS_ORDER; j++) + { + outvalues[m_position * CC] += m_coeff[1][j] * + invalues[((m_position + j) % AUD_HIGHPASS_ORDER) * CC] - + m_coeff[0][j] * + outvalues[((m_position + j) % AUD_HIGHPASS_ORDER) * CC]; + } + + buffer[i * CC] = outvalues[m_position * CC]; + + m_position = (m_position + AUD_HIGHPASS_ORDER-1) % + AUD_HIGHPASS_ORDER; + } + } +} diff --git a/intern/audaspace/FX/AUD_HighpassReader.h b/intern/audaspace/FX/AUD_HighpassReader.h new file mode 100644 index 00000000000..dc28a62e45b --- /dev/null +++ b/intern/audaspace/FX/AUD_HighpassReader.h @@ -0,0 +1,83 @@ +/* + * $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_HIGHPASSREADER +#define AUD_HIGHPASSREADER + +#include "AUD_EffectReader.h" +class AUD_Buffer; + +#define AUD_HIGHPASS_ORDER 3 + +/** + * This class represents a highpass filter. + */ +class AUD_HighpassReader : public AUD_EffectReader +{ +private: + /** + * The playback buffer. + */ + AUD_Buffer *m_buffer; + + /** + * The last out values buffer. + */ + AUD_Buffer *m_outvalues; + + /** + * The last in values buffer. + */ + AUD_Buffer *m_invalues; + + /** + * The position for buffer cycling. + */ + int m_position; + + /** + * Filter coefficients. + */ + float m_coeff[2][AUD_HIGHPASS_ORDER]; + +public: + /** + * Creates a new highpass reader. + * \param reader The reader to read from. + * \param frequency The cutoff frequency. + * \param Q The Q factor. + * \exception AUD_Exception Thrown if the reader specified is NULL. + */ + AUD_HighpassReader(AUD_IReader* reader, float frequency, float Q); + + /** + * Destroys the reader. + */ + virtual ~AUD_HighpassReader(); + + virtual void read(int & length, sample_t* & buffer); +}; + +#endif //AUD_HIGHPASSREADER diff --git a/intern/audaspace/FX/AUD_LoopReader.cpp b/intern/audaspace/FX/AUD_LoopReader.cpp index 9e270321013..7d70fc20221 100644 --- a/intern/audaspace/FX/AUD_LoopReader.cpp +++ b/intern/audaspace/FX/AUD_LoopReader.cpp @@ -27,7 +27,6 @@ #include "AUD_Buffer.h" #include <cstring> -#include <stdio.h> AUD_LoopReader::AUD_LoopReader(AUD_IReader* reader, int loop) : AUD_EffectReader(reader), m_loop(loop) @@ -62,7 +61,8 @@ bool AUD_LoopReader::notify(AUD_Message &message) void AUD_LoopReader::read(int & length, sample_t* & buffer) { - int samplesize = AUD_SAMPLE_SIZE(m_reader->getSpecs()); + AUD_Specs specs = m_reader->getSpecs(); + int samplesize = AUD_SAMPLE_SIZE(specs); int len = length; @@ -72,10 +72,10 @@ void AUD_LoopReader::read(int & length, sample_t* & buffer) { int pos = 0; - if(m_buffer->getSize() < length*samplesize) - m_buffer->resize(length*samplesize); + if(m_buffer->getSize() < length * samplesize) + m_buffer->resize(length * samplesize); - memcpy(m_buffer->getBuffer() + pos * samplesize, + memcpy(m_buffer->getBuffer() + pos * specs.channels, buffer, len * samplesize); pos += len; @@ -93,7 +93,7 @@ void AUD_LoopReader::read(int & length, sample_t* & buffer) if(!len) break; - memcpy(m_buffer->getBuffer() + pos * samplesize, + memcpy(m_buffer->getBuffer() + pos * specs.channels, buffer, len * samplesize); pos += len; diff --git a/intern/audaspace/FX/AUD_LowpassFactory.cpp b/intern/audaspace/FX/AUD_LowpassFactory.cpp new file mode 100644 index 00000000000..05dc5ff3994 --- /dev/null +++ b/intern/audaspace/FX/AUD_LowpassFactory.cpp @@ -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 ***** + */ + +#include "AUD_LowpassFactory.h" +#include "AUD_LowpassReader.h" + +AUD_LowpassFactory::AUD_LowpassFactory(AUD_IFactory* factory, float frequency, + float Q) : + AUD_EffectFactory(factory), + m_frequency(frequency), + m_Q(Q) {} + +AUD_LowpassFactory::AUD_LowpassFactory(float frequency, float Q) : + AUD_EffectFactory(0), + m_frequency(frequency), + m_Q(Q) {} + +AUD_IReader* AUD_LowpassFactory::createReader() +{ + AUD_IReader* reader = getReader(); + + if(reader != 0) + { + reader = new AUD_LowpassReader(reader, m_frequency, m_Q); + AUD_NEW("reader") + } + + return reader; +} diff --git a/intern/audaspace/FX/AUD_LowpassFactory.h b/intern/audaspace/FX/AUD_LowpassFactory.h new file mode 100644 index 00000000000..8a419823de0 --- /dev/null +++ b/intern/audaspace/FX/AUD_LowpassFactory.h @@ -0,0 +1,66 @@ +/* + * $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_LOWPASSFACTORY +#define AUD_LOWPASSFACTORY + +#include "AUD_EffectFactory.h" + +/** + * This factory creates a lowpass filter reader. + */ +class AUD_LowpassFactory : public AUD_EffectFactory +{ +private: + /** + * The attack value in seconds. + */ + float m_frequency; + + /** + * The Q factor. + */ + float m_Q; + +public: + /** + * Creates a new lowpass factory. + * \param factory The input factory. + * \param frequency The cutoff frequency. + * \param Q The Q factor. + */ + AUD_LowpassFactory(AUD_IFactory* factory, float frequency, float Q = 1.0f); + + /** + * Creates a new lowpass factory. + * \param frequency The cutoff frequency. + * \param Q The Q factor. + */ + AUD_LowpassFactory(float frequency, float Q = 1.0f); + + virtual AUD_IReader* createReader(); +}; + +#endif //AUD_LOWPASSFACTORY diff --git a/intern/audaspace/FX/AUD_LowpassReader.cpp b/intern/audaspace/FX/AUD_LowpassReader.cpp new file mode 100644 index 00000000000..6dc0bf66a96 --- /dev/null +++ b/intern/audaspace/FX/AUD_LowpassReader.cpp @@ -0,0 +1,115 @@ +/* + * $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_LowpassReader.h" +#include "AUD_Buffer.h" + +#include <cstring> +#include <cmath> + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +#define CC channels + channel + +AUD_LowpassReader::AUD_LowpassReader(AUD_IReader* reader, float frequency, + float Q) : + AUD_EffectReader(reader) +{ + AUD_Specs specs = reader->getSpecs(); + int samplesize = AUD_SAMPLE_SIZE(specs); + + m_buffer = new AUD_Buffer(); AUD_NEW("buffer") + + m_outvalues = new AUD_Buffer(samplesize * AUD_LOWPASS_ORDER); + AUD_NEW("buffer") + memset(m_outvalues->getBuffer(), 0, samplesize * AUD_LOWPASS_ORDER); + + m_invalues = new AUD_Buffer(samplesize * AUD_LOWPASS_ORDER); + AUD_NEW("buffer") + memset(m_invalues->getBuffer(), 0, samplesize * AUD_LOWPASS_ORDER); + + m_position = 0; + + // calculate coefficients + float w0 = 2 * M_PI * frequency / specs.rate; + float alpha = sin(w0) / (2 * Q); + float norm = 1 + alpha; + m_coeff[0][0] = 0; + m_coeff[0][1] = -2 * cos(w0) / norm; + m_coeff[0][2] = (1 - alpha) / norm; + m_coeff[1][2] = m_coeff[1][0] = (1 - cos(w0)) / (2 * norm); + m_coeff[1][1] = (1 - cos(w0)) / norm; +} + +AUD_LowpassReader::~AUD_LowpassReader() +{ + delete m_buffer; AUD_DELETE("buffer") + + delete m_outvalues; AUD_DELETE("buffer") + delete m_invalues; AUD_DELETE("buffer"); +} + +void AUD_LowpassReader::read(int & length, sample_t* & buffer) +{ + sample_t* buf; + sample_t* outvalues; + sample_t* invalues; + + outvalues = m_outvalues->getBuffer(); + invalues = m_invalues->getBuffer(); + + 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(); + int channels = specs.channels; + + for(int channel = 0; channel < channels; channel++) + { + for(int i = 0; i < length; i++) + { + invalues[m_position * CC] = buf[i * CC]; + outvalues[m_position * CC] = 0; + + for(int j = 0; j < AUD_LOWPASS_ORDER; j++) + { + outvalues[m_position * CC] += m_coeff[1][j] * + invalues[((m_position + j) % AUD_LOWPASS_ORDER) * CC] - + m_coeff[0][j] * + outvalues[((m_position + j) % AUD_LOWPASS_ORDER) * CC]; + } + + buffer[i * CC] = outvalues[m_position * CC]; + + m_position = (m_position + AUD_LOWPASS_ORDER-1) % AUD_LOWPASS_ORDER; + } + } +} diff --git a/intern/audaspace/FX/AUD_LowpassReader.h b/intern/audaspace/FX/AUD_LowpassReader.h new file mode 100644 index 00000000000..a490ba52c1c --- /dev/null +++ b/intern/audaspace/FX/AUD_LowpassReader.h @@ -0,0 +1,83 @@ +/* + * $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_LOWPASSREADER +#define AUD_LOWPASSREADER + +#include "AUD_EffectReader.h" +class AUD_Buffer; + +#define AUD_LOWPASS_ORDER 3 + +/** + * This class represents a lowpass filter. + */ +class AUD_LowpassReader : public AUD_EffectReader +{ +private: + /** + * The playback buffer. + */ + AUD_Buffer *m_buffer; + + /** + * The last out values buffer. + */ + AUD_Buffer *m_outvalues; + + /** + * The last in values buffer. + */ + AUD_Buffer *m_invalues; + + /** + * The position for buffer cycling. + */ + int m_position; + + /** + * Filter coefficients. + */ + float m_coeff[2][AUD_LOWPASS_ORDER]; + +public: + /** + * Creates a new lowpass reader. + * \param reader The reader to read from. + * \param frequency The cutoff frequency. + * \param Q The Q factor. + * \exception AUD_Exception Thrown if the reader specified is NULL. + */ + AUD_LowpassReader(AUD_IReader* reader, float frequency, float Q); + + /** + * Destroys the reader. + */ + virtual ~AUD_LowpassReader(); + + virtual void read(int & length, sample_t* & buffer); +}; + +#endif //AUD_LOWPASSREADER diff --git a/intern/audaspace/FX/AUD_PitchFactory.h b/intern/audaspace/FX/AUD_PitchFactory.h index 3209aa46983..96c4d0d7e92 100644 --- a/intern/audaspace/FX/AUD_PitchFactory.h +++ b/intern/audaspace/FX/AUD_PitchFactory.h @@ -45,7 +45,7 @@ public: * \param factory The input factory. * \param pitch The desired pitch. */ - AUD_PitchFactory(AUD_IFactory* factory = 0, float pitch = 1.0); + AUD_PitchFactory(AUD_IFactory* factory = 0, float pitch = 1.0f); /** * Creates a new pitch factory. diff --git a/intern/audaspace/FX/AUD_RectifyReader.cpp b/intern/audaspace/FX/AUD_RectifyReader.cpp index 9839aefa838..5d3ce80e811 100644 --- a/intern/audaspace/FX/AUD_RectifyReader.cpp +++ b/intern/audaspace/FX/AUD_RectifyReader.cpp @@ -26,39 +26,11 @@ #include "AUD_RectifyReader.h" #include "AUD_Buffer.h" -#include <cstring> +#include <cmath> 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") } @@ -73,10 +45,11 @@ void AUD_RectifyReader::read(int & length, sample_t* & buffer) 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)); + 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); + for(int i = 0; i < length * specs.channels; i++) + buffer[i] = fabs(buf[i]); } diff --git a/intern/audaspace/FX/AUD_RectifyReader.h b/intern/audaspace/FX/AUD_RectifyReader.h index 17423811cdc..afbe2e59cab 100644 --- a/intern/audaspace/FX/AUD_RectifyReader.h +++ b/intern/audaspace/FX/AUD_RectifyReader.h @@ -27,7 +27,6 @@ #define AUD_RECTIFYREADER #include "AUD_EffectReader.h" -#include "AUD_ConverterFunctions.h" class AUD_Buffer; /** @@ -41,11 +40,6 @@ private: */ AUD_Buffer *m_buffer; - /** - * Rectifying function. - */ - AUD_rectify_f m_rectify; - public: /** * Creates a new rectify reader. diff --git a/intern/audaspace/FX/AUD_ReverseReader.cpp b/intern/audaspace/FX/AUD_ReverseReader.cpp index 043480b91b9..82d6c70ce53 100644 --- a/intern/audaspace/FX/AUD_ReverseReader.cpp +++ b/intern/audaspace/FX/AUD_ReverseReader.cpp @@ -65,7 +65,7 @@ int AUD_ReverseReader::getPosition() void AUD_ReverseReader::read(int & length, sample_t* & buffer) { // first correct the length - if(m_position+length > m_length) + if(m_position + length > m_length) length = m_length-m_position; if(length <= 0) @@ -74,7 +74,8 @@ void AUD_ReverseReader::read(int & length, sample_t* & buffer) return; } - int samplesize = AUD_SAMPLE_SIZE(getSpecs()); + AUD_Specs specs = getSpecs(); + int samplesize = AUD_SAMPLE_SIZE(specs); // resize buffer if needed if(m_buffer->getSize() < length * samplesize) @@ -86,23 +87,20 @@ void AUD_ReverseReader::read(int & length, sample_t* & buffer) int len = length; // read from reader - m_reader->seek(m_length-m_position-len); + m_reader->seek(m_length - m_position - len); m_reader->read(len, buf); // set null if reader didn't give enough data if(len < length) { - if(getSpecs().format == AUD_FORMAT_U8) - memset(buffer, 0x80, (length-len)*samplesize); - else - memset(buffer, 0, (length-len)*samplesize); - buffer += length-len; + memset(buffer, 0, (length - len) * samplesize); + buffer += (length - len) * specs.channels; } // copy the samples reverted for(int i = 0; i < len; i++) - memcpy(buffer + i * samplesize, - buf + (len - 1 - i) * samplesize, + memcpy(buffer + i * specs.channels, + buf + (len - 1 - i) * specs.channels, samplesize); m_position += length; diff --git a/intern/audaspace/FX/AUD_SquareFactory.cpp b/intern/audaspace/FX/AUD_SquareFactory.cpp new file mode 100644 index 00000000000..638acaa9a32 --- /dev/null +++ b/intern/audaspace/FX/AUD_SquareFactory.cpp @@ -0,0 +1,57 @@ +/* + * $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_SquareFactory.h" +#include "AUD_SquareReader.h" + +AUD_SquareFactory::AUD_SquareFactory(AUD_IFactory* factory, float threshold) : + AUD_EffectFactory(factory), + m_threshold(threshold) {} + +AUD_SquareFactory::AUD_SquareFactory(float threshold) : + AUD_EffectFactory(0), + m_threshold(threshold) {} + +float AUD_SquareFactory::getThreshold() +{ + return m_threshold; +} + +void AUD_SquareFactory::setThreshold(float threshold) +{ + m_threshold = threshold; +} + +AUD_IReader* AUD_SquareFactory::createReader() +{ + AUD_IReader* reader = getReader(); + + if(reader != 0) + { + reader = new AUD_SquareReader(reader, m_threshold); AUD_NEW("reader") + } + + return reader; +} diff --git a/intern/audaspace/SDL/AUD_SDLMixer.h b/intern/audaspace/FX/AUD_SquareFactory.h index 2cc4e51f66d..dfbe5ae2887 100644 --- a/intern/audaspace/SDL/AUD_SDLMixer.h +++ b/intern/audaspace/FX/AUD_SquareFactory.h @@ -23,54 +23,48 @@ * ***** END LGPL LICENSE BLOCK ***** */ -#ifndef AUD_SDLMIXER -#define AUD_SDLMIXER +#ifndef AUD_SQUAREFACTORY +#define AUD_SQUAREFACTORY -#include "AUD_IMixer.h" -class AUD_SDLMixerFactory; -#include <list> - -struct AUD_SDLMixerBuffer -{ - sample_t* buffer; - int length; - float volume; -}; +#include "AUD_EffectFactory.h" /** - * This class is able to mix audiosignals with the help of SDL. + * This factory Transforms any signal to a square signal. */ -class AUD_SDLMixer : public AUD_IMixer +class AUD_SquareFactory : public AUD_EffectFactory { private: /** - * The mixer factory that prepares all readers for superposition. + * The threshold. */ - AUD_SDLMixerFactory* m_factory; + float m_threshold; +public: /** - * The list of buffers to superpose. + * Creates a new square factory. + * \param factory The input factory. + * \param threshold The threshold. */ - std::list<AUD_SDLMixerBuffer> m_buffers; + AUD_SquareFactory(AUD_IFactory* factory = 0, float threshold = 0.0f); /** - * The size of an output sample. + * Creates a new square factory. + * \param threshold The threshold. */ - int m_samplesize; + AUD_SquareFactory(float threshold); -public: /** - * Creates the mixer. + * Returns the threshold. */ - AUD_SDLMixer(); + float getThreshold(); - virtual ~AUD_SDLMixer(); + /** + * Sets the threshold. + * \param threshold The new threshold value. Should be between 0.0 and 1.0. + */ + void setThreshold(float threshold); - virtual AUD_IReader* prepare(AUD_IReader* reader); - virtual void setSpecs(AUD_Specs specs); - virtual void add(sample_t* buffer, AUD_Specs specs, int length, - float volume); - virtual void superpose(sample_t* buffer, int length, float volume); + virtual AUD_IReader* createReader(); }; -#endif //AUD_SDLMIXER +#endif //AUD_SQUAREFACTORY diff --git a/intern/audaspace/FX/AUD_SquareReader.cpp b/intern/audaspace/FX/AUD_SquareReader.cpp new file mode 100644 index 00000000000..2d4dc52fe27 --- /dev/null +++ b/intern/audaspace/FX/AUD_SquareReader.cpp @@ -0,0 +1,63 @@ +/* + * $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_SquareReader.h" +#include "AUD_Buffer.h" + +#include <cstring> + +AUD_SquareReader::AUD_SquareReader(AUD_IReader* reader, float threshold) : + AUD_EffectReader(reader), + m_threshold(threshold) +{ + m_buffer = new AUD_Buffer(); AUD_NEW("buffer") +} + +AUD_SquareReader::~AUD_SquareReader() +{ + delete m_buffer; AUD_DELETE("buffer") +} + +void AUD_SquareReader::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(); + + for(int i = 0; i < length * specs.channels; i++) + { + if(buf[i] >= m_threshold) + buffer[i] = 1.0f; + else if(buf[i] <= -m_threshold) + buffer[i] = -1.0f; + else + buffer[i] = 0.0f; + } +} diff --git a/intern/audaspace/FX/AUD_SquareReader.h b/intern/audaspace/FX/AUD_SquareReader.h new file mode 100644 index 00000000000..63dda351445 --- /dev/null +++ b/intern/audaspace/FX/AUD_SquareReader.h @@ -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_SQUAREREADER +#define AUD_SQUAREREADER + +#include "AUD_EffectReader.h" +class AUD_Buffer; + +/** + * This class changes another signal into a square signal. + */ +class AUD_SquareReader : public AUD_EffectReader +{ +private: + /** + * The playback buffer. + */ + AUD_Buffer *m_buffer; + + /** + * The threshold level. + */ + float m_threshold; + +public: + /** + * Creates a new square reader. + * \param reader The reader to read from. + * \param threshold The size of the buffer. + * \exception AUD_Exception Thrown if the reader specified is NULL. + */ + AUD_SquareReader(AUD_IReader* reader, float threshold); + + /** + * Destroys the reader. + */ + virtual ~AUD_SquareReader(); + + virtual void read(int & length, sample_t* & buffer); +}; + +#endif //AUD_SQUAREREADER diff --git a/intern/audaspace/FX/AUD_SumFactory.cpp b/intern/audaspace/FX/AUD_SumFactory.cpp new file mode 100644 index 00000000000..f7990aab8a1 --- /dev/null +++ b/intern/audaspace/FX/AUD_SumFactory.cpp @@ -0,0 +1,43 @@ +/* + * $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_SumFactory.h" +#include "AUD_SumReader.h" + +AUD_SumFactory::AUD_SumFactory(AUD_IFactory* factory) : + AUD_EffectFactory(factory) {} + +AUD_IReader* AUD_SumFactory::createReader() +{ + AUD_IReader* reader = getReader(); + + if(reader != 0) + { + reader = new AUD_SumReader(reader); + AUD_NEW("reader") + } + + return reader; +} diff --git a/intern/audaspace/SDL/AUD_SDLMixerFactory.h b/intern/audaspace/FX/AUD_SumFactory.h index 44b36d06859..5cb48e26b10 100644 --- a/intern/audaspace/SDL/AUD_SDLMixerFactory.h +++ b/intern/audaspace/FX/AUD_SumFactory.h @@ -23,23 +23,24 @@ * ***** END LGPL LICENSE BLOCK ***** */ -#ifndef AUD_SDLMIXERFACTORY -#define AUD_SDLMIXERFACTORY +#ifndef AUD_SUMFACTORY +#define AUD_SUMFACTORY -#include "AUD_MixerFactory.h" +#include "AUD_EffectFactory.h" /** - * This factory creates a resampling reader that uses SDL's resampling - * functionality which unfortunately is very very very limited. + * This factory creates a sum reader. */ -class AUD_SDLMixerFactory : public AUD_MixerFactory +class AUD_SumFactory : public AUD_EffectFactory { public: - AUD_SDLMixerFactory(AUD_IReader* reader, AUD_Specs specs); - AUD_SDLMixerFactory(AUD_IFactory* factory, AUD_Specs specs); - AUD_SDLMixerFactory(AUD_Specs specs); + /** + * Creates a new sum factory. + * \param factory The input factory. + */ + AUD_SumFactory(AUD_IFactory* factory = 0); virtual AUD_IReader* createReader(); }; -#endif //AUD_SDLMIXERFACTORY +#endif //AUD_SUMFACTORY diff --git a/intern/audaspace/FX/AUD_SumReader.cpp b/intern/audaspace/FX/AUD_SumReader.cpp new file mode 100644 index 00000000000..08747790fc9 --- /dev/null +++ b/intern/audaspace/FX/AUD_SumReader.cpp @@ -0,0 +1,68 @@ +/* + * $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_SumReader.h" +#include "AUD_Buffer.h" + +#include <cstring> + +#define CC specs.channels + channel + +AUD_SumReader::AUD_SumReader(AUD_IReader* reader) : + AUD_EffectReader(reader) +{ + AUD_Specs specs = reader->getSpecs(); + int samplesize = AUD_SAMPLE_SIZE(specs); + + m_buffer = new AUD_Buffer(); AUD_NEW("buffer") + + m_sums = new AUD_Buffer(samplesize); AUD_NEW("buffer") + memset(m_sums->getBuffer(), 0, samplesize); +} + +AUD_SumReader::~AUD_SumReader() +{ + delete m_buffer; AUD_DELETE("buffer") + delete m_sums; AUD_DELETE("buffer") +} + +void AUD_SumReader::read(int & length, sample_t* & buffer) +{ + sample_t* buf; + sample_t* sums; + sums = m_sums->getBuffer(); + + 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(); + + for(int channel = 0; channel < specs.channels; channel++) + for(int i = 0; i < length * specs.channels; i++) + buffer[i * CC] = sums[channel] = sums[channel] + buf[i * CC]; +} diff --git a/intern/audaspace/FX/AUD_SumReader.h b/intern/audaspace/FX/AUD_SumReader.h new file mode 100644 index 00000000000..76ccf2f863a --- /dev/null +++ b/intern/audaspace/FX/AUD_SumReader.h @@ -0,0 +1,64 @@ +/* + * $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_SUMREADER +#define AUD_SUMREADER + +#include "AUD_EffectReader.h" +class AUD_Buffer; + +/** + * This class represents an summer. + */ +class AUD_SumReader : public AUD_EffectReader +{ +private: + /** + * The playback buffer. + */ + AUD_Buffer *m_buffer; + + /** + * The sums of the specific channels. + */ + AUD_Buffer *m_sums; + +public: + /** + * Creates a new sum reader. + * \param reader The reader to read from. + * \exception AUD_Exception Thrown if the reader specified is NULL. + */ + AUD_SumReader(AUD_IReader* reader); + + /** + * Destroys the reader. + */ + virtual ~AUD_SumReader(); + + virtual void read(int & length, sample_t* & buffer); +}; + +#endif //AUD_SUMREADER diff --git a/intern/audaspace/FX/AUD_VolumeFactory.h b/intern/audaspace/FX/AUD_VolumeFactory.h index d2812536d83..09f91241b47 100644 --- a/intern/audaspace/FX/AUD_VolumeFactory.h +++ b/intern/audaspace/FX/AUD_VolumeFactory.h @@ -47,7 +47,7 @@ public: * \param factory The input factory. * \param volume The desired volume. */ - AUD_VolumeFactory(AUD_IFactory* factory = 0, float volume = 1.0); + AUD_VolumeFactory(AUD_IFactory* factory = 0, float volume = 1.0f); /** * Creates a new volume factory. diff --git a/intern/audaspace/FX/AUD_VolumeReader.cpp b/intern/audaspace/FX/AUD_VolumeReader.cpp index fc3f20152a6..f094c1e4ea3 100644 --- a/intern/audaspace/FX/AUD_VolumeReader.cpp +++ b/intern/audaspace/FX/AUD_VolumeReader.cpp @@ -32,35 +32,6 @@ AUD_VolumeReader::AUD_VolumeReader(AUD_IReader* reader, float volume) : AUD_EffectReader(reader), m_volume(volume) { - int bigendian = 1; - bigendian = (((char*)&bigendian)[0]) ? 0: 1; // 1 if Big Endian - - switch(m_reader->getSpecs().format) - { - case AUD_FORMAT_S16: - m_adjust = AUD_volume_adjust<int16_t>; - break; - case AUD_FORMAT_S32: - m_adjust = AUD_volume_adjust<int32_t>; - break; - case AUD_FORMAT_FLOAT32: - m_adjust = AUD_volume_adjust<float>; - break; - case AUD_FORMAT_FLOAT64: - m_adjust = AUD_volume_adjust<double>; - break; - case AUD_FORMAT_U8: - m_adjust = AUD_volume_adjust_u8; - break; - case AUD_FORMAT_S24: - m_adjust = bigendian ? AUD_volume_adjust_s24_be : - AUD_volume_adjust_s24_le; - break; - default: - delete m_reader; - AUD_THROW(AUD_ERROR_READER); - } - m_buffer = new AUD_Buffer(); AUD_NEW("buffer") } @@ -93,5 +64,6 @@ void AUD_VolumeReader::read(int & length, sample_t* & buffer) buffer = m_buffer->getBuffer(); - m_adjust(buffer, buf, length * specs.channels, m_volume); + for(int i = 0; i < length * specs.channels; i++) + buffer[i] = buf[i] * m_volume; } diff --git a/intern/audaspace/FX/AUD_VolumeReader.h b/intern/audaspace/FX/AUD_VolumeReader.h index f38ae4d265c..489f85b10f2 100644 --- a/intern/audaspace/FX/AUD_VolumeReader.h +++ b/intern/audaspace/FX/AUD_VolumeReader.h @@ -27,7 +27,6 @@ #define AUD_VOLUMEREADER #include "AUD_EffectReader.h" -#include "AUD_ConverterFunctions.h" class AUD_Buffer; /** @@ -46,11 +45,6 @@ private: */ float m_volume; - /** - * Volume adjustment function. - */ - AUD_volume_adjust_f m_adjust; - public: /** * Creates a new volume reader. diff --git a/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp b/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp index aa9f425d6fb..0d90b014943 100644 --- a/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp +++ b/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp @@ -25,7 +25,6 @@ #include "AUD_OpenALDevice.h" #include "AUD_IReader.h" -#include "AUD_IMixer.h" #include "AUD_ConverterFactory.h" #include "AUD_SourceCaps.h" @@ -119,7 +118,7 @@ void AUD_OpenALDevice::updateStreams() sample_t* buffer; ALint info; - AUD_Specs specs; + AUD_DeviceSpecs specs = m_specs; while(1) { @@ -145,7 +144,7 @@ void AUD_OpenALDevice::updateStreams() if(info) { - specs = sound->reader->getSpecs(); + specs.specs = sound->reader->getSpecs(); // for all empty buffers while(info--) @@ -177,8 +176,8 @@ void AUD_OpenALDevice::updateStreams() // fill with new data alBufferData(sound->buffers[sound->current], sound->format, - buffer, - length * AUD_SAMPLE_SIZE(specs), + buffer, length * + AUD_DEVICE_SAMPLE_SIZE(specs), specs.rate); if(alGetError() != AL_NO_ERROR) @@ -264,7 +263,7 @@ bool AUD_OpenALDevice::isValid(AUD_Handle* handle) return false; } -AUD_OpenALDevice::AUD_OpenALDevice(AUD_Specs specs, int buffersize) +AUD_OpenALDevice::AUD_OpenALDevice(AUD_DeviceSpecs specs, int buffersize) { // cannot determine how many channels or which format OpenAL uses, but // it at least is able to play 16 bit stereo audio @@ -289,14 +288,17 @@ AUD_OpenALDevice::AUD_OpenALDevice(AUD_Specs specs, int buffersize) // check for specific formats and channel counts to be played back if(alIsExtensionPresent("AL_EXT_FLOAT32") == AL_TRUE) + { specs.format = AUD_FORMAT_FLOAT32; + m_converter = NULL; + } + else + m_converter = new AUD_ConverterFactory(specs); AUD_NEW("factory") m_useMC = alIsExtensionPresent("AL_EXT_MCFORMATS") == AL_TRUE; alGetError(); - m_converter = new AUD_ConverterFactory(specs); AUD_NEW("factory") - m_specs = specs; m_buffersize = buffersize; m_playing = false; @@ -378,12 +380,13 @@ AUD_OpenALDevice::~AUD_OpenALDevice() alcDestroyContext(m_context); alcCloseDevice(m_device); - delete m_converter; AUD_DELETE("factory") + if(m_converter) + delete m_converter; AUD_DELETE("factory") pthread_mutex_destroy(&m_mutex); } -AUD_Specs AUD_OpenALDevice::getSpecs() +AUD_DeviceSpecs AUD_OpenALDevice::getSpecs() { return m_specs; } @@ -393,45 +396,8 @@ bool AUD_OpenALDevice::getFormat(ALenum &format, AUD_Specs specs) bool valid = true; format = 0; - switch(specs.format) + switch(m_specs.format) { - case AUD_FORMAT_U8: - switch(specs.channels) - { - case AUD_CHANNELS_MONO: - format = AL_FORMAT_MONO8; - break; - case AUD_CHANNELS_STEREO: - format = AL_FORMAT_STEREO8; - break; - case AUD_CHANNELS_SURROUND4: - if(m_useMC) - { - format = alGetEnumValue("AL_FORMAT_QUAD8"); - break; - } - case AUD_CHANNELS_SURROUND51: - if(m_useMC) - { - format = alGetEnumValue("AL_FORMAT_51CHN8"); - break; - } - case AUD_CHANNELS_SURROUND61: - if(m_useMC) - { - format = alGetEnumValue("AL_FORMAT_61CHN8"); - break; - } - case AUD_CHANNELS_SURROUND71: - if(m_useMC) - { - format = alGetEnumValue("AL_FORMAT_71CHN8"); - break; - } - default: - valid = false; - } - break; case AUD_FORMAT_S16: switch(specs.channels) { @@ -591,23 +557,16 @@ AUD_Handle* AUD_OpenALDevice::play(AUD_IFactory* factory, bool keep) if(reader == NULL) AUD_THROW(AUD_ERROR_READER); - AUD_Specs specs; - - specs = reader->getSpecs(); + AUD_DeviceSpecs specs = m_specs; + specs.specs = reader->getSpecs(); // check format - bool valid = true; + bool valid = specs.channels != AUD_CHANNELS_INVALID; - if(specs.format == AUD_FORMAT_INVALID) - valid = false; - else if(specs.format == AUD_FORMAT_S24 || - specs.format == AUD_FORMAT_S32 || - specs.format == AUD_FORMAT_FLOAT32 || - specs.format == AUD_FORMAT_FLOAT64) + if(m_converter) { m_converter->setReader(reader); reader = m_converter->createReader(); - specs = reader->getSpecs(); } // create the handle @@ -618,7 +577,7 @@ AUD_Handle* AUD_OpenALDevice::play(AUD_IFactory* factory, bool keep) sound->isBuffered = false; sound->data_end = false; - valid &= getFormat(sound->format, specs); + valid &= getFormat(sound->format, specs.specs); if(!valid) { @@ -647,7 +606,8 @@ AUD_Handle* AUD_OpenALDevice::play(AUD_IFactory* factory, bool keep) length = m_buffersize; reader->read(length, buf); alBufferData(sound->buffers[i], sound->format, buf, - length * AUD_SAMPLE_SIZE(specs), specs.rate); + length * AUD_DEVICE_SAMPLE_SIZE(specs), + specs.rate); if(alGetError() != AL_NO_ERROR) AUD_THROW(AUD_ERROR_OPENAL); } @@ -875,14 +835,16 @@ bool AUD_OpenALDevice::seek(AUD_Handle* handle, float position) { sample_t* buf; int length; - AUD_Specs specs = alhandle->reader->getSpecs(); + AUD_DeviceSpecs specs = m_specs; + specs.specs = alhandle->reader->getSpecs(); for(int i = 0; i < AUD_OPENAL_CYCLE_BUFFERS; i++) { length = m_buffersize; alhandle->reader->read(length, buf); alBufferData(alhandle->buffers[i], alhandle->format, - buf, length * AUD_SAMPLE_SIZE(specs), + buf, + length * AUD_DEVICE_SAMPLE_SIZE(specs), specs.rate); if(alGetError() != AL_NO_ERROR) @@ -906,7 +868,7 @@ bool AUD_OpenALDevice::seek(AUD_Handle* handle, float position) float AUD_OpenALDevice::getPosition(AUD_Handle* handle) { - float position = 0.0; + float position = 0.0f; lock(); @@ -1021,6 +983,7 @@ bool AUD_OpenALDevice::setCapability(int capability, void *value) // load the factory into an OpenAL buffer if(factory) { + // check if the factory is already buffered lock(); for(AUD_BFIterator i = m_bufferedFactories->begin(); i != m_bufferedFactories->end(); i++) @@ -1040,32 +1003,25 @@ bool AUD_OpenALDevice::setCapability(int capability, void *value) if(reader == NULL) return false; - AUD_Specs specs; - - specs = reader->getSpecs(); + AUD_DeviceSpecs specs = m_specs; + specs.specs = reader->getSpecs(); // determine format bool valid = reader->getType() == AUD_TYPE_BUFFER; if(valid) { - if(specs.format == AUD_FORMAT_INVALID) - valid = false; - else if(specs.format == AUD_FORMAT_S24 || - specs.format == AUD_FORMAT_S32 || - specs.format == AUD_FORMAT_FLOAT32 || - specs.format == AUD_FORMAT_FLOAT64) + if(m_converter) { m_converter->setReader(reader); reader = m_converter->createReader(); - specs = reader->getSpecs(); } } ALenum format; if(valid) - valid = getFormat(format, specs); + valid = getFormat(format, specs.specs); if(!valid) { @@ -1094,7 +1050,7 @@ bool AUD_OpenALDevice::setCapability(int capability, void *value) reader->read(length, buf); alBufferData(bf->buffer, format, buf, - length * AUD_SAMPLE_SIZE(specs), + length * AUD_DEVICE_SAMPLE_SIZE(specs), specs.rate); if(alGetError() != AL_NO_ERROR) AUD_THROW(AUD_ERROR_OPENAL); @@ -1327,7 +1283,7 @@ bool AUD_OpenALDevice::setSourceSetting(AUD_Handle* handle, result = true; break; case AUD_3DSS_IS_RELATIVE: - alSourcei(source, AL_SOURCE_RELATIVE, value > 0.0); + alSourcei(source, AL_SOURCE_RELATIVE, value > 0.0f); result = true; break; case AUD_3DSS_MAX_DISTANCE: @@ -1385,7 +1341,7 @@ float AUD_OpenALDevice::getSourceSetting(AUD_Handle* handle, { ALint i; alGetSourcei(source, AL_SOURCE_RELATIVE, &i); - result = i ? 1.0 : 0.0; + result = i ? 1.0f : 0.0f; break; } case AUD_3DSS_MAX_DISTANCE: diff --git a/intern/audaspace/OpenAL/AUD_OpenALDevice.h b/intern/audaspace/OpenAL/AUD_OpenALDevice.h index 074cd3d1924..cb8c83ab810 100644 --- a/intern/audaspace/OpenAL/AUD_OpenALDevice.h +++ b/intern/audaspace/OpenAL/AUD_OpenALDevice.h @@ -56,7 +56,7 @@ private: /** * The specification of the device. */ - AUD_Specs m_specs; + AUD_DeviceSpecs m_specs; /** * Whether the device has the AL_EXT_MCFORMATS extension. @@ -64,8 +64,8 @@ private: bool m_useMC; /** - * The converter factory for readers with wrong input format. - */ + * The converter factory for readers with wrong input format. + */ AUD_ConverterFactory* m_converter; /** @@ -118,7 +118,7 @@ private: /** * Gets the format according to the specs. * \param format The variable to put the format into. - * \param specs The specs to read the format from. + * \param specs The specs to read the channel count from. * \return Whether the format is valid or not. */ bool getFormat(ALenum &format, AUD_Specs specs); @@ -132,7 +132,8 @@ public: * \note The buffersize will be multiplicated by three for this device. * \exception AUD_Exception Thrown if the audio device cannot be opened. */ - AUD_OpenALDevice(AUD_Specs specs, int buffersize = AUD_DEFAULT_BUFFER_SIZE); + AUD_OpenALDevice(AUD_DeviceSpecs specs, + int buffersize = AUD_DEFAULT_BUFFER_SIZE); /** * Streaming thread main function. @@ -141,7 +142,7 @@ public: virtual ~AUD_OpenALDevice(); - virtual AUD_Specs getSpecs(); + virtual AUD_DeviceSpecs getSpecs(); virtual AUD_Handle* play(AUD_IFactory* factory, bool keep = false); virtual bool pause(AUD_Handle* handle); virtual bool resume(AUD_Handle* handle); diff --git a/intern/audaspace/SConscript b/intern/audaspace/SConscript index ac3f8ca71a0..bbd2442c480 100644 --- a/intern/audaspace/SConscript +++ b/intern/audaspace/SConscript @@ -36,4 +36,7 @@ if env['WITH_BF_FFTW3']: incs += ' fftw ' + env['BF_FFTW3_INC'] defs.append('WITH_FFTW3') +if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc'): + incs += ' ' + env['BF_PTHREADS_INC'] + env.BlenderLib ('bf_audaspace', sources, Split(incs), defs, libtype=['intern','player'], priority = [25,215] ) diff --git a/intern/audaspace/SDL/AUD_SDLDevice.cpp b/intern/audaspace/SDL/AUD_SDLDevice.cpp index dd443e7f5c7..1a385af8a0c 100644 --- a/intern/audaspace/SDL/AUD_SDLDevice.cpp +++ b/intern/audaspace/SDL/AUD_SDLDevice.cpp @@ -23,7 +23,6 @@ * ***** END LGPL LICENSE BLOCK ***** */ -#include "AUD_SDLMixer.h" #include "AUD_SDLDevice.h" #include "AUD_IReader.h" @@ -31,10 +30,10 @@ void AUD_SDLDevice::SDL_mix(void *data, Uint8* buffer, int length) { AUD_SDLDevice* device = (AUD_SDLDevice*)data; - device->mix((sample_t*)buffer, length/AUD_SAMPLE_SIZE(device->m_specs)); + device->mix((data_t*)buffer,length/AUD_DEVICE_SAMPLE_SIZE(device->m_specs)); } -AUD_SDLDevice::AUD_SDLDevice(AUD_Specs specs, int buffersize) +AUD_SDLDevice::AUD_SDLDevice(AUD_DeviceSpecs specs, int buffersize) { if(specs.channels == AUD_CHANNELS_INVALID) specs.channels = AUD_CHANNELS_STEREO; @@ -69,9 +68,6 @@ AUD_SDLDevice::AUD_SDLDevice(AUD_Specs specs, int buffersize) else AUD_THROW(AUD_ERROR_SDL); - m_mixer = new AUD_SDLMixer(); AUD_NEW("mixer") - m_mixer->setSpecs(m_specs); - create(); } diff --git a/intern/audaspace/SDL/AUD_SDLDevice.h b/intern/audaspace/SDL/AUD_SDLDevice.h index e2c6f7631b7..4b7de1996e8 100644 --- a/intern/audaspace/SDL/AUD_SDLDevice.h +++ b/intern/audaspace/SDL/AUD_SDLDevice.h @@ -55,7 +55,8 @@ public: * \note The specification really used for opening the device may differ. * \exception AUD_Exception Thrown if the audio device cannot be opened. */ - AUD_SDLDevice(AUD_Specs specs, int buffersize = AUD_DEFAULT_BUFFER_SIZE); + AUD_SDLDevice(AUD_DeviceSpecs specs, + int buffersize = AUD_DEFAULT_BUFFER_SIZE); /** * Closes the SDL audio device. diff --git a/intern/audaspace/SDL/AUD_SDLMixer.cpp b/intern/audaspace/SDL/AUD_SDLMixer.cpp deleted file mode 100644 index cacc0c7063c..00000000000 --- a/intern/audaspace/SDL/AUD_SDLMixer.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* - * $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_SDLMixer.h" -#include "AUD_SDLMixerFactory.h" - -#include <SDL.h> - -AUD_SDLMixer::AUD_SDLMixer() -{ - m_factory = NULL; -} - -AUD_SDLMixer::~AUD_SDLMixer() -{ - if(m_factory) - { - delete m_factory; AUD_DELETE("factory") - } -} - -AUD_IReader* AUD_SDLMixer::prepare(AUD_IReader* reader) -{ - m_factory->setReader(reader); - return m_factory->createReader(); -} - -void AUD_SDLMixer::setSpecs(AUD_Specs specs) -{ - m_samplesize = AUD_SAMPLE_SIZE(specs); - if(m_factory) - { - delete m_factory; AUD_DELETE("factory") - } - m_factory = new AUD_SDLMixerFactory(specs); AUD_NEW("factory") -} - -void AUD_SDLMixer::add(sample_t* buffer, AUD_Specs specs, int length, - float volume) -{ - AUD_SDLMixerBuffer buf; - buf.buffer = buffer; - buf.length = length; - buf.volume = volume; - m_buffers.push_back(buf); -} - -void AUD_SDLMixer::superpose(sample_t* buffer, int length, float volume) -{ - AUD_SDLMixerBuffer buf; - - while(!m_buffers.empty()) - { - buf = m_buffers.front(); - m_buffers.pop_front(); - SDL_MixAudio((Uint8*)buffer, - (Uint8*)buf.buffer, - buf.length * m_samplesize, - (int)(SDL_MIX_MAXVOLUME * volume * buf.volume)); - } -} diff --git a/intern/audaspace/SDL/AUD_SDLMixerReader.cpp b/intern/audaspace/SDL/AUD_SDLMixerReader.cpp deleted file mode 100644 index 0a47e36533a..00000000000 --- a/intern/audaspace/SDL/AUD_SDLMixerReader.cpp +++ /dev/null @@ -1,216 +0,0 @@ -/* - * $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_SDLMixerReader.h" -#include "AUD_Buffer.h" - -#include <cstring> - -inline Uint16 AUD_TO_SDL(AUD_SampleFormat format) -{ - // SDL only supports 8 and 16 bit audio - switch(format) - { - case AUD_FORMAT_U8: - return AUDIO_U8; - case AUD_FORMAT_S16: - return AUDIO_S16SYS; - default: - AUD_THROW(AUD_ERROR_SDL); - } -} - -// greatest common divisor -inline int gcd(int a, int b) -{ - int c; - - // make sure a is the bigger - if(b > a) - { - c = b; - b = a; - a = c; - } - - // greetings from Euclides - while(b != 0) - { - c = a % b; - a = b; - b = c; - } - return a; -} - -AUD_SDLMixerReader::AUD_SDLMixerReader(AUD_IReader* reader, - AUD_Specs specs) -{ - if(reader == NULL) - AUD_THROW(AUD_ERROR_READER); - - m_reader = reader; - m_tspecs = specs; - m_sspecs = reader->getSpecs(); - - try - { - // SDL only supports 8 and 16 bit sample formats - if(SDL_BuildAudioCVT(&m_cvt, - AUD_TO_SDL(m_sspecs.format), - m_sspecs.channels, - m_sspecs.rate, - AUD_TO_SDL(specs.format), - specs.channels, - specs.rate) == -1) - AUD_THROW(AUD_ERROR_SDL); - } - catch(AUD_Exception) - { - delete m_reader; AUD_DELETE("reader") - throw; - } - - m_eor = false; - m_rsposition = 0; - m_rssize = 0; - m_ssize = m_sspecs.rate / gcd(specs.rate, m_sspecs.rate); - m_tsize = m_tspecs.rate * m_ssize / m_sspecs.rate; - - m_buffer = new AUD_Buffer(); AUD_NEW("buffer") - m_rsbuffer = new AUD_Buffer(); AUD_NEW("buffer") -} - -AUD_SDLMixerReader::~AUD_SDLMixerReader() -{ - delete m_reader; AUD_DELETE("reader") - delete m_buffer; AUD_DELETE("buffer") - delete m_rsbuffer; AUD_DELETE("buffer") -} - -bool AUD_SDLMixerReader::isSeekable() -{ - return m_reader->isSeekable(); -} - -void AUD_SDLMixerReader::seek(int position) -{ - m_reader->seek(position * m_ssize / m_tsize); - m_eor = false; -} - -int AUD_SDLMixerReader::getLength() -{ - return m_reader->getLength() * m_tsize / m_ssize; -} - -int AUD_SDLMixerReader::getPosition() -{ - return m_reader->getPosition() * m_tsize / m_ssize; -} - -AUD_Specs AUD_SDLMixerReader::getSpecs() -{ - return m_tspecs; -} - -AUD_ReaderType AUD_SDLMixerReader::getType() -{ - return m_reader->getType(); -} - -bool AUD_SDLMixerReader::notify(AUD_Message &message) -{ - return m_reader->notify(message); -} - -void AUD_SDLMixerReader::read(int & length, sample_t* & buffer) -{ - // sample count for the target buffer without getting a shift - int tns = length + m_tsize - length % m_tsize; - // sample count for the source buffer without getting a shift - int sns = tns * m_ssize / m_tsize; - // target sample size - int tss = AUD_SAMPLE_SIZE(m_tspecs); - // source sample size - int sss = AUD_SAMPLE_SIZE(m_sspecs); - - // input is output buffer - int buf_size = AUD_MAX(tns*tss, sns*sss); - - // resize if necessary - if(m_rsbuffer->getSize() < buf_size) - m_rsbuffer->resize(buf_size, true); - - if(m_buffer->getSize() < length*tss) - m_buffer->resize(length*tss); - - buffer = m_buffer->getBuffer(); - int size; - int index = 0; - sample_t* buf; - - while(index < length) - { - if(m_rsposition == m_rssize) - { - // no more data - if(m_eor) - length = index; - // mix - else - { - // read from source - size = sns; - m_reader->read(size, buf); - - // prepare - m_cvt.buf = m_rsbuffer->getBuffer(); - m_cvt.len = size*sss; - memcpy(m_cvt.buf, buf, size*sss); - - // convert - SDL_ConvertAudio(&m_cvt); - - // end of reader - if(size < sns) - m_eor = true; - - m_rsposition = 0; - m_rssize = size * m_tsize / m_ssize; - } - } - - // size to copy - size = AUD_MIN(m_rssize-m_rsposition, length-index); - - // copy - memcpy(m_buffer->getBuffer() + index * tss, - m_rsbuffer->getBuffer() + m_rsposition * tss, - size*tss); - m_rsposition += size; - index += size; - } -} diff --git a/intern/audaspace/SDL/AUD_SDLMixerReader.h b/intern/audaspace/SDL/AUD_SDLMixerReader.h deleted file mode 100644 index 56668d02171..00000000000 --- a/intern/audaspace/SDL/AUD_SDLMixerReader.h +++ /dev/null @@ -1,128 +0,0 @@ -/* - * $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_SDLMIXERREADER -#define AUD_SDLMIXERREADER - -#include "AUD_IReader.h" -class AUD_Buffer; - -#include <SDL.h> - -/** - * This class mixes a sound source with help of the SDL library. - * Unfortunately SDL is only capable of 8 and 16 bit audio, mono and stereo, as - * well as resampling only 2^n sample rate relationships where n is a natural - * number. - * \warning Although SDL can only resample 2^n sample rate relationships, this - * class doesn't check for compliance, so in case of other factors, - * the behaviour is undefined. - */ -class AUD_SDLMixerReader : public AUD_IReader -{ -private: - /** - * The reader that is being mixed. - */ - AUD_IReader* m_reader; - - /** - * The current reading position in the resampling buffer. - */ - int m_rsposition; - - /** - * The count of mixed samples in the resampling buffer. - */ - int m_rssize; - - /** - * The smallest count of source samples to get a fractionless resampling - * factor. - */ - int m_ssize; - - /** - * The smallest count of target samples to get a fractionless resampling - * factor. - */ - int m_tsize; - - /** - * The sound output buffer. - */ - AUD_Buffer *m_buffer; - - /** - * The resampling buffer. - */ - AUD_Buffer *m_rsbuffer; - - /** - * The target specification. - */ - AUD_Specs m_tspecs; - - /** - * The sample specification of the source. - */ - AUD_Specs m_sspecs; - - /** - * Saves whether the end of the source has been reached. - */ - bool m_eor; - - /** - * The SDL_AudioCVT structure used for resampling. - */ - SDL_AudioCVT m_cvt; - -public: - /** - * Creates a resampling reader. - * \param reader The reader to mix. - * \param specs The target specification. - * \exception AUD_Exception Thrown if the source specification cannot be - * mixed to the target specification or if the reader is - * NULL. - */ - AUD_SDLMixerReader(AUD_IReader* reader, AUD_Specs specs); - /** - * Destroys the reader. - */ - ~AUD_SDLMixerReader(); - - virtual bool isSeekable(); - virtual void seek(int position); - virtual int getLength(); - virtual int getPosition(); - virtual AUD_Specs getSpecs(); - virtual AUD_ReaderType getType(); - virtual bool notify(AUD_Message &message); - virtual void read(int & length, sample_t* & buffer); -}; - -#endif //AUD_SDLMIXERREADER diff --git a/intern/audaspace/SRC/AUD_SRCResampleFactory.cpp b/intern/audaspace/SRC/AUD_SRCResampleFactory.cpp index bcace340b24..caafbd14327 100644 --- a/intern/audaspace/SRC/AUD_SRCResampleFactory.cpp +++ b/intern/audaspace/SRC/AUD_SRCResampleFactory.cpp @@ -27,14 +27,14 @@ #include "AUD_SRCResampleReader.h" AUD_SRCResampleFactory::AUD_SRCResampleFactory(AUD_IReader* reader, - AUD_Specs specs) : + AUD_DeviceSpecs specs) : AUD_ResampleFactory(reader, specs) {} AUD_SRCResampleFactory::AUD_SRCResampleFactory(AUD_IFactory* factory, - AUD_Specs specs) : + AUD_DeviceSpecs specs) : AUD_ResampleFactory(factory, specs) {} -AUD_SRCResampleFactory::AUD_SRCResampleFactory(AUD_Specs specs) : +AUD_SRCResampleFactory::AUD_SRCResampleFactory(AUD_DeviceSpecs specs) : AUD_ResampleFactory(specs) {} AUD_IReader* AUD_SRCResampleFactory::createReader() @@ -45,7 +45,7 @@ AUD_IReader* AUD_SRCResampleFactory::createReader() { if(reader->getSpecs().rate != m_specs.rate) { - reader = new AUD_SRCResampleReader(reader, m_specs); + reader = new AUD_SRCResampleReader(reader, m_specs.specs); AUD_NEW("reader") } } diff --git a/intern/audaspace/SRC/AUD_SRCResampleFactory.h b/intern/audaspace/SRC/AUD_SRCResampleFactory.h index c23c1d2c82e..4b16c70169c 100644 --- a/intern/audaspace/SRC/AUD_SRCResampleFactory.h +++ b/intern/audaspace/SRC/AUD_SRCResampleFactory.h @@ -31,14 +31,13 @@ /** * This factory creates a resampling reader that uses libsamplerate for * resampling. - * \note The format of the input must be float. */ class AUD_SRCResampleFactory : public AUD_ResampleFactory { public: - AUD_SRCResampleFactory(AUD_IReader* reader, AUD_Specs specs); - AUD_SRCResampleFactory(AUD_IFactory* factory, AUD_Specs specs); - AUD_SRCResampleFactory(AUD_Specs specs); + AUD_SRCResampleFactory(AUD_IReader* reader, AUD_DeviceSpecs specs); + AUD_SRCResampleFactory(AUD_IFactory* factory, AUD_DeviceSpecs specs); + AUD_SRCResampleFactory(AUD_DeviceSpecs specs); virtual AUD_IReader* createReader(); }; diff --git a/intern/audaspace/SRC/AUD_SRCResampleReader.cpp b/intern/audaspace/SRC/AUD_SRCResampleReader.cpp index f7564d3c010..940f4245316 100644 --- a/intern/audaspace/SRC/AUD_SRCResampleReader.cpp +++ b/intern/audaspace/SRC/AUD_SRCResampleReader.cpp @@ -26,9 +26,9 @@ #include "AUD_SRCResampleReader.h" #include "AUD_Buffer.h" -#include <math.h> +#include <cmath> #include <cstring> -#include <stdio.h> +#include <cstdio> static long src_callback(void *cb_data, float **data) { @@ -41,15 +41,8 @@ AUD_SRCResampleReader::AUD_SRCResampleReader(AUD_IReader* reader, { m_sspecs = reader->getSpecs(); - if(m_sspecs.format != AUD_FORMAT_FLOAT32) - { - delete m_reader; AUD_DELETE("reader") - AUD_THROW(AUD_ERROR_READER); - } - m_tspecs = specs; m_tspecs.channels = m_sspecs.channels; - m_tspecs.format = m_sspecs.format; m_factor = (double)m_tspecs.rate / (double)m_sspecs.rate; int error; @@ -71,9 +64,9 @@ AUD_SRCResampleReader::AUD_SRCResampleReader(AUD_IReader* reader, AUD_SRCResampleReader::~AUD_SRCResampleReader() { - delete m_buffer; AUD_DELETE("buffer") - src_delete(m_src); + + delete m_buffer; AUD_DELETE("buffer") } long AUD_SRCResampleReader::doCallback(float** data) @@ -83,7 +76,7 @@ long AUD_SRCResampleReader::doCallback(float** data) m_reader->read(length, buffer); - *data = (float*)buffer; + *data = buffer; return length; } @@ -110,10 +103,12 @@ AUD_Specs AUD_SRCResampleReader::getSpecs() void AUD_SRCResampleReader::read(int & length, sample_t* & buffer) { - if(m_buffer->getSize() < length * m_tspecs.channels * 4) - m_buffer->resize(length * m_tspecs.channels * 4); + int size = length * AUD_SAMPLE_SIZE(m_tspecs); + + if(m_buffer->getSize() < size) + m_buffer->resize(size); buffer = m_buffer->getBuffer(); - length = src_callback_read(m_src, m_factor, length, (float*)buffer); + length = src_callback_read(m_src, m_factor, length, buffer); } diff --git a/intern/audaspace/SRC/AUD_SRCResampleReader.h b/intern/audaspace/SRC/AUD_SRCResampleReader.h index 1bacdb3965c..4fe30b48c6e 100644 --- a/intern/audaspace/SRC/AUD_SRCResampleReader.h +++ b/intern/audaspace/SRC/AUD_SRCResampleReader.h @@ -32,13 +32,7 @@ class AUD_Buffer; #include <samplerate.h> /** - * This class mixes a sound source with help of the SDL library. - * Unfortunately SDL is only capable of 8 and 16 bit audio, mono and stereo, as - * well as resampling only 2^n sample rate relationships where n is a natural - * number. - * \warning Although SDL can only resample 2^n sample rate relationships, this - * class doesn't check for compliance, so in case of other factors, - * the behaviour is undefined. + * This resampling reader uses libsamplerate for resampling. */ class AUD_SRCResampleReader : public AUD_EffectReader { diff --git a/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp index 0384ba5e0e6..027ac015eb5 100644 --- a/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp +++ b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp @@ -34,26 +34,6 @@ extern "C" { #include <libavformat/avformat.h> } -// This function transforms a FFMPEG SampleFormat to our own sample format -static inline AUD_SampleFormat FFMPEG_TO_AUD(SampleFormat fmt) -{ - switch(fmt) - { - case SAMPLE_FMT_U8: - return AUD_FORMAT_U8; - case SAMPLE_FMT_S16: - return AUD_FORMAT_S16; - case SAMPLE_FMT_S32: - return AUD_FORMAT_S32; - case SAMPLE_FMT_FLT: - return AUD_FORMAT_FLOAT32; - case SAMPLE_FMT_DBL: - return AUD_FORMAT_FLOAT64; - default: - return AUD_FORMAT_INVALID; - } -} - int AUD_FFMPEGReader::decode(AVPacket* packet, AUD_Buffer* buffer) { // save packet parameters @@ -78,11 +58,11 @@ int AUD_FFMPEGReader::decode(AVPacket* packet, AUD_Buffer* buffer) // read samples from the packet data_size = buf_size - buf_pos; /*read_length = avcodec_decode_audio3(m_codecCtx, - (int16_t*)(buffer->getBuffer()+buf_pos), + (int16_t*)(((data_t*)buffer->getBuffer())+buf_pos), &data_size, packet);*/ read_length = avcodec_decode_audio2(m_codecCtx, - (int16_t*)(buffer->getBuffer()+buf_pos), + (int16_t*)(((data_t*)buffer->getBuffer())+buf_pos), &data_size, audio_pkg_data, audio_pkg_size); @@ -101,78 +81,108 @@ int AUD_FFMPEGReader::decode(AVPacket* packet, AUD_Buffer* buffer) return buf_pos; } -AUD_FFMPEGReader::AUD_FFMPEGReader(const char* filename) +void AUD_FFMPEGReader::init() { m_position = 0; m_pkgbuf_left = 0; - m_byteiocontext = NULL; - // open file - if(av_open_input_file(&m_formatCtx, filename, NULL, 0, NULL)!=0) - AUD_THROW(AUD_ERROR_FILE); + if(av_find_stream_info(m_formatCtx)<0) + AUD_THROW(AUD_ERROR_FFMPEG); - try - { - if(av_find_stream_info(m_formatCtx)<0) - AUD_THROW(AUD_ERROR_FFMPEG); + // find audio stream and codec + m_stream = -1; - // find audio stream and codec - m_stream = -1; + for(unsigned int i = 0; i < m_formatCtx->nb_streams; i++) + if((m_formatCtx->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO) + && (m_stream < 0)) + { + m_stream=i; + break; + } + if(m_stream == -1) + AUD_THROW(AUD_ERROR_FFMPEG); - for(unsigned int i = 0; i < m_formatCtx->nb_streams; i++) - if((m_formatCtx->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO) - && (m_stream < 0)) - { - m_stream=i; - break; - } - if(m_stream == -1) - AUD_THROW(AUD_ERROR_FFMPEG); + m_codecCtx = m_formatCtx->streams[m_stream]->codec; - m_codecCtx = m_formatCtx->streams[m_stream]->codec; + // get a decoder and open it + AVCodec *aCodec = avcodec_find_decoder(m_codecCtx->codec_id); + if(!aCodec) + AUD_THROW(AUD_ERROR_FFMPEG); - // get a decoder and open it - AVCodec *aCodec = avcodec_find_decoder(m_codecCtx->codec_id); - if(!aCodec) - AUD_THROW(AUD_ERROR_FFMPEG); + if(avcodec_open(m_codecCtx, aCodec)<0) + AUD_THROW(AUD_ERROR_FFMPEG); - if(avcodec_open(m_codecCtx, aCodec)<0) - AUD_THROW(AUD_ERROR_FFMPEG); + // XXX this prints file information to stdout: + //dump_format(m_formatCtx, 0, NULL, 0); - // XXX this prints file information to stdout: - //dump_format(m_formatCtx, 0, filename, 0); + m_specs.channels = (AUD_Channels) m_codecCtx->channels; - m_specs.channels = (AUD_Channels) m_codecCtx->channels; - m_specs.format = FFMPEG_TO_AUD(m_codecCtx->sample_fmt); - m_specs.rate = (AUD_SampleRate) m_codecCtx->sample_rate; - } - catch(AUD_Exception) + switch(m_codecCtx->sample_fmt) { - av_close_input_file(m_formatCtx); - throw; + case SAMPLE_FMT_U8: + m_convert = AUD_convert_u8_float; + m_specs.format = AUD_FORMAT_U8; + break; + case SAMPLE_FMT_S16: + m_convert = AUD_convert_s16_float; + m_specs.format = AUD_FORMAT_S16; + break; + case SAMPLE_FMT_S32: + m_convert = AUD_convert_s32_float; + m_specs.format = AUD_FORMAT_S32; + break; + case SAMPLE_FMT_FLT: + m_convert = AUD_convert_copy<float>; + m_specs.format = AUD_FORMAT_FLOAT32; + break; + case SAMPLE_FMT_DBL: + m_convert = AUD_convert_double_float; + m_specs.format = AUD_FORMAT_FLOAT64; + break; + default: + AUD_THROW(AUD_ERROR_FILE); } + m_specs.rate = (AUD_SampleRate) m_codecCtx->sample_rate; + // last but not least if there hasn't been any error, create the buffers m_buffer = new AUD_Buffer(); AUD_NEW("buffer") m_pkgbuf = new AUD_Buffer(AVCODEC_MAX_AUDIO_FRAME_SIZE<<1); AUD_NEW("buffer") } +AUD_FFMPEGReader::AUD_FFMPEGReader(const char* filename) +{ + m_byteiocontext = NULL; + + // open file + if(av_open_input_file(&m_formatCtx, filename, NULL, 0, NULL)!=0) + AUD_THROW(AUD_ERROR_FILE); + + try + { + init(); + } + catch(AUD_Exception) + { + av_close_input_file(m_formatCtx); + throw; + } +} + AUD_FFMPEGReader::AUD_FFMPEGReader(AUD_Reference<AUD_Buffer> buffer) { - m_position = 0; - m_pkgbuf_left = 0; m_byteiocontext = (ByteIOContext*)av_mallocz(sizeof(ByteIOContext)); AUD_NEW("byteiocontext") m_membuffer = buffer; - if(init_put_byte(m_byteiocontext, buffer.get()->getBuffer(), buffer.get()->getSize(), 0, - NULL, NULL, NULL, NULL) != 0) + if(init_put_byte(m_byteiocontext, (data_t*)buffer.get()->getBuffer(), + buffer.get()->getSize(), 0, NULL, NULL, NULL, NULL) != 0) AUD_THROW(AUD_ERROR_FILE); AVProbeData probe_data; probe_data.filename = ""; - probe_data.buf = buffer.get()->getBuffer(); + probe_data.buf = (data_t*)buffer.get()->getBuffer(); probe_data.buf_size = buffer.get()->getSize(); AVInputFormat* fmt = av_probe_input_format(&probe_data, 1); @@ -182,38 +192,7 @@ AUD_FFMPEGReader::AUD_FFMPEGReader(AUD_Reference<AUD_Buffer> buffer) try { - if(av_find_stream_info(m_formatCtx)<0) - AUD_THROW(AUD_ERROR_FFMPEG); - - // find audio stream and codec - m_stream = -1; - - for(unsigned int i = 0; i < m_formatCtx->nb_streams; i++) - if((m_formatCtx->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO) - && (m_stream < 0)) - { - m_stream=i; - break; - } - if(m_stream == -1) - AUD_THROW(AUD_ERROR_FFMPEG); - - m_codecCtx = m_formatCtx->streams[m_stream]->codec; - - // get a decoder and open it - AVCodec *aCodec = avcodec_find_decoder(m_codecCtx->codec_id); - if(!aCodec) - AUD_THROW(AUD_ERROR_FFMPEG); - - if(avcodec_open(m_codecCtx, aCodec)<0) - AUD_THROW(AUD_ERROR_FFMPEG); - - // XXX this prints stream information to stdout: - //dump_format(m_formatCtx, 0, NULL, 0); - - m_specs.channels = (AUD_Channels) m_codecCtx->channels; - m_specs.format = FFMPEG_TO_AUD(m_codecCtx->sample_fmt); - m_specs.rate = (AUD_SampleRate) m_codecCtx->sample_rate; + init(); } catch(AUD_Exception) { @@ -221,11 +200,6 @@ AUD_FFMPEGReader::AUD_FFMPEGReader(AUD_Reference<AUD_Buffer> buffer) av_free(m_byteiocontext); AUD_DELETE("byteiocontext") throw; } - - // last but not least if there hasn't been any error, create the buffers - m_buffer = new AUD_Buffer(); AUD_NEW("buffer") - m_pkgbuf = new AUD_Buffer(AVCODEC_MAX_AUDIO_FRAME_SIZE<<1); - AUD_NEW("buffer") } AUD_FFMPEGReader::~AUD_FFMPEGReader() @@ -316,7 +290,7 @@ int AUD_FFMPEGReader::getPosition() AUD_Specs AUD_FFMPEGReader::getSpecs() { - return m_specs; + return m_specs.specs; } AUD_ReaderType AUD_FFMPEGReader::getType() @@ -336,11 +310,11 @@ void AUD_FFMPEGReader::read(int & length, sample_t* & buffer) int data_size = 0; int pkgbuf_pos; int left = length; - int sample_size = AUD_SAMPLE_SIZE(m_specs); + int sample_size = AUD_DEVICE_SAMPLE_SIZE(m_specs); // resize output buffer if necessary - if(m_buffer->getSize() < length*sample_size) - m_buffer->resize(length*sample_size); + if(m_buffer->getSize() < length * AUD_SAMPLE_SIZE(m_specs)) + m_buffer->resize(length * AUD_SAMPLE_SIZE(m_specs)); buffer = m_buffer->getBuffer(); pkgbuf_pos = m_pkgbuf_left; @@ -350,8 +324,9 @@ void AUD_FFMPEGReader::read(int & length, sample_t* & buffer) if(pkgbuf_pos > 0) { data_size = AUD_MIN(pkgbuf_pos, left * sample_size); - memcpy(buffer, m_pkgbuf->getBuffer(), data_size); - buffer += data_size; + m_convert((data_t*) buffer, (data_t*) m_pkgbuf->getBuffer(), + data_size / AUD_FORMAT_SIZE(m_specs.format)); + buffer += data_size / AUD_FORMAT_SIZE(m_specs.format); left -= data_size/sample_size; } @@ -366,8 +341,9 @@ void AUD_FFMPEGReader::read(int & length, sample_t* & buffer) // copy to output buffer data_size = AUD_MIN(pkgbuf_pos, left * sample_size); - memcpy(buffer, m_pkgbuf->getBuffer(), data_size); - buffer += data_size; + m_convert((data_t*) buffer, (data_t*) m_pkgbuf->getBuffer(), + data_size / AUD_FORMAT_SIZE(m_specs.format)); + buffer += data_size / AUD_FORMAT_SIZE(m_specs.format); left -= data_size/sample_size; } av_free_packet(&packet); @@ -376,7 +352,8 @@ void AUD_FFMPEGReader::read(int & length, sample_t* & buffer) if(pkgbuf_pos > data_size) { m_pkgbuf_left = pkgbuf_pos-data_size; - memmove(m_pkgbuf->getBuffer(), m_pkgbuf->getBuffer()+data_size, + memmove(m_pkgbuf->getBuffer(), + ((data_t*)m_pkgbuf->getBuffer())+data_size, pkgbuf_pos-data_size); } diff --git a/intern/audaspace/ffmpeg/AUD_FFMPEGReader.h b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.h index 6e303934f36..f992fdf7a34 100644 --- a/intern/audaspace/ffmpeg/AUD_FFMPEGReader.h +++ b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.h @@ -26,6 +26,7 @@ #ifndef AUD_FFMPEGREADER #define AUD_FFMPEGREADER +#include "AUD_ConverterFunctions.h" #include "AUD_IReader.h" #include "AUD_Reference.h" class AUD_Buffer; @@ -59,7 +60,7 @@ private: /** * The specification of the audio data. */ - AUD_Specs m_specs; + AUD_DeviceSpecs m_specs; /** * The buffer for package reading. @@ -92,6 +93,11 @@ private: int m_stream; /** + * Converter function. + */ + AUD_convert_f m_convert; + + /** * The memory file to read from, only saved to keep the buffer alive. */ AUD_Reference<AUD_Buffer> m_membuffer; @@ -104,6 +110,11 @@ private: */ int decode(AVPacket* packet, AUD_Buffer* buffer); + /** + * Initializes the object. + */ + void init(); + public: /** * Creates a new reader. diff --git a/intern/audaspace/fftw/AUD_BandPassFactory.cpp b/intern/audaspace/fftw/AUD_BandPassFactory.cpp index 5a957081208..2950cdf8bad 100644 --- a/intern/audaspace/fftw/AUD_BandPassFactory.cpp +++ b/intern/audaspace/fftw/AUD_BandPassFactory.cpp @@ -63,16 +63,8 @@ AUD_IReader* AUD_BandPassFactory::createReader() 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; - } + reader = new AUD_BandPassReader(reader, m_low, m_high); + AUD_NEW("reader") } return reader; diff --git a/intern/audaspace/fftw/AUD_BandPassReader.cpp b/intern/audaspace/fftw/AUD_BandPassReader.cpp index 34d7193866f..67729914c6d 100644 --- a/intern/audaspace/fftw/AUD_BandPassReader.cpp +++ b/intern/audaspace/fftw/AUD_BandPassReader.cpp @@ -77,7 +77,6 @@ void AUD_BandPassReader::read(int & length, sample_t* & buffer) } m_length = length; - printf("WINDOW: %d\n", m_length); if(m_length * sizeof(double) > m_in->getSize()) { @@ -95,22 +94,21 @@ void AUD_BandPassReader::read(int & length, sample_t* & buffer) FFTW_ESTIMATE); } - float* source = (float*) buffer; double* target = (double*) m_in->getBuffer(); - float* target2 = (float*) m_buffer->getBuffer(); + sample_t* target2 = 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]; + target[i] = buffer[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); + frequency = i * specs.rate / (m_length / 2.0f + 1.0f); if((frequency < m_low) || (frequency > m_high)) complex[i][0] = complex[i][1] = 0.0; } diff --git a/intern/audaspace/intern/AUD_Buffer.cpp b/intern/audaspace/intern/AUD_Buffer.cpp index 71deae0e87e..a8e74a023bf 100644 --- a/intern/audaspace/intern/AUD_Buffer.cpp +++ b/intern/audaspace/intern/AUD_Buffer.cpp @@ -27,14 +27,14 @@ #include "AUD_Space.h" #include <cstring> -#include <stdlib.h> +#include <cstdlib> #define AUD_ALIGN(a) (a + 16 - ((long)a & 15)) AUD_Buffer::AUD_Buffer(int size) { m_size = size; - m_buffer = (sample_t*) malloc(size+16); AUD_NEW("buffer") + m_buffer = (data_t*) malloc(size+16); AUD_NEW("buffer") } AUD_Buffer::~AUD_Buffer() @@ -44,7 +44,7 @@ AUD_Buffer::~AUD_Buffer() sample_t* AUD_Buffer::getBuffer() { - return AUD_ALIGN(m_buffer); + return (sample_t*) AUD_ALIGN(m_buffer); } int AUD_Buffer::getSize() @@ -54,7 +54,7 @@ int AUD_Buffer::getSize() void AUD_Buffer::resize(int size, bool keep) { - sample_t* buffer = (sample_t*) malloc(size+16); AUD_NEW("buffer") + data_t* buffer = (data_t*) malloc(size+16); AUD_NEW("buffer") // copy old data over if wanted if(keep) diff --git a/intern/audaspace/intern/AUD_Buffer.h b/intern/audaspace/intern/AUD_Buffer.h index 64959b03799..f745ee6154b 100644 --- a/intern/audaspace/intern/AUD_Buffer.h +++ b/intern/audaspace/intern/AUD_Buffer.h @@ -39,7 +39,7 @@ private: int m_size; /// The pointer to the buffer memory. - sample_t* m_buffer; + data_t* m_buffer; public: /** diff --git a/intern/audaspace/intern/AUD_BufferReader.cpp b/intern/audaspace/intern/AUD_BufferReader.cpp index 6cea849bdfc..0101de338bd 100644 --- a/intern/audaspace/intern/AUD_BufferReader.cpp +++ b/intern/audaspace/intern/AUD_BufferReader.cpp @@ -79,11 +79,11 @@ void AUD_BufferReader::read(int & length, sample_t* & buffer) { int sample_size = AUD_SAMPLE_SIZE(m_specs); - buffer = m_buffer.get()->getBuffer()+m_position*sample_size; + buffer = m_buffer.get()->getBuffer() + m_position * m_specs.channels; // 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; + if(m_buffer.get()->getSize() < (m_position + length) * sample_size) + length = m_buffer.get()->getSize() / sample_size - m_position; if(length < 0) length = 0; diff --git a/intern/audaspace/intern/AUD_C-API.cpp b/intern/audaspace/intern/AUD_C-API.cpp index cd6b95b1d9e..b7d0183cb5e 100644 --- a/intern/audaspace/intern/AUD_C-API.cpp +++ b/intern/audaspace/intern/AUD_C-API.cpp @@ -23,6 +23,9 @@ * ***** END LGPL LICENSE BLOCK ***** */ +#include <cstdlib> +#include <cstring> + #include "AUD_NULLDevice.h" #include "AUD_I3DDevice.h" #include "AUD_FileFactory.h" @@ -32,13 +35,21 @@ #include "AUD_PingPongFactory.h" #include "AUD_LoopFactory.h" #include "AUD_RectifyFactory.h" +#include "AUD_EnvelopeFactory.h" +#include "AUD_LinearResampleFactory.h" +#include "AUD_LowpassFactory.h" +#include "AUD_HighpassFactory.h" +#include "AUD_AccumulatorFactory.h" +#include "AUD_SumFactory.h" +#include "AUD_SquareFactory.h" +#include "AUD_ChannelMapperFactory.h" +#include "AUD_Buffer.h" #include "AUD_ReadDevice.h" #include "AUD_SourceCaps.h" #include "AUD_IReader.h" #ifdef WITH_SDL #include "AUD_SDLDevice.h" -#include "AUD_FloatMixer.h" #endif #ifdef WITH_OPENAL @@ -55,7 +66,7 @@ extern "C" { } #endif -#include <assert.h> +#include <cassert> typedef AUD_IFactory AUD_Sound; typedef AUD_ReadDevice AUD_Device; @@ -71,7 +82,7 @@ static AUD_IDevice* AUD_device = NULL; static int AUD_available_devices[4]; static AUD_I3DDevice* AUD_3ddevice = NULL; -int AUD_init(AUD_DeviceType device, AUD_Specs specs, int buffersize) +int AUD_init(AUD_DeviceType device, AUD_DeviceSpecs specs, int buffersize) { #ifdef WITH_FFMPEG av_register_all(); @@ -90,12 +101,8 @@ int AUD_init(AUD_DeviceType device, AUD_Specs specs, int buffersize) break; #ifdef WITH_SDL case AUD_SDL_DEVICE: - { - dev = new AUD_SDLDevice(specs, buffersize); - AUD_FloatMixer* mixer = new AUD_FloatMixer(); - ((AUD_SDLDevice*)dev)->setMixer(mixer); - break; - } + dev = new AUD_SDLDevice(specs, buffersize); + break; #endif #ifdef WITH_OPENAL case AUD_OPENAL_DEVICE: @@ -177,9 +184,8 @@ AUD_SoundInfo AUD_getInfo(AUD_Sound* sound) else { info.specs.channels = AUD_CHANNELS_INVALID; - info.specs.format = AUD_FORMAT_INVALID; info.specs.rate = AUD_RATE_INVALID; - info.length = 0.0; + info.length = 0.0f; } return info; @@ -424,7 +430,7 @@ float AUD_get3DSetting(AUD_3DSetting setting) catch(AUD_Exception) { } - return 0.0; + return 0.0f; } int AUD_update3DSource(AUD_Handle* handle, AUD_3DData* data) @@ -480,7 +486,7 @@ float AUD_get3DSourceSetting(AUD_Handle* handle, AUD_3DSourceSetting setting) { } } - return 0.0; + return 0.0f; } int AUD_setSoundVolume(AUD_Handle* handle, float volume) @@ -519,7 +525,7 @@ int AUD_setSoundPitch(AUD_Handle* handle, float pitch) return false; } -AUD_Device* AUD_openReadDevice(AUD_Specs specs) +AUD_Device* AUD_openReadDevice(AUD_DeviceSpecs specs) { try { @@ -578,7 +584,7 @@ int AUD_setDeviceSoundVolume(AUD_Device* device, AUD_Handle* handle, return false; } -int AUD_readDevice(AUD_Device* device, sample_t* buffer, int length) +int AUD_readDevice(AUD_Device* device, data_t* buffer, int length) { assert(device); assert(buffer); @@ -605,3 +611,55 @@ void AUD_closeReadDevice(AUD_Device* device) { } } + +float* AUD_readSoundBuffer(const char* filename, float low, float high, + float attack, float release, float threshold, + int accumulate, int additive, int square, + float sthreshold, int samplerate, int* length) +{ + AUD_Buffer buffer; + AUD_DeviceSpecs specs; + specs.channels = AUD_CHANNELS_MONO; + specs.rate = (AUD_SampleRate)samplerate; + AUD_Sound* sound; + + AUD_FileFactory file(filename); + AUD_ChannelMapperFactory mapper(&file, specs); + AUD_LowpassFactory lowpass(&mapper, high); + AUD_HighpassFactory highpass(&lowpass, low); + AUD_EnvelopeFactory envelope(&highpass, attack, release, threshold, 0.1f); + AUD_LinearResampleFactory resampler(&envelope, specs); + sound = &resampler; + AUD_SquareFactory squaref(sound, sthreshold); + if(square) + sound = &squaref; + AUD_AccumulatorFactory accumulator(sound, additive); + AUD_SumFactory sum(sound); + if(accumulate) + sound = &accumulator; + else if(additive) + sound = ∑ + + AUD_IReader* reader = sound->createReader(); + + if(reader == NULL) + return NULL; + + int len; + int position = 0; + sample_t* readbuffer; + do + { + len = samplerate; + buffer.resize((position + len) * sizeof(float), true); + reader->read(len, readbuffer); + memcpy(buffer.getBuffer() + position, readbuffer, len * sizeof(float)); + position += len; + } while(len != 0); + delete reader; + + float* result = (float*)malloc(position * sizeof(float)); + memcpy(result, buffer.getBuffer(), position * sizeof(float)); + *length = position; + return result; +} diff --git a/intern/audaspace/intern/AUD_C-API.h b/intern/audaspace/intern/AUD_C-API.h index 866f0248cb2..c3439f89ade 100644 --- a/intern/audaspace/intern/AUD_C-API.h +++ b/intern/audaspace/intern/AUD_C-API.h @@ -59,7 +59,7 @@ typedef struct * \param buffersize The buffersize for the device. * \return Whether the device has been initialized. */ -extern int AUD_init(AUD_DeviceType device, AUD_Specs specs, int buffersize); +extern int AUD_init(AUD_DeviceType device, AUD_DeviceSpecs specs, int buffersize); /** * Returns a integer list with available sound devices. The last one is always @@ -304,7 +304,7 @@ extern int AUD_setSoundPitch(AUD_Handle* handle, float pitch); * \param specs The specification of the audio data. * \return A device handle. */ -extern AUD_Device* AUD_openReadDevice(AUD_Specs specs); +extern AUD_Device* AUD_openReadDevice(AUD_DeviceSpecs specs); /** * Sets the main volume of a device. @@ -342,7 +342,7 @@ extern int AUD_setDeviceSoundVolume(AUD_Device* device, * played back currently, in that case the buffer is filled with * silence. */ -extern int AUD_readDevice(AUD_Device* device, sample_t* buffer, int length); +extern int AUD_readDevice(AUD_Device* device, data_t* buffer, int length); /** * Closes a read device. @@ -350,6 +350,16 @@ extern int AUD_readDevice(AUD_Device* device, sample_t* buffer, int length); */ extern void AUD_closeReadDevice(AUD_Device* device); +/** + * Reads a sound file into a newly created float buffer. + * The sound is therefore bandpassed, rectified and resampled. + */ +extern float* AUD_readSoundBuffer(const char* filename, float low, float high, + float attack, float release, float threshold, + int accumulate, int additive, int square, + float sthreshold, int samplerate, + int* length); + #ifdef __cplusplus } #endif diff --git a/intern/audaspace/intern/AUD_ChannelMapperFactory.cpp b/intern/audaspace/intern/AUD_ChannelMapperFactory.cpp index 66205a58015..3420ed16649 100644 --- a/intern/audaspace/intern/AUD_ChannelMapperFactory.cpp +++ b/intern/audaspace/intern/AUD_ChannelMapperFactory.cpp @@ -29,20 +29,20 @@ #include <cstring> AUD_ChannelMapperFactory::AUD_ChannelMapperFactory(AUD_IReader* reader, - AUD_Specs specs) : + AUD_DeviceSpecs specs) : AUD_MixerFactory(reader, specs) { memset(m_mapping, 0, sizeof(m_mapping)); } AUD_ChannelMapperFactory::AUD_ChannelMapperFactory(AUD_IFactory* factory, - AUD_Specs specs) : + AUD_DeviceSpecs specs) : AUD_MixerFactory(factory, specs) { memset(m_mapping, 0, sizeof(m_mapping)); } -AUD_ChannelMapperFactory::AUD_ChannelMapperFactory(AUD_Specs specs) : +AUD_ChannelMapperFactory::AUD_ChannelMapperFactory(AUD_DeviceSpecs specs) : AUD_MixerFactory(specs) { memset(m_mapping, 0, sizeof(m_mapping)); diff --git a/intern/audaspace/intern/AUD_ChannelMapperFactory.h b/intern/audaspace/intern/AUD_ChannelMapperFactory.h index c2c39f4bdf6..a67bfa12123 100644 --- a/intern/audaspace/intern/AUD_ChannelMapperFactory.h +++ b/intern/audaspace/intern/AUD_ChannelMapperFactory.h @@ -41,9 +41,9 @@ private: float **m_mapping[9]; public: - AUD_ChannelMapperFactory(AUD_IReader* reader, AUD_Specs specs); - AUD_ChannelMapperFactory(AUD_IFactory* factory, AUD_Specs specs); - AUD_ChannelMapperFactory(AUD_Specs specs); + AUD_ChannelMapperFactory(AUD_IReader* reader, AUD_DeviceSpecs specs); + AUD_ChannelMapperFactory(AUD_IFactory* factory, AUD_DeviceSpecs specs); + AUD_ChannelMapperFactory(AUD_DeviceSpecs specs); virtual ~AUD_ChannelMapperFactory(); diff --git a/intern/audaspace/intern/AUD_ChannelMapperReader.cpp b/intern/audaspace/intern/AUD_ChannelMapperReader.cpp index 61f97c08a8e..d78278219e8 100644 --- a/intern/audaspace/intern/AUD_ChannelMapperReader.cpp +++ b/intern/audaspace/intern/AUD_ChannelMapperReader.cpp @@ -32,12 +32,6 @@ AUD_ChannelMapperReader::AUD_ChannelMapperReader(AUD_IReader* reader, { m_specs = reader->getSpecs(); - if(m_specs.format != AUD_FORMAT_FLOAT32) - { - delete m_reader; AUD_DELETE("reader") - AUD_THROW(AUD_ERROR_READER); - } - int channels = -1; m_rch = m_specs.channels; while(mapping[++channels] != 0); @@ -55,7 +49,8 @@ AUD_ChannelMapperReader::AUD_ChannelMapperReader(AUD_IReader* reader, for(i=0; i < m_rch; i++) sum += mapping[channels][i]; for(i=0; i < m_rch; i++) - m_mapping[channels][i] = sum > 0.0 ? mapping[channels][i]/sum : 0.0; + m_mapping[channels][i] = sum > 0.0f ? + mapping[channels][i]/sum : 0.0f; } m_buffer = new AUD_Buffer(); AUD_NEW("buffer") @@ -89,9 +84,9 @@ void AUD_ChannelMapperReader::read(int & length, sample_t* & buffer) if(m_buffer->getSize() < length * 4 * channels) m_buffer->resize(length * 4 * channels); - float* in = (float*)buffer; - float* out = (float*)m_buffer->getBuffer(); - float sum; + sample_t* in = buffer; + sample_t* out = m_buffer->getBuffer(); + sample_t sum; for(int i = 0; i < length; i++) { diff --git a/intern/audaspace/intern/AUD_ConverterFactory.cpp b/intern/audaspace/intern/AUD_ConverterFactory.cpp index a1a86662072..1c6d5468251 100644 --- a/intern/audaspace/intern/AUD_ConverterFactory.cpp +++ b/intern/audaspace/intern/AUD_ConverterFactory.cpp @@ -27,14 +27,14 @@ #include "AUD_ConverterReader.h" AUD_ConverterFactory::AUD_ConverterFactory(AUD_IReader* reader, - AUD_Specs specs) : + AUD_DeviceSpecs specs) : AUD_MixerFactory(reader, specs) {} AUD_ConverterFactory::AUD_ConverterFactory(AUD_IFactory* factory, - AUD_Specs specs) : + AUD_DeviceSpecs specs) : AUD_MixerFactory(factory, specs) {} -AUD_ConverterFactory::AUD_ConverterFactory(AUD_Specs specs) : +AUD_ConverterFactory::AUD_ConverterFactory(AUD_DeviceSpecs specs) : AUD_MixerFactory(specs) {} AUD_IReader* AUD_ConverterFactory::createReader() @@ -43,7 +43,7 @@ AUD_IReader* AUD_ConverterFactory::createReader() if(reader != 0) { - if(reader->getSpecs().format != m_specs.format) + if(m_specs.format != AUD_FORMAT_FLOAT32) { reader = new AUD_ConverterReader(reader, m_specs); AUD_NEW("reader") diff --git a/intern/audaspace/intern/AUD_ConverterFactory.h b/intern/audaspace/intern/AUD_ConverterFactory.h index 3778e8d8f03..11ca6c9f0a8 100644 --- a/intern/audaspace/intern/AUD_ConverterFactory.h +++ b/intern/audaspace/intern/AUD_ConverterFactory.h @@ -35,9 +35,9 @@ class AUD_ConverterFactory : public AUD_MixerFactory { public: - AUD_ConverterFactory(AUD_IReader* reader, AUD_Specs specs); - AUD_ConverterFactory(AUD_IFactory* factory, AUD_Specs specs); - AUD_ConverterFactory(AUD_Specs specs); + AUD_ConverterFactory(AUD_IReader* reader, AUD_DeviceSpecs specs); + AUD_ConverterFactory(AUD_IFactory* factory, AUD_DeviceSpecs specs); + AUD_ConverterFactory(AUD_DeviceSpecs specs); virtual AUD_IReader* createReader(); }; diff --git a/intern/audaspace/intern/AUD_ConverterFunctions.cpp b/intern/audaspace/intern/AUD_ConverterFunctions.cpp index 1b5d07bcc61..0d48df04a64 100644 --- a/intern/audaspace/intern/AUD_ConverterFunctions.cpp +++ b/intern/audaspace/intern/AUD_ConverterFunctions.cpp @@ -29,21 +29,21 @@ #define AUD_U8_0 0x80 #define AUD_S16_MAX 0x7FFF #define AUD_S16_MIN 0x8000 -#define AUD_S16_FLT 32768.0 +#define AUD_S16_FLT 32768.0f #define AUD_S32_MAX 0x7FFFFFFF #define AUD_S32_MIN 0x80000000 -#define AUD_S32_FLT 2147483648.0 -#define AUD_FLT_MAX 1.0 -#define AUD_FLT_MIN -1.0 +#define AUD_S32_FLT 2147483648.0f +#define AUD_FLT_MAX 1.0f +#define AUD_FLT_MIN -1.0f -void AUD_convert_u8_s16(sample_t* target, sample_t* source, int length) +void AUD_convert_u8_s16(data_t* target, data_t* source, int length) { int16_t* t = (int16_t*) target; for(int i = 0; i < length; i++) t[i] = (((int16_t)source[i]) - AUD_U8_0) << 8; } -void AUD_convert_u8_s24_be(sample_t* target, sample_t* source, int length) +void AUD_convert_u8_s24_be(data_t* target, data_t* source, int length) { for(int i = 0; i < length; i++) { @@ -53,7 +53,7 @@ void AUD_convert_u8_s24_be(sample_t* target, sample_t* source, int length) } } -void AUD_convert_u8_s24_le(sample_t* target, sample_t* source, int length) +void AUD_convert_u8_s24_le(data_t* target, data_t* source, int length) { for(int i = 0; i < length; i++) { @@ -63,35 +63,35 @@ void AUD_convert_u8_s24_le(sample_t* target, sample_t* source, int length) } } -void AUD_convert_u8_s32(sample_t* target, sample_t* source, int length) +void AUD_convert_u8_s32(data_t* target, data_t* source, int length) { int32_t* t = (int32_t*) target; for(int i = 0; i < length; i++) t[i] = (((int32_t)source[i]) - AUD_U8_0) << 24; } -void AUD_convert_u8_float(sample_t* target, sample_t* source, int length) +void AUD_convert_u8_float(data_t* target, data_t* source, int length) { float* t = (float*) target; for(int i = 0; i < length; i++) t[i] = (((int32_t)source[i]) - AUD_U8_0) / ((float)AUD_U8_0); } -void AUD_convert_u8_double(sample_t* target, sample_t* source, int length) +void AUD_convert_u8_double(data_t* target, data_t* source, int length) { double* t = (double*) target; for(int i = 0; i < length; i++) t[i] = (((int32_t)source[i]) - AUD_U8_0) / ((double)AUD_U8_0); } -void AUD_convert_s16_u8(sample_t* target, sample_t* source, int length) +void AUD_convert_s16_u8(data_t* target, data_t* source, int length) { int16_t* s = (int16_t*) source; for(int i = 0; i < length; i++) target[i] = (unsigned char)((s[i] >> 8) + AUD_U8_0); } -void AUD_convert_s16_s24_be(sample_t* target, sample_t* source, int length) +void AUD_convert_s16_s24_be(data_t* target, data_t* source, int length) { int16_t* s = (int16_t*) source; for(int i = 0; i < length; i++) @@ -102,7 +102,7 @@ void AUD_convert_s16_s24_be(sample_t* target, sample_t* source, int length) } } -void AUD_convert_s16_s24_le(sample_t* target, sample_t* source, int length) +void AUD_convert_s16_s24_le(data_t* target, data_t* source, int length) { int16_t* s = (int16_t*) source; for(int i = 0; i < length; i++) @@ -113,7 +113,7 @@ void AUD_convert_s16_s24_le(sample_t* target, sample_t* source, int length) } } -void AUD_convert_s16_s32(sample_t* target, sample_t* source, int length) +void AUD_convert_s16_s32(data_t* target, data_t* source, int length) { int16_t* s = (int16_t*) source; int32_t* t = (int32_t*) target; @@ -121,7 +121,7 @@ void AUD_convert_s16_s32(sample_t* target, sample_t* source, int length) t[i] = ((int32_t)s[i]) << 16; } -void AUD_convert_s16_float(sample_t* target, sample_t* source, int length) +void AUD_convert_s16_float(data_t* target, data_t* source, int length) { int16_t* s = (int16_t*) source; float* t = (float*) target; @@ -129,7 +129,7 @@ void AUD_convert_s16_float(sample_t* target, sample_t* source, int length) t[i] = s[i] / AUD_S16_FLT; } -void AUD_convert_s16_double(sample_t* target, sample_t* source, int length) +void AUD_convert_s16_double(data_t* target, data_t* source, int length) { int16_t* s = (int16_t*) source; double* t = (double*) target; @@ -137,52 +137,52 @@ void AUD_convert_s16_double(sample_t* target, sample_t* source, int length) t[i] = s[i] / AUD_S16_FLT; } -void AUD_convert_s24_u8_be(sample_t* target, sample_t* source, int length) +void AUD_convert_s24_u8_be(data_t* target, data_t* source, int length) { for(int i = 0; i < length; i++) target[i] = source[i*3] ^ AUD_U8_0; } -void AUD_convert_s24_u8_le(sample_t* target, sample_t* source, int length) +void AUD_convert_s24_u8_le(data_t* target, data_t* source, int length) { for(int i = 0; i < length; i++) target[i] = source[i*3+2] ^ AUD_U8_0; } -void AUD_convert_s24_s16_be(sample_t* target, sample_t* source, int length) +void AUD_convert_s24_s16_be(data_t* target, data_t* source, int length) { int16_t* t = (int16_t*) target; for(int i = 0; i < length; i++) t[i] = source[i*3] << 8 | source[i*3+1]; } -void AUD_convert_s24_s16_le(sample_t* target, sample_t* source, int length) +void AUD_convert_s24_s16_le(data_t* target, data_t* source, int length) { int16_t* t = (int16_t*) target; for(int i = 0; i < length; i++) t[i] = source[i*3+2] << 8 | source[i*3+1]; } -void AUD_convert_s24_s24(sample_t* target, sample_t* source, int length) +void AUD_convert_s24_s24(data_t* target, data_t* source, int length) { memcpy(target, source, length * 3); } -void AUD_convert_s24_s32_be(sample_t* target, sample_t* source, int length) +void AUD_convert_s24_s32_be(data_t* target, data_t* source, int length) { int32_t* t = (int32_t*) target; for(int i = 0; i < length; i++) t[i] = source[i*3] << 24 | source[i*3+1] << 16 | source[i*3+2] << 8; } -void AUD_convert_s24_s32_le(sample_t* target, sample_t* source, int length) +void AUD_convert_s24_s32_le(data_t* target, data_t* source, int length) { int32_t* t = (int32_t*) target; for(int i = 0; i < length; i++) t[i] = source[i*3+2] << 24 | source[i*3+1] << 16 | source[i*3] << 8; } -void AUD_convert_s24_float_be(sample_t* target, sample_t* source, int length) +void AUD_convert_s24_float_be(data_t* target, data_t* source, int length) { float* t = (float*) target; int32_t s; @@ -193,7 +193,7 @@ void AUD_convert_s24_float_be(sample_t* target, sample_t* source, int length) } } -void AUD_convert_s24_float_le(sample_t* target, sample_t* source, int length) +void AUD_convert_s24_float_le(data_t* target, data_t* source, int length) { float* t = (float*) target; int32_t s; @@ -204,7 +204,7 @@ void AUD_convert_s24_float_le(sample_t* target, sample_t* source, int length) } } -void AUD_convert_s24_double_be(sample_t* target, sample_t* source, int length) +void AUD_convert_s24_double_be(data_t* target, data_t* source, int length) { double* t = (double*) target; int32_t s; @@ -215,7 +215,7 @@ void AUD_convert_s24_double_be(sample_t* target, sample_t* source, int length) } } -void AUD_convert_s24_double_le(sample_t* target, sample_t* source, int length) +void AUD_convert_s24_double_le(data_t* target, data_t* source, int length) { double* t = (double*) target; int32_t s; @@ -226,14 +226,14 @@ void AUD_convert_s24_double_le(sample_t* target, sample_t* source, int length) } } -void AUD_convert_s32_u8(sample_t* target, sample_t* source, int length) +void AUD_convert_s32_u8(data_t* target, data_t* source, int length) { int16_t* s = (int16_t*) source; for(int i = 0; i < length; i++) target[i] = (unsigned char)((s[i] >> 24) + AUD_U8_0); } -void AUD_convert_s32_s16(sample_t* target, sample_t* source, int length) +void AUD_convert_s32_s16(data_t* target, data_t* source, int length) { int16_t* t = (int16_t*) target; int32_t* s = (int32_t*) source; @@ -241,7 +241,7 @@ void AUD_convert_s32_s16(sample_t* target, sample_t* source, int length) t[i] = s[i] >> 16; } -void AUD_convert_s32_s24_be(sample_t* target, sample_t* source, int length) +void AUD_convert_s32_s24_be(data_t* target, data_t* source, int length) { int32_t* s = (int32_t*) source; for(int i = 0; i < length; i++) @@ -252,7 +252,7 @@ void AUD_convert_s32_s24_be(sample_t* target, sample_t* source, int length) } } -void AUD_convert_s32_s24_le(sample_t* target, sample_t* source, int length) +void AUD_convert_s32_s24_le(data_t* target, data_t* source, int length) { int16_t* s = (int16_t*) source; for(int i = 0; i < length; i++) @@ -263,7 +263,7 @@ void AUD_convert_s32_s24_le(sample_t* target, sample_t* source, int length) } } -void AUD_convert_s32_float(sample_t* target, sample_t* source, int length) +void AUD_convert_s32_float(data_t* target, data_t* source, int length) { int32_t* s = (int32_t*) source; float* t = (float*) target; @@ -271,7 +271,7 @@ void AUD_convert_s32_float(sample_t* target, sample_t* source, int length) t[i] = s[i] / AUD_S32_FLT; } -void AUD_convert_s32_double(sample_t* target, sample_t* source, int length) +void AUD_convert_s32_double(data_t* target, data_t* source, int length) { int32_t* s = (int32_t*) source; double* t = (double*) target; @@ -279,7 +279,7 @@ void AUD_convert_s32_double(sample_t* target, sample_t* source, int length) t[i] = s[i] / AUD_S32_FLT; } -void AUD_convert_float_u8(sample_t* target, sample_t* source, int length) +void AUD_convert_float_u8(data_t* target, data_t* source, int length) { float* s = (float*) source; float t; @@ -295,7 +295,7 @@ void AUD_convert_float_u8(sample_t* target, sample_t* source, int length) } } -void AUD_convert_float_s16(sample_t* target, sample_t* source, int length) +void AUD_convert_float_s16(data_t* target, data_t* source, int length) { int16_t* t = (int16_t*) target; float* s = (float*) source; @@ -310,7 +310,7 @@ void AUD_convert_float_s16(sample_t* target, sample_t* source, int length) } } -void AUD_convert_float_s24_be(sample_t* target, sample_t* source, int length) +void AUD_convert_float_s24_be(data_t* target, data_t* source, int length) { int32_t t; float* s = (float*) source; @@ -328,7 +328,7 @@ void AUD_convert_float_s24_be(sample_t* target, sample_t* source, int length) } } -void AUD_convert_float_s24_le(sample_t* target, sample_t* source, int length) +void AUD_convert_float_s24_le(data_t* target, data_t* source, int length) { int32_t t; float* s = (float*) source; @@ -346,7 +346,7 @@ void AUD_convert_float_s24_le(sample_t* target, sample_t* source, int length) } } -void AUD_convert_float_s32(sample_t* target, sample_t* source, int length) +void AUD_convert_float_s32(data_t* target, data_t* source, int length) { int32_t* t = (int32_t*) target; float* s = (float*) source; @@ -361,7 +361,7 @@ void AUD_convert_float_s32(sample_t* target, sample_t* source, int length) } } -void AUD_convert_float_double(sample_t* target, sample_t* source, int length) +void AUD_convert_float_double(data_t* target, data_t* source, int length) { float* s = (float*) source; double* t = (double*) target; @@ -369,7 +369,7 @@ void AUD_convert_float_double(sample_t* target, sample_t* source, int length) t[i] = s[i]; } -void AUD_convert_double_u8(sample_t* target, sample_t* source, int length) +void AUD_convert_double_u8(data_t* target, data_t* source, int length) { double* s = (double*) source; double t; @@ -385,7 +385,7 @@ void AUD_convert_double_u8(sample_t* target, sample_t* source, int length) } } -void AUD_convert_double_s16(sample_t* target, sample_t* source, int length) +void AUD_convert_double_s16(data_t* target, data_t* source, int length) { int16_t* t = (int16_t*) target; double* s = (double*) source; @@ -400,7 +400,7 @@ void AUD_convert_double_s16(sample_t* target, sample_t* source, int length) } } -void AUD_convert_double_s24_be(sample_t* target, sample_t* source, int length) +void AUD_convert_double_s24_be(data_t* target, data_t* source, int length) { int32_t t; double* s = (double*) source; @@ -418,7 +418,7 @@ void AUD_convert_double_s24_be(sample_t* target, sample_t* source, int length) } } -void AUD_convert_double_s24_le(sample_t* target, sample_t* source, int length) +void AUD_convert_double_s24_le(data_t* target, data_t* source, int length) { int32_t t; double* s = (double*) source; @@ -436,7 +436,7 @@ void AUD_convert_double_s24_le(sample_t* target, sample_t* source, int length) } } -void AUD_convert_double_s32(sample_t* target, sample_t* source, int length) +void AUD_convert_double_s32(data_t* target, data_t* source, int length) { int32_t* t = (int32_t*) target; double* s = (double*) source; @@ -451,92 +451,10 @@ void AUD_convert_double_s32(sample_t* target, sample_t* source, int length) } } -void AUD_convert_double_float(sample_t* target, sample_t* source, int length) +void AUD_convert_double_float(data_t* target, data_t* source, int length) { double* s = (double*) source; float* t = (float*) target; for(int i = 0; i < length; i++) t[i] = s[i]; } - -void AUD_volume_adjust_u8(sample_t* target, sample_t* source, - int count, float volume) -{ - for(int i=0; i<count; i++) - target[i] = (unsigned char)((source[i]-0x0080) * volume + 0x80); -} - -void AUD_volume_adjust_s24_le(sample_t* target, sample_t* source, - int count, float volume) -{ - 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; - value *= volume; - target[i+2] = value >> 16; - target[i+1] = value >> 8; - target[i] = value; - } -} - -void AUD_volume_adjust_s24_be(sample_t* target, sample_t* source, - int count, float volume) -{ - 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; - value *= volume; - target[i] = value >> 16; - target[i+1] = value >> 8; - target[i+2] = value; - } -} - -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; - } -} - diff --git a/intern/audaspace/intern/AUD_ConverterFunctions.h b/intern/audaspace/intern/AUD_ConverterFunctions.h index 686e58704b7..a925f138aa2 100644 --- a/intern/audaspace/intern/AUD_ConverterFunctions.h +++ b/intern/audaspace/intern/AUD_ConverterFunctions.h @@ -41,133 +41,94 @@ #include <stdint.h> #endif -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); +typedef void (*AUD_convert_f)(data_t* target, data_t* source, int length); template <class T> -void AUD_convert_copy(sample_t* target, sample_t* source, int length) +void AUD_convert_copy(data_t* target, data_t* source, int length) { memcpy(target, source, length*sizeof(T)); } -void AUD_convert_u8_s16(sample_t* target, sample_t* source, int length); - -void AUD_convert_u8_s24_be(sample_t* target, sample_t* source, int length); - -void AUD_convert_u8_s24_le(sample_t* target, sample_t* source, int length); - -void AUD_convert_u8_s32(sample_t* target, sample_t* source, int length); - -void AUD_convert_u8_float(sample_t* target, sample_t* source, int length); - -void AUD_convert_u8_double(sample_t* target, sample_t* source, int length); - -void AUD_convert_s16_u8(sample_t* target, sample_t* source, int length); +void AUD_convert_u8_s16(data_t* target, data_t* source, int length); -void AUD_convert_s16_s24_be(sample_t* target, sample_t* source, int length); +void AUD_convert_u8_s24_be(data_t* target, data_t* source, int length); -void AUD_convert_s16_s24_le(sample_t* target, sample_t* source, int length); +void AUD_convert_u8_s24_le(data_t* target, data_t* source, int length); -void AUD_convert_s16_s32(sample_t* target, sample_t* source, int length); +void AUD_convert_u8_s32(data_t* target, data_t* source, int length); -void AUD_convert_s16_float(sample_t* target, sample_t* source, int length); +void AUD_convert_u8_float(data_t* target, data_t* source, int length); -void AUD_convert_s16_double(sample_t* target, sample_t* source, int length); +void AUD_convert_u8_double(data_t* target, data_t* source, int length); -void AUD_convert_s24_u8_be(sample_t* target, sample_t* source, int length); +void AUD_convert_s16_u8(data_t* target, data_t* source, int length); -void AUD_convert_s24_u8_le(sample_t* target, sample_t* source, int length); +void AUD_convert_s16_s24_be(data_t* target, data_t* source, int length); -void AUD_convert_s24_s16_be(sample_t* target, sample_t* source, int length); +void AUD_convert_s16_s24_le(data_t* target, data_t* source, int length); -void AUD_convert_s24_s16_le(sample_t* target, sample_t* source, int length); +void AUD_convert_s16_s32(data_t* target, data_t* source, int length); -void AUD_convert_s24_s24(sample_t* target, sample_t* source, int length); +void AUD_convert_s16_float(data_t* target, data_t* source, int length); -void AUD_convert_s24_s32_be(sample_t* target, sample_t* source, int length); +void AUD_convert_s16_double(data_t* target, data_t* source, int length); -void AUD_convert_s24_s32_le(sample_t* target, sample_t* source, int length); +void AUD_convert_s24_u8_be(data_t* target, data_t* source, int length); -void AUD_convert_s24_float_be(sample_t* target, sample_t* source, int length); +void AUD_convert_s24_u8_le(data_t* target, data_t* source, int length); -void AUD_convert_s24_float_le(sample_t* target, sample_t* source, int length); +void AUD_convert_s24_s16_be(data_t* target, data_t* source, int length); -void AUD_convert_s24_double_be(sample_t* target, sample_t* source, int length); +void AUD_convert_s24_s16_le(data_t* target, data_t* source, int length); -void AUD_convert_s24_double_le(sample_t* target, sample_t* source, int length); +void AUD_convert_s24_s24(data_t* target, data_t* source, int length); -void AUD_convert_s32_u8(sample_t* target, sample_t* source, int length); +void AUD_convert_s24_s32_be(data_t* target, data_t* source, int length); -void AUD_convert_s32_s16(sample_t* target, sample_t* source, int length); +void AUD_convert_s24_s32_le(data_t* target, data_t* source, int length); -void AUD_convert_s32_s24_be(sample_t* target, sample_t* source, int length); +void AUD_convert_s24_float_be(data_t* target, data_t* source, int length); -void AUD_convert_s32_s24_le(sample_t* target, sample_t* source, int length); +void AUD_convert_s24_float_le(data_t* target, data_t* source, int length); -void AUD_convert_s32_float(sample_t* target, sample_t* source, int length); +void AUD_convert_s24_double_be(data_t* target, data_t* source, int length); -void AUD_convert_s32_double(sample_t* target, sample_t* source, int length); +void AUD_convert_s24_double_le(data_t* target, data_t* source, int length); -void AUD_convert_float_u8(sample_t* target, sample_t* source, int length); +void AUD_convert_s32_u8(data_t* target, data_t* source, int length); -void AUD_convert_float_s16(sample_t* target, sample_t* source, int length); +void AUD_convert_s32_s16(data_t* target, data_t* source, int length); -void AUD_convert_float_s24_be(sample_t* target, sample_t* source, int length); +void AUD_convert_s32_s24_be(data_t* target, data_t* source, int length); -void AUD_convert_float_s24_le(sample_t* target, sample_t* source, int length); +void AUD_convert_s32_s24_le(data_t* target, data_t* source, int length); -void AUD_convert_float_s32(sample_t* target, sample_t* source, int length); +void AUD_convert_s32_float(data_t* target, data_t* source, int length); -void AUD_convert_float_double(sample_t* target, sample_t* source, int length); +void AUD_convert_s32_double(data_t* target, data_t* source, int length); -void AUD_convert_double_u8(sample_t* target, sample_t* source, int length); +void AUD_convert_float_u8(data_t* target, data_t* source, int length); -void AUD_convert_double_s16(sample_t* target, sample_t* source, int length); +void AUD_convert_float_s16(data_t* target, data_t* source, int length); -void AUD_convert_double_s24_be(sample_t* target, sample_t* source, int length); +void AUD_convert_float_s24_be(data_t* target, data_t* source, int length); -void AUD_convert_double_s24_le(sample_t* target, sample_t* source, int length); +void AUD_convert_float_s24_le(data_t* target, data_t* source, int length); -void AUD_convert_double_s32(sample_t* target, sample_t* source, int length); +void AUD_convert_float_s32(data_t* target, data_t* source, int length); -void AUD_convert_double_float(sample_t* target, sample_t* source, int length); +void AUD_convert_float_double(data_t* target, data_t* source, int length); -template <class T> -void AUD_volume_adjust(sample_t* target, sample_t* source, - int count, float volume) -{ - T* t = (T*)target; - T* s = (T*)source; - for(int i=0; i < count; i++) - t[i] = (T)(s[i] * volume); -} - -void AUD_volume_adjust_u8(sample_t* target, sample_t* source, - int count, float volume); +void AUD_convert_double_u8(data_t* target, data_t* source, int length); -void AUD_volume_adjust_s24_le(sample_t* target, sample_t* source, - int count, float volume); +void AUD_convert_double_s16(data_t* target, data_t* source, int length); -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_convert_double_s24_be(data_t* target, data_t* source, int length); -void AUD_rectify_u8(sample_t* target, sample_t* source, int count); +void AUD_convert_double_s24_le(data_t* target, data_t* source, int length); -void AUD_rectify_s24_le(sample_t* target, sample_t* source, int count); +void AUD_convert_double_s32(data_t* target, data_t* source, int length); -void AUD_rectify_s24_be(sample_t* target, sample_t* source, int count); +void AUD_convert_double_float(data_t* target, data_t* source, int length); #endif //AUD_CONVERTERFUNCTIONS diff --git a/intern/audaspace/intern/AUD_ConverterReader.cpp b/intern/audaspace/intern/AUD_ConverterReader.cpp index da25a2b7460..808144085bb 100644 --- a/intern/audaspace/intern/AUD_ConverterReader.cpp +++ b/intern/audaspace/intern/AUD_ConverterReader.cpp @@ -26,205 +26,37 @@ #include "AUD_ConverterReader.h" #include "AUD_Buffer.h" -AUD_ConverterReader::AUD_ConverterReader(AUD_IReader* reader, AUD_Specs specs) : +AUD_ConverterReader::AUD_ConverterReader(AUD_IReader* reader, + AUD_DeviceSpecs specs) : AUD_EffectReader(reader) { - m_specs = reader->getSpecs(); + m_specs.specs = reader->getSpecs(); int bigendian = 1; bigendian = (((char*)&bigendian)[0]) ? 0: 1; // 1 if Big Endian - switch(m_specs.format) + switch(specs.format) { case AUD_FORMAT_U8: - switch(specs.format) - { - case AUD_FORMAT_U8: - m_convert = AUD_convert_copy<unsigned char>; - break; - case AUD_FORMAT_S16: - m_convert = AUD_convert_u8_s16; - break; - case AUD_FORMAT_S24: - if(bigendian) - m_convert = AUD_convert_u8_s24_be; - else - m_convert = AUD_convert_u8_s24_le; - break; - case AUD_FORMAT_S32: - m_convert = AUD_convert_u8_s32; - break; - case AUD_FORMAT_FLOAT32: - m_convert = AUD_convert_u8_float; - break; - case AUD_FORMAT_FLOAT64: - m_convert = AUD_convert_u8_double; - break; - default: - break; - } + m_convert = AUD_convert_float_u8; break; case AUD_FORMAT_S16: - switch(specs.format) - { - case AUD_FORMAT_U8: - m_convert = AUD_convert_s16_u8; - break; - case AUD_FORMAT_S16: - m_convert = AUD_convert_copy<int16_t>; - break; - case AUD_FORMAT_S24: - if(bigendian) - m_convert = AUD_convert_s16_s24_be; - else - m_convert = AUD_convert_s16_s24_le; - break; - case AUD_FORMAT_S32: - m_convert = AUD_convert_s16_s32; - break; - case AUD_FORMAT_FLOAT32: - m_convert = AUD_convert_s16_float; - break; - case AUD_FORMAT_FLOAT64: - m_convert = AUD_convert_s16_double; - break; - default: - break; - } + m_convert = AUD_convert_float_s16; break; case AUD_FORMAT_S24: if(bigendian) - switch(specs.format) - { - case AUD_FORMAT_U8: - m_convert = AUD_convert_u8_s24_be; - break; - case AUD_FORMAT_S16: - m_convert = AUD_convert_s16_s24_be; - break; - case AUD_FORMAT_S24: - m_convert = AUD_convert_s24_s24; - break; - case AUD_FORMAT_S32: - m_convert = AUD_convert_s32_s24_be; - break; - case AUD_FORMAT_FLOAT32: - m_convert = AUD_convert_float_s24_be; - break; - case AUD_FORMAT_FLOAT64: - m_convert = AUD_convert_double_s24_be; - break; - default: - break; - } + m_convert = AUD_convert_float_s24_be; else - switch(specs.format) - { - case AUD_FORMAT_U8: - m_convert = AUD_convert_u8_s24_le; - break; - case AUD_FORMAT_S16: - m_convert = AUD_convert_s16_s24_le; - break; - case AUD_FORMAT_S24: - m_convert = AUD_convert_s24_s24; - break; - case AUD_FORMAT_S32: - m_convert = AUD_convert_s32_s24_le; - break; - case AUD_FORMAT_FLOAT32: - m_convert = AUD_convert_float_s24_le; - break; - case AUD_FORMAT_FLOAT64: - m_convert = AUD_convert_double_s24_le; - break; - default: - break; - } + m_convert = AUD_convert_float_s24_le; break; case AUD_FORMAT_S32: - switch(specs.format) - { - case AUD_FORMAT_U8: - m_convert = AUD_convert_s32_u8; - break; - case AUD_FORMAT_S16: - m_convert = AUD_convert_s32_s16; - break; - case AUD_FORMAT_S24: - if(bigendian) - m_convert = AUD_convert_s32_s24_be; - else - m_convert = AUD_convert_s32_s24_le; - break; - case AUD_FORMAT_S32: - m_convert = AUD_convert_copy<int32_t>; - break; - case AUD_FORMAT_FLOAT32: - m_convert = AUD_convert_s32_float; - break; - case AUD_FORMAT_FLOAT64: - m_convert = AUD_convert_s32_double; - break; - default: - break; - } + m_convert = AUD_convert_float_s32; break; case AUD_FORMAT_FLOAT32: - switch(specs.format) - { - case AUD_FORMAT_U8: - m_convert = AUD_convert_float_u8; - break; - case AUD_FORMAT_S16: - m_convert = AUD_convert_float_s16; - break; - case AUD_FORMAT_S24: - if(bigendian) - m_convert = AUD_convert_float_s24_be; - else - m_convert = AUD_convert_float_s24_le; - break; - case AUD_FORMAT_S32: - m_convert = AUD_convert_float_s32; - break; - case AUD_FORMAT_FLOAT32: - m_convert = AUD_convert_copy<float>; - break; - case AUD_FORMAT_FLOAT64: - m_convert = AUD_convert_float_double; - break; - default: - break; - } + m_convert = AUD_convert_copy<float>; break; case AUD_FORMAT_FLOAT64: - switch(specs.format) - { - case AUD_FORMAT_U8: - m_convert = AUD_convert_double_u8; - break; - case AUD_FORMAT_S16: - m_convert = AUD_convert_double_s16; - break; - case AUD_FORMAT_S24: - if(bigendian) - m_convert = AUD_convert_double_s24_be; - else - m_convert = AUD_convert_double_s24_le; - break; - case AUD_FORMAT_S32: - m_convert = AUD_convert_double_s32; - break; - case AUD_FORMAT_FLOAT32: - m_convert = AUD_convert_double_float; - break; - case AUD_FORMAT_FLOAT64: - m_convert = AUD_convert_copy<double>; - break; - default: - break; - } + m_convert = AUD_convert_float_double; break; default: break; @@ -242,7 +74,7 @@ AUD_ConverterReader::~AUD_ConverterReader() AUD_Specs AUD_ConverterReader::getSpecs() { - return m_specs; + return m_specs.specs; } void AUD_ConverterReader::read(int & length, sample_t* & buffer) @@ -254,7 +86,8 @@ void AUD_ConverterReader::read(int & length, sample_t* & buffer) if(m_buffer->getSize() < length*samplesize) m_buffer->resize(length*samplesize); - m_convert(m_buffer->getBuffer(), buffer, length*m_specs.channels); + m_convert((data_t*)m_buffer->getBuffer(), (data_t*)buffer, + length * m_specs.channels); buffer = m_buffer->getBuffer(); } diff --git a/intern/audaspace/intern/AUD_ConverterReader.h b/intern/audaspace/intern/AUD_ConverterReader.h index f855372b636..ba49bbfd9ba 100644 --- a/intern/audaspace/intern/AUD_ConverterReader.h +++ b/intern/audaspace/intern/AUD_ConverterReader.h @@ -44,7 +44,7 @@ private: /** * The target specification. */ - AUD_Specs m_specs; + AUD_DeviceSpecs m_specs; /** * Converter function. @@ -58,7 +58,7 @@ public: * \param specs The target specification. * \exception AUD_Exception Thrown if the reader is NULL. */ - AUD_ConverterReader(AUD_IReader* reader, AUD_Specs specs); + AUD_ConverterReader(AUD_IReader* reader, AUD_DeviceSpecs specs); /** * Destroys the reader. */ diff --git a/intern/audaspace/intern/AUD_FloatMixer.h b/intern/audaspace/intern/AUD_FloatMixer.h deleted file mode 100644 index 728a0faf3cb..00000000000 --- a/intern/audaspace/intern/AUD_FloatMixer.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * $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_FLOATMIXER -#define AUD_FLOATMIXER - -#include "AUD_IMixer.h" -#include "AUD_ConverterFunctions.h" -class AUD_ConverterFactory; -class AUD_SRCResampleFactory; -class AUD_ChannelMapperFactory; -class AUD_Buffer; -#include <list> - -struct AUD_FloatMixerBuffer -{ - sample_t* buffer; - int length; - float volume; -}; - -/** - * This class is able to mix two audiosignals with floats. - */ -class AUD_FloatMixer : public AUD_IMixer -{ -private: - /** - * The converter factory that converts all readers for superposition. - */ - AUD_ConverterFactory* m_converter; - - /** - * The resampling factory that resamples all readers for superposition. - */ - AUD_SRCResampleFactory* m_resampler; - - /** - * The channel mapper factory that maps all readers for superposition. - */ - AUD_ChannelMapperFactory* m_mapper; - - /** - * The list of buffers to superpose. - */ - std::list<AUD_FloatMixerBuffer> m_buffers; - - /** - * The output specification. - */ - AUD_Specs m_specs; - - /** - * The temporary mixing buffer. - */ - AUD_Buffer* m_buffer; - - /** - * Converter function. - */ - AUD_convert_f m_convert; - -public: - /** - * Creates the mixer. - */ - AUD_FloatMixer(); - - virtual ~AUD_FloatMixer(); - - virtual AUD_IReader* prepare(AUD_IReader* reader); - virtual void setSpecs(AUD_Specs specs); - virtual void add(sample_t* buffer, AUD_Specs specs, int length, - float volume); - virtual void superpose(sample_t* buffer, int length, float volume); -}; - -#endif //AUD_FLOATMIXER diff --git a/intern/audaspace/intern/AUD_IDevice.h b/intern/audaspace/intern/AUD_IDevice.h index af2cae206f3..e924f57cefc 100644 --- a/intern/audaspace/intern/AUD_IDevice.h +++ b/intern/audaspace/intern/AUD_IDevice.h @@ -53,7 +53,7 @@ public: /** * Returns the specification of the device. */ - virtual AUD_Specs getSpecs()=0; + virtual AUD_DeviceSpecs getSpecs()=0; /** * Plays a sound source. diff --git a/intern/audaspace/SDL/AUD_SDLMixerFactory.cpp b/intern/audaspace/intern/AUD_LinearResampleFactory.cpp index e0b0c7d3603..e738fc17693 100644 --- a/intern/audaspace/SDL/AUD_SDLMixerFactory.cpp +++ b/intern/audaspace/intern/AUD_LinearResampleFactory.cpp @@ -23,42 +23,30 @@ * ***** END LGPL LICENSE BLOCK ***** */ -#include "AUD_SDLMixerFactory.h" -#include "AUD_SDLMixerReader.h" +#include "AUD_LinearResampleFactory.h" +#include "AUD_LinearResampleReader.h" -#include <cstring> +AUD_LinearResampleFactory::AUD_LinearResampleFactory(AUD_IReader* reader, + AUD_DeviceSpecs specs) : + AUD_ResampleFactory(reader, specs) {} -AUD_SDLMixerFactory::AUD_SDLMixerFactory(AUD_IReader* reader, AUD_Specs specs) : - AUD_MixerFactory(reader, specs) {} +AUD_LinearResampleFactory::AUD_LinearResampleFactory(AUD_IFactory* factory, + AUD_DeviceSpecs specs) : + AUD_ResampleFactory(factory, specs) {} -AUD_SDLMixerFactory::AUD_SDLMixerFactory(AUD_IFactory* factory, AUD_Specs specs) : - AUD_MixerFactory(factory, specs) {} +AUD_LinearResampleFactory::AUD_LinearResampleFactory(AUD_DeviceSpecs specs) : + AUD_ResampleFactory(specs) {} -AUD_SDLMixerFactory::AUD_SDLMixerFactory(AUD_Specs specs) : - AUD_MixerFactory(specs) {} - -AUD_IReader* AUD_SDLMixerFactory::createReader() +AUD_IReader* AUD_LinearResampleFactory::createReader() { AUD_IReader* reader = getReader(); if(reader != 0) { - AUD_Specs specs = reader->getSpecs(); - if(memcmp(&m_specs, &specs, sizeof(AUD_Specs)) != 0) + if(reader->getSpecs().rate != m_specs.rate) { - try - { - reader = new AUD_SDLMixerReader(reader, m_specs); - AUD_NEW("reader") - } - catch(AUD_Exception e) - { - // return 0 in case SDL cannot mix the source - if(e.error != AUD_ERROR_SDL) - throw; - else - reader = NULL; - } + reader = new AUD_LinearResampleReader(reader, m_specs.specs); + AUD_NEW("reader") } } return reader; diff --git a/intern/audaspace/intern/AUD_LinearResampleFactory.h b/intern/audaspace/intern/AUD_LinearResampleFactory.h new file mode 100644 index 00000000000..81a9d623815 --- /dev/null +++ b/intern/audaspace/intern/AUD_LinearResampleFactory.h @@ -0,0 +1,44 @@ +/* + * $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_LINEARRESAMPLEFACTORY +#define AUD_LINEARRESAMPLEFACTORY + +#include "AUD_ResampleFactory.h" + +/** + * This factory creates a resampling reader that does simple linear resampling. + */ +class AUD_LinearResampleFactory : public AUD_ResampleFactory +{ +public: + AUD_LinearResampleFactory(AUD_IReader* reader, AUD_DeviceSpecs specs); + AUD_LinearResampleFactory(AUD_IFactory* factory, AUD_DeviceSpecs specs); + AUD_LinearResampleFactory(AUD_DeviceSpecs specs); + + virtual AUD_IReader* createReader(); +}; + +#endif //AUD_LINEARRESAMPLEFACTORY diff --git a/intern/audaspace/intern/AUD_LinearResampleReader.cpp b/intern/audaspace/intern/AUD_LinearResampleReader.cpp new file mode 100644 index 00000000000..dcd5310575d --- /dev/null +++ b/intern/audaspace/intern/AUD_LinearResampleReader.cpp @@ -0,0 +1,133 @@ +/* + * $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_LinearResampleReader.h" +#include "AUD_Buffer.h" + +#include <cmath> +#include <cstring> + +#define CC channels + channel + +AUD_LinearResampleReader::AUD_LinearResampleReader(AUD_IReader* reader, + AUD_Specs specs) : + AUD_EffectReader(reader) +{ + m_sspecs = reader->getSpecs(); + + m_tspecs = specs; + m_tspecs.channels = m_sspecs.channels; + m_factor = (float)m_tspecs.rate / (float)m_sspecs.rate; + + m_position = 0; + m_sposition = 0; + + m_buffer = new AUD_Buffer(); AUD_NEW("buffer") + m_cache = new AUD_Buffer(2 * AUD_SAMPLE_SIZE(specs)); AUD_NEW("buffer") +} + +AUD_LinearResampleReader::~AUD_LinearResampleReader() +{ + delete m_buffer; AUD_DELETE("buffer") + delete m_cache; AUD_DELETE("buffer") +} + +void AUD_LinearResampleReader::seek(int position) +{ + m_position = position; + m_sposition = floor(position / m_factor); + m_reader->seek(m_sposition); +} + +int AUD_LinearResampleReader::getLength() +{ + return m_reader->getLength() * m_factor; +} + +int AUD_LinearResampleReader::getPosition() +{ + return m_position; +} + +AUD_Specs AUD_LinearResampleReader::getSpecs() +{ + return m_tspecs; +} + +void AUD_LinearResampleReader::read(int & length, sample_t* & buffer) +{ + int samplesize = AUD_SAMPLE_SIZE(m_tspecs); + int size = length * samplesize; + + if(m_buffer->getSize() < size) + m_buffer->resize(size); + + int need = ceil((m_position + length) / m_factor) + 1 - m_sposition; + int len = need; + sample_t* buf; + buffer = m_buffer->getBuffer(); + + m_reader->read(len, buf); + + if(len < need) + length = floor((m_sposition + len - 1) * m_factor) - m_position; + + float spos; + sample_t low, high; + int channels = m_sspecs.channels; + + for(int channel = 0; channel < channels; channel++) + { + for(int i = 0; i < length; i++) + { + spos = (m_position + i) / m_factor - m_sposition; + + if(floor(spos) < 0) + { + low = m_cache->getBuffer()[(int)(floor(spos) + 2) * CC]; + if(ceil(spos) < 0) + high = m_cache->getBuffer()[(int)(ceil(spos) + 2) * CC]; + else + high = buf[(int)ceil(spos) * CC]; + } + else + { + low = buf[(int)floor(spos) * CC]; + high = buf[(int)ceil(spos) * CC]; + } + buffer[i * CC] = low + (spos - floor(spos)) * (high - low); + } + } + + if(len > 1) + memcpy(m_cache->getBuffer(), + buf + (len - 2) * channels, + 2 * samplesize); + else if(len == 1) + memcpy(m_cache->getBuffer() + 1 * channels, buf, samplesize); + + m_sposition += len; + m_position += length; +} diff --git a/intern/audaspace/intern/AUD_LinearResampleReader.h b/intern/audaspace/intern/AUD_LinearResampleReader.h new file mode 100644 index 00000000000..c86b8b76c59 --- /dev/null +++ b/intern/audaspace/intern/AUD_LinearResampleReader.h @@ -0,0 +1,94 @@ +/* + * $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_LINEARRESAMPLEREADER +#define AUD_LINEARRESAMPLEREADER + +#include "AUD_EffectReader.h" +class AUD_Buffer; + +/** + * This resampling reader uses libsamplerate for resampling. + */ +class AUD_LinearResampleReader : public AUD_EffectReader +{ +private: + /** + * The resampling factor. + */ + float m_factor; + + /** + * The current position. + */ + int m_position; + + /** + * The current reading source position. + */ + int m_sposition; + + /** + * The sound output buffer. + */ + AUD_Buffer *m_buffer; + + /** + * The input caching buffer. + */ + AUD_Buffer *m_cache; + + /** + * The target specification. + */ + AUD_Specs m_tspecs; + + /** + * The sample specification of the source. + */ + AUD_Specs m_sspecs; + +public: + /** + * Creates a resampling reader. + * \param reader The reader to mix. + * \param specs The target specification. + * \exception AUD_Exception Thrown if the reader is NULL. + */ + AUD_LinearResampleReader(AUD_IReader* reader, AUD_Specs specs); + + /** + * Destroys the reader. + */ + ~AUD_LinearResampleReader(); + + virtual void seek(int position); + virtual int getLength(); + virtual int getPosition(); + virtual AUD_Specs getSpecs(); + virtual void read(int & length, sample_t* & buffer); +}; + +#endif //AUD_LINEARRESAMPLEREADER diff --git a/intern/audaspace/intern/AUD_FloatMixer.cpp b/intern/audaspace/intern/AUD_Mixer.cpp index f7133b9c30e..bddc719b179 100644 --- a/intern/audaspace/intern/AUD_FloatMixer.cpp +++ b/intern/audaspace/intern/AUD_Mixer.cpp @@ -23,8 +23,7 @@ * ***** END LGPL LICENSE BLOCK ***** */ -#include "AUD_FloatMixer.h" -#include "AUD_ConverterFactory.h" +#include "AUD_Mixer.h" #include "AUD_SRCResampleFactory.h" #include "AUD_ChannelMapperFactory.h" #include "AUD_IReader.h" @@ -32,23 +31,19 @@ #include <cstring> -AUD_FloatMixer::AUD_FloatMixer() +AUD_Mixer::AUD_Mixer() { m_buffer = new AUD_Buffer(); AUD_NEW("buffer") - m_converter = NULL; m_resampler = NULL; m_mapper = NULL; } -AUD_FloatMixer::~AUD_FloatMixer() +AUD_Mixer::~AUD_Mixer() { delete m_buffer; AUD_DELETE("buffer") - if(m_converter) - { - delete m_converter; AUD_DELETE("factory") - } + if(m_resampler) { delete m_resampler; AUD_DELETE("factory") @@ -59,11 +54,8 @@ AUD_FloatMixer::~AUD_FloatMixer() } } -AUD_IReader* AUD_FloatMixer::prepare(AUD_IReader* reader) +AUD_IReader* AUD_Mixer::prepare(AUD_IReader* reader) { - m_converter->setReader(reader); - reader = m_converter->createReader(); - m_resampler->setReader(reader); reader = m_resampler->createReader(); @@ -76,14 +68,10 @@ AUD_IReader* AUD_FloatMixer::prepare(AUD_IReader* reader) return reader; } -void AUD_FloatMixer::setSpecs(AUD_Specs specs) +void AUD_Mixer::setSpecs(AUD_DeviceSpecs specs) { m_specs = specs; - if(m_converter) - { - delete m_converter; AUD_DELETE("factory") - } if(m_resampler) { delete m_resampler; AUD_DELETE("factory") @@ -93,9 +81,6 @@ void AUD_FloatMixer::setSpecs(AUD_Specs specs) delete m_mapper; AUD_DELETE("factory") } - specs.format = AUD_FORMAT_FLOAT32; - - m_converter = new AUD_ConverterFactory(specs); AUD_NEW("factory") m_resampler = new AUD_SRCResampleFactory(specs); AUD_NEW("factory") m_mapper = new AUD_ChannelMapperFactory(specs); AUD_NEW("factory") @@ -130,27 +115,26 @@ void AUD_FloatMixer::setSpecs(AUD_Specs specs) } } -void AUD_FloatMixer::add(sample_t* buffer, AUD_Specs specs, int length, - float volume) +void AUD_Mixer::add(sample_t* buffer, int length, float volume) { - AUD_FloatMixerBuffer buf; + AUD_MixerBuffer buf; buf.buffer = buffer; buf.length = length; buf.volume = volume; m_buffers.push_back(buf); } -void AUD_FloatMixer::superpose(sample_t* buffer, int length, float volume) +void AUD_Mixer::superpose(data_t* buffer, int length, float volume) { - AUD_FloatMixerBuffer buf; + AUD_MixerBuffer buf; int channels = m_specs.channels; if(m_buffer->getSize() < length * channels * 4) m_buffer->resize(length * channels * 4); - float* out = (float*)m_buffer->getBuffer(); - float* in; + sample_t* out = m_buffer->getBuffer(); + sample_t* in; memset(out, 0, length * channels * 4); @@ -162,11 +146,11 @@ void AUD_FloatMixer::superpose(sample_t* buffer, int length, float volume) m_buffers.pop_front(); end = buf.length*channels; - in = (float*) buf.buffer; + in = buf.buffer; for(int i = 0; i < end; i++) out[i] += in[i]*buf.volume * volume; } - m_convert(buffer, (sample_t*) out, length * channels); + m_convert(buffer, (data_t*) out, length * channels); } diff --git a/intern/audaspace/intern/AUD_IMixer.h b/intern/audaspace/intern/AUD_Mixer.h index c65e4c69cf7..5097b9ec2a6 100644 --- a/intern/audaspace/intern/AUD_IMixer.h +++ b/intern/audaspace/intern/AUD_Mixer.h @@ -23,47 +23,95 @@ * ***** END LGPL LICENSE BLOCK ***** */ -#ifndef AUD_IMIXER -#define AUD_IMIXER +#ifndef AUD_MIXER +#define AUD_MIXER -#include "AUD_Space.h" +#include "AUD_ConverterFunctions.h" +class AUD_ConverterFactory; +class AUD_SRCResampleFactory; +class AUD_ChannelMapperFactory; +class AUD_Buffer; class AUD_IReader; +#include <list> + +struct AUD_MixerBuffer +{ + sample_t* buffer; + int length; + float volume; +}; /** - * This class is able to mix audiosignals of different format and channel count. - * \note This class doesn't do resampling! + * This class is able to mix audiosignals of different channel count and sample + * rate and convert it to a specific output format. + * It uses a default ChannelMapperFactory and a SRCResampleFactory for + * the perparation. */ -class AUD_IMixer +class AUD_Mixer { +private: + /** + * The resampling factory that resamples all readers for superposition. + */ + AUD_SRCResampleFactory* m_resampler; + + /** + * The channel mapper factory that maps all readers for superposition. + */ + AUD_ChannelMapperFactory* m_mapper; + + /** + * The list of buffers to superpose. + */ + std::list<AUD_MixerBuffer> m_buffers; + + /** + * The output specification. + */ + AUD_DeviceSpecs m_specs; + + /** + * The temporary mixing buffer. + */ + AUD_Buffer* m_buffer; + + /** + * Converter function. + */ + AUD_convert_f m_convert; + public: /** + * Creates the mixer. + */ + AUD_Mixer(); + + /** * Destroys the mixer. */ - virtual ~AUD_IMixer(){} + ~AUD_Mixer(); /** * This funuction prepares a reader for playback. * \param reader The reader to prepare. * \return The reader that should be used for playback. */ - virtual AUD_IReader* prepare(AUD_IReader* reader)=0; + AUD_IReader* prepare(AUD_IReader* reader); /** * Sets the target specification for superposing. * \param specs The target specification. */ - virtual void setSpecs(AUD_Specs specs)=0; + void setSpecs(AUD_DeviceSpecs specs); /** * Adds a buffer for superposition. * \param buffer The buffer to superpose. - * \param specs The specification of the buffer. * \param start The start sample of the buffer. * \param length The length of the buffer in samples. * \param volume The mixing volume. Must be a value between 0.0 and 1.0. */ - virtual void add(sample_t* buffer, AUD_Specs specs, int length, - float volume)=0; + void add(sample_t* buffer, int length, float volume); /** * Superposes all added buffers into an output buffer. @@ -71,7 +119,7 @@ public: * \param length The length of the buffer in samples. * \param volume The mixing volume. Must be a value between 0.0 and 1.0. */ - virtual void superpose(sample_t* buffer, int length, float volume)=0; + void superpose(data_t* buffer, int length, float volume); }; -#endif //AUD_IMIXER +#endif //AUD_MIXER diff --git a/intern/audaspace/intern/AUD_MixerFactory.cpp b/intern/audaspace/intern/AUD_MixerFactory.cpp index db38d1004db..e78818301fa 100644 --- a/intern/audaspace/intern/AUD_MixerFactory.cpp +++ b/intern/audaspace/intern/AUD_MixerFactory.cpp @@ -49,7 +49,7 @@ AUD_IReader* AUD_MixerFactory::getReader() } AUD_MixerFactory::AUD_MixerFactory(AUD_IReader* reader, - AUD_Specs specs) + AUD_DeviceSpecs specs) { m_specs = specs; m_reader = reader; @@ -57,14 +57,14 @@ AUD_MixerFactory::AUD_MixerFactory(AUD_IReader* reader, } AUD_MixerFactory::AUD_MixerFactory(AUD_IFactory* factory, - AUD_Specs specs) + AUD_DeviceSpecs specs) { m_specs = specs; m_reader = 0; m_factory = factory; } -AUD_MixerFactory::AUD_MixerFactory(AUD_Specs specs) +AUD_MixerFactory::AUD_MixerFactory(AUD_DeviceSpecs specs) { m_specs = specs; m_reader = 0; @@ -79,12 +79,12 @@ AUD_MixerFactory::~AUD_MixerFactory() } } -AUD_Specs AUD_MixerFactory::getSpecs() +AUD_DeviceSpecs AUD_MixerFactory::getSpecs() { return m_specs; } -void AUD_MixerFactory::setSpecs(AUD_Specs specs) +void AUD_MixerFactory::setSpecs(AUD_DeviceSpecs specs) { m_specs = specs; } diff --git a/intern/audaspace/intern/AUD_MixerFactory.h b/intern/audaspace/intern/AUD_MixerFactory.h index c61dd283c67..a2f4aa78d76 100644 --- a/intern/audaspace/intern/AUD_MixerFactory.h +++ b/intern/audaspace/intern/AUD_MixerFactory.h @@ -47,7 +47,7 @@ protected: /** * The target specification for resampling. */ - AUD_Specs m_specs; + AUD_DeviceSpecs m_specs; /** * Returns the reader created out of the factory or taken from m_reader. @@ -63,20 +63,20 @@ public: * \param reader The reader to mix. * \param specs The target specification. */ - AUD_MixerFactory(AUD_IReader* reader, AUD_Specs specs); + AUD_MixerFactory(AUD_IReader* reader, AUD_DeviceSpecs specs); /** * Creates a new factory. * \param factory The factory to create the readers to mix out of. * \param specs The target specification. */ - AUD_MixerFactory(AUD_IFactory* factory, AUD_Specs specs); + AUD_MixerFactory(AUD_IFactory* factory, AUD_DeviceSpecs specs); /** * Creates a new factory. * \param specs The target specification. */ - AUD_MixerFactory(AUD_Specs specs); + AUD_MixerFactory(AUD_DeviceSpecs specs); /** * Destroys the resampling factory. @@ -86,13 +86,13 @@ public: /** * Returns the target specification for resampling. */ - AUD_Specs getSpecs(); + AUD_DeviceSpecs getSpecs(); /** * Sets the target specification for resampling. * \param specs The specification. */ - void setSpecs(AUD_Specs specs); + void setSpecs(AUD_DeviceSpecs specs); /** * Sets the reader for resampling. diff --git a/intern/audaspace/intern/AUD_NULLDevice.cpp b/intern/audaspace/intern/AUD_NULLDevice.cpp index d237b71b67e..3936695c28f 100644 --- a/intern/audaspace/intern/AUD_NULLDevice.cpp +++ b/intern/audaspace/intern/AUD_NULLDevice.cpp @@ -34,7 +34,7 @@ AUD_NULLDevice::AUD_NULLDevice() m_specs.rate = AUD_RATE_INVALID; } -AUD_Specs AUD_NULLDevice::getSpecs() +AUD_DeviceSpecs AUD_NULLDevice::getSpecs() { return m_specs; } diff --git a/intern/audaspace/intern/AUD_NULLDevice.h b/intern/audaspace/intern/AUD_NULLDevice.h index 155f24f8837..91ddd23cf71 100644 --- a/intern/audaspace/intern/AUD_NULLDevice.h +++ b/intern/audaspace/intern/AUD_NULLDevice.h @@ -37,7 +37,7 @@ private: /** * The specs of the device. */ - AUD_Specs m_specs; + AUD_DeviceSpecs m_specs; public: /** @@ -45,7 +45,7 @@ public: */ AUD_NULLDevice(); - virtual AUD_Specs getSpecs(); + virtual AUD_DeviceSpecs getSpecs(); virtual AUD_Handle* play(AUD_IFactory* factory, bool keep = false); virtual bool pause(AUD_Handle* handle); virtual bool resume(AUD_Handle* handle); diff --git a/intern/audaspace/intern/AUD_ReadDevice.cpp b/intern/audaspace/intern/AUD_ReadDevice.cpp index e2c1d2fac81..37a7d1ae295 100644 --- a/intern/audaspace/intern/AUD_ReadDevice.cpp +++ b/intern/audaspace/intern/AUD_ReadDevice.cpp @@ -23,17 +23,17 @@ * ***** END LGPL LICENSE BLOCK ***** */ -#include "AUD_FloatMixer.h" +#include "AUD_Mixer.h" #include "AUD_ReadDevice.h" #include "AUD_IReader.h" #include <cstring> -AUD_ReadDevice::AUD_ReadDevice(AUD_Specs specs) +AUD_ReadDevice::AUD_ReadDevice(AUD_DeviceSpecs specs) { m_specs = specs; - m_mixer = new AUD_FloatMixer(); AUD_NEW("mixer") + m_mixer = new AUD_Mixer(); AUD_NEW("mixer") m_mixer->setSpecs(m_specs); m_playing = false; @@ -46,15 +46,15 @@ AUD_ReadDevice::~AUD_ReadDevice() destroy(); } -bool AUD_ReadDevice::read(sample_t* buffer, int length) +bool AUD_ReadDevice::read(data_t* buffer, int length) { if(m_playing) mix(buffer, length); else if(m_specs.format == AUD_FORMAT_U8) - memset(buffer, 0x80, length * AUD_SAMPLE_SIZE(m_specs)); + memset(buffer, 0x80, length * AUD_DEVICE_SAMPLE_SIZE(m_specs)); else - memset(buffer, 0, length * AUD_SAMPLE_SIZE(m_specs)); + memset(buffer, 0, length * AUD_DEVICE_SAMPLE_SIZE(m_specs)); return m_playing; } diff --git a/intern/audaspace/intern/AUD_ReadDevice.h b/intern/audaspace/intern/AUD_ReadDevice.h index d69b0c31ea5..3fd90df7755 100644 --- a/intern/audaspace/intern/AUD_ReadDevice.h +++ b/intern/audaspace/intern/AUD_ReadDevice.h @@ -47,7 +47,7 @@ public: * Creates a new read device. * \param specs The wanted audio specification. */ - AUD_ReadDevice(AUD_Specs specs); + AUD_ReadDevice(AUD_DeviceSpecs specs); /** * Closes the device. @@ -62,7 +62,7 @@ public: * played back currently, in that case the buffer is filled with * silence. */ - bool read(sample_t* buffer, int length); + bool read(data_t* buffer, int length); }; #endif //AUD_READDEVICE diff --git a/intern/audaspace/intern/AUD_SinusReader.cpp b/intern/audaspace/intern/AUD_SinusReader.cpp index 87e2f789d66..c52513d5d2e 100644 --- a/intern/audaspace/intern/AUD_SinusReader.cpp +++ b/intern/audaspace/intern/AUD_SinusReader.cpp @@ -26,7 +26,7 @@ #include "AUD_SinusReader.h" #include "AUD_Buffer.h" -#include <math.h> +#include <cmath> #ifndef M_PI #define M_PI 3.14159265358979323846 @@ -69,8 +69,7 @@ AUD_Specs AUD_SinusReader::getSpecs() { AUD_Specs specs; specs.rate = m_sampleRate; - specs.format = AUD_FORMAT_S16; - specs.channels = AUD_CHANNELS_STEREO; + specs.channels = AUD_CHANNELS_MONO; return specs; } @@ -87,18 +86,16 @@ bool AUD_SinusReader::notify(AUD_Message &message) void AUD_SinusReader::read(int & length, sample_t* & buffer) { // resize if necessary - if(m_buffer->getSize() < length*4) - m_buffer->resize(length*4); + if(m_buffer->getSize() < length * sizeof(sample_t)) + m_buffer->resize(length * sizeof(sample_t)); // fill with sine data - short* buf = (short*) m_buffer->getBuffer(); - for(int i=0; i < length; i++) + buffer = m_buffer->getBuffer(); + for(int i = 0; i < length; i++) { - buf[i*2] = sin((m_position + i) * 2.0 * M_PI * m_frequency / - (float)m_sampleRate) * 32700; - buf[i*2+1] = buf[i*2]; + buffer[i] = sin((m_position + i) * 2.0f * M_PI * m_frequency / + (float)m_sampleRate); } - buffer = (sample_t*)buf; m_position += length; } diff --git a/intern/audaspace/intern/AUD_SoftwareDevice.cpp b/intern/audaspace/intern/AUD_SoftwareDevice.cpp index 42a90a6f15e..a615bcd0245 100644 --- a/intern/audaspace/intern/AUD_SoftwareDevice.cpp +++ b/intern/audaspace/intern/AUD_SoftwareDevice.cpp @@ -25,7 +25,7 @@ #include "AUD_SoftwareDevice.h" #include "AUD_IReader.h" -#include "AUD_IMixer.h" +#include "AUD_Mixer.h" #include "AUD_IFactory.h" #include "AUD_SourceCaps.h" @@ -51,7 +51,9 @@ void AUD_SoftwareDevice::create() m_playingSounds = new std::list<AUD_SoftwareHandle*>(); AUD_NEW("list") m_pausedSounds = new std::list<AUD_SoftwareHandle*>(); AUD_NEW("list") m_playback = false; - m_volume = 1.0; + m_volume = 1.0f; + m_mixer = new AUD_Mixer(); AUD_NEW("mixer") + m_mixer->setSpecs(m_specs); pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); @@ -90,7 +92,7 @@ void AUD_SoftwareDevice::destroy() pthread_mutex_destroy(&m_mutex); } -void AUD_SoftwareDevice::mix(sample_t* buffer, int length) +void AUD_SoftwareDevice::mix(data_t* buffer, int length) { lock(); @@ -98,7 +100,7 @@ void AUD_SoftwareDevice::mix(sample_t* buffer, int length) AUD_SoftwareHandle* sound; int len; sample_t* buf; - int sample_size = AUD_SAMPLE_SIZE(m_specs); + int sample_size = AUD_DEVICE_SAMPLE_SIZE(m_specs); std::list<AUD_SoftwareHandle*> stopSounds; // for all sounds @@ -114,7 +116,7 @@ void AUD_SoftwareDevice::mix(sample_t* buffer, int length) len = length; sound->reader->read(len, buf); - m_mixer->add(buf, sound->reader->getSpecs(), len, sound->volume); + m_mixer->add(buf, len, sound->volume); // in case the end of the sound is reached if(len < length) @@ -159,14 +161,7 @@ bool AUD_SoftwareDevice::isValid(AUD_Handle* handle) return false; } -void AUD_SoftwareDevice::setMixer(AUD_IMixer* mixer) -{ - delete m_mixer; AUD_DELETE("mixer") - m_mixer = mixer; - mixer->setSpecs(m_specs); -} - -AUD_Specs AUD_SoftwareDevice::getSpecs() +AUD_DeviceSpecs AUD_SoftwareDevice::getSpecs() { return m_specs; } @@ -189,7 +184,7 @@ AUD_Handle* AUD_SoftwareDevice::play(AUD_IFactory* factory, bool keep) AUD_SoftwareHandle* sound = new AUD_SoftwareHandle; AUD_NEW("handle") sound->keep = keep; sound->reader = reader; - sound->volume = 1.0; + sound->volume = 1.0f; lock(); m_playingSounds->push_back(sound); @@ -426,10 +421,10 @@ bool AUD_SoftwareDevice::setCapability(int capability, void *value) case AUD_CAPS_VOLUME: lock(); m_volume = *((float*)value); - if(m_volume > 1.0) - m_volume = 1.0; - else if(m_volume < 0.0) - m_volume = 0.0; + if(m_volume > 1.0f) + m_volume = 1.0f; + else if(m_volume < 0.0f) + m_volume = 0.0f; unlock(); return true; case AUD_CAPS_SOURCE_VOLUME: @@ -440,10 +435,10 @@ bool AUD_SoftwareDevice::setCapability(int capability, void *value) { AUD_SoftwareHandle* handle = (AUD_SoftwareHandle*)caps->handle; handle->volume = caps->value; - if(handle->volume > 1.0) - handle->volume = 1.0; - else if(handle->volume < 0.0) - handle->volume = 0.0; + if(handle->volume > 1.0f) + handle->volume = 1.0f; + else if(handle->volume < 0.0f) + handle->volume = 0.0f; result = true; } unlock(); diff --git a/intern/audaspace/intern/AUD_SoftwareDevice.h b/intern/audaspace/intern/AUD_SoftwareDevice.h index 3768786fa9c..a12fddb1e00 100644 --- a/intern/audaspace/intern/AUD_SoftwareDevice.h +++ b/intern/audaspace/intern/AUD_SoftwareDevice.h @@ -28,7 +28,7 @@ #include "AUD_IDevice.h" struct AUD_SoftwareHandle; -class AUD_IMixer; +class AUD_Mixer; #include <list> #include <pthread.h> @@ -47,12 +47,12 @@ protected: /** * The specification of the device. */ - AUD_Specs m_specs; + AUD_DeviceSpecs m_specs; /** - * The mixer. Will be deleted by the destroy function. + * The mixer. */ - AUD_IMixer* m_mixer; + AUD_Mixer* m_mixer; /** * Initializes member variables. @@ -69,7 +69,7 @@ protected: * \param buffer The target buffer. * \param length The length in samples to be filled. */ - void mix(sample_t* buffer, int length); + void mix(data_t* buffer, int length); /** * This function tells the device, to start or pause playback. @@ -111,13 +111,7 @@ private: bool isValid(AUD_Handle* handle); public: - /** - * Sets a new mixer. - * \param mixer The new mixer. - */ - void setMixer(AUD_IMixer* mixer); - - virtual AUD_Specs getSpecs(); + virtual AUD_DeviceSpecs getSpecs(); virtual AUD_Handle* play(AUD_IFactory* factory, bool keep = false); virtual bool pause(AUD_Handle* handle); virtual bool resume(AUD_Handle* handle); diff --git a/intern/audaspace/intern/AUD_Space.h b/intern/audaspace/intern/AUD_Space.h index 123d9c272a0..1d60be3979b 100644 --- a/intern/audaspace/intern/AUD_Space.h +++ b/intern/audaspace/intern/AUD_Space.h @@ -28,8 +28,10 @@ /// The size of a format in bytes. #define AUD_FORMAT_SIZE(format) (format & 0x0F) +/// The size of a sample in the specified device format in bytes. +#define AUD_DEVICE_SAMPLE_SIZE(specs) (specs.channels * (specs.format & 0x0F)) /// The size of a sample in the specified format in bytes. -#define AUD_SAMPLE_SIZE(specs) (specs.channels * (specs.format & 0x0F)) +#define AUD_SAMPLE_SIZE(specs) (specs.channels * sizeof(sample_t)) /// Throws a AUD_Exception with the provided error code. #define AUD_THROW(exception) { AUD_Exception e; e.error = exception; throw e; } @@ -233,22 +235,42 @@ typedef enum AUD_3DSS_CONE_OUTER_GAIN /// Cone outer gain. } AUD_3DSourceSetting; -/// Sample pointer type. -typedef unsigned char sample_t; +/// Sample type.(float samples) +typedef float sample_t; -/// Specification of a sound source or device. +/// Sample data type (format samples) +typedef unsigned char data_t; + +/// Specification of a sound source. typedef struct { /// Sample rate in Hz. AUD_SampleRate rate; - /// Sample format. - AUD_SampleFormat format; - /// Channel count. AUD_Channels channels; } AUD_Specs; +/// Specification of a sound device. +typedef struct +{ + /// Sample format. + AUD_SampleFormat format; + + union + { + struct + { + /// Sample rate in Hz. + AUD_SampleRate rate; + + /// Channel count. + AUD_Channels channels; + }; + AUD_Specs specs; + }; +} AUD_DeviceSpecs; + /// Exception structure. typedef struct { diff --git a/intern/audaspace/intern/AUD_StreamBufferFactory.cpp b/intern/audaspace/intern/AUD_StreamBufferFactory.cpp index 11391fa4a08..4d2cd9e2505 100644 --- a/intern/audaspace/intern/AUD_StreamBufferFactory.cpp +++ b/intern/audaspace/intern/AUD_StreamBufferFactory.cpp @@ -61,9 +61,9 @@ AUD_StreamBufferFactory::AUD_StreamBufferFactory(AUD_IFactory* factory) // read more length = size-index; reader->read(length, buffer); - memcpy(m_buffer.get()->getBuffer()+index*sample_size, + memcpy(m_buffer.get()->getBuffer() + index * m_specs.channels, buffer, - length*sample_size); + length * sample_size); size += AUD_BUFFER_RESIZE_BYTES / sample_size; index += length; } diff --git a/intern/audaspace/jack/AUD_JackDevice.cpp b/intern/audaspace/jack/AUD_JackDevice.cpp index 4d8ab93d672..acd37de870c 100644 --- a/intern/audaspace/jack/AUD_JackDevice.cpp +++ b/intern/audaspace/jack/AUD_JackDevice.cpp @@ -23,7 +23,7 @@ * ***** END LGPL LICENSE BLOCK ***** */ -#include "AUD_FloatMixer.h" +#include "AUD_Mixer.h" #include "AUD_JackDevice.h" #include "AUD_IReader.h" #include "AUD_Buffer.h" @@ -38,7 +38,7 @@ int AUD_JackDevice::jack_mix(jack_nframes_t length, void *data) unsigned int samplesize = AUD_SAMPLE_SIZE(device->m_specs); if(device->m_buffer->getSize() < samplesize * length) device->m_buffer->resize(samplesize * length); - device->mix(device->m_buffer->getBuffer(), length); + device->mix((data_t*)device->m_buffer->getBuffer(), length); float* in = (float*) device->m_buffer->getBuffer(); float* out; @@ -60,7 +60,7 @@ void AUD_JackDevice::jack_shutdown(void *data) device->m_valid = false; } -AUD_JackDevice::AUD_JackDevice(AUD_Specs specs) +AUD_JackDevice::AUD_JackDevice(AUD_DeviceSpecs specs) { if(specs.channels == AUD_CHANNELS_INVALID) specs.channels = AUD_CHANNELS_STEREO; @@ -123,9 +123,6 @@ AUD_JackDevice::AUD_JackDevice(AUD_Specs specs) free(ports); } - m_mixer = new AUD_FloatMixer(); AUD_NEW("mixer") - m_mixer->setSpecs(m_specs); - m_valid = true; create(); diff --git a/intern/audaspace/jack/AUD_JackDevice.h b/intern/audaspace/jack/AUD_JackDevice.h index f0c887a2f43..5a073a69432 100644 --- a/intern/audaspace/jack/AUD_JackDevice.h +++ b/intern/audaspace/jack/AUD_JackDevice.h @@ -81,7 +81,7 @@ public: * \param specs The wanted audio specification, where only the channel count is important. * \exception AUD_Exception Thrown if the audio device cannot be opened. */ - AUD_JackDevice(AUD_Specs specs); + AUD_JackDevice(AUD_DeviceSpecs specs); /** * Closes the Jack client. diff --git a/intern/audaspace/make/msvc_9_0/audaspace.vcproj b/intern/audaspace/make/msvc_9_0/audaspace.vcproj index 37ac98c0cf2..bdf14255391 100644 --- a/intern/audaspace/make/msvc_9_0/audaspace.vcproj +++ b/intern/audaspace/make/msvc_9_0/audaspace.vcproj @@ -394,31 +394,43 @@ >
</File>
<File
- RelativePath="..\..\intern\AUD_FloatMixer.cpp"
+ RelativePath="..\..\intern\AUD_I3DDevice.h"
>
</File>
<File
- RelativePath="..\..\intern\AUD_FloatMixer.h"
+ RelativePath="..\..\intern\AUD_IDevice.h"
>
</File>
<File
- RelativePath="..\..\intern\AUD_I3DDevice.h"
+ RelativePath="..\..\intern\AUD_IFactory.h"
>
</File>
<File
- RelativePath="..\..\intern\AUD_IDevice.h"
+ RelativePath="..\..\intern\AUD_IReader.h"
>
</File>
<File
- RelativePath="..\..\intern\AUD_IFactory.h"
+ RelativePath="..\..\intern\AUD_LinearResampleFactory.cpp"
>
</File>
<File
- RelativePath="..\..\intern\AUD_IMixer.h"
+ RelativePath="..\..\intern\AUD_LinearResampleFactory.h"
>
</File>
<File
- RelativePath="..\..\intern\AUD_IReader.h"
+ RelativePath="..\..\intern\AUD_LinearResampleReader.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\intern\AUD_LinearResampleReader.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\intern\AUD_Mixer.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\intern\AUD_Mixer.h"
>
</File>
<File
@@ -518,6 +530,38 @@ Name="FX"
>
<File
+ RelativePath="..\..\FX\AUD_AccumulatorFactory.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\FX\AUD_AccumulatorFactory.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\FX\AUD_AccumulatorReader.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\FX\AUD_AccumulatorReader.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\FX\AUD_ButterworthFactory.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\FX\AUD_ButterworthFactory.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\FX\AUD_ButterworthReader.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\FX\AUD_ButterworthReader.h"
+ >
+ </File>
+ <File
RelativePath="..\..\FX\AUD_DelayFactory.cpp"
>
</File>
@@ -558,6 +602,22 @@ >
</File>
<File
+ RelativePath="..\..\FX\AUD_EnvelopeFactory.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\FX\AUD_EnvelopeFactory.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\FX\AUD_EnvelopeReader.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\FX\AUD_EnvelopeReader.h"
+ >
+ </File>
+ <File
RelativePath="..\..\FX\AUD_FaderFactory.cpp"
>
</File>
@@ -574,6 +634,22 @@ >
</File>
<File
+ RelativePath="..\..\FX\AUD_HighpassFactory.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\FX\AUD_HighpassFactory.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\FX\AUD_HighpassReader.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\FX\AUD_HighpassReader.h"
+ >
+ </File>
+ <File
RelativePath="..\..\FX\AUD_LimiterFactory.cpp"
>
</File>
@@ -606,6 +682,22 @@ >
</File>
<File
+ RelativePath="..\..\FX\AUD_LowpassFactory.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\FX\AUD_LowpassFactory.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\FX\AUD_LowpassReader.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\FX\AUD_LowpassReader.h"
+ >
+ </File>
+ <File
RelativePath="..\..\FX\AUD_PingPongFactory.cpp"
>
</File>
@@ -662,67 +754,75 @@ >
</File>
<File
- RelativePath="..\..\FX\AUD_VolumeFactory.cpp"
+ RelativePath="..\..\FX\AUD_SquareFactory.cpp"
>
</File>
<File
- RelativePath="..\..\FX\AUD_VolumeFactory.h"
+ RelativePath="..\..\FX\AUD_SquareFactory.h"
>
</File>
<File
- RelativePath="..\..\FX\AUD_VolumeReader.cpp"
+ RelativePath="..\..\FX\AUD_SquareReader.cpp"
>
</File>
<File
- RelativePath="..\..\FX\AUD_VolumeReader.h"
+ RelativePath="..\..\FX\AUD_SquareReader.h"
>
</File>
- </Filter>
- <Filter
- Name="OpenAL"
- >
<File
- RelativePath="..\..\OpenAL\AUD_OpenALDevice.cpp"
+ RelativePath="..\..\FX\AUD_SumFactory.cpp"
>
</File>
<File
- RelativePath="..\..\OpenAL\AUD_OpenALDevice.h"
+ RelativePath="..\..\FX\AUD_SumFactory.h"
>
</File>
- </Filter>
- <Filter
- Name="SDL"
- >
<File
- RelativePath="..\..\SDL\AUD_SDLDevice.cpp"
+ RelativePath="..\..\FX\AUD_SumReader.cpp"
>
</File>
<File
- RelativePath="..\..\SDL\AUD_SDLDevice.h"
+ RelativePath="..\..\FX\AUD_SumReader.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\FX\AUD_VolumeFactory.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\FX\AUD_VolumeFactory.h"
>
</File>
<File
- RelativePath="..\..\SDL\AUD_SDLMixer.cpp"
+ RelativePath="..\..\FX\AUD_VolumeReader.cpp"
>
</File>
<File
- RelativePath="..\..\SDL\AUD_SDLMixer.h"
+ RelativePath="..\..\FX\AUD_VolumeReader.h"
>
</File>
+ </Filter>
+ <Filter
+ Name="OpenAL"
+ >
<File
- RelativePath="..\..\SDL\AUD_SDLMixerFactory.cpp"
+ RelativePath="..\..\OpenAL\AUD_OpenALDevice.cpp"
>
</File>
<File
- RelativePath="..\..\SDL\AUD_SDLMixerFactory.h"
+ RelativePath="..\..\OpenAL\AUD_OpenALDevice.h"
>
</File>
+ </Filter>
+ <Filter
+ Name="SDL"
+ >
<File
- RelativePath="..\..\SDL\AUD_SDLMixerReader.cpp"
+ RelativePath="..\..\SDL\AUD_SDLDevice.cpp"
>
</File>
<File
- RelativePath="..\..\SDL\AUD_SDLMixerReader.h"
+ RelativePath="..\..\SDL\AUD_SDLDevice.h"
>
</File>
</Filter>
diff --git a/intern/audaspace/sndfile/AUD_SndFileReader.cpp b/intern/audaspace/sndfile/AUD_SndFileReader.cpp index 485818552bb..f9ed8d6388e 100644 --- a/intern/audaspace/sndfile/AUD_SndFileReader.cpp +++ b/intern/audaspace/sndfile/AUD_SndFileReader.cpp @@ -28,31 +28,14 @@ #include <cstring> -// This function transforms a SampleFormat to our own sample format -static inline AUD_SampleFormat SNDFILE_TO_AUD(int fmt) -{ - switch(fmt & SF_FORMAT_SUBMASK) - { - // only read s16, s32 and double as they are - case SF_FORMAT_PCM_16: - return AUD_FORMAT_S16; - case SF_FORMAT_PCM_32: - return AUD_FORMAT_S32; - case SF_FORMAT_DOUBLE: - return AUD_FORMAT_FLOAT64; - // read all other formats as floats - default: - return AUD_FORMAT_FLOAT32; - } -} - sf_count_t AUD_SndFileReader::vio_get_filelen(void *user_data) { AUD_SndFileReader* reader = (AUD_SndFileReader*)user_data; return reader->m_membuffer.get()->getSize(); } -sf_count_t AUD_SndFileReader::vio_seek(sf_count_t offset, int whence, void *user_data) +sf_count_t AUD_SndFileReader::vio_seek(sf_count_t offset, int whence, + void *user_data) { AUD_SndFileReader* reader = (AUD_SndFileReader*)user_data; @@ -72,14 +55,16 @@ sf_count_t AUD_SndFileReader::vio_seek(sf_count_t offset, int whence, void *user return reader->m_memoffset; } -sf_count_t AUD_SndFileReader::vio_read(void *ptr, sf_count_t count, void *user_data) +sf_count_t AUD_SndFileReader::vio_read(void *ptr, sf_count_t count, + void *user_data) { AUD_SndFileReader* reader = (AUD_SndFileReader*)user_data; if(reader->m_memoffset + count > reader->m_membuffer.get()->getSize()) count = reader->m_membuffer.get()->getSize() - reader->m_memoffset; - memcpy(ptr, reader->m_membuffer.get()->getBuffer() + reader->m_memoffset, count); + memcpy(ptr, ((data_t*)reader->m_membuffer.get()->getBuffer()) + + reader->m_memoffset, count); reader->m_memoffset += count; return count; @@ -103,27 +88,11 @@ AUD_SndFileReader::AUD_SndFileReader(const char* filename) AUD_THROW(AUD_ERROR_FILE); m_specs.channels = (AUD_Channels) sfinfo.channels; - m_specs.format = SNDFILE_TO_AUD(sfinfo.format); m_specs.rate = (AUD_SampleRate) sfinfo.samplerate; m_length = sfinfo.frames; m_seekable = sfinfo.seekable; m_position = 0; - switch(m_specs.format) - { - case AUD_FORMAT_S16: - m_read = (sf_read_f) sf_readf_short; - break; - case AUD_FORMAT_S32: - m_read = (sf_read_f) sf_readf_int; - break; - case AUD_FORMAT_FLOAT64: - m_read = (sf_read_f) sf_readf_double; - break; - default: - m_read = (sf_read_f) sf_readf_float; - } - m_buffer = new AUD_Buffer(); AUD_NEW("buffer") } @@ -147,27 +116,11 @@ AUD_SndFileReader::AUD_SndFileReader(AUD_Reference<AUD_Buffer> buffer) AUD_THROW(AUD_ERROR_FILE); m_specs.channels = (AUD_Channels) sfinfo.channels; - m_specs.format = SNDFILE_TO_AUD(sfinfo.format); m_specs.rate = (AUD_SampleRate) sfinfo.samplerate; m_length = sfinfo.frames; m_seekable = sfinfo.seekable; m_position = 0; - switch(m_specs.format) - { - case AUD_FORMAT_S16: - m_read = (sf_read_f) sf_readf_short; - break; - case AUD_FORMAT_S32: - m_read = (sf_read_f) sf_readf_int; - break; - case AUD_FORMAT_FLOAT64: - m_read = (sf_read_f) sf_readf_double; - break; - default: - m_read = (sf_read_f) sf_readf_float; - } - m_buffer = new AUD_Buffer(); AUD_NEW("buffer") } @@ -227,7 +180,7 @@ void AUD_SndFileReader::read(int & length, sample_t* & buffer) buffer = m_buffer->getBuffer(); - length = m_read(m_sndfile, buffer, length); + length = sf_readf_float(m_sndfile, buffer, length); m_position += length; } diff --git a/intern/audaspace/sndfile/AUD_SndFileReader.h b/intern/audaspace/sndfile/AUD_SndFileReader.h index da890ef53ca..8886b6e9efc 100644 --- a/intern/audaspace/sndfile/AUD_SndFileReader.h +++ b/intern/audaspace/sndfile/AUD_SndFileReader.h @@ -71,11 +71,6 @@ private: SNDFILE* m_sndfile; /** - * The reading function. - */ - sf_read_f m_read; - - /** * The virtual IO structure for memory file reading. */ SF_VIRTUAL_IO m_vio; diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h index d4788ae9e86..7e7b24721eb 100644 --- a/intern/ghost/GHOST_C-api.h +++ b/intern/ghost/GHOST_C-api.h @@ -162,6 +162,8 @@ extern void GHOST_GetMainDisplayDimensions(GHOST_SystemHandle systemhandle, * @param height The height the window. * @param state The state of the window when opened. * @param type The type of drawing context installed in this window. + * @param stereoVisual Stereo visual for quad buffered stereo. + * @param numOfAASamples Number of samples used for AA (zero if no AA) * @return A handle to the new window ( == NULL if creation failed). */ extern GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle, @@ -172,7 +174,8 @@ extern GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle, GHOST_TUns32 height, GHOST_TWindowState state, GHOST_TDrawingContextType type, - const int stereoVisual); + const int stereoVisual, + const GHOST_TUns16 numOfAASamples); /** * Returns the window user data. diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h index 305caa70ae4..d1449aaef59 100644 --- a/intern/ghost/GHOST_ISystem.h +++ b/intern/ghost/GHOST_ISystem.h @@ -216,14 +216,15 @@ public: * Create a new window. * The new window is added to the list of windows managed. * Never explicitly delete the window, use disposeWindow() instead. - * @param title The name of the window (displayed in the title bar of the window if the OS supports it). - * @param left The coordinate of the left edge of the window. - * @param top The coordinate of the top edge of the window. - * @param width The width the window. - * @param height The height the window. - * @param state The state of the window when opened. - * @param type The type of drawing context installed in this window. + * @param title The name of the window (displayed in the title bar of the window if the OS supports it). + * @param left The coordinate of the left edge of the window. + * @param top The coordinate of the top edge of the window. + * @param width The width the window. + * @param height The height the window. + * @param state The state of the window when opened. + * @param type The type of drawing context installed in this window. * @param stereoVisual Create a stereo visual for quad buffered stereo. + * @param numOfAASamples Number of samples used for AA (zero if no AA) * @param parentWindow Parent (embedder) window * @return The new window (or 0 if creation failed). */ @@ -231,7 +232,8 @@ public: const STR_String& title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, GHOST_TUns32 height, GHOST_TWindowState state, GHOST_TDrawingContextType type, - const bool stereoVisual, + const bool stereoVisual = false, + const GHOST_TUns16 numOfAASamples = 0, const GHOST_TEmbedderWindowID parentWindow = 0) = 0; /** diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp index 556176809f4..be726282d80 100644 --- a/intern/ghost/intern/GHOST_C-api.cpp +++ b/intern/ghost/intern/GHOST_C-api.cpp @@ -140,7 +140,8 @@ GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle, GHOST_TUns32 height, GHOST_TWindowState state, GHOST_TDrawingContextType type, - const int stereoVisual) + const int stereoVisual, + const GHOST_TUns16 numOfAASamples) { GHOST_ISystem* system = (GHOST_ISystem*) systemhandle; bool bstereoVisual; @@ -151,7 +152,7 @@ GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle, bstereoVisual = false; return (GHOST_WindowHandle) system->createWindow(title, left, top, width, height, - state, type, bstereoVisual); + state, type, bstereoVisual, numOfAASamples); } GHOST_TUserDataPtr GHOST_GetWindowUserData(GHOST_WindowHandle windowhandle) diff --git a/intern/ghost/intern/GHOST_SystemCarbon.cpp b/intern/ghost/intern/GHOST_SystemCarbon.cpp index 57d6f6c06cc..3813a5ee450 100644 --- a/intern/ghost/intern/GHOST_SystemCarbon.cpp +++ b/intern/ghost/intern/GHOST_SystemCarbon.cpp @@ -402,6 +402,7 @@ GHOST_IWindow* GHOST_SystemCarbon::createWindow( GHOST_TWindowState state, GHOST_TDrawingContextType type, bool stereoVisual, + const GHOST_TUns16 numOfAASamples, const GHOST_TEmbedderWindowID parentWindow ) { diff --git a/intern/ghost/intern/GHOST_SystemCarbon.h b/intern/ghost/intern/GHOST_SystemCarbon.h index 5b3b786a5ac..7ebbbd8e97b 100644 --- a/intern/ghost/intern/GHOST_SystemCarbon.h +++ b/intern/ghost/intern/GHOST_SystemCarbon.h @@ -115,6 +115,7 @@ public: GHOST_TWindowState state, GHOST_TDrawingContextType type, const bool stereoVisual, + const GHOST_TUns16 numOfAASamples = 0, const GHOST_TEmbedderWindowID parentWindow = 0 ); diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h index 81eb8978588..5b78f9b8fa3 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.h +++ b/intern/ghost/intern/GHOST_SystemCocoa.h @@ -93,13 +93,15 @@ public: * Create a new window. * The new window is added to the list of windows managed. * Never explicitly delete the window, use disposeWindow() instead. - * @param title The name of the window (displayed in the title bar of the window if the OS supports it). - * @param left The coordinate of the left edge of the window. - * @param top The coordinate of the top edge of the window. - * @param width The width the window. - * @param height The height the window. - * @param state The state of the window when opened. - * @param type The type of drawing context installed in this window. + * @param title The name of the window (displayed in the title bar of the window if the OS supports it). + * @param left The coordinate of the left edge of the window. + * @param top The coordinate of the top edge of the window. + * @param width The width the window. + * @param height The height the window. + * @param state The state of the window when opened. + * @param type The type of drawing context installed in this window. + * @param stereoVisual Stereo visual for quad buffered stereo. + * @param numOfAASamples Number of samples used for AA (zero if no AA) * @param parentWindow Parent (embedder) window * @return The new window (or 0 if creation failed). */ @@ -111,7 +113,8 @@ public: GHOST_TUns32 height, GHOST_TWindowState state, GHOST_TDrawingContextType type, - const bool stereoVisual, + const bool stereoVisual = false, + const GHOST_TUns16 numOfAASamples = 0, const GHOST_TEmbedderWindowID parentWindow = 0 ); diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index 71465822bee..1ba20315512 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -374,6 +374,25 @@ static GHOST_TKey convertKey(int rawCode, unichar recvChar) } +#pragma mark defines for 10.6 api not documented in 10.5 +#ifndef MAC_OS_X_VERSION_10_6 + +@interface NSEvent(SnowLeopardEvents) +/* modifier keys currently down. This returns the state of devices combined + with synthesized events at the moment, independent of which events + have been delivered via the event stream. */ +#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 ++ (unsigned int)modifierFlags; //NSUInteger is defined only from 10.5 +#else ++ (NSUInteger)modifierFlags; +#endif +@end + +#endif + + +#pragma mark Utility functions + #define FIRSTFILEBUFLG 512 static bool g_hasFirstFile = false; static char g_firstFileBuf[512]; @@ -638,6 +657,7 @@ GHOST_IWindow* GHOST_SystemCocoa::createWindow( GHOST_TWindowState state, GHOST_TDrawingContextType type, bool stereoVisual, + const GHOST_TUns16 numOfAASamples, const GHOST_TEmbedderWindowID parentWindow ) { @@ -653,7 +673,7 @@ GHOST_IWindow* GHOST_SystemCocoa::createWindow( left = left > contentRect.origin.x ? left : contentRect.origin.x; top = top > contentRect.origin.y ? top : contentRect.origin.y; - window = new GHOST_WindowCocoa (this, title, left, top, width, height, state, type); + window = new GHOST_WindowCocoa (this, title, left, top, width, height, state, type, stereoVisual, numOfAASamples); if (window) { if (window->getValid()) { @@ -883,11 +903,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleApplicationBecomeActiveEvent() #else //If build against an older SDK, check if running on 10.6 to use the correct function if ([NSEvent respondsToSelector:@selector(modifierFlags)]) { -#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 - modifiers = (unsigned int)[NSEvent modifierFlags]; -#else - modifiers = (NSUInteger)[NSEvent modifierFlags]; -#endif + modifiers = [NSEvent modifierFlags]; } else { //TODO: need to find a better workaround for the missing cocoa "getModifierFlag" function in 10.4/10.5 diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 15914a5bf43..d7d657fb496 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -190,7 +190,7 @@ GHOST_IWindow* GHOST_SystemWin32::createWindow( const STR_String& title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, GHOST_TUns32 height, GHOST_TWindowState state, GHOST_TDrawingContextType type, - bool stereoVisual, const GHOST_TEmbedderWindowID parentWindow ) + bool stereoVisual, const GHOST_TUns16 numOfAASamples, const GHOST_TEmbedderWindowID parentWindow ) { GHOST_Window* window = 0; window = new GHOST_WindowWin32 (this, title, left, top, width, height, state, type, stereoVisual); diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h index 517f7ddbeea..65d6a57ede3 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.h +++ b/intern/ghost/intern/GHOST_SystemWin32.h @@ -110,6 +110,8 @@ public: * @param height The height the window. * @param state The state of the window when opened. * @param type The type of drawing context installed in this window. + * @param stereoVisual Stereo visual for quad buffered stereo. + * @param numOfAASamples Number of samples used for AA (zero if no AA) * @param parentWindow Parent (embedder) window * @return The new window (or 0 if creation failed). */ @@ -117,7 +119,9 @@ public: const STR_String& title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, GHOST_TUns32 height, GHOST_TWindowState state, GHOST_TDrawingContextType type, - const bool stereoVisual, const GHOST_TEmbedderWindowID parentWindow = 0 ); + const bool stereoVisual = false, + const GHOST_TUns16 numOfAASamples = 0, + const GHOST_TEmbedderWindowID parentWindow = 0 ); /*************************************************************************************** ** Event management functionality diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index ad8647d2246..3ee3c1a29f3 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -228,6 +228,8 @@ getMainDisplayDimensions( * @param height The height the window. * @param state The state of the window when opened. * @param type The type of drawing context installed in this window. + * @param stereoVisual Stereo visual for quad buffered stereo. + * @param numOfAASamples Number of samples used for AA (zero if no AA) * @param parentWindow Parent (embedder) window * @return The new window (or 0 if creation failed). */ @@ -242,6 +244,7 @@ createWindow( GHOST_TWindowState state, GHOST_TDrawingContextType type, bool stereoVisual, + const GHOST_TUns16 numOfAASamples, const GHOST_TEmbedderWindowID parentWindow ){ GHOST_WindowX11 * window = 0; diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h index d76c3991beb..361db783102 100644 --- a/intern/ghost/intern/GHOST_SystemX11.h +++ b/intern/ghost/intern/GHOST_SystemX11.h @@ -127,6 +127,7 @@ public: GHOST_TWindowState state, GHOST_TDrawingContextType type, const bool stereoVisual, + const GHOST_TUns16 numOfAASamples = 0, const GHOST_TEmbedderWindowID parentWindow = 0 ); diff --git a/intern/ghost/intern/GHOST_Window.cpp b/intern/ghost/intern/GHOST_Window.cpp index 14a255e2e5e..939a911dfac 100644 --- a/intern/ghost/intern/GHOST_Window.cpp +++ b/intern/ghost/intern/GHOST_Window.cpp @@ -44,13 +44,15 @@ GHOST_Window::GHOST_Window( GHOST_TInt32 /*left*/, GHOST_TInt32 /*top*/, GHOST_TUns32 width, GHOST_TUns32 height, GHOST_TWindowState state, GHOST_TDrawingContextType type, - const bool stereoVisual) + const bool stereoVisual, + const GHOST_TUns16 numOfAASamples) : m_drawingContextType(type), m_cursorVisible(true), m_cursorGrab(GHOST_kGrabDisable), m_cursorShape(GHOST_kStandardCursorDefault), - m_stereoVisual(stereoVisual) + m_stereoVisual(stereoVisual), + m_numOfAASamples(numOfAASamples) { m_isUnsavedChanges = false; m_canAcceptDragOperation = false; diff --git a/intern/ghost/intern/GHOST_Window.h b/intern/ghost/intern/GHOST_Window.h index 1b5681dc41c..8aab9125130 100644 --- a/intern/ghost/intern/GHOST_Window.h +++ b/intern/ghost/intern/GHOST_Window.h @@ -75,14 +75,15 @@ public: * Constructor. * Creates a new window and opens it. * To check if the window was created properly, use the getValid() method. - * @param title The text shown in the title bar of the window. - * @param left The coordinate of the left edge of the window. - * @param top The coordinate of the top edge of the window. - * @param width The width the window. - * @param heigh The height the window. - * @param state The state the window is initially opened with. - * @param type The type of drawing context installed in this window. - * @param stereoVisual Stereo visual for quad buffered stereo. + * @param title The text shown in the title bar of the window. + * @param left The coordinate of the left edge of the window. + * @param top The coordinate of the top edge of the window. + * @param width The width the window. + * @param heigh The height the window. + * @param state The state the window is initially opened with. + * @param type The type of drawing context installed in this window. + * @param stereoVisual Stereo visual for quad buffered stereo. + * @param numOfAASamples Number of samples used for AA (zero if no AA) */ GHOST_Window( const STR_String& title, @@ -92,7 +93,8 @@ public: GHOST_TUns32 height, GHOST_TWindowState state, GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone, - const bool stereoVisual = false); + const bool stereoVisual = false, + const GHOST_TUns16 numOfAASamples = 0); /** * @section Interface inherited from GHOST_IWindow left for derived class @@ -319,6 +321,9 @@ protected: * the graphics h/w */ bool m_stereoVisual; + + /** Number of samples used in anti-aliasing, set to 0 if no AA **/ + GHOST_TUns16 m_numOfAASamples; /** Full-screen width */ GHOST_TUns32 m_fullScreenWidth; diff --git a/intern/ghost/intern/GHOST_WindowCarbon.cpp b/intern/ghost/intern/GHOST_WindowCarbon.cpp index 362e949a0a4..3e53a052146 100644 --- a/intern/ghost/intern/GHOST_WindowCarbon.cpp +++ b/intern/ghost/intern/GHOST_WindowCarbon.cpp @@ -98,7 +98,8 @@ GHOST_WindowCarbon::GHOST_WindowCarbon( GHOST_TUns32 height, GHOST_TWindowState state, GHOST_TDrawingContextType type, - const bool stereoVisual + const bool stereoVisual, + const GHOST_TUns16 numOfAASamples ) : GHOST_Window(title, left, top, width, height, state, GHOST_kDrawingContextTypeNone), m_windowRef(0), diff --git a/intern/ghost/intern/GHOST_WindowCarbon.h b/intern/ghost/intern/GHOST_WindowCarbon.h index dd00add7fb1..b91e5410ddd 100644 --- a/intern/ghost/intern/GHOST_WindowCarbon.h +++ b/intern/ghost/intern/GHOST_WindowCarbon.h @@ -80,7 +80,8 @@ public: GHOST_TUns32 height, GHOST_TWindowState state, GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone, - const bool stereoVisual = false + const bool stereoVisual = false, + const GHOST_TUns16 numOfAASamples = 0 ); /** diff --git a/intern/ghost/intern/GHOST_WindowCocoa.h b/intern/ghost/intern/GHOST_WindowCocoa.h index e59d9c17333..b54634b08d7 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.h +++ b/intern/ghost/intern/GHOST_WindowCocoa.h @@ -61,15 +61,16 @@ public: * Constructor. * Creates a new window and opens it. * To check if the window was created properly, use the getValid() method. - * @param systemCocoa The associated system class to forward events to - * @param title The text shown in the title bar of the window. - * @param left The coordinate of the left edge of the window. - * @param top The coordinate of the top edge of the window. - * @param width The width the window. - * @param height The height the window. - * @param state The state the window is initially opened with. - * @param type The type of drawing context installed in this window. - * @param stereoVisual Stereo visual for quad buffered stereo. + * @param systemCocoa The associated system class to forward events to + * @param title The text shown in the title bar of the window. + * @param left The coordinate of the left edge of the window. + * @param top The coordinate of the top edge of the window. + * @param width The width the window. + * @param height The height the window. + * @param state The state the window is initially opened with. + * @param type The type of drawing context installed in this window. + * @param stereoVisual Stereo visual for quad buffered stereo. + * @param numOfAASamples Number of samples used for AA (zero if no AA) */ GHOST_WindowCocoa( GHOST_SystemCocoa *systemCocoa, @@ -80,7 +81,8 @@ public: GHOST_TUns32 height, GHOST_TWindowState state, GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone, - const bool stereoVisual = false + const bool stereoVisual = false, + const GHOST_TUns16 numOfAASamples = 0 ); /** diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm index 8c9f8a7647d..66c6d75b6d7 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.mm +++ b/intern/ghost/intern/GHOST_WindowCocoa.mm @@ -34,9 +34,11 @@ #include <Carbon/Carbon.h> #endif +#include <OpenGL/gl.h> /***** Multithreaded opengl code : uncomment for enabling #include <OpenGL/OpenGL.h> */ + #include "GHOST_WindowCocoa.h" #include "GHOST_SystemCocoa.h" @@ -277,14 +279,15 @@ GHOST_WindowCocoa::GHOST_WindowCocoa( GHOST_TUns32 height, GHOST_TWindowState state, GHOST_TDrawingContextType type, - const bool stereoVisual + const bool stereoVisual, const GHOST_TUns16 numOfAASamples ) : - GHOST_Window(title, left, top, width, height, state, GHOST_kDrawingContextTypeNone, stereoVisual), + GHOST_Window(title, left, top, width, height, state, GHOST_kDrawingContextTypeNone, stereoVisual, numOfAASamples), m_customCursor(0) { NSOpenGLPixelFormatAttribute pixelFormatAttrsWindow[40]; + NSOpenGLPixelFormat *pixelFormat = nil; int i; - + m_systemCocoa = systemCocoa; m_fullScreen = false; @@ -329,13 +332,52 @@ GHOST_WindowCocoa::GHOST_WindowCocoa( if (stereoVisual) pixelFormatAttrsWindow[i++] = NSOpenGLPFAStereo; + if (numOfAASamples>0) { + // Multisample anti-aliasing + pixelFormatAttrsWindow[i++] = NSOpenGLPFAMultisample; + + pixelFormatAttrsWindow[i++] = NSOpenGLPFASampleBuffers; + pixelFormatAttrsWindow[i++] = (NSOpenGLPixelFormatAttribute) 1; + + pixelFormatAttrsWindow[i++] = NSOpenGLPFASamples; + pixelFormatAttrsWindow[i++] = (NSOpenGLPixelFormatAttribute) numOfAASamples; + + pixelFormatAttrsWindow[i++] = NSOpenGLPFANoRecovery; + } + pixelFormatAttrsWindow[i] = (NSOpenGLPixelFormatAttribute) 0; - - //Creates the OpenGL View inside the window - NSOpenGLPixelFormat *pixelFormat = - [[NSOpenGLPixelFormat alloc] initWithAttributes:pixelFormatAttrsWindow]; + pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:pixelFormatAttrsWindow]; + + + //Fall back to no multisampling if Antialiasing init failed + if (pixelFormat == nil) { + i=0; + pixelFormatAttrsWindow[i++] = NSOpenGLPFADoubleBuffer; + pixelFormatAttrsWindow[i++] = NSOpenGLPFAAccelerated; + //pixelFormatAttrsWindow[i++] = NSOpenGLPFAAllowOfflineRenderers,; // Removed to allow 10.4 builds, and 2 GPUs rendering is not used anyway + + pixelFormatAttrsWindow[i++] = NSOpenGLPFADepthSize; + pixelFormatAttrsWindow[i++] = (NSOpenGLPixelFormatAttribute) 32; + + if (stereoVisual) pixelFormatAttrsWindow[i++] = NSOpenGLPFAStereo; + + pixelFormatAttrsWindow[i] = (NSOpenGLPixelFormatAttribute) 0; + + pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:pixelFormatAttrsWindow]; + + } + if (numOfAASamples>0) { //Set m_numOfAASamples to the actual value + GLint gli; + [pixelFormat getValues:&gli forAttribute:NSOpenGLPFASamples forVirtualScreen:0]; + if (m_numOfAASamples != (GHOST_TUns16)gli) { + m_numOfAASamples = (GHOST_TUns16)gli; + printf("GHOST_Window could be created with anti-aliasing of only %i samples\n",m_numOfAASamples); + } + } + + //Creates the OpenGL View inside the window m_openGLView = [[CocoaOpenGLView alloc] initWithFrame:rect pixelFormat:pixelFormat]; @@ -398,14 +440,7 @@ GHOST_WindowCocoa::~GHOST_WindowCocoa() bool GHOST_WindowCocoa::getValid() const { - bool valid; - if (!m_fullScreen) { - valid = (m_window != 0); //&& ::IsValidWindowPtr(m_windowRef); - } - else { - valid = true; - } - return valid; + return (m_window != 0); } @@ -842,6 +877,9 @@ GHOST_TSuccess GHOST_WindowCocoa::activateDrawingContext() if (m_openGLContext != nil) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; [m_openGLContext makeCurrentContext]; + + // Disable AA by default + if (m_numOfAASamples > 0) glDisable(GL_MULTISAMPLE_ARB); [pool drain]; return GHOST_kSuccess; } diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp index ea14f1dfc1b..e276f216fb7 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.cpp +++ b/intern/ghost/intern/GHOST_WindowWin32.cpp @@ -105,10 +105,11 @@ GHOST_WindowWin32::GHOST_WindowWin32( GHOST_TUns32 height, GHOST_TWindowState state, GHOST_TDrawingContextType type, - const bool stereoVisual) + const bool stereoVisual, + const GHOST_TUns16 numOfAASamples) : GHOST_Window(title, left, top, width, height, state, GHOST_kDrawingContextTypeNone, - stereoVisual), + stereoVisual,numOfAASamples), m_system(system), m_hDC(0), m_hGlRc(0), diff --git a/intern/ghost/intern/GHOST_WindowWin32.h b/intern/ghost/intern/GHOST_WindowWin32.h index 07a31911a5e..954546f3d82 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.h +++ b/intern/ghost/intern/GHOST_WindowWin32.h @@ -75,6 +75,7 @@ public: * @param state The state the window is initially opened with. * @param type The type of drawing context installed in this window. * @param stereoVisual Stereo visual for quad buffered stereo. + * @param numOfAASamples Number of samples used for AA (zero if no AA) */ GHOST_WindowWin32( GHOST_SystemWin32 * system, @@ -85,7 +86,8 @@ public: GHOST_TUns32 height, GHOST_TWindowState state, GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone, - const bool stereoVisual = false + const bool stereoVisual = false, + const GHOST_TUns16 numOfAASamples = 0 ); /** diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp index d9c2654f446..4afaa09b3f1 100644 --- a/intern/ghost/intern/GHOST_WindowX11.cpp +++ b/intern/ghost/intern/GHOST_WindowX11.cpp @@ -153,9 +153,10 @@ GHOST_WindowX11( GHOST_TWindowState state, const GHOST_TEmbedderWindowID parentWindow, GHOST_TDrawingContextType type, - const bool stereoVisual + const bool stereoVisual, + const GHOST_TUns16 numOfAASamples ) : - GHOST_Window(title,left,top,width,height,state,type,stereoVisual), + GHOST_Window(title,left,top,width,height,state,type,stereoVisual,numOfAASamples), m_context(NULL), m_display(display), m_system (system), @@ -170,8 +171,14 @@ GHOST_WindowX11( int attributes[40], i = 0; Atom atoms[2]; - int natom; - + int natom; + int glxVersionMajor, glxVersionMinor; // As in GLX major.minor + + if (!glXQueryVersion(m_display, &glxVersionMajor, &glxVersionMinor)) { + printf("%s:%d: X11 glXQueryVersion() failed, verify working openGL system!\n", __FILE__, __LINE__); + return; + } + if(m_stereoVisual) attributes[i++] = GLX_STEREO; @@ -181,13 +188,18 @@ GHOST_WindowX11( attributes[i++] = GLX_BLUE_SIZE; attributes[i++] = 1; attributes[i++] = GLX_GREEN_SIZE; attributes[i++] = 1; attributes[i++] = GLX_DEPTH_SIZE; attributes[i++] = 1; + /* GLX 1.4+, multi-sample */ + if(m_numOfAASamples && (glxVersionMajor >= 1) && (glxVersionMinor >= 4)) { + attributes[i++] = GLX_SAMPLE_BUFFERS; attributes[i++] = 1; + attributes[i++] = GLX_SAMPLES; attributes[i++] = m_numOfAASamples; + } attributes[i] = None; - + m_visual = glXChooseVisual(m_display, DefaultScreen(m_display), attributes); if (m_visual == NULL) { // barf : no visual meeting these requirements could be found. - printf("%s:%d: X11 glxChooseVisual() failed for OpenGL, verify working openGL system!\n", __FILE__, __LINE__); + printf("%s:%d: X11 glXChooseVisual() failed, verify working openGL system!\n", __FILE__, __LINE__); return; } @@ -1226,10 +1238,7 @@ GHOST_WindowX11:: if(m_xtablet.EraserDevice) XCloseDevice(m_display, m_xtablet.EraserDevice); - if (m_context) { - if (m_context == s_firstContext) { - s_firstContext = NULL; - } + if (m_context != s_firstContext) { glXDestroyContext(m_display, m_context); } diff --git a/intern/ghost/intern/GHOST_WindowX11.h b/intern/ghost/intern/GHOST_WindowX11.h index 0dba1776553..9a299e16eb4 100644 --- a/intern/ghost/intern/GHOST_WindowX11.h +++ b/intern/ghost/intern/GHOST_WindowX11.h @@ -67,6 +67,7 @@ public: * @param parentWindow Parent (embedder) window * @param type The type of drawing context installed in this window. * @param stereoVisual Stereo visual for quad buffered stereo. + * @param numOfAASamples Number of samples used for AA (zero if no AA) */ GHOST_WindowX11( GHOST_SystemX11 *system, @@ -79,7 +80,8 @@ public: GHOST_TWindowState state, const GHOST_TEmbedderWindowID parentWindow, GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone, - const bool stereoVisual = false + const bool stereoVisual = false, + const GHOST_TUns16 numOfAASamples = 0 ); bool diff --git a/intern/ghost/intern/Makefile b/intern/ghost/intern/Makefile index a6392662c30..d9f2bfe7cde 100644 --- a/intern/ghost/intern/Makefile +++ b/intern/ghost/intern/Makefile @@ -42,7 +42,7 @@ CCSRCS += GHOST_NDOFManager.cpp ifeq ($(OS),$(findstring $(OS), "darwin")) ifeq ($(WITH_COCOA), true) - OCSRCS += $(wildcard *Cocoa.mm) + OCCSRCS += $(wildcard *Cocoa.mm) CPPFLAGS += -DGHOST_COCOA ifeq ($(WITH_QUICKTIME), true) CPPFLAGS += -DWITH_QUICKTIME diff --git a/projectfiles_vc9/blender/editors/ED_editors.vcproj b/projectfiles_vc9/blender/editors/ED_editors.vcproj index 0602112106d..d8e8f5a9eca 100644 --- a/projectfiles_vc9/blender/editors/ED_editors.vcproj +++ b/projectfiles_vc9/blender/editors/ED_editors.vcproj @@ -1072,6 +1072,10 @@ >
</File>
<File
+ RelativePath="..\..\..\source\blender\editors\object\object_bake.c"
+ >
+ </File>
+ <File
RelativePath="..\..\..\source\blender\editors\object\object_constraint.c"
>
</File>
diff --git a/release/scripts/io/engine_render_pov.py b/release/scripts/io/engine_render_pov.py index 3ad75f41709..5275574d903 100644 --- a/release/scripts/io/engine_render_pov.py +++ b/release/scripts/io/engine_render_pov.py @@ -537,7 +537,7 @@ def write_pov(filename, scene=None, info_callback=None): writeMatrix(matrix) file.write('}\n') - bpy.data.remove_mesh(me) + bpy.data.meshes.remove(me) def exportWorld(world): if not world: diff --git a/release/scripts/io/export_3ds.py b/release/scripts/io/export_3ds.py index 23fd44acc3f..979c53c581d 100644 --- a/release/scripts/io/export_3ds.py +++ b/release/scripts/io/export_3ds.py @@ -1061,7 +1061,7 @@ def save_3ds(filename, context): kfdata.add_subchunk(make_kf_obj_node(ob, name_to_id)) ''' # if not blender_mesh.users: - bpy.data.remove_mesh(blender_mesh) + bpy.data.meshes.remove(blender_mesh) # blender_mesh.verts = None i+=i diff --git a/release/scripts/io/export_fbx.py b/release/scripts/io/export_fbx.py index 6407f9b6e49..a7e126446bd 100644 --- a/release/scripts/io/export_fbx.py +++ b/release/scripts/io/export_fbx.py @@ -651,7 +651,7 @@ def write(filename, batch_objects = None, \ }''' % (curtime)) file.write('\nCreationTime: "%.4i-%.2i-%.2i %.2i:%.2i:%.2i:000"' % curtime) - file.write('\nCreator: "Blender3D version %s"' % bpy.version_string) + file.write('\nCreator: "Blender3D version %s"' % bpy.app.version_string) pose_items = [] # list of (fbxName, matrix) to write pose data for, easier to collect allong the way @@ -2989,7 +2989,7 @@ Takes: {''') # Clear mesh data Only when writing with modifiers applied for me in meshes_to_clear: - bpy.data.remove_mesh(me) + bpy.data.meshes.remove(me) # me.verts = None # --------------------------- Footer @@ -3391,8 +3391,7 @@ class ExportFBX(bpy.types.Operator): def poll(self, context): - print("Poll") - return context.active_object != None + return context.active_object def execute(self, context): if not self.properties.path: diff --git a/release/scripts/io/export_obj.py b/release/scripts/io/export_obj.py index 6135375d185..8d1a9a9aced 100644 --- a/release/scripts/io/export_obj.py +++ b/release/scripts/io/export_obj.py @@ -361,7 +361,7 @@ def write(filename, objects, scene, file = open(filename, "w") # Write Header - file.write('# Blender3D v%s OBJ File: %s\n' % (bpy.version_string, bpy.data.filename.split('/')[-1].split('\\')[-1] )) + file.write('# Blender3D v%s OBJ File: %s\n' % (bpy.app.version_string, bpy.data.filename.split('/')[-1].split('\\')[-1] )) file.write('# www.blender3d.org\n') # Tell the obj file what material file to use. @@ -447,7 +447,7 @@ def write(filename, objects, scene, break if has_quads: - newob = bpy.data.add_object('MESH', 'temp_object') + newob = bpy.data.objects.new('temp_object', 'MESH') newob.data = me # if we forget to set Object.data - crash scene.objects.link(newob) @@ -468,7 +468,7 @@ def write(filename, objects, scene, if not (len(face_index_pairs)+len(edges)+len(me.verts)): # Make sure there is somthing to write # clean up - bpy.data.remove_mesh(me) + bpy.data.meshes.remove(me) continue # dont bother with this mesh. @@ -510,24 +510,12 @@ def write(filename, objects, scene, # XXX update tface = me.active_uv_texture.data - # exception only raised if Python 2.3 or lower... - try: - face_index_pairs.sort(key = lambda a: (a[0].material_index, tface[a[1]].image, a[0].smooth)) - except: - face_index_pairs.sort(lambda a,b: cmp((a[0].material_index, tface[a[1]].image, a[0].smooth), - (b[0].material_index, tface[b[1]].image, b[0].smooth))) + face_index_pairs.sort(key=lambda a: (a[0].material_index, tface[a[1]].image, a[0].smooth)) elif len(materials) > 1: - try: - face_index_pairs.sort(key = lambda a: (a[0].material_index, a[0].smooth)) - except: - face_index_pairs.sort(lambda a,b: cmp((a[0].material_index, a[0].smooth), - (b[0].material_index, b[0].smooth))) + face_index_pairs.sort(key = lambda a: (a[0].material_index, a[0].smooth)) else: # no materials - try: - face_index_pairs.sort(key = lambda a: a[0].smooth) - except: - face_index_pairs.sort(lambda a,b: cmp(a[0].smooth, b[0].smooth)) + face_index_pairs.sort(key = lambda a: a[0].smooth) # if EXPORT_KEEP_VERT_ORDER: # pass # elif faceuv: @@ -609,7 +597,8 @@ def write(filename, objects, scene, if EXPORT_NORMALS: for f in faces: if f.smooth: - for v in f: + for vIdx in f.verts: + v = me.verts[vIdx] noKey = veckey3d(v.normal) if noKey not in globalNormals: globalNormals[noKey] = totno @@ -779,7 +768,7 @@ def write(filename, objects, scene, totuvco += uv_unique_count # clean up - bpy.data.remove_mesh(me) + bpy.data.meshes.remove(me) if ob_main.dupli_type != 'NONE': ob_main.free_dupli_list() diff --git a/release/scripts/io/export_ply.py b/release/scripts/io/export_ply.py index 3c9e1f86ee2..58f65e928cf 100644 --- a/release/scripts/io/export_ply.py +++ b/release/scripts/io/export_ply.py @@ -205,7 +205,7 @@ def write(filename, scene, ob, \ file.write('ply\n') file.write('format ascii 1.0\n') - 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('comment Created by Blender3D %s - www.blender.org, source file: %s\n' % (bpy.app.version_string, bpy.data.filename.split('/')[-1].split('\\')[-1])) file.write('element vertex %d\n' % len(ply_verts)) @@ -254,7 +254,7 @@ def write(filename, scene, ob, \ print("writing", filename, "done") if EXPORT_APPLY_MODIFIERS: - bpy.data.remove_mesh(mesh) + bpy.data.meshes.remove(mesh) # XXX """ diff --git a/release/scripts/io/export_x3d.py b/release/scripts/io/export_x3d.py index 4c3540a458e..6b94a0cc91a 100644 --- a/release/scripts/io/export_x3d.py +++ b/release/scripts/io/export_x3d.py @@ -879,7 +879,7 @@ class x3d_class: # free mesh created with create_mesh() if me != ob.data: - bpy.data.remove_mesh(me) + bpy.data.meshes.remove(me) elif objType == "LAMP": # elif objType == "Lamp": diff --git a/release/scripts/io/import_scene_3ds.py b/release/scripts/io/import_scene_3ds.py index 4420f6ef6f0..5f55b169d27 100644 --- a/release/scripts/io/import_scene_3ds.py +++ b/release/scripts/io/import_scene_3ds.py @@ -410,8 +410,7 @@ def process_next_chunk(file, previous_chunk, importedObjects, IMAGE_SEARCH): myVertMapping = dict( [ (ii, i) for i, ii in enumerate(vertsToUse) ] ) tempName= '%s_%s' % (contextObName, matName) # matName may be None. - bmesh = bpy.data.add_mesh(tempName) -# bmesh = bpy.data.meshes.new(tempName) + bmesh = bpy.data.meshes.new(tempName) if matName == None: img = None @@ -465,7 +464,7 @@ def process_next_chunk(file, previous_chunk, importedObjects, IMAGE_SEARCH): # targetFace.image = img # bmesh.transform(contextMatrix) - ob = bpy.data.add_object("MESH", tempName) + ob = bpy.data.objects.new(tempName, 'MESH') ob.data = bmesh SCN.objects.link(ob) # ob = SCN_OBJECTS.new(bmesh, tempName) @@ -766,8 +765,8 @@ def process_next_chunk(file, previous_chunk, importedObjects, IMAGE_SEARCH): x,y,z = struct.unpack('<3f', temp_data) new_chunk.bytes_read += STRUCT_SIZE_3FLOAT - ob = bpy.data.add_object("LAMP", "Lamp") - ob.data = bpy.data.add_lamp("Lamp") + ob = bpy.data.objects.new("Lamp", 'LAMP') + ob.data = bpy.data.lamps.new("Lamp") SCN.objects.link(ob) contextLamp[1]= ob.data diff --git a/release/scripts/io/import_scene_obj.py b/release/scripts/io/import_scene_obj.py index 228084561b8..001ed923699 100644 --- a/release/scripts/io/import_scene_obj.py +++ b/release/scripts/io/import_scene_obj.py @@ -712,8 +712,7 @@ def create_mesh(scn, new_objects, has_ngons, CREATE_FGONS, CREATE_EDGES, verts_l for name, index in list(material_mapping.items()): materials[index]= unique_materials[name] - me= bpy.data.add_mesh(dataname) -# me= bpy.data.meshes.new(dataname) + me= bpy.data.meshes.new(dataname) # make sure the list isnt too big for material in materials[0:16]: @@ -864,7 +863,7 @@ def create_mesh(scn, new_objects, has_ngons, CREATE_FGONS, CREATE_EDGES, verts_l me.update() # me.calcNormals() - ob= bpy.data.add_object("MESH", "Mesh") + ob= bpy.data.objects.new("Mesh", 'MESH') ob.data= me scn.objects.link(ob) # ob= scn.objects.new(me) @@ -886,12 +885,12 @@ def create_nurbs(scn, context_nurbs, vert_loc, new_objects): Add nurbs object to blender, only support one type at the moment ''' deg = context_nurbs.get('deg', (3,)) - curv_range = context_nurbs.get('curv_range', None) + curv_range = context_nurbs.get('curv_range') curv_idx = context_nurbs.get('curv_idx', []) parm_u = context_nurbs.get('parm_u', []) parm_v = context_nurbs.get('parm_v', []) name = context_nurbs.get('name', 'ObjNurb') - cstype = context_nurbs.get('cstype', None) + cstype = context_nurbs.get('cstype') if cstype == None: print('\tWarning, cstype not found') diff --git a/release/scripts/io/netrender/__init__.py b/release/scripts/io/netrender/__init__.py index 77ab95535aa..b182ef7f452 100644 --- a/release/scripts/io/netrender/__init__.py +++ b/release/scripts/io/netrender/__init__.py @@ -32,3 +32,6 @@ jobs = [] slaves = [] blacklist = [] +init_file = "" +init_data = True +init_address = True
\ No newline at end of file diff --git a/release/scripts/io/netrender/balancing.py b/release/scripts/io/netrender/balancing.py index e09b19f956c..344bacde90a 100644 --- a/release/scripts/io/netrender/balancing.py +++ b/release/scripts/io/netrender/balancing.py @@ -22,14 +22,23 @@ from netrender.utils import * import netrender.model class RatingRule: + def __init__(self): + self.enabled = True + def rate(self, job): return 0 class ExclusionRule: + def __init__(self): + self.enabled = True + def test(self, job): return False class PriorityRule: + def __init__(self): + self.enabled = True + def test(self, job): return False @@ -39,6 +48,19 @@ class Balancer: self.priorities = [] self.exceptions = [] + def ruleByID(self, rule_id): + for rule in self.rules: + if id(rule) == rule_id: + return rule + for rule in self.priorities: + if id(rule) == rule_id: + return rule + for rule in self.exceptions: + if id(rule) == rule_id: + return rule + + return None + def addRule(self, rule): self.rules.append(rule) @@ -49,18 +71,18 @@ class Balancer: self.exceptions.append(exception) def applyRules(self, job): - return sum((rule.rate(job) for rule in self.rules)) + return sum((rule.rate(job) for rule in self.rules if rule.enabled)) def applyPriorities(self, job): for priority in self.priorities: - if priority.test(job): + if priority.enabled and priority.test(job): return True # priorities are first return False def applyExceptions(self, job): for exception in self.exceptions: - if exception.test(job): + if exception.enabled and exception.test(job): return True # exceptions are last return False @@ -82,18 +104,20 @@ class Balancer: class RatingUsage(RatingRule): def __str__(self): - return "Usage rating" + return "Usage per job" 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): + super().__init__() self.getJobs = get_jobs + + def __str__(self): + return "Usage per category" + 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]) @@ -102,49 +126,61 @@ class RatingUsageByCategory(RatingRule): return total_category_usage / maximum_priority class NewJobPriority(PriorityRule): + def __init__(self, limit = 1): + super().__init__() + self.limit = limit + + def setLimit(self, value): + self.limit = int(value) + 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 __init__(self, limit = 10): + super().__init__() + self.limit = limit + + def setLimit(self, value): + self.limit = int(value) + 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 class ExcludeQueuedEmptyJob(ExclusionRule): def __str__(self): - return "Exclude queued and empty jobs" + return "Exclude non queued or empty jobs" def test(self, job): return job.status != JOB_QUEUED or job.countFrames(status = QUEUED) == 0 class ExcludeSlavesLimit(ExclusionRule): + def __init__(self, count_jobs, count_slaves, limit = 0.75): + super().__init__() + self.count_jobs = count_jobs + self.count_slaves = count_slaves + self.limit = limit + + def setLimit(self, value): + self.limit = float(value) + 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 ) diff --git a/release/scripts/io/netrender/client.py b/release/scripts/io/netrender/client.py index d71d6a072ba..01130907553 100644 --- a/release/scripts/io/netrender/client.py +++ b/release/scripts/io/netrender/client.py @@ -197,11 +197,11 @@ class NetworkRenderEngine(bpy.types.RenderEngine): 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) + master.runMaster((address, netsettings.server_port), netsettings.master_broadcast, netsettings.master_clear, netsettings.path, self.update_stats, self.test_break) def render_slave(self, scene): - slave.render_slave(self, scene.network_render) + slave.render_slave(self, scene.network_render, scene.render_data.threads) def render_client(self, scene): netsettings = scene.network_render @@ -276,6 +276,6 @@ def compatible(module): except: pass del module -compatible("properties_render") +#compatible("properties_render") compatible("properties_world") compatible("properties_material") diff --git a/release/scripts/io/netrender/master.py b/release/scripts/io/netrender/master.py index a33606d19a0..5056eba750d 100644 --- a/release/scripts/io/netrender/master.py +++ b/release/scripts/io/netrender/master.py @@ -19,6 +19,7 @@ import sys, os import http, http.client, http.server, urllib, socket import subprocess, shutil, time, hashlib +import select # for select.error from netrender.utils import * import netrender.model @@ -105,6 +106,17 @@ class MRenderJob(netrender.model.RenderJob): break else: self.status = JOB_FINISHED + + def pause(self, status = None): + if self.status not in {JOB_PAUSED, JOB_QUEUED}: + return + + if status == None: + self.status = JOB_PAUSED if self.status == JOB_QUEUED else JOB_QUEUED + elif status: + self.status = JOB_QUEUED + else: + self.status = JOB_PAUSED def start(self): self.status = JOB_QUEUED @@ -163,9 +175,11 @@ class MRenderFrame(netrender.model.RenderFrame): # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- file_pattern = re.compile("/file_([a-zA-Z0-9]+)_([0-9]+)") render_pattern = re.compile("/render_([a-zA-Z0-9]+)_([0-9]+).exr") +thumb_pattern = re.compile("/thumb_([a-zA-Z0-9]+)_([0-9]+).jpg") log_pattern = re.compile("/log_([a-zA-Z0-9]+)_([0-9]+).log") reset_pattern = re.compile("/reset(all|)_([a-zA-Z0-9]+)_([0-9]+)") cancel_pattern = re.compile("/cancel_([a-zA-Z0-9]+)") +pause_pattern = re.compile("/pause_([a-zA-Z0-9]+)") edit_pattern = re.compile("/edit_([a-zA-Z0-9]+)") class RenderHandler(http.server.BaseHTTPRequestHandler): @@ -217,7 +231,7 @@ class RenderHandler(http.server.BaseHTTPRequestHandler): if match: job_id = match.groups()[0] frame_number = int(match.groups()[1]) - + job = self.server.getJobID(job_id) if job: @@ -228,13 +242,53 @@ class RenderHandler(http.server.BaseHTTPRequestHandler): self.send_head(http.client.ACCEPTED) elif frame.status == DONE: self.server.stats("", "Sending result to client") - f = open(job.save_path + "%04d" % frame_number + ".exr", 'rb') + + filename = job.save_path + "%04d" % frame_number + ".exr" + + f = open(filename, 'rb') + self.send_head(content = "image/x-exr") + shutil.copyfileobj(f, self.wfile) + f.close() + elif frame.status == ERROR: + self.send_head(http.client.PARTIAL_CONTENT) + else: + # no such frame + self.send_head(http.client.NO_CONTENT) + else: + # no such job id + self.send_head(http.client.NO_CONTENT) + else: + # invalid url + self.send_head(http.client.NO_CONTENT) + # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + elif self.path.startswith("/thumb"): + match = thumb_pattern.match(self.path) - self.send_head() + if match: + job_id = match.groups()[0] + frame_number = int(match.groups()[1]) - shutil.copyfileobj(f, self.wfile) + job = self.server.getJobID(job_id) - f.close() + if job: + frame = job[frame_number] + + if frame: + if frame.status in (QUEUED, DISPATCHED): + self.send_head(http.client.ACCEPTED) + elif frame.status == DONE: + filename = job.save_path + "%04d" % frame_number + ".exr" + + thumbname = thumbnail(filename) + + if thumbname: + f = open(thumbname, 'rb') + self.send_head(content = "image/jpeg") + shutil.copyfileobj(f, self.wfile) + f.close() + else: # thumbnail couldn't be generated + self.send_head(http.client.PARTIAL_CONTENT) + return elif frame.status == ERROR: self.send_head(http.client.PARTIAL_CONTENT) else: @@ -456,17 +510,48 @@ class RenderHandler(http.server.BaseHTTPRequestHandler): # invalid url self.send_head(http.client.NO_CONTENT) # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + elif self.path == "/balance_limit": + length = int(self.headers['content-length']) + info_map = eval(str(self.rfile.read(length), encoding='utf8')) + for rule_id, limit in info_map.items(): + try: + rule = self.server.balancer.ruleByID(rule_id) + if rule: + rule.setLimit(limit) + except: + pass # invalid type + + self.send_head() + # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + elif self.path == "/balance_enable": + length = int(self.headers['content-length']) + info_map = eval(str(self.rfile.read(length), encoding='utf8')) + for rule_id, enabled in info_map.items(): + rule = self.server.balancer.ruleByID(rule_id) + if rule: + rule.enabled = enabled + + self.send_head() + # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- elif self.path.startswith("/cancel"): match = cancel_pattern.match(self.path) if match: + length = int(self.headers['content-length']) + + if length > 0: + info_map = eval(str(self.rfile.read(length), encoding='utf8')) + clear = info_map.get("clear", False) + else: + clear = False + job_id = match.groups()[0] job = self.server.getJobID(job_id) if job: self.server.stats("", "Cancelling job") - self.server.removeJob(job) + self.server.removeJob(job, clear) self.send_head() else: # no such job id @@ -474,12 +559,46 @@ class RenderHandler(http.server.BaseHTTPRequestHandler): else: # invalid url self.send_head(http.client.NO_CONTENT) + # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + elif self.path.startswith("/pause"): + match = pause_pattern.match(self.path) + + if match: + length = int(self.headers['content-length']) + + if length > 0: + info_map = eval(str(self.rfile.read(length), encoding='utf8')) + status = info_map.get("status", None) + else: + status = None + + job_id = match.groups()[0] + job = self.server.getJobID(job_id) + + if job: + self.server.stats("", "Pausing job") + job.pause(status) + self.send_head() + else: + # no such job id + self.send_head(http.client.NO_CONTENT) + else: + # invalid url + self.send_head(http.client.NO_CONTENT) # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- elif self.path == "/clear": # cancel all jobs + length = int(self.headers['content-length']) + + if length > 0: + info_map = eval(str(self.rfile.read(length), encoding='utf8')) + clear = info_map.get("clear", False) + else: + clear = False + self.server.stats("", "Clearing jobs") - self.server.clear() + self.server.clear(clear) self.send_head() # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- @@ -647,8 +766,6 @@ class RenderHandler(http.server.BaseHTTPRequestHandler): if not slave.id in job.blacklist: job.blacklist.append(slave.id) - self.server.stats("", "Receiving result") - slave.finishedFrame(job_frame) frame.status = job_result @@ -664,6 +781,44 @@ class RenderHandler(http.server.BaseHTTPRequestHandler): else: # invalid slave id self.send_head(http.client.NO_CONTENT) # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + elif self.path == "/thumb": + self.server.stats("", "Receiving thumbnail result") + + # need some message content here or the slave doesn't like it + self.wfile.write(bytes("foo", encoding='utf8')) + + slave_id = self.headers['slave-id'] + + slave = self.server.getSeenSlave(slave_id) + + if slave: # only if slave id is valid + job_id = self.headers['job-id'] + + job = self.server.getJobID(job_id) + + if job: + job_frame = int(self.headers['job-frame']) + + frame = job[job_frame] + + if frame: + if job.type == netrender.model.JOB_BLENDER: + length = int(self.headers['content-length']) + buf = self.rfile.read(length) + f = open(job.save_path + "%04d" % job_frame + ".jpg", 'wb') + f.write(buf) + f.close() + + del buf + + self.send_head() + else: # frame not found + self.send_head(http.client.NO_CONTENT) + else: # job not found + self.send_head(http.client.NO_CONTENT) + else: # invalid slave id + self.send_head(http.client.NO_CONTENT) + # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- elif self.path.startswith("/log"): self.server.stats("", "Receiving log file") @@ -737,7 +892,7 @@ class RenderMasterServer(http.server.HTTPServer): self.slaves_map.pop(slave.id) def getSlave(self, slave_id): - return self.slaves_map.get(slave_id, None) + return self.slaves_map.get(slave_id) def getSeenSlave(self, slave_id): slave = self.getSlave(slave_id) @@ -775,11 +930,11 @@ class RenderMasterServer(http.server.HTTPServer): slave.job.usage += slave_usage - def clear(self): + def clear(self, clear_files = False): removed = self.jobs[:] for job in removed: - self.removeJob(job) + self.removeJob(job, clear_files) def balance(self): self.balancer.balance(self.jobs) @@ -798,10 +953,13 @@ class RenderMasterServer(http.server.HTTPServer): def countSlaves(self): return len(self.slaves) - def removeJob(self, job): + def removeJob(self, job, clear_files = False): self.jobs.remove(job) self.jobs_map.pop(job.id) - + + if clear_files: + shutil.rmtree(job.save_path) + for slave in self.slaves: if slave.job == job: slave.job = None @@ -819,7 +977,7 @@ class RenderMasterServer(http.server.HTTPServer): job.save() def getJobID(self, id): - return self.jobs_map.get(id, None) + return self.jobs_map.get(id) def __iter__(self): for job in self.jobs: @@ -833,7 +991,10 @@ class RenderMasterServer(http.server.HTTPServer): return None, None -def runMaster(address, broadcast, path, update_stats, test_break): +def clearMaster(path): + shutil.rmtree(path) + +def runMaster(address, broadcast, clear, path, update_stats, test_break): httpd = RenderMasterServer(address, RenderHandler, path) httpd.timeout = 1 httpd.stats = update_stats @@ -845,7 +1006,10 @@ def runMaster(address, broadcast, path, update_stats, test_break): start_time = time.time() while not test_break(): - httpd.handle_request() + try: + httpd.handle_request() + except select.error: + pass if time.time() - start_time >= 10: # need constant here httpd.timeoutSlaves() @@ -858,3 +1022,5 @@ def runMaster(address, broadcast, path, update_stats, test_break): start_time = time.time() httpd.server_close() + if clear: + clearMaster(httpd.path) diff --git a/release/scripts/io/netrender/master_html.py b/release/scripts/io/netrender/master_html.py index af4db43ae9d..3fff6d0b88c 100644 --- a/release/scripts/io/netrender/master_html.py +++ b/release/scripts/io/netrender/master_html.py @@ -37,8 +37,11 @@ def get(handler): output("<link rel='stylesheet' href='/html/netrender.css' type='text/css'>") - def link(text, url): - return "<a href='%s'>%s</a>" % (url, text) + def link(text, url, script=""): + return "<a href='%s' %s>%s</a>" % (url, script, text) + + def tag(name, text, attr=""): + return "<%s %s>%s</%s>" % (name, attr, text, name) def startTable(border=1, class_style = None, caption = None): output("<table border='%i'" % border) @@ -80,6 +83,9 @@ def get(handler): def endTable(): output("</table>") + + def checkbox(title, value, script=""): + return """<input type="checkbox" title="%s" %s %s>""" % (title, "checked" if value else "", ("onclick=\"%s\"" % script) if script else "") if handler.path == "/html/netrender.js": f = open(os.path.join(src_folder, "netrender.js"), 'rb') @@ -101,20 +107,38 @@ def get(handler): output("<h2>Master</h2>") - output("""<button title="remove all jobs" onclick="request('/clear', null);">CLEAR JOB LIST</button>""") + output("""<button title="remove all jobs" onclick="clear_jobs();">CLEAR JOB LIST</button>""") startTable(caption = "Rules", class_style = "rules") - headerTable("type", "description", "limit") + headerTable("type", "enabled", "description", "limit") for rule in handler.server.balancer.rules: - rowTable("rating", rule, rule.str_limit() if hasattr(rule, "limit") else " ") + rowTable( + "rating", + checkbox("", rule.enabled, "balance_enable('%i', '%s')" % (id(rule), str(not rule.enabled))), + rule, + rule.str_limit() + + """<button title="edit limit" onclick="balance_edit('%i', '%s');">edit</button>""" % (id(rule), str(rule.limit)) if hasattr(rule, "limit") else " " + ) for rule in handler.server.balancer.priorities: - rowTable("priority", rule, rule.str_limit() if hasattr(rule, "limit") else " ") + rowTable( + "priority", + checkbox("", rule.enabled, "balance_enable('%i', '%s')" % (id(rule), str(not rule.enabled))), + rule, + rule.str_limit() + + """<button title="edit limit" onclick="balance_edit('%i', '%s');">edit</button>""" % (id(rule), str(rule.limit)) if hasattr(rule, "limit") else " " + ) for rule in handler.server.balancer.exceptions: - rowTable("exception", rule, rule.str_limit() if hasattr(rule, "limit") else " ") + rowTable( + "exception", + checkbox("", rule.enabled, "balance_enable('%i', '%s')" % (id(rule), str(not rule.enabled))), + rule, + rule.str_limit() + + """<button title="edit limit" onclick="balance_edit('%i', '%s');">edit</button>""" % (id(rule), str(rule.limit)) if hasattr(rule, "limit") else " " + ) endTable() @@ -132,49 +156,51 @@ def get(handler): startTable() headerTable( - " ", - "id", - "name", - "category", - "chunks", - "priority", - "usage", - "wait", - "status", - "length", - "done", - "dispatched", - "error", - "first", - "exception" - ) + " ", + "id", + "name", + "category", + "chunks", + "priority", + "usage", + "wait", + "status", + "length", + "done", + "dispatched", + "error", + "priority", + "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', "{'chunks': %i}");">+</button>""" % (job.id, job.chunks + 1) + - """<button title="decrease priority" onclick="request('/edit_%s', "{'chunks': %i}");" %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', "{'priority': %i}");">+</button>""" % (job.id, job.priority + 1) + - """<button title="decrease chunks size" onclick="request('/edit_%s', "{'priority': %i}");" %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) - ) + """<button title="cancel job" onclick="cancel_job('%s');">X</button>""" % job.id + + """<button title="pause job" onclick="request('/pause_%s', null);">P</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 chunks size" onclick="request('/edit_%s', "{'chunks': %i}");">+</button>""" % (job.id, job.chunks + 1) + + """<button title="decrease chunks size" onclick="request('/edit_%s', "{'chunks': %i}");" %s>-</button>""" % (job.id, job.chunks - 1, "disabled=True" if job.chunks == 1 else ""), + str(job.priority) + + """<button title="increase priority" onclick="request('/edit_%s', "{'priority': %i}");">+</button>""" % (job.id, job.priority + 1) + + """<button title="decrease priority" onclick="request('/edit_%s', "{'priority': %i}");" %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 ""), + "yes" if handler.server.balancer.applyPriorities(job) else "no", + "yes" if handler.server.balancer.applyExceptions(job) else "no" + ) endTable() @@ -236,10 +262,19 @@ def get(handler): output("<h2>Frames</h2>") startTable() - headerTable("no", "status", "render time", "slave", "log", "result") + 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 " ", link("view log", logURL(job_id, frame.number)) if frame.log_path else " ", link("view result", renderURL(job_id, frame.number)) if frame.status == DONE else " ") + rowTable( + frame.number, + frame.statusText(), + "%.1fs" % frame.time, + frame.slave.name if frame.slave else " ", + link("view log", logURL(job_id, frame.number)) if frame.log_path else " ", + link("view result", renderURL(job_id, frame.number)) + " [" + + tag("span", "show", attr="class='thumb' onclick='showThumb(%s, %i)'" % (job.id, frame.number)) + "]" if frame.status == DONE else " ", + "<img name='thumb%i' title='hide thumbnails' src='' class='thumb' onclick='showThumb(%s, %i)'>" % (frame.number, job.id, frame.number) + ) endTable() else: diff --git a/release/scripts/io/netrender/netrender.css b/release/scripts/io/netrender/netrender.css index 87de1083315..cc8a93bb9a7 100644 --- a/release/scripts/io/netrender/netrender.css +++ b/release/scripts/io/netrender/netrender.css @@ -60,7 +60,6 @@ button { cursor: pointer; } - .cache { display: none; } @@ -72,4 +71,14 @@ button { .rules { width: 60em; text-align: left; -}
\ No newline at end of file +} + +img.thumb { + display: none; + cursor: pointer; +} + +span.thumb { + text-decoration: underline; + cursor: pointer; +} diff --git a/release/scripts/io/netrender/netrender.js b/release/scripts/io/netrender/netrender.js index 23f9f25c763..041a39a3ebc 100644 --- a/release/scripts/io/netrender/netrender.js +++ b/release/scripts/io/netrender/netrender.js @@ -1,3 +1,7 @@ +lastFrame = -1 +maxFrame = -1 +minFrame = -1 + function request(url, data) { xmlhttp = new XMLHttpRequest(); @@ -11,6 +15,105 @@ function edit(id, info) request("/edit_" + id, info) } +function clear_jobs() +{ + var r=confirm("Also delete files on master?"); + + if (r==true) { + request('/clear', "{'clear':True}"); + } else { + request('/clear', "{'clear':False}"); + } +} + +function cancel_job(id) +{ + var r=confirm("Also delete files on master?"); + + if (r==true) { + request('/cancel_' + id, "{'clear':True}"); + } else { + request('/cancel_' + id, "{'clear':False}"); + } +} + +function balance_edit(id, old_value) +{ + var new_value = prompt("New limit", old_value); + if (new_value != null && new_value != "") { + request("/balance_limit", "{" + id + ":'" + new_value + "'}"); + } +} + +function balance_enable(id, value) +{ + request("/balance_enable", "{" + id + ":" + value + "}"); +} + +function showThumb(job, frame) +{ + if (lastFrame != -1) { + if (maxFrame != -1 && minFrame != -1) { + if (frame >= minFrame && frame <= maxFrame) { + for(i = minFrame; i <= maxFrame; i=i+1) { + toggleThumb(job, i); + } + minFrame = -1; + maxFrame = -1; + lastFrame = -1; + } else if (frame > maxFrame) { + for(i = maxFrame+1; i <= frame; i=i+1) { + toggleThumb(job, i); + } + maxFrame = frame; + lastFrame = frame; + } else { + for(i = frame; i <= minFrame-1; i=i+1) { + toggleThumb(job, i); + } + minFrame = frame; + lastFrame = frame; + } + } else if (frame == lastFrame) { + toggleThumb(job, frame); + } else if (frame < lastFrame) { + minFrame = frame; + maxFrame = lastFrame; + + for(i = minFrame; i <= maxFrame-1; i=i+1) { + toggleThumb(job, i); + } + lastFrame = frame; + } else { + minFrame = lastFrame; + maxFrame = frame; + + for(i = minFrame+1; i <= maxFrame; i=i+1) { + toggleThumb(job, i); + } + lastFrame = frame; + } + } else { + toggleThumb(job, frame); + } +} + +function toggleThumb(job, frame) +{ + img = document.images["thumb" + frame]; + url = "/thumb_" + job + "_" + frame + ".jpg" + + if (img.style.display == "block") { + img.style.display = "none"; + img.src = ""; + lastFrame = -1; + } else { + img.src = url; + img.style.display = "block"; + lastFrame = frame; + } +} + function returnObjById( id ) { if (document.getElementById) diff --git a/release/scripts/io/netrender/operators.py b/release/scripts/io/netrender/operators.py index 8052b43e5b6..232d70a25be 100644 --- a/release/scripts/io/netrender/operators.py +++ b/release/scripts/io/netrender/operators.py @@ -112,6 +112,23 @@ class RENDER_OT_netclientanim(bpy.types.Operator): return self.execute(context) @rnaType +class RENDER_OT_netclientrun(bpy.types.Operator): + '''Start network rendering service''' + bl_idname = "render.netclientstart" + bl_label = "Start Service" + + def poll(self, context): + return True + + def execute(self, context): + 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" @@ -390,8 +407,7 @@ class netclientdownload(bpy.types.Operator): @rnaType class netclientscan(bpy.types.Operator): - __slots__ = [] - '''Operator documentation text, will be used for the operator tooltip and python docs.''' + '''Listen on network for master server broadcasting its address and port.''' bl_idname = "render.netclientscan" bl_label = "Client Scan" @@ -410,7 +426,6 @@ class netclientscan(bpy.types.Operator): return {'FINISHED'} def invoke(self, context, event): - print(dir(self)) return self.execute(context) @rnaType diff --git a/release/scripts/io/netrender/slave.py b/release/scripts/io/netrender/slave.py index e7cac28ace3..c0848d7874f 100644 --- a/release/scripts/io/netrender/slave.py +++ b/release/scripts/io/netrender/slave.py @@ -16,7 +16,7 @@ # # ##### END GPL LICENSE BLOCK ##### -import sys, os, platform +import sys, os, platform, shutil import http, http.client, http.server, urllib import subprocess, time @@ -45,6 +45,9 @@ else: def RestoreErrorMode(val): pass +def clearSlave(path): + shutil.rmtree(path) + def slave_Info(): sysname, nodename, release, version, machine, processor = platform.uname() slave = netrender.model.RenderSlave() @@ -85,7 +88,7 @@ def testFile(conn, job_id, slave_id, file_index, JOB_PREFIX, file_path, main_pat return job_full_path -def render_slave(engine, netsettings): +def render_slave(engine, netsettings, threads): timeout = 1 engine.update_stats("", "Network render node initiation") @@ -103,7 +106,6 @@ def render_slave(engine, netsettings): os.mkdir(NODE_PREFIX) while not engine.test_break(): - conn.request("GET", "/job", headers={"slave-id":slave_id}) response = conn.getresponse() @@ -149,7 +151,7 @@ def render_slave(engine, netsettings): 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) + process = subprocess.Popen([BLENDER_PATH, "-b", "-noaudio", job_full_path, "-t", str(threads), "-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 @@ -162,8 +164,8 @@ def render_slave(engine, netsettings): cancelled = False stdout = bytes() run_t = time.time() - while process.poll() == None and not cancelled: - stdout += process.stdout.read(32) + while not cancelled and process.poll() == None: + stdout += process.stdout.read(1024) current_t = time.time() cancelled = engine.test_break() if current_t - run_t > CANCEL_POLL_SPEED: @@ -211,14 +213,26 @@ def render_slave(engine, netsettings): 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') + + filename = JOB_PREFIX + "%06d" % frame.number + ".exr" + + # thumbnail first + if netsettings.slave_thumb: + thumbname = thumbnail(filename) + + f = open(thumbname, 'rb') + conn.request("PUT", "/thumb", f, headers=headers) + f.close() + conn.getresponse() + + f = open(filename, '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: @@ -238,10 +252,12 @@ def render_slave(engine, netsettings): for i in range(timeout): time.sleep(1) if engine.test_break(): - conn.close() - return + break conn.close() + + if netsettings.slave_clear: + clearSlave(NODE_PREFIX) if __name__ == "__main__": pass diff --git a/release/scripts/io/netrender/ui.py b/release/scripts/io/netrender/ui.py index 86eb4bf5c30..e8b9f2a6ed3 100644 --- a/release/scripts/io/netrender/ui.py +++ b/release/scripts/io/netrender/ui.py @@ -36,6 +36,46 @@ DISPATCHED = 1 DONE = 2 ERROR = 3 +def init_file(): + if netrender.init_file != bpy.data.filename: + netrender.init_file = bpy.data.filename + netrender.init_data = True + netrender.init_address = True + +def init_data(netsettings): + init_file() + + if netrender.init_data: + netrender.init_data = False + + netsettings.active_slave_index = 0 + while(len(netsettings.slaves) > 0): + netsettings.slaves.remove(0) + + netsettings.active_blacklisted_slave_index = 0 + while(len(netsettings.slaves_blacklist) > 0): + netsettings.slaves_blacklist.remove(0) + + netsettings.active_job_index = 0 + while(len(netsettings.jobs) > 0): + netsettings.jobs.remove(0) + +def verify_address(netsettings): + init_file() + + if netrender.init_address: + netrender.init_address = False + + try: + conn = clientConnection(netsettings.server_address, netsettings.server_port, scan = False) + except: + conn = None + + if conn: + conn.close() + else: + netsettings.server_address = "[default]" + class RenderButtonsPanel(bpy.types.Panel): bl_space_type = "PROPERTIES" bl_region_type = "WINDOW" @@ -56,30 +96,75 @@ class RENDER_PT_network_settings(RenderButtonsPanel): layout = self.layout scene = context.scene - rd = scene.render_data + netsettings = scene.network_render + + verify_address(netsettings) - layout.active = True + layout.prop(netsettings, "mode", expand=True) - split = layout.split() + if netsettings.mode in ("RENDER_MASTER", "RENDER_SLAVE"): + layout.operator("render.netclientstart", icon='PLAY') + layout.prop(netsettings, "path") + + split = layout.split(percentage=0.7) + + col = split.column() + col.label(text="Server Adress:") + col.prop(netsettings, "server_address", text="") + col = split.column() + col.label(text="Port:") + col.prop(netsettings, "server_port", text="") + if netsettings.mode != "RENDER_MASTER": + layout.operator("render.netclientscan", icon='FILE_REFRESH', text="") - if scene.network_render.mode in ("RENDER_MASTER", "RENDER_SLAVE"): - col.operator("screen.render", text="Start", icon='PLAY').animation = True + layout.operator("render.netclientweb", icon='QUESTION') - 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") +@rnaType +class RENDER_PT_network_slave_settings(RenderButtonsPanel): + bl_label = "Slave Settings" + COMPAT_ENGINES = {'NET_RENDER'} - if scene.network_render.mode == "RENDER_MASTER": - col.prop(scene.network_render, "server_broadcast") - else: - col.operator("render.netclientscan", icon='FILE_REFRESH', text="") + def poll(self, context): + scene = context.scene + return (super().poll(context) + and scene.network_render.mode == "RENDER_SLAVE") - col.operator("render.netclientweb", icon='QUESTION') + def draw(self, context): + layout = self.layout + + scene = context.scene + rd = scene.render_data + netsettings = scene.network_render + layout.prop(netsettings, "slave_clear") + layout.prop(netsettings, "slave_thumb") + layout.label(text="Threads:") + layout.prop(rd, "threads_mode", expand=True) + sub = layout.column() + sub.enabled = rd.threads_mode == 'THREADS_FIXED' + sub.prop(rd, "threads") +@rnaType +class RENDER_PT_network_master_settings(RenderButtonsPanel): + bl_label = "Master Settings" + COMPAT_ENGINES = {'NET_RENDER'} + + def poll(self, context): + scene = context.scene + return (super().poll(context) + and scene.network_render.mode == "RENDER_MASTER") + + def draw(self, context): + layout = self.layout + + scene = context.scene + netsettings = scene.network_render + + layout.prop(netsettings, "master_broadcast") + layout.prop(netsettings, "master_clear") + @rnaType class RENDER_PT_network_job(RenderButtonsPanel): bl_label = "Job Settings" @@ -94,23 +179,31 @@ class RENDER_PT_network_job(RenderButtonsPanel): layout = self.layout scene = context.scene - rd = scene.render_data - - layout.active = True - - split = layout.split() + netsettings = scene.network_render + verify_address(netsettings) + + if netsettings.server_address != "[default]": + layout.operator("render.netclientanim", icon='RENDER_ANIMATION') + layout.operator("render.netclientsend", icon='FILE_BLEND') + if netsettings.job_id: + row = layout.row() + row.operator("screen.render", text="Get Image", icon='RENDER_STILL') + row.operator("screen.render", text="Get Animation", icon='RENDER_ANIMATION').animation = True + + split = layout.split(percentage=0.3) + + col = split.column() + col.label(text="Name:") + col.label(text="Category:") + 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") + col.prop(netsettings, "job_name", text="") + col.prop(netsettings, "job_category", text="") + + row = layout.row() + row.prop(netsettings, "priority") + row.prop(netsettings, "chunks") @rnaType class RENDER_PT_network_slaves(RenderButtonsPanel): @@ -119,9 +212,11 @@ class RENDER_PT_network_slaves(RenderButtonsPanel): def poll(self, context): scene = context.scene + netsettings = scene.network_render + verify_address(netsettings) return (super().poll(context) - and scene.network_render.mode == "RENDER_CLIENT" - and scene.network_render.server_address != "[default]") + and netsettings.mode == "RENDER_CLIENT" + and netsettings.server_address != "[default]") def draw(self, context): layout = self.layout @@ -136,9 +231,7 @@ class RENDER_PT_network_slaves(RenderButtonsPanel): 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) + init_data(netsettings) if netsettings.active_slave_index >= 0 and len(netsettings.slaves) > 0: layout.separator() @@ -157,9 +250,11 @@ class RENDER_PT_network_slaves_blacklist(RenderButtonsPanel): def poll(self, context): scene = context.scene + netsettings = scene.network_render + verify_address(netsettings) return (super().poll(context) - and scene.network_render.mode == "RENDER_CLIENT" - and scene.network_render.server_address != "[default]") + and netsettings.mode == "RENDER_CLIENT" + and netsettings.server_address != "[default]") def draw(self, context): layout = self.layout @@ -173,9 +268,7 @@ class RENDER_PT_network_slaves_blacklist(RenderButtonsPanel): 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) + init_data(netsettings) if netsettings.active_blacklisted_slave_index >= 0 and len(netsettings.slaves_blacklist) > 0: layout.separator() @@ -194,9 +287,11 @@ class RENDER_PT_network_jobs(RenderButtonsPanel): def poll(self, context): scene = context.scene + netsettings = scene.network_render + verify_address(netsettings) return (super().poll(context) - and scene.network_render.mode == "RENDER_CLIENT" - and scene.network_render.server_address != "[default]") + and netsettings.mode == "RENDER_CLIENT" + and netsettings.server_address != "[default]") def draw(self, context): layout = self.layout @@ -213,9 +308,7 @@ class RENDER_PT_network_jobs(RenderButtonsPanel): 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) + init_data(netsettings) if netsettings.active_job_index >= 0 and len(netsettings.jobs) > 0: layout.separator() @@ -254,12 +347,27 @@ NetRenderSettings.IntProperty( attr="server_port", min=1, max=65535) -NetRenderSettings.BoolProperty( attr="server_broadcast", - name="Broadcast server address", - description="broadcast server address on local network", +NetRenderSettings.BoolProperty( attr="master_broadcast", + name="Broadcast", + description="broadcast master server address on local network", + default = True) + +NetRenderSettings.BoolProperty( attr="slave_clear", + name="Clear on exit", + description="delete downloaded files on exit", default = True) -default_path = os.environ.get("TEMP", None) +NetRenderSettings.BoolProperty( attr="slave_thumb", + name="Generate thumbnails", + description="Generate thumbnails on slaves instead of master", + default = False) + +NetRenderSettings.BoolProperty( attr="master_clear", + name="Clear on exit", + description="delete saved files on exit", + default = False) + +default_path = os.environ.get("TEMP") if not default_path: if os.name == 'nt': diff --git a/release/scripts/io/netrender/utils.py b/release/scripts/io/netrender/utils.py index 84275710391..1871a969f80 100644 --- a/release/scripts/io/netrender/utils.py +++ b/release/scripts/io/netrender/utils.py @@ -28,7 +28,7 @@ try: except: bpy = None -VERSION = bytes("0.7", encoding='utf8') +VERSION = bytes("0.8", encoding='utf8') # Jobs status JOB_WAITING = 0 # before all data has been entered @@ -96,15 +96,18 @@ def clientScan(report = None): return ("", 8000) # return default values -def clientConnection(address, port, report = None): +def clientConnection(address, port, report = None, scan = True): if address == "[default]": # calling operator from python is fucked, scene isn't in context # if bpy: # bpy.ops.render.netclientscan() # else: - address, port = clientScan() - if address == "": - return None + if not scan: + return None + + address, port = clientScan() + if address == "": + return None try: conn = http.client.HTTPConnection(address, port) @@ -169,3 +172,28 @@ def prefixPath(prefix_directory, file_path, prefix_path): full_path = prefix_directory + file_path return full_path + +def thumbnail(filename): + root = os.path.splitext(filename)[0] + imagename = os.path.split(filename)[1] + thumbname = root + ".jpg" + + if os.path.exists(thumbname): + return thumbname + + if bpy: + sce = bpy.data.scenes[0] + sce.render_data.file_format = "JPEG" + sce.render_data.quality = 90 + bpy.ops.image.open(path = filename) + img = bpy.data.images[imagename] + img.save(thumbname, scene = sce) + + try: + process = subprocess.Popen(["convert", thumbname, "-resize", "300x300", thumbname]) + process.wait() + return thumbname + except: + pass + + return None diff --git a/release/scripts/modules/bpy/__init__.py b/release/scripts/modules/bpy/__init__.py index 65bf75b43e9..6209cbe4f0e 100644 --- a/release/scripts/modules/bpy/__init__.py +++ b/release/scripts/modules/bpy/__init__.py @@ -27,6 +27,7 @@ context = _bpy.context # python modules from bpy import utils +from bpy import app from bpy import ops as _ops_module @@ -100,9 +101,4 @@ def _main(): load_scripts() -# constants -version = _bpy._VERSION -version_string = _bpy._VERSION_STR -home = _bpy._HOME - _main() diff --git a/release/scripts/modules/bpy/app.py b/release/scripts/modules/bpy/app.py new file mode 100644 index 00000000000..da45ab8eb30 --- /dev/null +++ b/release/scripts/modules/bpy/app.py @@ -0,0 +1,26 @@ +# ##### 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> + +# constants +import _bpy +version = _bpy._VERSION +version_string = _bpy._VERSION_STR +home = _bpy._HOME +binary_path = _bpy._BINPATH diff --git a/release/scripts/modules/bpy/ops.py b/release/scripts/modules/bpy/ops.py index 268189b2db4..75976ebf9a1 100644 --- a/release/scripts/modules/bpy/ops.py +++ b/release/scripts/modules/bpy/ops.py @@ -22,8 +22,6 @@ from _bpy import ops as ops_module # op_add = ops_module.add -op_remove = ops_module.remove -op_add_macro = ops_module.add_macro op_dir = ops_module.dir op_call = ops_module.call op_as_string = ops_module.as_string @@ -57,15 +55,6 @@ class bpy_ops(object): raise AttributeError(module) return bpy_ops_submodule(module) - def add(self, pyop): - op_add(pyop) - - def add_macro(self, pyop): - op_add_macro(pyop) - - def remove(self, pyop): - op_remove(pyop) - def __dir__(self): submodules = set() diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py index 4af724fa3f6..2a757f83208 100644 --- a/release/scripts/modules/bpy_types.py +++ b/release/scripts/modules/bpy_types.py @@ -46,6 +46,19 @@ class Object(bpy_types.ID): import bpy return [child for child in bpy.data.objects if child.parent == self] + @property + def group_users(self): + """The groups this object is in""" + import bpy + name = self.name + return [group for group in bpy.data.groups if name in group.objects] + + @property + def scene_users(self): + """The scenes this object is in""" + import bpy + name = self.name + return [scene for scene in bpy.data.scenes if name in scene.objects] class _GenericBone: """ @@ -97,6 +110,11 @@ class _GenericBone: return parent_list @property + def center(self): + """The midpoint between the head and the tail.""" + return (self.head + self.tail) * 0.5 + + @property def length(self): """The distance from head to tail, when set the head is moved to fit the length.""" return self.vector.length @@ -193,6 +211,19 @@ class EditBone(StructRNA, _GenericBone): self.tail = self.head + vec self.roll = other.roll + def transform(self, matrix): + """ + Transform the the bones head, tail, roll and envalope (when the matrix has a scale component). + Expects a 4x4 or 3x3 matrix. + """ + from Mathutils import Vector + z_vec = self.matrix.rotationPart() * Vector(0.0, 0.0, 1.0) + self.tail = matrix * self.tail + self.head = matrix * self.head + scalar = matrix.median_scale + self.head_radius *= scalar + self.tail_radius *= scalar + self.align_roll(matrix * z_vec) def ord_ind(i1, i2): if i1 < i2: diff --git a/release/scripts/modules/retopo.py b/release/scripts/modules/retopo.py index 15c4c504b32..6fba34b7b58 100644 --- a/release/scripts/modules/retopo.py +++ b/release/scripts/modules/retopo.py @@ -21,7 +21,7 @@ import bpy EPS_SPLINE_DIV = 15.0 # remove doubles is ~15th the length of the spline - +ANGLE_JOIN_LIMIT = 25.0 # limit for joining splines into 1. def get_hub(co, _hubs, EPS_SPLINE): @@ -118,13 +118,105 @@ class Hub(object): return faces +class BBox(object): + __slots__ = "xmin", "ymin", "zmin", "xmax", "ymax", "zmax" + + def __init__(self): + self.xmin = self.ymin = self.zmin = 100000000.0 + self.xmax = self.ymax = self.zmax = -100000000.0 + + @property + def xdim(self): + return self.xmax - self.xmin + + @property + def ydim(self): + return self.ymax - self.ymin + + @property + def zdim(self): + return self.zmax - self.zmin + + def calc(self, points): + xmin = ymin = zmin = 100000000.0 + xmax = ymax = zmax = -100000000.0 + + for pt in points: + x, y, z = pt + if x < xmin: + xmin = x + if y < ymin: + ymin = y + if z < zmin: + zmin = z + + if x > xmax: + xmax = x + if y > ymax: + ymax = y + if z > zmax: + zmax = z + + self.xmin, self.ymin, self.zmin = xmin, ymin, zmin + self.xmax, self.ymax, self.zmax = xmax, ymax, zmax + + def xsect(self, other, margin=0.0): + if margin == 0.0: + if self.xmax < other.xmin: + return False + if self.ymax < other.ymin: + return False + if self.zmax < other.zmin: + return False + + if self.xmin > other.xmax: + return False + if self.ymin > other.ymax: + return False + if self.zmin > other.zmax: + return False + + else: + xmargin = ((self.xdim + other.xdim) / 2.0) * margin + ymargin = ((self.ydim + other.ydim) / 2.0) * margin + zmargin = ((self.zdim + other.zdim) / 2.0) * margin + + if self.xmax < other.xmin - xmargin: + return False + if self.ymax < other.ymin - ymargin: + return False + if self.zmax < other.zmin - zmargin: + return False + + if self.xmin > other.xmax + xmargin: + return False + if self.ymin > other.ymax + ymargin: + return False + if self.zmin > other.zmax + zmargin: + return False + return True + + def __iadd__(self, other): + self.xmin = min(self.xmin, other.xmin) + self.ymin = min(self.ymin, other.ymin) + self.zmin = min(self.zmin, other.zmin) + + self.xmax = max(self.xmax, other.xmax) + self.ymax = max(self.ymax, other.ymax) + self.zmax = max(self.zmax, other.zmax) + return self + class Spline(object): - __slots__ = "points", "hubs", "length" + __slots__ = "points", "hubs", "length", "bb" def __init__(self, points): self.points = points self.hubs = [] + self.calc_length() + self.bb = BBox() + self.bb.calc(points) + def calc_length(self): # calc length f = 0.0 co_prev = self.points[0] @@ -215,8 +307,120 @@ def xsect_spline(sp_a, sp_b, _hubs): pt_a_prev = pt_a +def connect_splines(splines): + HASH_PREC = 8 + from Mathutils import AngleBetweenVecs + from math import radians + ANG_LIMIT = radians(ANGLE_JOIN_LIMIT) + def sort_pair(a, b): + if a < b: + return a, b + else: + return b, a + + #def test_join(p1a, p1b, p2a, p2b, length_average): + def test_join(s1, s2, dir1, dir2, length_average): + if dir1 is False: + p1a = s1.points[0] + p1b = s1.points[1] + else: + p1a = s1.points[-1] + p1b = s1.points[-2] + + if dir2 is False: + p2a = s2.points[0] + p2b = s2.points[1] + else: + p2a = s2.points[-1] + p2b = s2.points[-2] + + # compare length between tips + if (p1a - p2a).length > (length_average / EPS_SPLINE_DIV): + return False + + v1 = p1a - p1b + v2 = p2b - p2a + + if AngleBetweenVecs(v1, v2) > ANG_LIMIT: + return False + + # print("joining!") + return True + + # lazy, hash the points that have been compared. + comparisons = set() + + do_join = True + while do_join: + do_join = False + for i, s1 in enumerate(splines): + key1a = s1.points[0].toTuple(HASH_PREC) + key1b = s1.points[-1].toTuple(HASH_PREC) + + for j, s2 in enumerate(splines): + if s1 is s2: + continue + + length_average = min(s1.length, s2.length) + + key2a = s2.points[0].toTuple(HASH_PREC) + key2b = s2.points[-1].toTuple(HASH_PREC) + + # there are 4 ways this may be joined + key_pair = sort_pair(key1a, key2a) + if key_pair not in comparisons: + comparisons.add(key_pair) + if test_join(s1, s2, False, False, length_average): + s1.points[:0] = reversed(s2.points) + s1.bb += s2.bb + s1.calc_length() + del splines[j] + do_join = True + break + + key_pair = sort_pair(key1a, key2b) + if key_pair not in comparisons: + comparisons.add(key_pair) + if test_join(s1, s2, False, True, length_average): + s1.points[:0] = s2.points + s1.bb += s2.bb + s1.calc_length() + del splines[j] + do_join = True + break + + key_pair = sort_pair(key1b, key2b) + if key_pair not in comparisons: + comparisons.add(key_pair) + if test_join(s1, s2, True, True, length_average): + s1.points += list(reversed(s2.points)) + s1.bb += s2.bb + s1.calc_length() + del splines[j] + do_join = True + break + + key_pair = sort_pair(key1b, key2a) + if key_pair not in comparisons: + comparisons.add(key_pair) + if test_join(s1, s2, True, False, length_average): + s1.points += s2.points + s1.bb += s2.bb + s1.calc_length() + del splines[j] + do_join = True + break + + if do_join: + break + + def calculate(gp): splines = get_splines(gp) + + # spline endpoints may be co-linear, join these into single splines + connect_splines(splines) + _hubs = {} for i, sp in enumerate(splines): @@ -224,7 +428,8 @@ def calculate(gp): if j <= i: continue - xsect_spline(sp, sp_other, _hubs) + if sp.bb.xsect(sp_other.bb, margin=0.1): + xsect_spline(sp, sp_other, _hubs) for sp in splines: sp.link() @@ -263,12 +468,12 @@ def calculate(gp): # remove double faces faces = dict([(tuple(sorted(f)), f) for f in faces]).values() - mesh = bpy.data.add_mesh("Retopo") + mesh = bpy.data.meshes.new("Retopo") mesh.from_pydata(verts, [], faces) scene = bpy.context.scene mesh.update() - obj_new = bpy.data.add_object('MESH', "Torus") + obj_new = bpy.data.objects.new("Torus", 'MESH') obj_new.data = mesh scene.objects.link(obj_new) diff --git a/release/scripts/modules/rigify/__init__.py b/release/scripts/modules/rigify/__init__.py index 95ae2fed76c..6857d7e8f6d 100644 --- a/release/scripts/modules/rigify/__init__.py +++ b/release/scripts/modules/rigify/__init__.py @@ -26,6 +26,12 @@ from rna_prop_ui import rna_idprop_ui_prop_get SPECIAL_TYPES = "root", LAYER_TYPES = "main", "extra", "ik", "fk" +ORG_LAYERS = [n==31 for n in range(0,32)] +MCH_LAYERS = [n==30 for n in range(0,32)] +DEF_LAYERS = [n==29 for n in range(0,32)] + + + class RigifyError(Exception): """Exception raised for errors in the metarig. @@ -341,10 +347,14 @@ def generate_rig(context, obj_orig, prefix="ORG-", META_DEF=True): layer_second_last[30] = True for bone_name, bone in arm.bones.items(): + bone.deform = False # Non DEF bones shouldn't deform if bone_name.startswith(prefix): - bone.layer = layer_last - elif bone_name.startswith("MCH"): # XXX fixme - bone.layer = layer_second_last + bone.layer = ORG_LAYERS + elif bone_name.startswith("MCH-"): # XXX fixme + bone.layer = MCH_LAYERS + elif bone_name.startswith("DEF-"): # XXX fixme + bone.layer = DEF_LAYERS + bone.deform = True layer_tot[:] = [max(lay) for lay in zip(layer_tot, bone.layer)] @@ -370,8 +380,8 @@ def generate_test(context, metarig_type="", GENERATE_FINAL=True): scene = context.scene def create_empty_armature(name): - obj_new = bpy.data.add_object('ARMATURE', name) - armature = bpy.data.add_armature(name) + obj_new = bpy.data.objects.new(name, 'ARMATURE') + armature = bpy.data.armatures.new(name) obj_new.data = armature scene.objects.link(obj_new) scene.objects.active = obj_new diff --git a/release/scripts/modules/rigify/arm_biped_generic.py b/release/scripts/modules/rigify/arm_biped_generic.py index 509f1bb7aef..0974b1b8010 100644 --- a/release/scripts/modules/rigify/arm_biped_generic.py +++ b/release/scripts/modules/rigify/arm_biped_generic.py @@ -254,11 +254,11 @@ def fk(obj, definitions, base_names, options): driver = driver_fcurve.driver driver.type = 'AVERAGE' - tar = driver.targets.new() - tar.name = "hinge" - tar.id_type = 'OBJECT' - tar.id = obj - tar.data_path = controller_path + '["hinge"]' + var = driver.variables.new() + var.name = "hinge" + var.targets[0].id_type = 'OBJECT' + var.targets[0].id = obj + var.targets[0].data_path = controller_path + '["hinge"]' mod = driver_fcurve.modifiers[0] mod.poly_order = 1 @@ -283,9 +283,99 @@ def fk(obj, definitions, base_names, options): return None, fk_chain.arm, fk_chain.forearm, fk_chain.hand +def deform(obj, definitions, base_names, options): + bpy.ops.object.mode_set(mode='EDIT') + + # Create upper arm bones: two bones, each half of the upper arm. + uarm1 = copy_bone_simple(obj.data, definitions[1], "DEF-%s.01" % base_names[definitions[1]], parent=True) + uarm2 = copy_bone_simple(obj.data, definitions[1], "DEF-%s.02" % base_names[definitions[1]], parent=True) + uarm1.connected = False + uarm2.connected = False + uarm2.parent = uarm1 + center = uarm1.center + uarm1.tail = center + uarm2.head = center + + # Create forearm bones: two bones, each half of the forearm. + farm1 = copy_bone_simple(obj.data, definitions[2], "DEF-%s.01" % base_names[definitions[2]], parent=True) + farm2 = copy_bone_simple(obj.data, definitions[2], "DEF-%s.02" % base_names[definitions[2]], parent=True) + farm1.connected = False + farm2.connected = False + farm2.parent = farm1 + center = farm1.center + farm1.tail = center + farm2.head = center + + # Create twist bone + twist = copy_bone_simple(obj.data, definitions[2], "MCH-arm_twist") + twist.connected = False + twist.parent = obj.data.edit_bones[definitions[3]] + twist.length /= 2 + + # Create hand bone + hand = copy_bone_simple(obj.data, definitions[3], "DEF-%s" % base_names[definitions[3]], parent=True) + + # Store names before leaving edit mode + uarm1_name = uarm1.name + uarm2_name = uarm2.name + farm1_name = farm1.name + farm2_name = farm2.name + twist_name = twist.name + hand_name = hand.name + + # Leave edit mode + bpy.ops.object.mode_set(mode='OBJECT') + + # Get the pose bones + uarm1 = obj.pose.bones[uarm1_name] + uarm2 = obj.pose.bones[uarm2_name] + farm1 = obj.pose.bones[farm1_name] + farm2 = obj.pose.bones[farm2_name] + twist = obj.pose.bones[twist_name] + hand = obj.pose.bones[hand_name] + + # Upper arm constraints + con = uarm1.constraints.new('DAMPED_TRACK') + con.name = "trackto" + con.target = obj + con.subtarget = definitions[2] + + con = uarm2.constraints.new('COPY_ROTATION') + con.name = "copy_rot" + con.target = obj + con.subtarget = definitions[1] + + # Forearm constraints + con = farm1.constraints.new('COPY_ROTATION') + con.name = "copy_rot" + con.target = obj + con.subtarget = definitions[2] + + con = farm2.constraints.new('COPY_ROTATION') + con.name = "copy_rot" + con.target = obj + con.subtarget = twist.name + + con = farm2.constraints.new('DAMPED_TRACK') + con.name = "trackto" + con.target = obj + con.subtarget = definitions[3] + + # Hand constraint + con = hand.constraints.new('COPY_ROTATION') + con.name = "copy_rot" + con.target = obj + con.subtarget = definitions[3] + + bpy.ops.object.mode_set(mode='EDIT') + return (uarm1_name, uarm2_name, farm1_name, farm2_name, hand_name) + + def main(obj, bone_definition, base_names, options): bones_fk = fk(obj, bone_definition, base_names, options) bones_ik = ik(obj, bone_definition, base_names, options) + bones_deform = deform(obj, bone_definition, base_names, options) bpy.ops.object.mode_set(mode='OBJECT') - blend_bone_list(obj, bone_definition, bones_fk, bones_ik, target_bone=bones_fk[1], blend_default=1.0) + blend_bone_list(obj, bone_definition, bones_fk, bones_ik, target_bone=bones_ik[3], target_prop="ik", blend_default=0.0) + diff --git a/release/scripts/modules/rigify/copy.py b/release/scripts/modules/rigify/copy.py index 11c16d2d197..a84487e8e21 100644 --- a/release/scripts/modules/rigify/copy.py +++ b/release/scripts/modules/rigify/copy.py @@ -42,7 +42,31 @@ def metarig_template(): def metarig_definition(obj, orig_bone_name): - return [orig_bone_name] + return (orig_bone_name,) + + +def deform(obj, definitions, base_names, options): + bpy.ops.object.mode_set(mode='EDIT') + + # Create deform bone. + bone = copy_bone_simple(obj.data, definitions[0], "DEF-%s" % base_names[definitions[0]], parent=True) + + # Store name before leaving edit mode + bone_name = bone.name + + # Leave edit mode + bpy.ops.object.mode_set(mode='OBJECT') + + # Get the pose bone + bone = obj.pose.bones[bone_name] + + # Constrain to the original bone + con = bone.constraints.new('COPY_TRANSFORMS') + con.name = "copy_loc" + con.target = obj + con.subtarget = definitions[0] + + return (bone_name,) def main(obj, bone_definition, base_names, options): @@ -59,18 +83,10 @@ def main(obj, bone_definition, base_names, options): cp.update() mt.update() - if not cp.cpy_b.connected: - con = mt.cpy_p.constraints.new('COPY_LOCATION') - con.target = obj - con.subtarget = cp.cpy - - con = mt.cpy_p.constraints.new('COPY_ROTATION') + con = mt.cpy_p.constraints.new('COPY_TRANSFORMS') con.target = obj con.subtarget = cp.cpy - con = mt.cpy_p.constraints.new('COPY_SCALE') - con.target = obj - con.subtarget = cp.cpy # Rotation mode and axis locks cp.cpy_p.rotation_mode = mt.cpy_p.rotation_mode @@ -79,9 +95,13 @@ def main(obj, bone_definition, base_names, options): cp.cpy_p.lock_rotation = tuple(mt.cpy_p.lock_rotation) cp.cpy_p.lock_rotation_w = mt.cpy_p.lock_rotation_w cp.cpy_p.lock_scale = tuple(mt.cpy_p.lock_scale) + + # Create deform bone + deform_bone = deform(obj, bone_definition, base_names, options)[0] # setup layers last layers = get_layer_dict(options) cp.cpy_b.layer = layers["main"] - return [mt.cpy] + return (mt.cpy,) + diff --git a/release/scripts/modules/rigify/finger_curl.py b/release/scripts/modules/rigify/finger_curl.py index a4688ee8b5b..4c00f134e19 100644 --- a/release/scripts/modules/rigify/finger_curl.py +++ b/release/scripts/modules/rigify/finger_curl.py @@ -86,6 +86,68 @@ def metarig_definition(obj, orig_bone_name): return bone_definition +def deform(obj, definitions, base_names, options): + """ Creates the deform rig. + """ + bpy.ops.object.mode_set(mode='EDIT') + + # Create base digit bones: two bones, each half of the base digit. + f1a = copy_bone_simple(obj.data, definitions[0], "DEF-%s.01" % base_names[definitions[0]], parent=True) + f1b = copy_bone_simple(obj.data, definitions[0], "DEF-%s.02" % base_names[definitions[0]], parent=True) + f1a.connected = False + f1b.connected = False + f1b.parent = f1a + center = f1a.center + f1a.tail = center + f1b.head = center + + # Create the other deform bones. + f2 = copy_bone_simple(obj.data, definitions[1], "DEF-%s" % base_names[definitions[1]], parent=True) + f3 = copy_bone_simple(obj.data, definitions[2], "DEF-%s" % base_names[definitions[2]], parent=True) + + # Store names before leaving edit mode + f1a_name = f1a.name + f1b_name = f1b.name + f2_name = f2.name + f3_name = f3.name + + # Leave edit mode + bpy.ops.object.mode_set(mode='OBJECT') + + # Get the pose bones + f1a = obj.pose.bones[f1a_name] + f1b = obj.pose.bones[f1b_name] + f2 = obj.pose.bones[f2_name] + f3 = obj.pose.bones[f3_name] + + # Constrain the base digit's bones + con = f1a.constraints.new('DAMPED_TRACK') + con.name = "trackto" + con.target = obj + con.subtarget = definitions[1] + + con = f1a.constraints.new('COPY_SCALE') + con.name = "copy_scale" + con.target = obj + con.subtarget = definitions[0] + + con = f1b.constraints.new('COPY_ROTATION') + con.name = "copy_rot" + con.target = obj + con.subtarget = definitions[0] + + # Constrain the other digit's bones + con = f2.constraints.new('COPY_TRANSFORMS') + con.name = "copy_transforms" + con.target = obj + con.subtarget = definitions[1] + + con = f3.constraints.new('COPY_TRANSFORMS') + con.name = "copy_transforms" + con.target = obj + con.subtarget = definitions[2] + + def main(obj, bone_definition, base_names, options): # *** EDITMODE @@ -139,6 +201,7 @@ def main(obj, bone_definition, base_names, options): del control_ebone + deform(obj, bone_definition, base_names, options) # *** POSEMODE bpy.ops.object.mode_set(mode='OBJECT') @@ -188,18 +251,18 @@ def main(obj, bone_definition, base_names, options): driver = fcurve_driver.driver # scale target - tar = driver.targets.new() - tar.name = "scale" - tar.id_type = 'OBJECT' - tar.id = obj - tar.data_path = controller_path + '.scale[1]' + var = driver.variables.new() + var.name = "scale" + var.targets[0].id_type = 'OBJECT' + var.targets[0].id = obj + var.targets[0].data_path = controller_path + '.scale[1]' # bend target - tar = driver.targets.new() - tar.name = "br" - tar.id_type = 'OBJECT' - tar.id = obj - tar.data_path = controller_path + '["bend_ratio"]' + var = driver.variables.new() + var.name = "br" + var.targets[0].id_type = 'OBJECT' + var.targets[0].id = obj + var.targets[0].data_path = controller_path + '["bend_ratio"]' # XXX - todo, any number if i == 0: diff --git a/release/scripts/modules/rigify/leg_biped_generic.py b/release/scripts/modules/rigify/leg_biped_generic.py index 745ee49cbfe..2bf53ddc1ce 100644 --- a/release/scripts/modules/rigify/leg_biped_generic.py +++ b/release/scripts/modules/rigify/leg_biped_generic.py @@ -271,7 +271,7 @@ def ik(obj, bone_definition, base_names, options): bpy.ops.object.mode_set(mode='EDIT') - return None, ik_chain.thigh, ik_chain.shin, ik_chain.foot, ik_chain.toe, None + return (None, ik_chain.thigh, ik_chain.shin, ik_chain.foot, ik_chain.toe, None, ik.foot) def fk(obj, bone_definition, base_names, options): @@ -336,12 +336,12 @@ def fk(obj, bone_definition, base_names, options): fcurve = con.driver_add("influence", 0) driver = fcurve.driver - tar = driver.targets.new() + var = driver.variables.new() driver.type = 'AVERAGE' - tar.name = "var" - tar.id_type = 'OBJECT' - tar.id = obj - tar.data_path = hinge_driver_path + var.name = "var" + var.targets[0].id_type = 'OBJECT' + var.targets[0].id = obj + var.targets[0].data_path = hinge_driver_path mod = fcurve.modifiers[0] mod.poly_order = 1 @@ -363,12 +363,112 @@ def fk(obj, bone_definition, base_names, options): bpy.ops.object.mode_set(mode='EDIT') # dont blend the hips or heel - return None, fk_chain.thigh, fk_chain.shin, fk_chain.foot, fk_chain.toe, None + return (None, fk_chain.thigh, fk_chain.shin, fk_chain.foot, fk_chain.toe, None, None) + + +def deform(obj, definitions, base_names, options): + bpy.ops.object.mode_set(mode='EDIT') + + # Create upper leg bones: two bones, each half of the upper leg. + uleg1 = copy_bone_simple(obj.data, definitions[1], "DEF-%s.01" % base_names[definitions[1]], parent=True) + uleg2 = copy_bone_simple(obj.data, definitions[1], "DEF-%s.02" % base_names[definitions[1]], parent=True) + uleg1.connected = False + uleg2.connected = False + uleg2.parent = uleg1 + center = uleg1.center + uleg1.tail = center + uleg2.head = center + + # Create lower leg bones: two bones, each half of the lower leg. + lleg1 = copy_bone_simple(obj.data, definitions[2], "DEF-%s.01" % base_names[definitions[2]], parent=True) + lleg2 = copy_bone_simple(obj.data, definitions[2], "DEF-%s.02" % base_names[definitions[2]], parent=True) + lleg1.connected = False + lleg2.connected = False + lleg2.parent = lleg1 + center = lleg1.center + lleg1.tail = center + lleg2.head = center + + # Create a bone for the second lower leg deform bone to twist with + twist = copy_bone_simple(obj.data, lleg2.name, "MCH-leg_twist") + twist.length /= 4 + twist.connected = False + twist.parent = obj.data.edit_bones[definitions[3]] + + # Create foot bone + foot = copy_bone_simple(obj.data, definitions[3], "DEF-%s" % base_names[definitions[3]], parent=True) + + # Create toe bone + toe = copy_bone_simple(obj.data, definitions[4], "DEF-%s" % base_names[definitions[4]], parent=True) + + # Store names before leaving edit mode + uleg1_name = uleg1.name + uleg2_name = uleg2.name + lleg1_name = lleg1.name + lleg2_name = lleg2.name + twist_name = twist.name + foot_name = foot.name + toe_name = toe.name + + # Leave edit mode + bpy.ops.object.mode_set(mode='OBJECT') + + # Get the pose bones + uleg1 = obj.pose.bones[uleg1_name] + uleg2 = obj.pose.bones[uleg2_name] + lleg1 = obj.pose.bones[lleg1_name] + lleg2 = obj.pose.bones[lleg2_name] + foot = obj.pose.bones[foot_name] + toe = obj.pose.bones[toe_name] + + # Upper leg constraints + con = uleg1.constraints.new('DAMPED_TRACK') + con.name = "trackto" + con.target = obj + con.subtarget = definitions[2] + + con = uleg2.constraints.new('COPY_ROTATION') + con.name = "copy_rot" + con.target = obj + con.subtarget = definitions[1] + + # Lower leg constraints + con = lleg1.constraints.new('COPY_ROTATION') + con.name = "copy_rot" + con.target = obj + con.subtarget = definitions[2] + + con = lleg2.constraints.new('COPY_ROTATION') + con.name = "copy_rot" + con.target = obj + con.subtarget = twist_name + + con = lleg2.constraints.new('DAMPED_TRACK') + con.name = "trackto" + con.target = obj + con.subtarget = definitions[3] + + # Foot constraint + con = foot.constraints.new('COPY_ROTATION') + con.name = "copy_rot" + con.target = obj + con.subtarget = definitions[3] + + # Toe constraint + con = toe.constraints.new('COPY_ROTATION') + con.name = "copy_rot" + con.target = obj + con.subtarget = definitions[4] + + bpy.ops.object.mode_set(mode='EDIT') + return (uleg1_name, uleg2_name, lleg1_name, lleg2_name, foot_name, toe_name, None) def main(obj, bone_definition, base_names, options): bones_fk = fk(obj, bone_definition, base_names, options) bones_ik = ik(obj, bone_definition, base_names, options) + deform(obj, bone_definition, base_names, options) bpy.ops.object.mode_set(mode='OBJECT') - blend_bone_list(obj, bone_definition, bones_fk, bones_ik, target_bone=bones_ik[1], blend_default=0.0) + blend_bone_list(obj, bone_definition + [None], bones_fk, bones_ik, target_bone=bones_ik[6], target_prop="ik", blend_default=0.0) + diff --git a/release/scripts/modules/rigify/leg_quadruped_generic.py b/release/scripts/modules/rigify/leg_quadruped_generic.py index 5f8f274c963..36481d91676 100644 --- a/release/scripts/modules/rigify/leg_quadruped_generic.py +++ b/release/scripts/modules/rigify/leg_quadruped_generic.py @@ -20,7 +20,7 @@ import bpy from rigify import RigifyError -from rigify_utils import bone_class_instance, copy_bone_simple, add_pole_target_bone +from rigify_utils import bone_class_instance, copy_bone_simple, add_pole_target_bone, get_base_name, get_side_name from Mathutils import Vector METARIG_NAMES = "hips", "thigh", "shin", "foot", "toe" @@ -119,7 +119,7 @@ def ik(obj, bone_definition, base_names, options): ik_chain.thigh_e.parent = mt.hips_e ik_chain.foot_e.parent = None - ik_chain.rename("foot", ik_chain.foot + "_ik") + ik_chain.rename("foot", get_base_name(ik_chain.foot) + "_ik" + get_side_name(ik_chain.foot)) # keep the foot_ik as the parent ik_chain.toe_e.connected = False @@ -130,14 +130,14 @@ def ik(obj, bone_definition, base_names, options): # children of ik_foot ik = bone_class_instance(obj, ["foot", "foot_roll", "foot_roll_01", "foot_roll_02", "knee_target", "foot_target"]) - ik.knee_target = add_pole_target_bone(obj, mt_chain.shin, "knee_target") #XXX - pick a better name + ik.knee_target = add_pole_target_bone(obj, mt_chain.shin, "knee_target" + get_side_name(base_names[mt_chain.foot])) #XXX - pick a better name ik.update() ik.knee_target_e.parent = mt.hips_e # foot roll is an interesting one! # plot a vector from the toe bones head, bactwards to the length of the foot # then align it with the foot but reverse direction. - ik.foot_roll_e = copy_bone_simple(arm, mt_chain.toe, base_names[mt_chain.foot] + "_roll") + ik.foot_roll_e = copy_bone_simple(arm, mt_chain.toe, get_base_name(base_names[mt_chain.foot]) + "_roll" + get_side_name(base_names[mt_chain.foot])) ik.foot_roll = ik.foot_roll_e.name ik.foot_roll_e.parent = ik_chain.foot_e ik.foot_roll_e.translate(- (mt_chain.toe_e.vector.normalize() * mt_chain.foot_e.length)) @@ -174,19 +174,19 @@ def ik(obj, bone_definition, base_names, options): ik_chain.update() # simple constraining of orig bones - con = mt_chain.thigh_p.constraints.new('COPY_ROTATION') + con = mt_chain.thigh_p.constraints.new('COPY_TRANSFORMS') con.target = obj con.subtarget = ik_chain.thigh - con = mt_chain.shin_p.constraints.new('COPY_ROTATION') + con = mt_chain.shin_p.constraints.new('COPY_TRANSFORMS') con.target = obj con.subtarget = ik_chain.shin - con = mt_chain.foot_p.constraints.new('COPY_ROTATION') + con = mt_chain.foot_p.constraints.new('COPY_TRANSFORMS') con.target = obj con.subtarget = ik.foot_roll_02 - con = mt_chain.toe_p.constraints.new('COPY_ROTATION') + con = mt_chain.toe_p.constraints.new('COPY_TRANSFORMS') con.target = obj con.subtarget = ik_chain.toe diff --git a/release/scripts/modules/rigify/neck_flex.py b/release/scripts/modules/rigify/neck_flex.py index c52230ed30a..a56c7dcb4e3 100644 --- a/release/scripts/modules/rigify/neck_flex.py +++ b/release/scripts/modules/rigify/neck_flex.py @@ -100,6 +100,30 @@ def metarig_definition(obj, orig_bone_name): return bone_definition +def deform(obj, definitions, base_names, options): + for org_bone_name in definitions[2:]: + bpy.ops.object.mode_set(mode='EDIT') + + # Create deform bone. + bone = copy_bone_simple(obj.data, org_bone_name, "DEF-%s" % base_names[org_bone_name], parent=True) + + # Store name before leaving edit mode + bone_name = bone.name + + # Leave edit mode + bpy.ops.object.mode_set(mode='OBJECT') + + # Get the pose bone + bone = obj.pose.bones[bone_name] + + # Constrain to the original bone + # XXX. Todo, is this needed if the bone is connected to its parent? + con = bone.constraints.new('COPY_TRANSFORMS') + con.name = "copy_loc" + con.target = obj + con.subtarget = org_bone_name + + def main(obj, bone_definition, base_names, options): from Mathutils import Vector @@ -180,6 +204,7 @@ def main(obj, bone_definition, base_names, options): else: neck_e_parent.parent = orig_parent + deform(obj, bone_definition, base_names, options) bpy.ops.object.mode_set(mode='OBJECT') @@ -213,12 +238,12 @@ def main(obj, bone_definition, base_names, options): fcurve = con.driver_add("influence", 0) driver = fcurve.driver - tar = driver.targets.new() + var = driver.variables.new() driver.type = 'AVERAGE' - tar.name = "var" - tar.id_type = 'OBJECT' - tar.id = obj - tar.data_path = hinge_driver_path + var.name = "var" + var.targets[0].id_type = 'OBJECT' + var.targets[0].id = obj + var.targets[0].data_path = hinge_driver_path #mod = fcurve_driver.modifiers.new('GENERATOR') mod = fcurve.modifiers[0] @@ -237,11 +262,11 @@ def main(obj, bone_definition, base_names, options): fcurve.modifiers.remove(0) # grr dont need a modifier for i in range(len(neck_chain)): - tar = driver.targets.new() - tar.name = target_names[i] - tar.id_type = 'OBJECT' - tar.id = obj - tar.data_path = head_driver_path + ('["bend_%.2d"]' % (i + 1)) + var = driver.variables.new() + var.name = target_names[i] + var.targets[0].id_type = 'OBJECT' + var.targets[0].id = obj + var.targets[0].data_path = head_driver_path + ('["bend_%.2d"]' % (i + 1)) for i, attr in enumerate(ex_chain.attr_names): @@ -277,17 +302,17 @@ def main(obj, bone_definition, base_names, options): # add target - tar = driver.targets.new() - tar.name = "bend_tot" - tar.id_type = 'OBJECT' - tar.id = obj - tar.data_path = head_driver_path + ('["bend_tot"]') - - tar = driver.targets.new() - tar.name = "bend" - tar.id_type = 'OBJECT' - tar.id = obj - tar.data_path = head_driver_path + ('["%s"]' % prop_name) + var = driver.variables.new() + var.name = "bend_tot" + var.targets[0].id_type = 'OBJECT' + var.targets[0].id = obj + var.targets[0].data_path = head_driver_path + ('["bend_tot"]') + + var = driver.variables.new() + var.name = "bend" + var.targets[0].id_type = 'OBJECT' + var.targets[0].id = obj + var.targets[0].data_path = head_driver_path + ('["%s"]' % prop_name) # finally constrain the original bone to this one diff --git a/release/scripts/modules/rigify/palm_curl.py b/release/scripts/modules/rigify/palm_curl.py index f2ddcca6d59..548c311f823 100644 --- a/release/scripts/modules/rigify/palm_curl.py +++ b/release/scripts/modules/rigify/palm_curl.py @@ -98,6 +98,30 @@ def metarig_definition(obj, orig_bone_name): return [palm_parent.name] + bone_definition +def deform(obj, definitions, base_names, options): + for org_bone_name in definitions[1:]: + bpy.ops.object.mode_set(mode='EDIT') + + # Create deform bone. + bone = copy_bone_simple(obj.data, org_bone_name, "DEF-%s" % base_names[org_bone_name], parent=True) + + # Store name before leaving edit mode + bone_name = bone.name + + # Leave edit mode + bpy.ops.object.mode_set(mode='OBJECT') + + # Get the pose bone + bone = obj.pose.bones[bone_name] + + # Constrain to the original bone + # XXX. Todo, is this needed if the bone is connected to its parent? + con = bone.constraints.new('COPY_TRANSFORMS') + con.name = "copy_loc" + con.target = obj + con.subtarget = org_bone_name + + def main(obj, bone_definition, base_names, options): arm = obj.data @@ -117,6 +141,8 @@ def main(obj, bone_definition, base_names, options): offset = (pinky_ebone.head - ring_ebone.head) control_ebone.translate(offset) + + deform(obj, bone_definition, base_names, options) bpy.ops.object.mode_set(mode='OBJECT') @@ -143,22 +169,22 @@ def main(obj, bone_definition, base_names, options): driver = driver_fcurves[0].driver driver.type = 'AVERAGE' - tar = driver.targets.new() - tar.name = "x" - tar.id_type = 'OBJECT' - tar.id = obj - tar.data_path = controller_path + ".rotation_euler[0]" + var = driver.variables.new() + var.name = "x" + var.targets[0].id_type = 'OBJECT' + var.targets[0].id = obj + var.targets[0].data_path = controller_path + ".rotation_euler[0]" # ***** driver = driver_fcurves[1].driver driver.expression = "-x/4.0" - tar = driver.targets.new() - tar.name = "x" - tar.id_type = 'OBJECT' - tar.id = obj - tar.data_path = controller_path + ".rotation_euler[0]" + var = driver.variables.new() + var.name = "x" + var.targets[0].id_type = 'OBJECT' + var.targets[0].id = obj + var.targets[0].data_path = controller_path + ".rotation_euler[0]" # ***** @@ -168,17 +194,17 @@ def main(obj, bone_definition, base_names, options): for fcurve in driver_fcurves: fcurve.modifiers.remove(0) # grr dont need a modifier - tar = driver.targets.new() - tar.name = "x" - tar.id_type = 'OBJECT' - tar.id = obj - tar.data_path = controller_path + ".rotation_euler[0]" - - tar = driver.targets.new() - tar.name = "s" - tar.id_type = 'OBJECT' - tar.id = obj - tar.data_path = controller_path + '["spread"]' + var = driver.variables.new() + var.name = "x" + var.targets[0].id_type = 'OBJECT' + var.targets[0].id = obj + var.targets[0].data_path = controller_path + ".rotation_euler[0]" + + var = driver.variables.new() + var.name = "s" + var.targets[0].id_type = 'OBJECT' + var.targets[0].id = obj + var.targets[0].data_path = controller_path + '["spread"]' for i, child_name in enumerate(children): diff --git a/release/scripts/modules/rigify/spine_pivot_flex.py b/release/scripts/modules/rigify/spine_pivot_flex.py index 895a5d854c0..c6a5fa67390 100644 --- a/release/scripts/modules/rigify/spine_pivot_flex.py +++ b/release/scripts/modules/rigify/spine_pivot_flex.py @@ -122,6 +122,30 @@ def fk(*args): main(*args) +def deform(obj, definitions, base_names, options): + for org_bone_name in definitions[2:]: + bpy.ops.object.mode_set(mode='EDIT') + + # Create deform bone. + bone = copy_bone_simple(obj.data, org_bone_name, "DEF-%s" % base_names[org_bone_name], parent=True) + + # Store name before leaving edit mode + bone_name = bone.name + + # Leave edit mode + bpy.ops.object.mode_set(mode='OBJECT') + + # Get the pose bone + bone = obj.pose.bones[bone_name] + + # Constrain to the original bone + # XXX. Todo, is this needed if the bone is connected to its parent? + con = bone.constraints.new('COPY_TRANSFORMS') + con.name = "copy_loc" + con.target = obj + con.subtarget = org_bone_name + + def main(obj, bone_definition, base_names, options): from Mathutils import Vector, RotationMatrix from math import radians, pi @@ -269,6 +293,7 @@ def main(obj, bone_definition, base_names, options): spine_e.roll += pi # 180d roll del spine_e + deform(obj, bone_definition, base_names, options) bpy.ops.object.mode_set(mode='OBJECT') @@ -316,12 +341,12 @@ def main(obj, bone_definition, base_names, options): # add driver fcurve = con.driver_add("influence", 0) driver = fcurve.driver - tar = driver.targets.new() + var = driver.variables.new() driver.type = 'AVERAGE' - tar.name = "var" - tar.id_type = 'OBJECT' - tar.id = obj - tar.data_path = ex.ribcage_copy_p.path_to_id() + '["hinge"]' + var.name = "var" + var.targets[0].id_type = 'OBJECT' + var.targets[0].id = obj + var.targets[0].data_path = ex.ribcage_copy_p.path_to_id() + '["hinge"]' mod = fcurve.modifiers[0] mod.poly_order = 1 @@ -401,11 +426,11 @@ def main(obj, bone_definition, base_names, options): fcurve.modifiers.remove(0) # grr dont need a modifier for i in range(spine_chain_len - 1): - tar = driver.targets.new() - tar.name = target_names[i] - tar.id_type = 'OBJECT' - tar.id = obj - tar.data_path = rib_driver_path + ('["bend_%.2d"]' % (i + 1)) + var = driver.variables.new() + var.name = target_names[i] + var.targets[0].id_type = 'OBJECT' + var.targets[0].id = obj + var.targets[0].data_path = rib_driver_path + ('["bend_%.2d"]' % (i + 1)) for i in range(1, spine_chain_len): @@ -436,17 +461,17 @@ def main(obj, bone_definition, base_names, options): # add target - tar = driver.targets.new() - tar.name = "bend_tot" - tar.id_type = 'OBJECT' - tar.id = obj - tar.data_path = rib_driver_path + ('["bend_tot"]') + var = driver.variables.new() + var.name = "bend_tot" + var.targets[0].id_type = 'OBJECT' + var.targets[0].id = obj + var.targets[0].data_path = rib_driver_path + ('["bend_tot"]') - tar = driver.targets.new() - tar.name = "bend" - tar.id_type = 'OBJECT' - tar.id = obj - tar.data_path = rib_driver_path + ('["%s"]' % prop_name) + var = driver.variables.new() + var.name = "bend" + var.targets[0].id_type = 'OBJECT' + var.targets[0].id = obj + var.targets[0].data_path = rib_driver_path + ('["%s"]' % prop_name) @@ -484,12 +509,12 @@ def main(obj, bone_definition, base_names, options): fcurve = con.driver_add("influence", 0) driver = fcurve.driver - tar = driver.targets.new() + var = driver.variables.new() driver.type = 'AVERAGE' - tar.name = "var" - tar.id_type = 'OBJECT' - tar.id = obj - tar.data_path = rib_driver_path + '["pivot_slide"]' + var.name = "var" + var.targets[0].id_type = 'OBJECT' + var.targets[0].id = obj + var.targets[0].data_path = rib_driver_path + '["pivot_slide"]' mod = fcurve.modifiers[0] mod.poly_order = 1 diff --git a/release/scripts/modules/rigify_utils.py b/release/scripts/modules/rigify_utils.py index 371792a3633..b453ef77d4f 100644 --- a/release/scripts/modules/rigify_utils.py +++ b/release/scripts/modules/rigify_utils.py @@ -129,7 +129,7 @@ def blend_bone_list(obj, apply_bones, from_bones, to_bones, target_bone=None, ta target_bone = apply_bones[-1] # default to the last bone prop_pbone = obj.pose.bones[target_bone] - if prop_pbone.get(target_bone, None) is None: + if prop_pbone.get(target_bone) is None: prop = rna_idprop_ui_prop_get(prop_pbone, target_prop, create=True) prop_pbone[target_prop] = blend_default prop["soft_min"] = 0.0 @@ -138,11 +138,11 @@ def blend_bone_list(obj, apply_bones, from_bones, to_bones, target_bone=None, ta driver_path = prop_pbone.path_to_id() + ('["%s"]' % target_prop) def blend_target(driver): - tar = driver.targets.new() - tar.name = target_bone - tar.id_type = 'OBJECT' - tar.id = obj - tar.data_path = driver_path + var = driver.variables.new() + var.name = target_bone + var.targets[0].id_type = 'OBJECT' + var.targets[0].id = obj + var.targets[0].data_path = driver_path def blend_location(new_pbone, from_bone_name, to_bone_name): con = new_pbone.constraints.new('COPY_LOCATION') @@ -402,9 +402,9 @@ def _bone_class_instance_update(self): for member in self.attr_names: name = getattr(self, member, None) if name is not None: - setattr(self, member + "_b", bbones.get(name, None)) - setattr(self, member + "_p", pbones.get(name, None)) - setattr(self, member + "_e", ebones.get(name, None)) + setattr(self, member + "_b", bbones.get(name)) + setattr(self, member + "_p", pbones.get(name)) + setattr(self, member + "_e", ebones.get(name)) def _bone_class_instance_rename(self, attr, new_name): diff --git a/release/scripts/modules/rna_info.py b/release/scripts/modules/rna_info.py index 86da0b56943..5d7bd5af70a 100644 --- a/release/scripts/modules/rna_info.py +++ b/release/scripts/modules/rna_info.py @@ -252,19 +252,22 @@ class InfoFunctionRNA: self.description = rna_func.description.strip() self.args = [] - self.return_value = None + self.return_values = () def build(self): rna_func = self.bl_func parent_id = rna_func + self.return_values = [] for rna_prop in rna_func.parameters.values(): prop = GetInfoPropertyRNA(rna_prop, parent_id) if rna_prop.use_return: - self.return_value = prop + self.return_values.append(prop) else: self.args.append(prop) + self.return_values = tuple(self.return_values) + def __repr__(self): txt = '' txt += ' * ' + self.identifier + '(' @@ -566,8 +569,8 @@ def BuildRNAInfo(): func.build() for prop in func.args: prop.build() - if func.return_value: - func.return_value.build() + for prop in func.return_values: + prop.build() # now for operators op_mods = dir(bpy.ops) diff --git a/release/scripts/modules/rna_prop_ui.py b/release/scripts/modules/rna_prop_ui.py index 543a10e47e9..f5b9e518c8f 100644 --- a/release/scripts/modules/rna_prop_ui.py +++ b/release/scripts/modules/rna_prop_ui.py @@ -124,6 +124,18 @@ def draw(layout, context, context_member, use_edit=True): assign_props(prop, val_draw, key) +class PropertyPanel(bpy.types.Panel): + """ + The subclass should have its own poll function + and the variable '_context_path' MUST be set. + """ + bl_label = "Custom Properties" + bl_default_closed = True + + def draw(self, context): + draw(self.layout, context, self._context_path) + + from bpy.props import * @@ -257,3 +269,4 @@ class WM_OT_properties_remove(bpy.types.Operator): item = eval("context.%s" % self.properties.path) del item[self.properties.property] return {'FINISHED'} + diff --git a/release/scripts/op/add_mesh_torus.py b/release/scripts/op/add_mesh_torus.py index 372afb3654f..865b1d57daf 100644 --- a/release/scripts/op/add_mesh_torus.py +++ b/release/scripts/op/add_mesh_torus.py @@ -101,7 +101,7 @@ class AddTorus(bpy.types.Operator): self.properties.major_segments, self.properties.minor_segments) - mesh = bpy.data.add_mesh("Torus") + mesh = bpy.data.meshes.new("Torus") mesh.add_geometry(int(len(verts_loc) / 3), 0, int(len(faces) / 4)) mesh.verts.foreach_set("co", verts_loc) @@ -114,7 +114,7 @@ class AddTorus(bpy.types.Operator): ob.selected = False mesh.update() - ob_new = bpy.data.add_object('MESH', "Torus") + ob_new = bpy.data.objects.new("Torus", 'MESH') ob_new.data = mesh scene.objects.link(ob_new) scene.objects.active = ob_new diff --git a/release/scripts/op/object.py b/release/scripts/op/object.py index 5e261c18c23..dd95c6f51a6 100644 --- a/release/scripts/op/object.py +++ b/release/scripts/op/object.py @@ -145,6 +145,7 @@ class Retopo(bpy.types.Operator): def execute(self, context): import retopo + reload(retopo) retopo.main() return {'FINISHED'} @@ -176,11 +177,12 @@ class ShapeTransfer(bpy.types.Operator): def me_cos(verts): return [v.co.copy() for v in verts] - def ob_add_shape(ob): + def ob_add_shape(ob, name): me = ob.data - ob.add_shape_key(from_mix=False) + key = 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 + key = ob.add_shape_key(from_mix=False) # we need a rest + key.name = name ob.active_shape_key_index = len(me.shape_keys.keys) - 1 ob.shape_key_lock = True @@ -191,6 +193,7 @@ class ShapeTransfer(bpy.types.Operator): use_clamp = False me = ob_act.data + orig_key_name = ob_act.active_shape_key.name orig_shape_coords = me_cos(ob_act.active_shape_key.data) @@ -206,7 +209,7 @@ class ShapeTransfer(bpy.types.Operator): target_normals = me_nos(me_other.verts) target_coords = me_cos(me_other.verts) - ob_add_shape(ob_other) + ob_add_shape(ob_other, orig_key_name) # editing the final coords, only list that stores wrapped coords target_shape_coords = [v.co for v in ob_other.active_shape_key.data] @@ -310,6 +313,9 @@ class ShapeTransfer(bpy.types.Operator): def execute(self, context): C = bpy.context ob_act = C.active_object + if ob_act.active_shape_key is None: + self.report({'ERROR'}, "Active object has no shape key") + return {'CANCELLED'} 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) diff --git a/release/scripts/op/screen_play_rendered_anim.py b/release/scripts/op/screen_play_rendered_anim.py index a8c97010cce..b52bdf46ebd 100644 --- a/release/scripts/op/screen_play_rendered_anim.py +++ b/release/scripts/op/screen_play_rendered_anim.py @@ -29,39 +29,6 @@ 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', - } - -movie_formats = ('QUICKTIME_QTKIT', - 'QUICKTIME_CARBONTKIT', - 'AVIRAW', - 'AVIJPEG', - 'AVICODEC', - 'XVID', - 'THEORA') - - def guess_player_path(preset): if preset == 'BLENDER24': player_path = 'blender' @@ -112,16 +79,13 @@ class PlayRenderedAnim(bpy.types.Operator): if player_path == '': player_path = guess_player_path(preset) - # doesn't support ### frame notation yet - if rd.file_format in movie_formats: - file = "%s%04d_%04d" % (file_path, sce.start_frame, sce.end_frame) - elif preset in ('BLENDER24', 'DJV', 'CUSTOM'): - file = "%s%04d" % (file_path, sce.start_frame) - elif preset in ('FRAMECYCLER', 'RV'): - file = "%s#" % file_path - - if rd.file_extensions: - file += '.' + img_format_exts[rd.file_format] + if preset in ('FRAMECYCLER', 'RV'): + # replace the number with '#' + file_a, file_b = rd.frame_path(frame=0), rd.frame_path(frame=1) + file = ''.join([(c if file_b[i] == c else "#") for i, c in enumerate(file_a)]) + else: + # works for movies and images + file = rd.frame_path(frame=sce.start_frame) cmd = [player_path] # extra options, fps controls etc. diff --git a/release/scripts/op/wm.py b/release/scripts/op/wm.py index ef7386049c3..4796ec8c97c 100644 --- a/release/scripts/op/wm.py +++ b/release/scripts/op/wm.py @@ -42,6 +42,8 @@ rna_path_prop = StringProperty(name="Context Attributes", rna_reverse_prop = BoolProperty(name="Reverse", description="Cycle backwards", default=False) +rna_relative_prop = BoolProperty(name="Relative", + description="Apply relative to the current value (delta)", default=False) def context_path_validate(context, path): import sys @@ -61,7 +63,12 @@ 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'} - exec("context.%s=self.properties.value" % self.properties.path) + + if getattr(self.properties, "relative", False): + exec("context.%s+=self.properties.value" % self.properties.path) + else: + exec("context.%s=self.properties.value" % self.properties.path) + return {'FINISHED'} @@ -86,6 +93,7 @@ class WM_OT_context_set_int(bpy.types.Operator): # same as enum path = rna_path_prop value = IntProperty(name="Value", description="Assign value", default=0) + relative = rna_relative_prop execute = execute_context_assign @@ -97,8 +105,8 @@ class WM_OT_context_set_float(bpy.types.Operator): # same as enum bl_undo = True path = rna_path_prop - value = FloatProperty(name="Value", - description="Assignment value", default=0.0) + value = FloatProperty(name="Value", description="Assignment value", default=0.0) + relative = rna_relative_prop execute = execute_context_assign @@ -204,25 +212,26 @@ class WM_OT_context_cycle_int(bpy.types.Operator): reverse = rna_reverse_prop def execute(self, context): - - value = context_path_validate(context, self.properties.path) + path = self.properties.path + value = context_path_validate(context, path) if value is Ellipsis: return {'PASS_THROUGH'} - self.properties.value = value if self.properties.reverse: - self.properties.value -= 1 + value -= 1 else: - self.properties.value += 1 - execute_context_assign(self, context) + value += 1 + + exec("context.%s=value" % path) - if self.properties.value != eval("context.%s" % self.properties.path): + if value != eval("context.%s" % path): # relies on rna clamping int's out of the range if self.properties.reverse: - self.properties.value = (1 << 32) + value = (1 << 32) else: - self.properties.value = - (1 << 32) - execute_context_assign(self, context) + value = - (1 << 32) + + exec("context.%s=value" % path) return {'FINISHED'} diff --git a/release/scripts/ui/properties_data_armature.py b/release/scripts/ui/properties_data_armature.py index 28cf215fa62..bded38ee3cc 100644 --- a/release/scripts/ui/properties_data_armature.py +++ b/release/scripts/ui/properties_data_armature.py @@ -18,6 +18,7 @@ # <pep8 compliant> import bpy +from rna_prop_ui import PropertyPanel narrowui = 180 @@ -55,6 +56,10 @@ class DATA_PT_context_arm(DataButtonsPanel): layout.template_ID(ob, "data") +class DATA_PT_custom_props_arm(DataButtonsPanel, PropertyPanel): + _context_path = "object.data" + + class DATA_PT_skeleton(DataButtonsPanel): bl_label = "Skeleton" @@ -89,6 +94,7 @@ class DATA_PT_display(DataButtonsPanel): def draw(self, context): layout = self.layout + ob = context.object arm = context.armature wide_ui = context.region.width > narrowui @@ -108,6 +114,7 @@ class DATA_PT_display(DataButtonsPanel): col = split.column() col.prop(arm, "draw_group_colors", text="Colors") col.prop(arm, "delay_deform", text="Delay Refresh") + col.prop(ob, "x_ray", text="X-Ray (Object)") class DATA_PT_bone_groups(DataButtonsPanel): @@ -290,6 +297,7 @@ class DATA_PT_iksolver_itasc(DataButtonsPanel): row.prop(itasc, "dampmax", text="Damp", slider=True) row.prop(itasc, "dampeps", text="Eps", slider=True) + bpy.types.register(DATA_PT_context_arm) bpy.types.register(DATA_PT_skeleton) bpy.types.register(DATA_PT_display) @@ -297,3 +305,5 @@ bpy.types.register(DATA_PT_bone_groups) bpy.types.register(DATA_PT_paths) bpy.types.register(DATA_PT_ghost) bpy.types.register(DATA_PT_iksolver_itasc) + +bpy.types.register(DATA_PT_custom_props_arm) diff --git a/release/scripts/ui/properties_data_bone.py b/release/scripts/ui/properties_data_bone.py index 3369adab5a8..96cf400d738 100644 --- a/release/scripts/ui/properties_data_bone.py +++ b/release/scripts/ui/properties_data_bone.py @@ -18,6 +18,7 @@ # <pep8 compliant> import bpy +from rna_prop_ui import PropertyPanel narrowui = 180 @@ -47,6 +48,17 @@ class BONE_PT_context_bone(BoneButtonsPanel): row.prop(bone, "name", text="") +class BONE_PT_custom_props(BoneButtonsPanel, PropertyPanel): + + @property + def _context_path(self): + obj = bpy.context.object + if obj and obj.mode == 'POSE': + return "active_pose_bone" + else: + return "active_bone" + + class BONE_PT_transform(BoneButtonsPanel): bl_label = "Transform" @@ -223,8 +235,11 @@ class BONE_PT_display(BoneButtonsPanel): if wide_ui: col = split.column() + col.label(text="Custom Shape:") col.prop(pchan, "custom_shape", text="") + if pchan.custom_shape: + col.prop_object(pchan, "custom_shape_transform", ob.pose, "bones", text="At") class BONE_PT_inverse_kinematics(BoneButtonsPanel): @@ -373,21 +388,6 @@ class BONE_PT_deform(BoneButtonsPanel): col.prop(bone, "cyclic_offset") -class BONE_PT_properties(BoneButtonsPanel): - bl_label = "Properties" - bl_default_closed = True - - def draw(self, context): - import rna_prop_ui - # reload(rna_prop_ui) - obj = context.object - if obj and obj.mode == 'POSE': - item = "active_pose_bone" - else: - item = "active_bone" - - rna_prop_ui.draw(self.layout, context, item) - bpy.types.register(BONE_PT_context_bone) bpy.types.register(BONE_PT_transform) bpy.types.register(BONE_PT_transform_locks) @@ -395,4 +395,5 @@ bpy.types.register(BONE_PT_relations) bpy.types.register(BONE_PT_display) bpy.types.register(BONE_PT_inverse_kinematics) bpy.types.register(BONE_PT_deform) -bpy.types.register(BONE_PT_properties) + +bpy.types.register(BONE_PT_custom_props) diff --git a/release/scripts/ui/properties_data_camera.py b/release/scripts/ui/properties_data_camera.py index e8cba6be7df..d2889b6629e 100644 --- a/release/scripts/ui/properties_data_camera.py +++ b/release/scripts/ui/properties_data_camera.py @@ -18,6 +18,7 @@ # <pep8 compliant> import bpy +from rna_prop_ui import PropertyPanel narrowui = 180 @@ -58,6 +59,10 @@ class DATA_PT_context_camera(DataButtonsPanel): layout.template_ID(space, "pin_id") +class DATA_PT_custom_props_camera(DataButtonsPanel, PropertyPanel): + _context_path = "object.data" + + class DATA_PT_camera(DataButtonsPanel): bl_label = "Lens" @@ -140,6 +145,9 @@ class DATA_PT_camera_display(DataButtonsPanel): sub.active = cam.show_passepartout sub.prop(cam, "passepartout_alpha", text="Alpha", slider=True) + bpy.types.register(DATA_PT_context_camera) bpy.types.register(DATA_PT_camera) bpy.types.register(DATA_PT_camera_display) + +bpy.types.register(DATA_PT_custom_props_camera) diff --git a/release/scripts/ui/properties_data_curve.py b/release/scripts/ui/properties_data_curve.py index 3ee16ad9585..442590b8946 100644 --- a/release/scripts/ui/properties_data_curve.py +++ b/release/scripts/ui/properties_data_curve.py @@ -18,6 +18,7 @@ # <pep8 compliant> import bpy +from rna_prop_ui import PropertyPanel narrowui = 180 @@ -72,6 +73,10 @@ class DATA_PT_context_curve(DataButtonsPanel): layout.template_ID(ob, "data") +class DATA_PT_custom_props_curve(DataButtonsPanel, PropertyPanel): + _context_path = "object.data" + + class DATA_PT_shape_curve(DataButtonsPanel): bl_label = "Shape" @@ -377,6 +382,7 @@ class DATA_PT_textboxes(DataButtonsPanel): col.prop(box, "x", text="X") col.prop(box, "y", text="Y") + bpy.types.register(DATA_PT_context_curve) bpy.types.register(DATA_PT_shape_curve) bpy.types.register(DATA_PT_geometry_curve) @@ -385,3 +391,5 @@ bpy.types.register(DATA_PT_active_spline) bpy.types.register(DATA_PT_font) bpy.types.register(DATA_PT_paragraph) bpy.types.register(DATA_PT_textboxes) + +bpy.types.register(DATA_PT_custom_props_curve) diff --git a/release/scripts/ui/properties_data_lamp.py b/release/scripts/ui/properties_data_lamp.py index d5025983ff3..24f6486cdf6 100644 --- a/release/scripts/ui/properties_data_lamp.py +++ b/release/scripts/ui/properties_data_lamp.py @@ -18,6 +18,7 @@ # <pep8 compliant> import bpy +from rna_prop_ui import PropertyPanel narrowui = 180 @@ -65,6 +66,10 @@ class DATA_PT_context_lamp(DataButtonsPanel): layout.template_ID(space, "pin_id") +class DATA_PT_custom_props_lamp(DataButtonsPanel, PropertyPanel): + _context_path = "object.data" + + class DATA_PT_lamp(DataButtonsPanel): bl_label = "Lamp" @@ -374,6 +379,7 @@ class DATA_PT_falloff_curve(DataButtonsPanel): self.layout.template_curve_mapping(lamp, "falloff_curve") + bpy.types.register(DATA_PT_context_lamp) bpy.types.register(DATA_PT_preview) bpy.types.register(DATA_PT_lamp) @@ -382,3 +388,5 @@ bpy.types.register(DATA_PT_area) bpy.types.register(DATA_PT_spot) bpy.types.register(DATA_PT_shadow) bpy.types.register(DATA_PT_sunsky) + +bpy.types.register(DATA_PT_custom_props_lamp) diff --git a/release/scripts/ui/properties_data_lattice.py b/release/scripts/ui/properties_data_lattice.py index 640f625a7de..a6221fa5e63 100644 --- a/release/scripts/ui/properties_data_lattice.py +++ b/release/scripts/ui/properties_data_lattice.py @@ -18,6 +18,7 @@ # <pep8 compliant> import bpy +from rna_prop_ui import PropertyPanel narrowui = 180 @@ -58,6 +59,10 @@ class DATA_PT_context_lattice(DataButtonsPanel): layout.template_ID(space, "pin_id") +class DATA_PT_custom_props_lattice(DataButtonsPanel, PropertyPanel): + _context_path = "object.data" + + class DATA_PT_lattice(DataButtonsPanel): bl_label = "Lattice" @@ -90,5 +95,8 @@ class DATA_PT_lattice(DataButtonsPanel): layout.prop(lat, "outside") + bpy.types.register(DATA_PT_context_lattice) bpy.types.register(DATA_PT_lattice) + +bpy.types.register(DATA_PT_custom_props_lattice) diff --git a/release/scripts/ui/properties_data_mesh.py b/release/scripts/ui/properties_data_mesh.py index d6cdcfc2de9..a03d8d55005 100644 --- a/release/scripts/ui/properties_data_mesh.py +++ b/release/scripts/ui/properties_data_mesh.py @@ -18,6 +18,7 @@ # <pep8 compliant> import bpy +from rna_prop_ui import PropertyPanel narrowui = 180 @@ -58,6 +59,10 @@ class DATA_PT_context_mesh(DataButtonsPanel): layout.template_ID(space, "pin_id") +class DATA_PT_custom_props_mesh(DataButtonsPanel, PropertyPanel): + _context_path = "object.data" + + class DATA_PT_normals(DataButtonsPanel): bl_label = "Normals" @@ -150,7 +155,12 @@ class DATA_PT_shape_keys(DataButtonsPanel): ob = context.object key = ob.data.shape_keys - kb = ob.active_shape_key + if key and len(key.keys): + # this is so that we get the active shapekey from the + # shapekeys block, not from object data + kb = key.keys[ob.active_shape_key.name] + else: + kb = None wide_ui = context.region.width > narrowui enable_edit = ob.mode != 'EDIT' @@ -197,17 +207,12 @@ class DATA_PT_shape_keys(DataButtonsPanel): sub = row.row(align=True) subsub = sub.row(align=True) subsub.active = enable_edit_value - if ob.shape_key_lock: - subsub.prop(ob, "shape_key_lock", icon='PINNED', text="") - else: - subsub.prop(ob, "shape_key_lock", icon='UNPINNED', text="") - if kb.mute: - subsub.prop(kb, "mute", icon='MUTE_IPO_ON', text="") - else: - subsub.prop(kb, "mute", icon='MUTE_IPO_OFF', text="") + subsub.prop(ob, "shape_key_lock", icon='PINNED' if ob.shape_key_lock else 'UNPINNED', text="") + subsub.prop(kb, "mute", icon='MUTE_IPO_ON' if kb.mute else 'MUTE_IPO_OFF', text="") sub.prop(ob, "shape_key_edit_mode", text="") sub = row.row(align=True) + sub.operator("object.shape_key_transfer", icon='COPY_ID', text="") # icon is not ideal sub.operator("object.shape_key_mirror", icon='ARROW_LEFTRIGHT', text="") sub.operator("object.shape_key_clear", icon='X', text="") @@ -292,3 +297,6 @@ bpy.types.register(DATA_PT_vertex_groups) bpy.types.register(DATA_PT_shape_keys) bpy.types.register(DATA_PT_uv_texture) bpy.types.register(DATA_PT_vertex_colors) + +bpy.types.register(DATA_PT_custom_props_mesh) + diff --git a/release/scripts/ui/properties_data_metaball.py b/release/scripts/ui/properties_data_metaball.py index e36bdc991e1..8951693aaac 100644 --- a/release/scripts/ui/properties_data_metaball.py +++ b/release/scripts/ui/properties_data_metaball.py @@ -18,6 +18,7 @@ # <pep8 compliant> import bpy +from rna_prop_ui import PropertyPanel narrowui = 180 @@ -58,6 +59,10 @@ class DATA_PT_context_metaball(DataButtonsPanel): layout.template_ID(space, "pin_id") +class DATA_PT_custom_props_metaball(DataButtonsPanel, PropertyPanel): + _context_path = "object.data" + + class DATA_PT_metaball(DataButtonsPanel): bl_label = "Metaball" @@ -133,3 +138,7 @@ class DATA_PT_metaball_element(DataButtonsPanel): bpy.types.register(DATA_PT_context_metaball) bpy.types.register(DATA_PT_metaball) bpy.types.register(DATA_PT_metaball_element) + +bpy.types.register(DATA_PT_custom_props_metaball) + + diff --git a/release/scripts/ui/properties_material.py b/release/scripts/ui/properties_material.py index a48b3b1a30a..dfd4270e97b 100644 --- a/release/scripts/ui/properties_material.py +++ b/release/scripts/ui/properties_material.py @@ -18,6 +18,7 @@ # <pep8 compliant> import bpy +from rna_prop_ui import PropertyPanel narrowui = 180 @@ -125,6 +126,11 @@ class MATERIAL_PT_context_material(MaterialButtonsPanel): layout.prop(mat, "type", text="") +class MATERIAL_PT_custom_props(MaterialButtonsPanel, PropertyPanel): + COMPAT_ENGINES = {'BLENDER_RENDER'} + _context_path = "material" + + class MATERIAL_PT_shading(MaterialButtonsPanel): bl_label = "Shading" COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'} @@ -880,3 +886,5 @@ bpy.types.register(MATERIAL_PT_volume_shading) bpy.types.register(MATERIAL_PT_volume_lighting) bpy.types.register(MATERIAL_PT_volume_transp) bpy.types.register(MATERIAL_PT_volume_integration) + +bpy.types.register(MATERIAL_PT_custom_props) diff --git a/release/scripts/ui/properties_object.py b/release/scripts/ui/properties_object.py index ff7e15cde58..3b539506552 100644 --- a/release/scripts/ui/properties_object.py +++ b/release/scripts/ui/properties_object.py @@ -18,6 +18,7 @@ # <pep8 compliant> import bpy +from rna_prop_ui import PropertyPanel narrowui = 180 @@ -42,6 +43,10 @@ class OBJECT_PT_context_object(ObjectButtonsPanel): row.prop(ob, "name", text="") +class OBJECT_PT_custom_props(ObjectButtonsPanel, PropertyPanel): + _context_path = "object" + + class OBJECT_PT_transform(ObjectButtonsPanel): bl_label = "Transform" @@ -149,11 +154,13 @@ class OBJECT_PT_groups(ObjectButtonsPanel): if wide_ui: split = layout.split() - split.operator_menu_enum("object.group_add", "group", text="Add to Group") + split.operator_menu_enum("object.group_add", "group") split.label() else: - layout.operator_menu_enum("object.group_add", "group", text="Add to Group") + layout.operator_menu_enum("object.group_add", "group") + index = 0 + value = str(tuple(context.scene.cursor_location)) for group in bpy.data.groups: if ob.name in group.objects: col = layout.column(align=True) @@ -172,6 +179,11 @@ class OBJECT_PT_groups(ObjectButtonsPanel): if wide_ui: col = split.column() col.prop(group, "dupli_offset", text="") + + prop = col.operator("wm.context_set_value", text="From Cursor") + prop.path = "object.group_users[%d].dupli_offset" % index + prop.value = value + index += 1 class OBJECT_PT_display(ObjectButtonsPanel): @@ -235,20 +247,20 @@ class OBJECT_PT_duplication(ObjectButtonsPanel): col.prop(ob, "dupli_frames_on", text="On") col.prop(ob, "dupli_frames_off", text="Off") - layout.prop(ob, "dupli_frames_no_speed", text="No Speed") + layout.prop(ob, "use_dupli_frames_speed", text="Speed") elif ob.dupli_type == 'VERTS': - layout.prop(ob, "dupli_verts_rotation", text="Rotation") + layout.prop(ob, "use_dupli_verts_rotation", text="Rotation") elif ob.dupli_type == 'FACES': split = layout.split() col = split.column() - col.prop(ob, "dupli_faces_scale", text="Scale") + col.prop(ob, "use_dupli_faces_scale", text="Scale") if wide_ui: col = split.column() - col.prop(ob, "dupli_faces_inherit_scale", text="Inherit Scale") + col.prop(ob, "dupli_faces_scale", text="Inherit Scale") elif ob.dupli_type == 'GROUP': if wide_ui: @@ -293,16 +305,6 @@ class OBJECT_PT_animation(ObjectButtonsPanel): row.active = (ob.parent is not None) -class OBJECT_PT_properties(ObjectButtonsPanel): - bl_label = "Properties" - bl_default_closed = True - - def draw(self, context): - import rna_prop_ui - # reload(rna_prop_ui) - - rna_prop_ui.draw(self.layout, context, "object") - bpy.types.register(OBJECT_PT_context_object) bpy.types.register(OBJECT_PT_transform) bpy.types.register(OBJECT_PT_transform_locks) @@ -311,4 +313,5 @@ bpy.types.register(OBJECT_PT_groups) bpy.types.register(OBJECT_PT_display) bpy.types.register(OBJECT_PT_duplication) bpy.types.register(OBJECT_PT_animation) -bpy.types.register(OBJECT_PT_properties) + +bpy.types.register(OBJECT_PT_custom_props) diff --git a/release/scripts/ui/properties_object_constraint.py b/release/scripts/ui/properties_object_constraint.py index 12a12ff40dc..cb6f8cd71a2 100644 --- a/release/scripts/ui/properties_object_constraint.py +++ b/release/scripts/ui/properties_object_constraint.py @@ -37,8 +37,6 @@ class ConstraintButtonsPanel(bpy.types.Panel): # match enum type to our functions, avoids a lookup table. getattr(self, con.type)(context, box, con, wide_ui) - # show/key buttons here are most likely obsolete now, with - # keyframing functionality being part of every button if con.type not in ('RIGID_BODY_JOINT', 'SPLINE_IK', 'NULL'): box.prop(con, "influence") @@ -462,6 +460,12 @@ class ConstraintButtonsPanel(bpy.types.Panel): layout.prop(con, "use_offset") self.space_template(layout, con, wide_ui) + + def COPY_TRANSFORMS(self, context, layout, con, wide_ui): + self.target_template(layout, con, wide_ui) + + self.space_template(layout, con, wide_ui) + #def SCRIPT(self, context, layout, con): @@ -562,6 +566,8 @@ class ConstraintButtonsPanel(bpy.types.Panel): if wide_ui: row.label(text="Min/Max:") row.prop(con, "floor_location", expand=True) + + self.space_template(layout, con, wide_ui) def RIGID_BODY_JOINT(self, context, layout, con, wide_ui): self.target_template(layout, con, wide_ui) diff --git a/release/scripts/ui/properties_particle.py b/release/scripts/ui/properties_particle.py index a33a1a12f1b..14278ea197c 100644 --- a/release/scripts/ui/properties_particle.py +++ b/release/scripts/ui/properties_particle.py @@ -18,6 +18,7 @@ # <pep8 compliant> import bpy +from rna_prop_ui import PropertyPanel from properties_physics_common import point_cache_ui from properties_physics_common import effector_weights_ui @@ -47,7 +48,7 @@ class ParticleButtonsPanel(bpy.types.Panel): return particle_panel_poll(context) -class PARTICLE_PT_particles(ParticleButtonsPanel): +class PARTICLE_PT_context_particles(ParticleButtonsPanel): bl_label = "" bl_show_header = False @@ -130,6 +131,10 @@ class PARTICLE_PT_particles(ParticleButtonsPanel): split.prop(psys, "reactor_target_particle_system", text="Particle System") +class PARTICLE_PT_custom_props(ParticleButtonsPanel, PropertyPanel): + _context_path = "particle_system.settings" + + class PARTICLE_PT_emission(ParticleButtonsPanel): bl_label = "Emission" @@ -992,7 +997,7 @@ class PARTICLE_PT_vertexgroups(ParticleButtonsPanel): row.prop_object(psys, "vertex_group_field", ob, "vertex_groups", text="Field") row.prop(psys, "vertex_group_field_negate", text="") -bpy.types.register(PARTICLE_PT_particles) +bpy.types.register(PARTICLE_PT_context_particles) bpy.types.register(PARTICLE_PT_hair_dynamics) bpy.types.register(PARTICLE_PT_cache) bpy.types.register(PARTICLE_PT_emission) @@ -1006,3 +1011,5 @@ bpy.types.register(PARTICLE_PT_children) bpy.types.register(PARTICLE_PT_field_weights) bpy.types.register(PARTICLE_PT_force_fields) bpy.types.register(PARTICLE_PT_vertexgroups) + +bpy.types.register(PARTICLE_PT_custom_props) diff --git a/release/scripts/ui/properties_physics_field.py b/release/scripts/ui/properties_physics_field.py index c2f1703a912..90e0912896d 100644 --- a/release/scripts/ui/properties_physics_field.py +++ b/release/scripts/ui/properties_physics_field.py @@ -217,6 +217,7 @@ class PHYSICS_PT_collision(PhysicButtonsPanel): col = split.column() col.label(text="Particle:") col.prop(settings, "permeability", slider=True) + col.prop(settings, "stickness") col.prop(settings, "kill_particles") col.label(text="Particle Damping:") sub = col.column(align=True) diff --git a/release/scripts/ui/properties_render.py b/release/scripts/ui/properties_render.py index 5fb9662ba81..14396bb4c51 100644 --- a/release/scripts/ui/properties_render.py +++ b/release/scripts/ui/properties_render.py @@ -326,7 +326,7 @@ class RENDER_PT_output(RenderButtonsPanel): if wide_ui: col = split.column() - col.prop(rd, "file_extensions") + col.prop(rd, "use_file_extension") col.prop(rd, "use_overwrite") col.prop(rd, "use_placeholder") @@ -592,30 +592,42 @@ class RENDER_PT_bake(RenderButtonsPanel): 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") + layout.operator("object.bake_image", icon='RENDER_STILL') + + if wide_ui: + layout.prop(rd, "bake_type") + else: + layout.prop(rd, "bake_type", text="") + + if rd.bake_type == 'NORMALS': + if wide_ui: + layout.prop(rd, "bake_normal_space") + else: + layout.prop(rd, "bake_normal_space", text="") + elif rd.bake_type in ('DISPLACEMENT', 'AO'): + layout.prop(rd, "bake_normalized") + # col.prop(rd, "bake_aa_mode") # col.prop(rd, "bake_enable_aa") + + layout.separator() + + split = layout.split() - 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") - + col = split.column() + col.prop(rd, "bake_clear") + col.prop(rd, "bake_margin") + col.prop(rd, "bake_quad_split", text="Split") + + if wide_ui: + col = split.column() + col.prop(rd, "bake_active") + sub = col.column() + sub.active = rd.bake_active + sub.prop(rd, "bake_distance") + sub.prop(rd, "bake_bias") + bpy.types.register(RENDER_MT_presets) bpy.types.register(RENDER_PT_render) bpy.types.register(RENDER_PT_layers) diff --git a/release/scripts/ui/properties_scene.py b/release/scripts/ui/properties_scene.py index c059339c14e..68936a45759 100644 --- a/release/scripts/ui/properties_scene.py +++ b/release/scripts/ui/properties_scene.py @@ -18,6 +18,7 @@ # <pep8 compliant> import bpy +from rna_prop_ui import PropertyPanel narrowui = 180 @@ -48,6 +49,10 @@ class SCENE_PT_scene(SceneButtonsPanel): layout.prop(scene, "set", text="") +class SCENE_PT_custom_props(SceneButtonsPanel, PropertyPanel): + _context_path = "scene" + + class SCENE_PT_unit(SceneButtonsPanel): bl_label = "Units" COMPAT_ENGINES = {'BLENDER_RENDER'} @@ -178,3 +183,6 @@ bpy.types.register(SCENE_PT_unit) bpy.types.register(SCENE_PT_keying_sets) bpy.types.register(SCENE_PT_keying_set_paths) bpy.types.register(SCENE_PT_physics) + +bpy.types.register(SCENE_PT_custom_props) + diff --git a/release/scripts/ui/properties_texture.py b/release/scripts/ui/properties_texture.py index 4471f6f9644..7b70b355731 100644 --- a/release/scripts/ui/properties_texture.py +++ b/release/scripts/ui/properties_texture.py @@ -18,6 +18,7 @@ # <pep8 compliant> import bpy +from rna_prop_ui import PropertyPanel narrowui = 180 @@ -87,13 +88,15 @@ class TEXTURE_PT_context_texture(TextureButtonsPanel): def draw(self, context): layout = self.layout + space = context.space_data tex = context.texture wide_ui = context.region.width > narrowui idblock = context_tex_datablock(context) + tex_collection = space.pin_id == None and type(idblock) != bpy.types.Brush - space = context.space_data + - if idblock: + if tex_collection: row = layout.row() row.template_list(idblock, "textures", idblock, "active_texture_index", rows=2) @@ -101,24 +104,31 @@ class TEXTURE_PT_context_texture(TextureButtonsPanel): col = row.column(align=True) col.operator("texture.slot_move", text="", icon='TRIA_UP').type = 'UP' col.operator("texture.slot_move", text="", icon='TRIA_DOWN').type = 'DOWN' - - + if wide_ui: split = layout.split(percentage=0.65) - if idblock: - split.template_ID(idblock, "active_texture", new="texture.new") - elif tex: - split.template_ID(space, "pin_id") + col = split.column() else: - layout.template_ID(idblock, "active_texture", new="texture.new") - + col = layout.column() + + if tex_collection: + col.template_ID(idblock, "active_texture", new="texture.new") + elif idblock: + col.template_ID(idblock, "texture", new="texture.new") + + if space.pin_id: + col.template_ID(space, "pin_id") + + if wide_ui: + col = split.column() + if (not space.pin_id) and ( context.sculpt_object or context.vertex_paint_object or context.weight_paint_object or context.texture_paint_object): - split.prop(space, "brush_texture", text="Brush", toggle=True) + col.prop(space, "brush_texture", text="Brush", toggle=True) if tex: layout.prop(tex, "use_nodes") @@ -140,6 +150,13 @@ class TEXTURE_PT_context_texture(TextureButtonsPanel): layout.prop(tex, "type", text="") +class TEXTURE_PT_custom_props(TextureButtonsPanel, PropertyPanel): + _context_path = "texture" + + def poll(self, context): # use alternate poll since NONE texture type is ok + return context.texture + + class TEXTURE_PT_colors(TextureButtonsPanel): bl_label = "Colors" bl_default_closed = True @@ -268,6 +285,10 @@ class TEXTURE_PT_influence(TextureSlotPanel): bl_label = "Influence" def poll(self, context): + idblock = context_tex_datablock(context) + if type(idblock) == bpy.types.Brush: + return False + return context.texture_slot def draw(self, context): @@ -963,3 +984,5 @@ bpy.types.register(TEXTURE_PT_pointdensity_turbulence) bpy.types.register(TEXTURE_PT_colors) bpy.types.register(TEXTURE_PT_mapping) bpy.types.register(TEXTURE_PT_influence) + +bpy.types.register(TEXTURE_PT_custom_props) diff --git a/release/scripts/ui/properties_world.py b/release/scripts/ui/properties_world.py index b23a0dffbad..c4eaa049ce6 100644 --- a/release/scripts/ui/properties_world.py +++ b/release/scripts/ui/properties_world.py @@ -18,6 +18,7 @@ # <pep8 compliant> import bpy +from rna_prop_ui import PropertyPanel narrowui = 180 @@ -69,6 +70,11 @@ class WORLD_PT_context_world(WorldButtonsPanel): layout.template_ID(scene, "world", new="world.new") +class WORLD_PT_custom_props(WorldButtonsPanel, PropertyPanel): + COMPAT_ENGINES = {'BLENDER_RENDER'} + _context_path = "world" + + class WORLD_PT_world(WorldButtonsPanel): bl_label = "World" COMPAT_ENGINES = {'BLENDER_RENDER'} @@ -232,3 +238,5 @@ bpy.types.register(WORLD_PT_world) bpy.types.register(WORLD_PT_ambient_occlusion) bpy.types.register(WORLD_PT_mist) bpy.types.register(WORLD_PT_stars) + +bpy.types.register(WORLD_PT_custom_props)
\ No newline at end of file diff --git a/release/scripts/ui/space_dopesheet.py b/release/scripts/ui/space_dopesheet.py index 4710d9de3aa..d53443a3fb5 100644 --- a/release/scripts/ui/space_dopesheet.py +++ b/release/scripts/ui/space_dopesheet.py @@ -151,8 +151,7 @@ class DOPESHEET_MT_key(bpy.types.Menu): layout.operator_menu_enum("action.mirror", property="type", text="Mirror") layout.separator() - # Inconsistent naming? act/action - layout.operator("act.keyframe_insert") + layout.operator("action.keyframe_insert") layout.separator() layout.operator("action.duplicate") diff --git a/release/scripts/ui/space_image.py b/release/scripts/ui/space_image.py index 27d0aa91349..5d6bc70dd35 100644 --- a/release/scripts/ui/space_image.py +++ b/release/scripts/ui/space_image.py @@ -475,6 +475,7 @@ class IMAGE_PT_paint(bpy.types.Panel): if brush: col = layout.column() + col.template_color_wheel(brush, "color", value_slider=True) col.prop(brush, "color", text="") row = col.row(align=True) diff --git a/release/scripts/ui/space_info.py b/release/scripts/ui/space_info.py index 4f6a85156d0..b15315b8668 100644 --- a/release/scripts/ui/space_info.py +++ b/release/scripts/ui/space_info.py @@ -121,7 +121,7 @@ class INFO_MT_file_open_recent(bpy.types.Menu): import os layout = self.layout layout.operator_context = 'EXEC_AREA' - file = open(os.path.join(bpy.home, ".Blog"), "rU") + file = open(os.path.join(bpy.app.home, ".Blog"), "rU") for line in file: line = line.rstrip() layout.operator("wm.open_mainfile", text=line, icon='FILE_BLEND').path = line diff --git a/release/scripts/ui/space_nla.py b/release/scripts/ui/space_nla.py index 285ada5f46e..0060941b476 100644 --- a/release/scripts/ui/space_nla.py +++ b/release/scripts/ui/space_nla.py @@ -60,10 +60,7 @@ class NLA_MT_view(bpy.types.Menu): layout.separator() layout.prop(st, "show_cframe_indicator") - if st.show_seconds: - layout.operator("anim.time_toggle", text="Show Frames") - else: - layout.operator("anim.time_toggle", text="Show Seconds") + layout.operator("anim.time_toggle", text="Show Frames" if st.show_seconds else "Show Seconds") layout.prop(st, "show_strip_curves") diff --git a/release/scripts/ui/space_node.py b/release/scripts/ui/space_node.py index 9cf0a0c5ef3..3dc26f49a6f 100644 --- a/release/scripts/ui/space_node.py +++ b/release/scripts/ui/space_node.py @@ -120,6 +120,7 @@ class NODE_MT_node(bpy.types.Menu): layout.separator() layout.operator("node.link_make") + layout.operator("node.link_make", text="Make and Replace Links").replace=True layout.separator() layout.operator("node.group_edit") diff --git a/release/scripts/ui/space_sequencer.py b/release/scripts/ui/space_sequencer.py index 8edadb96de3..99298cc3988 100644 --- a/release/scripts/ui/space_sequencer.py +++ b/release/scripts/ui/space_sequencer.py @@ -606,13 +606,16 @@ class SEQUENCER_PT_filter(SequencerButtonsPanel): row = layout.row() row.active = strip.use_color_balance col = row.column() - col.prop(strip.color_balance, "lift") + col.template_color_wheel(strip.color_balance, "lift", value_slider=False) + col.row().prop(strip.color_balance, "lift") col.prop(strip.color_balance, "inverse_lift", text="Inverse") col = row.column() - col.prop(strip.color_balance, "gamma") + col.template_color_wheel(strip.color_balance, "gamma", value_slider=False) + col.row().prop(strip.color_balance, "gamma") col.prop(strip.color_balance, "inverse_gamma", text="Inverse") col = row.column() - col.prop(strip.color_balance, "gain") + col.template_color_wheel(strip.color_balance, "gain", value_slider=False) + col.row().prop(strip.color_balance, "gain") col.prop(strip.color_balance, "inverse_gain", text="Inverse") diff --git a/release/scripts/ui/space_userpref.py b/release/scripts/ui/space_userpref.py index 4c807fd9bd2..534735bfc24 100644 --- a/release/scripts/ui/space_userpref.py +++ b/release/scripts/ui/space_userpref.py @@ -19,6 +19,48 @@ # <pep8 compliant> import bpy +# General UI Theme Settings (User Interface) +def ui_items_general(col, context): + row = col.row() + sub = row.column() + sub.prop(context, "outline") + sub.prop(context, "item", slider=True) + sub = row.column() + sub.prop(context, "inner", slider=True) + sub.prop(context, "inner_sel", slider=True) + sub = row.column() + sub.prop(context, "text") + sub.prop(context, "text_sel") + sub = row.column() + sub.prop(context, "shaded") + subsub = sub.column(align=True) + subsub.active = context.shaded + subsub.prop(context, "shadetop") + subsub.prop(context, "shadedown") + + col.separator() + +def opengl_lamp_buttons(column, lamp): + split = column.split(percentage=0.1) + + if lamp.enabled == True: + split.prop(lamp, "enabled", text="", icon='OUTLINER_OB_LAMP') + else: + split.prop(lamp, "enabled", text="", icon='LAMP_DATA') + + col = split.column() + col.active = lamp.enabled + row = col.row() + row.label(text="Diffuse:") + row.prop(lamp, "diffuse_color", text="") + row = col.row() + row.label(text="Specular:") + row.prop(lamp, "specular_color", text="") + + col = split.column() + col.active = lamp.enabled + col.prop(lamp, "direction", text="") + KM_HIERARCHY = [ ('Window', 'EMPTY', 'WINDOW', []), # file save, window change, exit ('Screen', 'EMPTY', 'WINDOW', [ # full screen, undo, screenshot @@ -154,7 +196,6 @@ class USERPREF_PT_interface(bpy.types.Panel): row = layout.row() - col = row.column() col.label(text="Display:") col.prop(view, "tooltips") @@ -176,16 +217,15 @@ class USERPREF_PT_interface(bpy.types.Panel): sub.prop(view, "mini_axis_size", text="Size") sub.prop(view, "mini_axis_brightness", text="Brightness") - row.separator() row.separator() col = row.column() col.label(text="View Manipulation:") col.prop(view, "auto_depth") - col.prop(view, "global_pivot") col.prop(view, "zoom_to_mouse") col.prop(view, "rotate_around_selection") + col.prop(view, "global_pivot") col.separator() @@ -237,13 +277,11 @@ class USERPREF_PT_edit(bpy.types.Panel): userpref = context.user_preferences edit = userpref.edit - row = layout.row() - col = row.column() col.label(text="Link Materials To:") - col.row().prop(edit, "material_link", expand=True) + col.prop(edit, "material_link", text="") col.separator() col.separator() @@ -252,7 +290,7 @@ class USERPREF_PT_edit(bpy.types.Panel): col.label(text="New Objects:") col.prop(edit, "enter_edit_mode") col.label(text="Align To:") - col.row().prop(edit, "object_align", expand=True) + col.prop(edit, "object_align", text="") col.separator() col.separator() @@ -263,11 +301,9 @@ class USERPREF_PT_edit(bpy.types.Panel): col.prop(edit, "undo_steps", text="Steps") col.prop(edit, "undo_memory_limit", text="Memory Limit") - row.separator() row.separator() - col = row.column() col.label(text="Snap:") col.prop(edit, "snap_translate", text="Translate") @@ -283,11 +319,9 @@ class USERPREF_PT_edit(bpy.types.Panel): col.prop(edit, "grease_pencil_eraser_radius", text="Eraser Radius") col.prop(edit, "grease_pencil_smooth_stroke", text="Smooth Stroke") - row.separator() row.separator() - col = row.column() col.label(text="Keyframing:") col.prop(edit, "use_visual_keying") @@ -316,11 +350,9 @@ class USERPREF_PT_edit(bpy.types.Panel): col.label(text="Transform:") col.prop(edit, "drag_immediately") - row.separator() row.separator() - col = row.column() col.label(text="Duplicate Data:") col.prop(edit, "duplicate_mesh", text="Mesh") @@ -352,12 +384,11 @@ class USERPREF_PT_system(bpy.types.Panel): userpref = context.user_preferences system = userpref.system - lamp0 = system.solid_lights[0] - lamp1 = system.solid_lights[1] - lamp2 = system.solid_lights[2] split = layout.split() + + # 1. Column column = split.column() colsplit = column.split(percentage=0.85) @@ -377,7 +408,6 @@ class USERPREF_PT_system(bpy.types.Panel): sub = col.column() sub.active = system.audio_device != 'NONE' #sub.prop(system, "enable_all_codecs") - sub.prop(system, "game_sound") sub.prop(system, "audio_channels", text="Channels") sub.prop(system, "audio_mixing_buffer", text="Mixing Buffer") sub.prop(system, "audio_sample_rate", text="Sample Rate") @@ -387,8 +417,6 @@ class USERPREF_PT_system(bpy.types.Panel): col.separator() col.separator() - - #column = split.column() #colsplit = column.split(percentage=0.85) @@ -402,7 +430,9 @@ class USERPREF_PT_system(bpy.types.Panel): #col.separator() #col.prop(system, "use_textured_fonts") + + # 2. Column column = split.column() colsplit = column.split(percentage=0.85) @@ -411,6 +441,8 @@ class USERPREF_PT_system(bpy.types.Panel): col.prop(system, "clip_alpha", slider=True) col.prop(system, "use_mipmaps") col.prop(system, "use_vbos") + #Anti-aliasing is disabled as it breaks broder/lasso select + #col.prop(system, "use_antialiasing") col.label(text="Window Draw Method:") col.row().prop(system, "window_draw_method", expand=True) col.label(text="Textures:") @@ -425,7 +457,9 @@ class USERPREF_PT_system(bpy.types.Panel): col.label(text="Sequencer:") col.prop(system, "prefetch_frames") col.prop(system, "memory_cache_limit") + + # 3. Column column = split.column() column.label(text="Solid OpenGL lights:") @@ -434,79 +468,29 @@ class USERPREF_PT_system(bpy.types.Panel): split.label() split.label(text="Colors:") split.label(text="Direction:") - - - split = column.split(percentage=0.1) - - if lamp0.enabled == True: - split.prop(lamp0, "enabled", text="", icon='OUTLINER_OB_LAMP') - else: - split.prop(lamp0, "enabled", text="", icon='LAMP_DATA') - - col = split.column() - col.active = lamp0.enabled - row = col.row() - row.label(text="Diffuse:") - row.prop(lamp0, "diffuse_color", text="") - row = col.row() - row.label(text="Specular:") - row.prop(lamp0, "specular_color", text="") - - col = split.column() - col.active = lamp0.enabled - col.prop(lamp0, "direction", text="") - - - split = column.split(percentage=0.1) - - if lamp1.enabled == True: - split.prop(lamp1, "enabled", text="", icon='OUTLINER_OB_LAMP') - else: - split.prop(lamp1, "enabled", text="", icon='LAMP_DATA') - - col = split.column() - col.active = lamp1.enabled - row = col.row() - row.label(text="Diffuse:") - row.prop(lamp1, "diffuse_color", text="") - row = col.row() - row.label(text="Specular:") - row.prop(lamp1, "specular_color", text="") - - col = split.column() - col.active = lamp1.enabled - col.prop(lamp1, "direction", text="") - - - split = column.split(percentage=0.1) - - if lamp2.enabled == True: - split.prop(lamp2, "enabled", text="", icon='OUTLINER_OB_LAMP') - else: - split.prop(lamp2, "enabled", text="", icon='LAMP_DATA') - - col = split.column() - col.active = lamp2.enabled - row = col.row() - row.label(text="Diffuse:") - row.prop(lamp2, "diffuse_color", text="") - row = col.row() - row.label(text="Specular:") - row.prop(lamp2, "specular_color", text="") - - col = split.column() - col.active = lamp2.enabled - col.prop(lamp2, "direction", text="") - + + lamp = system.solid_lights[0] + opengl_lamp_buttons(column, lamp) + + lamp = system.solid_lights[1] + opengl_lamp_buttons(column, lamp) + + lamp = system.solid_lights[2] + opengl_lamp_buttons(column, lamp) column.separator() column.separator() column.separator() - - col = column.column() - - col.prop(system, "use_weight_color_range", text="Custom Weight Paint Range") - sub = col.column() + + column.label(text="Color Picker Type:") + column.row().prop(system, "color_picker_type", text="") + + column.separator() + column.separator() + column.separator() + + column.prop(system, "use_weight_color_range", text="Custom Weight Paint Range") + sub = column.column() sub.active = system.use_weight_color_range sub.template_color_ramp(system, "weight_color_range", expand=True) @@ -526,351 +510,78 @@ class USERPREF_PT_theme(bpy.types.Panel): theme = context.user_preferences.themes[0] - split = layout.split(percentage=0.33) - split.prop(theme, "active_theme", text="") - - layout.separator() - - split = layout.split() - - if theme.active_theme == 'VIEW_3D': - v3d = theme.view_3d - - col = split.column() - col.prop(v3d, "back") - col.prop(v3d, "button") - col.prop(v3d, "button_title") - col.prop(v3d, "button_text") - col.prop(v3d, "header") + split_themes = layout.split(percentage=0.2) + split_themes.prop(theme, "theme_area", expand=True) + split = split_themes.split() + + if theme.theme_area == 'USER_INTERFACE': col = split.column() - col.prop(v3d, "grid") - col.prop(v3d, "wire") - col.prop(v3d, "lamp", slider=True) - col.prop(v3d, "editmesh_active", slider=True) - col = split.column() - col.prop(v3d, "object_selected") - col.prop(v3d, "object_active") - col.prop(v3d, "object_grouped") - col.prop(v3d, "object_grouped_active") - col.prop(v3d, "transform") - - col = split.column() - col.prop(v3d, "vertex") - col.prop(v3d, "face", slider=True) - col.prop(v3d, "normal") - col.prop(v3d, "bone_solid") - col.prop(v3d, "bone_pose") - #col.prop(v3d, "edge") Doesn't seem to work - - elif theme.active_theme == 'USER_INTERFACE': ui = theme.user_interface.wcol_regular - layout.label(text="Regular:") - - row = layout.row() - sub = row.column() - sub.prop(ui, "outline") - sub.prop(ui, "item", slider=True) - sub = row.column() - sub.prop(ui, "inner", slider=True) - sub.prop(ui, "inner_sel", slider=True) - sub = row.column() - sub.prop(ui, "text") - sub.prop(ui, "text_sel") - sub = row.column() - sub.prop(ui, "shaded") - subsub = sub.column(align=True) - subsub.active = ui.shaded - subsub.prop(ui, "shadetop") - subsub.prop(ui, "shadedown") - - layout.separator() + col.label(text="Regular:") + ui_items_general(col, ui) ui = theme.user_interface.wcol_tool - layout.label(text="Tool:") - - row = layout.row() - sub = row.column() - sub.prop(ui, "outline") - sub.prop(ui, "item", slider=True) - sub = row.column() - sub.prop(ui, "inner", slider=True) - sub.prop(ui, "inner_sel", slider=True) - sub = row.column() - sub.prop(ui, "text") - sub.prop(ui, "text_sel") - sub = row.column() - sub.prop(ui, "shaded") - subsub = sub.column(align=True) - subsub.active = ui.shaded - subsub.prop(ui, "shadetop") - subsub.prop(ui, "shadedown") + col.label(text="Tool:") + ui_items_general(col, ui) ui = theme.user_interface.wcol_radio - layout.label(text="Radio Buttons:") - - row = layout.row() - sub = row.column() - sub.prop(ui, "outline") - sub.prop(ui, "item", slider=True) - sub = row.column() - sub.prop(ui, "inner", slider=True) - sub.prop(ui, "inner_sel", slider=True) - sub = row.column() - sub.prop(ui, "text") - sub.prop(ui, "text_sel") - sub = row.column() - sub.prop(ui, "shaded") - subsub = sub.column(align=True) - subsub.active = ui.shaded - subsub.prop(ui, "shadetop") - subsub.prop(ui, "shadedown") + col.label(text="Radio Buttons:") + ui_items_general(col, ui) ui = theme.user_interface.wcol_text - layout.label(text="Text:") - - row = layout.row() - sub = row.column() - sub.prop(ui, "outline") - sub.prop(ui, "item", slider=True) - sub = row.column() - sub.prop(ui, "inner", slider=True) - sub.prop(ui, "inner_sel", slider=True) - sub = row.column() - sub.prop(ui, "text") - sub.prop(ui, "text_sel") - sub = row.column() - sub.prop(ui, "shaded") - subsub = sub.column(align=True) - subsub.active = ui.shaded - subsub.prop(ui, "shadetop") - subsub.prop(ui, "shadedown") + col.label(text="Text:") + ui_items_general(col, ui) ui = theme.user_interface.wcol_option - layout.label(text="Option:") - - row = layout.row() - sub = row.column() - sub.prop(ui, "outline") - sub.prop(ui, "item", slider=True) - sub = row.column() - sub.prop(ui, "inner", slider=True) - sub.prop(ui, "inner_sel", slider=True) - sub = row.column() - sub.prop(ui, "text") - sub.prop(ui, "text_sel") - sub = row.column() - sub.prop(ui, "shaded") - subsub = sub.column(align=True) - subsub.active = ui.shaded - subsub.prop(ui, "shadetop") - subsub.prop(ui, "shadedown") + col.label(text="Option:") + ui_items_general(col, ui) ui = theme.user_interface.wcol_toggle - layout.label(text="Toggle:") - - row = layout.row() - sub = row.column() - sub.prop(ui, "outline") - sub.prop(ui, "item", slider=True) - sub = row.column() - sub.prop(ui, "inner", slider=True) - sub.prop(ui, "inner_sel", slider=True) - sub = row.column() - sub.prop(ui, "text") - sub.prop(ui, "text_sel") - sub = row.column() - sub.prop(ui, "shaded") - subsub = sub.column(align=True) - subsub.active = ui.shaded - subsub.prop(ui, "shadetop") - subsub.prop(ui, "shadedown") + col.label(text="Toggle:") + ui_items_general(col, ui) ui = theme.user_interface.wcol_num - layout.label(text="Number Field:") - - row = layout.row() - sub = row.column() - sub.prop(ui, "outline") - sub.prop(ui, "item", slider=True) - sub = row.column() - sub.prop(ui, "inner", slider=True) - sub.prop(ui, "inner_sel", slider=True) - sub = row.column() - sub.prop(ui, "text") - sub.prop(ui, "text_sel") - sub = row.column() - sub.prop(ui, "shaded") - subsub = sub.column(align=True) - subsub.active = ui.shaded - subsub.prop(ui, "shadetop") - subsub.prop(ui, "shadedown") + col.label(text="Number Field:") + ui_items_general(col, ui) ui = theme.user_interface.wcol_numslider - layout.label(text="Value Slider:") - - row = layout.row() - sub = row.column() - sub.prop(ui, "outline") - sub.prop(ui, "item", slider=True) - sub = row.column() - sub.prop(ui, "inner", slider=True) - sub.prop(ui, "inner_sel", slider=True) - sub = row.column() - sub.prop(ui, "text") - sub.prop(ui, "text_sel") - sub = row.column() - sub.prop(ui, "shaded") - subsub = sub.column(align=True) - subsub.active = ui.shaded - subsub.prop(ui, "shadetop") - subsub.prop(ui, "shadedown") + col.label(text="Value Slider:") + ui_items_general(col, ui) ui = theme.user_interface.wcol_box - layout.label(text="Box:") - - row = layout.row() - sub = row.column() - sub.prop(ui, "outline") - sub.prop(ui, "item", slider=True) - sub = row.column() - sub.prop(ui, "inner", slider=True) - sub.prop(ui, "inner_sel", slider=True) - sub = row.column() - sub.prop(ui, "text") - sub.prop(ui, "text_sel") - sub = row.column() - sub.prop(ui, "shaded") - subsub = sub.column(align=True) - subsub.active = ui.shaded - subsub.prop(ui, "shadetop") - subsub.prop(ui, "shadedown") + col.label(text="Box:") + ui_items_general(col, ui) ui = theme.user_interface.wcol_menu - layout.label(text="Menu:") - - row = layout.row() - sub = row.column() - sub.prop(ui, "outline") - sub.prop(ui, "item", slider=True) - sub = row.column() - sub.prop(ui, "inner", slider=True) - sub.prop(ui, "inner_sel", slider=True) - sub = row.column() - sub.prop(ui, "text") - sub.prop(ui, "text_sel") - sub = row.column() - sub.prop(ui, "shaded") - subsub = sub.column(align=True) - subsub.active = ui.shaded - subsub.prop(ui, "shadetop") - subsub.prop(ui, "shadedown") + col.label(text="Menu:") + ui_items_general(col, ui) ui = theme.user_interface.wcol_pulldown - layout.label(text="Pulldown:") - - row = layout.row() - sub = row.column() - sub.prop(ui, "outline") - sub.prop(ui, "item", slider=True) - sub = row.column() - sub.prop(ui, "inner", slider=True) - sub.prop(ui, "inner_sel", slider=True) - sub = row.column() - sub.prop(ui, "text") - sub.prop(ui, "text_sel") - sub = row.column() - sub.prop(ui, "shaded") - subsub = sub.column(align=True) - subsub.active = ui.shaded - subsub.prop(ui, "shadetop") - subsub.prop(ui, "shadedown") + col.label(text="Pulldown:") + ui_items_general(col, ui) ui = theme.user_interface.wcol_menu_back - layout.label(text="Menu Back:") - - row = layout.row() - sub = row.column() - sub.prop(ui, "outline") - sub.prop(ui, "item", slider=True) - sub = row.column() - sub.prop(ui, "inner", slider=True) - sub.prop(ui, "inner_sel", slider=True) - sub = row.column() - sub.prop(ui, "text") - sub.prop(ui, "text_sel") - sub = row.column() - sub.prop(ui, "shaded") - subsub = sub.column(align=True) - subsub.active = ui.shaded - subsub.prop(ui, "shadetop") - subsub.prop(ui, "shadedown") + col.label(text="Menu Back:") + ui_items_general(col, ui) ui = theme.user_interface.wcol_menu_item - layout.label(text="Menu Item:") - - row = layout.row() - sub = row.column() - sub.prop(ui, "outline") - sub.prop(ui, "item", slider=True) - sub = row.column() - sub.prop(ui, "inner", slider=True) - sub.prop(ui, "inner_sel", slider=True) - sub = row.column() - sub.prop(ui, "text") - sub.prop(ui, "text_sel") - sub = row.column() - sub.prop(ui, "shaded") - subsub = sub.column(align=True) - subsub.active = ui.shaded - subsub.prop(ui, "shadetop") - subsub.prop(ui, "shadedown") + col.label(text="Menu Item:") + ui_items_general(col, ui) ui = theme.user_interface.wcol_scroll - layout.label(text="Scroll Bar:") - - row = layout.row() - sub = row.column() - sub.prop(ui, "outline") - sub.prop(ui, "item", slider=True) - sub = row.column() - sub.prop(ui, "inner", slider=True) - sub.prop(ui, "inner_sel", slider=True) - sub = row.column() - sub.prop(ui, "text") - sub.prop(ui, "text_sel") - sub = row.column() - sub.prop(ui, "shaded") - subsub = sub.column(align=True) - subsub.active = ui.shaded - subsub.prop(ui, "shadetop") - subsub.prop(ui, "shadedown") + col.label(text="Scroll Bar:") + ui_items_general(col, ui) ui = theme.user_interface.wcol_list_item - layout.label(text="List Item:") - - row = layout.row() - sub = row.column() - sub.prop(ui, "outline") - sub.prop(ui, "item", slider=True) - sub = row.column() - sub.prop(ui, "inner", slider=True) - sub.prop(ui, "inner_sel", slider=True) - sub = row.column() - sub.prop(ui, "text") - sub.prop(ui, "text_sel") - sub = row.column() - sub.prop(ui, "shaded") - subsub = sub.column(align=True) - subsub.active = ui.shaded - subsub.prop(ui, "shadetop") - subsub.prop(ui, "shadedown") + col.label(text="List Item:") + ui_items_general(col, ui) ui = theme.user_interface.wcol_state - layout.label(text="State:") + col.label(text="State:") - row = layout.row() + row = col.row() sub = row.column() sub.prop(ui, "inner_anim") sub.prop(ui, "inner_anim_sel") @@ -884,16 +595,46 @@ class USERPREF_PT_theme(bpy.types.Panel): sub.prop(ui, "blend") ui = theme.user_interface - layout.separator() - - sub = layout.row() - sub.prop(ui, "icon_file") + col.separator() + col.separator() + col.prop(ui, "icon_file") layout.separator() layout.separator() - elif theme.active_theme == 'GRAPH_EDITOR': + elif theme.theme_area == 'VIEW_3D': + v3d = theme.view_3d + + col = split.column() + col.prop(v3d, "back") + col.prop(v3d, "button") + col.prop(v3d, "button_title") + col.prop(v3d, "button_text") + col.prop(v3d, "header") + + col = split.column() + col.prop(v3d, "grid") + col.prop(v3d, "wire") + col.prop(v3d, "lamp", slider=True) + col.prop(v3d, "editmesh_active", slider=True) + + col = split.column() + col.prop(v3d, "object_selected") + col.prop(v3d, "object_active") + col.prop(v3d, "object_grouped") + col.prop(v3d, "object_grouped_active") + col.prop(v3d, "transform") + + col = split.column() + col.prop(v3d, "vertex") + col.prop(v3d, "face", slider=True) + col.prop(v3d, "normal") + col.prop(v3d, "bone_solid") + col.prop(v3d, "bone_pose") + #col.prop(v3d, "edge") Doesn't seem to work + + elif theme.theme_area == 'GRAPH_EDITOR': graph = theme.graph_editor col = split.column() @@ -921,7 +662,7 @@ class USERPREF_PT_theme(bpy.types.Panel): col.separator() col.prop(graph, "handle_vertex_size") - elif theme.active_theme == 'FILE_BROWSER': + elif theme.theme_area == 'FILE_BROWSER': file_browse = theme.file_browser col = split.column() @@ -941,7 +682,7 @@ class USERPREF_PT_theme(bpy.types.Panel): col.prop(file_browse, "active_file") col.prop(file_browse, "active_file_text") - elif theme.active_theme == 'NLA_EDITOR': + elif theme.theme_area == 'NLA_EDITOR': nla = theme.nla_editor col = split.column() @@ -964,7 +705,7 @@ class USERPREF_PT_theme(bpy.types.Panel): col.prop(nla, "strips_selected") col.prop(nla, "current_frame") - elif theme.active_theme == 'DOPESHEET_EDITOR': + elif theme.theme_area == 'DOPESHEET_EDITOR': dope = theme.dopesheet_editor col = split.column() @@ -989,7 +730,7 @@ class USERPREF_PT_theme(bpy.types.Panel): col.prop(dope, "dopesheet_channel") col.prop(dope, "dopesheet_subchannel") - elif theme.active_theme == 'IMAGE_EDITOR': + elif theme.theme_area == 'IMAGE_EDITOR': image = theme.image_editor col = split.column() @@ -1006,7 +747,7 @@ class USERPREF_PT_theme(bpy.types.Panel): col = split.column() col.prop(image, "editmesh_active", slider=True) - elif theme.active_theme == 'SEQUENCE_EDITOR': + elif theme.theme_area == 'SEQUENCE_EDITOR': seq = theme.sequence_editor col = split.column() @@ -1035,7 +776,7 @@ class USERPREF_PT_theme(bpy.types.Panel): col.prop(seq, "keyframe") col.prop(seq, "draw_action") - elif theme.active_theme == 'PROPERTIES': + elif theme.theme_area == 'PROPERTIES': prop = theme.properties col = split.column() @@ -1050,7 +791,7 @@ class USERPREF_PT_theme(bpy.types.Panel): col = split.column() col.prop(prop, "header") - elif theme.active_theme == 'TEXT_EDITOR': + elif theme.theme_area == 'TEXT_EDITOR': text = theme.text_editor col = split.column() @@ -1076,7 +817,7 @@ class USERPREF_PT_theme(bpy.types.Panel): col.prop(text, "syntax_string") col.prop(text, "syntax_numbers") - elif theme.active_theme == 'TIMELINE': + elif theme.theme_area == 'TIMELINE': time = theme.timeline col = split.column() @@ -1092,7 +833,7 @@ class USERPREF_PT_theme(bpy.types.Panel): col = split.column() col.prop(time, "current_frame") - elif theme.active_theme == 'NODE_EDITOR': + elif theme.theme_area == 'NODE_EDITOR': node = theme.node_editor col = split.column() @@ -1118,7 +859,7 @@ class USERPREF_PT_theme(bpy.types.Panel): col.prop(node, "operator_node") col.prop(node, "group_node") - elif theme.active_theme == 'LOGIC_EDITOR': + elif theme.theme_area == 'LOGIC_EDITOR': logic = theme.logic_editor col = split.column() @@ -1136,7 +877,7 @@ class USERPREF_PT_theme(bpy.types.Panel): col = split.column() col.prop(logic, "panel") - elif theme.active_theme == 'OUTLINER': + elif theme.theme_area == 'OUTLINER': out = theme.outliner col = split.column() @@ -1151,7 +892,7 @@ class USERPREF_PT_theme(bpy.types.Panel): col = split.column() col.prop(out, "header") - elif theme.active_theme == 'INFO': + elif theme.theme_area == 'INFO': info = theme.info col = split.column() @@ -1165,7 +906,7 @@ class USERPREF_PT_theme(bpy.types.Panel): col = split.column() - elif theme.active_theme == 'USER_PREFERENCES': + elif theme.theme_area == 'USER_PREFERENCES': prefs = theme.user_preferences col = split.column() @@ -1475,11 +1216,11 @@ class USERPREF_PT_input(bpy.types.Panel): filter = kc.filter.lower() for km in kc.keymaps: + km = km.active() + filtered_items = [kmi for kmi in km.items if filter in kmi.name.lower()] if len(filtered_items) != 0: - km = km.active() - layout.set_context_pointer("keymap", km) col = layout.column() diff --git a/release/scripts/ui/space_view3d.py b/release/scripts/ui/space_view3d.py index 5563b727487..8c430d39aa3 100644 --- a/release/scripts/ui/space_view3d.py +++ b/release/scripts/ui/space_view3d.py @@ -1217,7 +1217,8 @@ class VIEW3D_MT_edit_mesh_edges(bpy.types.Menu): layout.separator() - layout.operator("TRANSFORM_OT_edge_slide", text="Edge Slide") + layout.operator("TRANSFORM_OT_edge_slide") + layout.operator("TRANSFORM_OT_edge_crease") layout.operator("mesh.loop_multi_select", text="Edge Loop") # uiItemO(layout, "Loopcut", 0, "mesh.loop_cut"); // CutEdgeloop(em, 1); diff --git a/release/scripts/ui/space_view3d_toolbar.py b/release/scripts/ui/space_view3d_toolbar.py index b2c8c39cb3a..a7a8968fb05 100644 --- a/release/scripts/ui/space_view3d_toolbar.py +++ b/release/scripts/ui/space_view3d_toolbar.py @@ -542,9 +542,10 @@ class VIEW3D_PT_tools_brush(PaintPanel): row = col.row(align=True) row.prop(brush, "size", slider=True) - row.prop(brush, "use_size_pressure", toggle=True, text="") if brush.sculpt_tool != 'GRAB': + row.prop(brush, "use_size_pressure", toggle=True, text="") + row = col.row(align=True) row.prop(brush, "strength", slider=True) row.prop(brush, "use_strength_pressure", text="") @@ -570,6 +571,7 @@ class VIEW3D_PT_tools_brush(PaintPanel): elif context.texture_paint_object and brush: col = layout.column() + col.template_color_wheel(brush, "color", value_slider=True) col.prop(brush, "color", text="") row = col.row(align=True) @@ -609,6 +611,7 @@ class VIEW3D_PT_tools_brush(PaintPanel): elif context.vertex_paint_object and brush: col = layout.column() + col.template_color_wheel(brush, "color", value_slider=True) col.prop(brush, "color", text="") row = col.row(align=True) @@ -624,6 +627,29 @@ 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_texture(PaintPanel): + bl_label = "Texture" + 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 + tex_slot = brush.texture_slot + + col = layout.column() + + col.template_ID_preview(brush, "texture", new="texture.new", rows=2, cols=4) + + col.row().prop(tex_slot, "map_mode", expand=True) + class VIEW3D_PT_tools_brush_tool(PaintPanel): bl_label = "Tool" bl_default_closed = True @@ -709,7 +735,7 @@ class VIEW3D_PT_tools_brush_curve(PaintPanel): settings = self.paint_settings(context) brush = settings.brush - layout.template_curve_mapping(brush, "curve") + layout.template_curve_mapping(brush, "curve", brush=True) layout.operator_menu_enum("brush.curve_preset", property="shape") @@ -777,9 +803,9 @@ class VIEW3D_PT_tools_weightpaint_options(View3DPanel): col.prop(wpaint, "normals") col.prop(wpaint, "spray") - data = context.weight_paint_object.data - if type(data) == bpy.types.Mesh: - col.prop(data, "use_mirror_x") + obj = context.weight_paint_object + if obj.type == 'MESH': + col.prop(obj.data, "use_mirror_x") # Commented out because the Apply button isn't an operator yet, making these settings useless # col.label(text="Gamma:") @@ -948,6 +974,7 @@ class VIEW3D_PT_tools_particlemode(View3DPanel): if not pe.hair: col.label(text="Correct:") col.prop(pe, "auto_velocity", text="Velocity") + col.prop(ob.data, "use_mirror_x") col = layout.column(align=True) col.active = pe.editable @@ -960,7 +987,6 @@ class VIEW3D_PT_tools_particlemode(View3DPanel): sub.active = pe.fade_time sub.prop(pe, "fade_frames", slider=True) - bpy.types.register(VIEW3D_PT_tools_weightpaint) bpy.types.register(VIEW3D_PT_tools_objectmode) bpy.types.register(VIEW3D_PT_tools_meshedit) @@ -975,6 +1001,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_texture) bpy.types.register(VIEW3D_PT_tools_brush_tool) bpy.types.register(VIEW3D_PT_tools_brush_stroke) bpy.types.register(VIEW3D_PT_tools_brush_curve) diff --git a/source/Makefile b/source/Makefile index e08def0f9e2..2f935c91095 100644 --- a/source/Makefile +++ b/source/Makefile @@ -211,6 +211,11 @@ ifeq ($(WITH_BINRELOC), true) COMLIB += $(OCGDIR)/extern/binreloc/$(DEBUG_DIR)libbinreloc.a endif +ifeq ($(WITH_OPENCOLLADA), true) + COMLIB += $(OCGDIR)/blender/bf_collada/$(DEBUG_DIR)/libbf_collada.a + COMLIB += $(BF_PCRE_LIBS) +endif + ifeq ($(OS), windows) ifeq ($(FREE_WINDOWS), true) COMLIB += $(NAN_FREETYPE)/lib/libfreetype.a @@ -519,7 +524,7 @@ endif $(DIR)/$(DEBUG_DIR)bin/blenderstatic: $(OBJS) $(GRPLIB) $(PULIB) $(COMLIB) @echo "****> Link $@" ifdef NAN_BUILDINFO - $(CCC) $(REL_CFLAGS) -DBUILD_DATE='"$(BUILD_DATE)"' -DBUILD_TIME='"$(BUILD_TIME)"' -DBUILD_REV='"$(BUILD_REV)"' -DBUILD_PLATFORM='"$(CONFIG_GUESS)"' -DBUILD_TYPE='"static"' $(BUILDINFO_C) -c -o $(BUILDINFO_O) -DNAN_BUILDINFO + $(CCC) $(CCFLAGS) $(REL_CCFLAGS) -DBUILD_DATE='"$(BUILD_DATE)"' -DBUILD_TIME='"$(BUILD_TIME)"' -DBUILD_REV='"$(BUILD_REV)"' -DBUILD_PLATFORM='"$(CONFIG_GUESS)"' -DBUILD_TYPE='"static"' $(BUILDINFO_C) -c -o $(BUILDINFO_O) -DNAN_BUILDINFO endif mkdir -p $(DIR)/$(DEBUG_DIR)bin $(CCC) $(CCFLAGS) $(LDFLAGS) -o $(DIR)/$(DEBUG_DIR)bin/blenderstatic $(BUILDINFO_O) $(OBJS) $(GRPLIB) $(PULIB) $(COMLIB) $(LLIBS) $(SADD) $(LOPTS) @@ -533,7 +538,7 @@ endif $(DIR)/$(DEBUG_DIR)bin/blender$(EXT): $(OBJS) $(GRPLIB) $(PULIB) $(COMLIB) @echo "****> Link $@" ifdef NAN_BUILDINFO - $(CCC) $(REL_CFLAGS) -DBUILD_DATE='"$(BUILD_DATE)"' -DBUILD_TIME='"$(BUILD_TIME)"' -DBUILD_REV='"$(BUILD_REV)"' -DBUILD_PLATFORM='"$(CONFIG_GUESS)"' -DBUILD_TYPE='"dynamic"' $(BUILDINFO_C) -c -o $(BUILDINFO_O) -DNAN_BUILDINFO + $(CCC) $(CCFLAGS) $(REL_CCFLAGS) -DBUILD_DATE='"$(BUILD_DATE)"' -DBUILD_TIME='"$(BUILD_TIME)"' -DBUILD_REV='"$(BUILD_REV)"' -DBUILD_PLATFORM='"$(CONFIG_GUESS)"' -DBUILD_TYPE='"dynamic"' $(BUILDINFO_C) -c -o $(BUILDINFO_O) -DNAN_BUILDINFO endif mkdir -p $(DIR)/$(DEBUG_DIR)bin $(CCC) $(CCFLAGS) $(LDFLAGS) -o $(DIR)/$(DEBUG_DIR)bin/blender$(EXT) $(BUILDINFO_O) $(OBJS) $(GRPLIB) $(PULIB) $(COMLIB) $(LLIBS) $(DADD) $(LOPTS) @@ -547,7 +552,7 @@ endif $(DIR)/$(DEBUG_DIR)bin/blenderplayer$(EXT): $(OBJS) $(SPLIB1) $(COMLIB) $(SPLIB) @echo "****> Link $@" ifdef NAN_BUILDINFO - $(CCC) $(REL_CFLAGS) -DBUILD_DATE='"$(BUILD_DATE)"' -DBUILD_TIME='"$(BUILD_TIME)"' -DBUILD_REV='"$(BUILD_REV)"' -DBUILD_PLATFORM='"$(CONFIG_GUESS)"' -DBUILD_TYPE='"dynamic"' $(BUILDINFO_C) -c -o $(BUILDINFO_O) -DNAN_BUILDINFO + $(CCC) $(CCFLAGS) $(REL_CCFLAGS) -DBUILD_DATE='"$(BUILD_DATE)"' -DBUILD_TIME='"$(BUILD_TIME)"' -DBUILD_REV='"$(BUILD_REV)"' -DBUILD_PLATFORM='"$(CONFIG_GUESS)"' -DBUILD_TYPE='"dynamic"' $(BUILDINFO_C) -c -o $(BUILDINFO_O) -DNAN_BUILDINFO endif mkdir -p $(DIR)/$(DEBUG_DIR)bin $(CCC) $(CCFLAGS) $(LDFLAGS) -o $(DIR)/$(DEBUG_DIR)bin/blenderplayer$(EXT) $(BUILDINFO_O) $(OBJS) $(SPLIB1) $(COMLIB) $(SPLIB) $(LLIBS) $(DADD) $(LOPTS) @@ -561,7 +566,7 @@ endif $(DIR)/$(DEBUG_DIR)bin/blenderdynplayer$(EXT): $(OBJS) $(COMLIB) $(SPLIB) @echo "****> Link $@" ifdef NAN_BUILDINFO - $(CCC) $(REL_CFLAGS) -DBUILD_DATE='"$(BUILD_DATE)"' -DBUILD_TIME='"$(BUILD_TIME)"' -DBUILD_REV='"$(BUILD_REV)"' -DBUILD_PLATFORM='"$(CONFIG_GUESS)"' -DBUILD_TYPE='"dynamic"' $(BUILDINFO_C) -c -o $(BUILDINFO_O) -DNAN_BUILDINFO + $(CCC) $(CCFLAGS) $(REL_CCFLAGS) -DBUILD_DATE='"$(BUILD_DATE)"' -DBUILD_TIME='"$(BUILD_TIME)"' -DBUILD_REV='"$(BUILD_REV)"' -DBUILD_PLATFORM='"$(CONFIG_GUESS)"' -DBUILD_TYPE='"dynamic"' $(BUILDINFO_C) -c -o $(BUILDINFO_O) -DNAN_BUILDINFO endif mkdir -p $(DIR)/$(DEBUG_DIR)bin $(CCC) $(CCFLAGS) $(LDFLAGS) -o $(DIR)/$(DEBUG_DIR)bin/blenderdynplayer$(EXT) $(BUILDINFO_O) $(OBJS) $(SPLIB1) $(COMLIB) $(SPLIB) $(LLIBS) $(DADD) $(LOPTS) @@ -575,7 +580,7 @@ endif $(DIR)/$(DEBUG_DIR)bin/Blender3DPlugin$(SOEXT): $(PLUGAPPLIB_XPLINK) @echo "****> Link $@" ifdef NAN_BUILDINFO - $(CCC) $(REL_CFLAGS) -DBUILD_DATE='"$(BUILD_DATE)"' -DBUILD_TIME='"$(BUILD_TIME)"' -DBUILD_REV='"$(BUILD_REV)"' -DBUILD_PLATFORM='"$(CONFIG_GUESS)"' -DBUILD_TYPE='"dynamic"' $(BUILDINFO_C) -c -o $(BUILDINFO_O) -DNAN_BUILDINFO + $(CCC) $(CCFLAGS) $(REL_CCFLAGS) -DBUILD_DATE='"$(BUILD_DATE)"' -DBUILD_TIME='"$(BUILD_TIME)"' -DBUILD_REV='"$(BUILD_REV)"' -DBUILD_PLATFORM='"$(CONFIG_GUESS)"' -DBUILD_TYPE='"dynamic"' $(BUILDINFO_C) -c -o $(BUILDINFO_O) -DNAN_BUILDINFO endif mkdir -p $(DIR)/$(DEBUG_DIR)bin $(CCC) $(CCFLAGS) $(DYNLDFLAGS) -o $@ $(PLUGAPPLIB_XPLINK) $(LOPTS) @@ -591,7 +596,7 @@ DEFFILE = ./gameengine/GamePlayer/netscape/src/npB3DPlg.def $(DIR)/$(DEBUG_DIR)npB3DPlg$(SOEXT): $(NSPLUGLIB) $(PLUGAPPLIB) $(COMLIB) $(SPLIB) @echo "****> Link $@" ifdef NAN_BUILDINFO - $(CCC) $(REL_CFLAGS) -DBUILD_DATE='"$(BUILD_DATE)"' -DBUILD_TIME='"$(BUILD_TIME)"' -DBUILD_REV='"$(BUILD_REV)"' -DBUILD_PLATFORM='"$(CONFIG_GUESS)"' -DBUILD_TYPE='"dynamic"' $(BUILDINFO_C) -c -o $(BUILDINFO_O) -DNAN_BUILDINFO + $(CCC) $(CCFLAGS) $(REL_CCFLAGS) -DBUILD_DATE='"$(BUILD_DATE)"' -DBUILD_TIME='"$(BUILD_TIME)"' -DBUILD_REV='"$(BUILD_REV)"' -DBUILD_PLATFORM='"$(CONFIG_GUESS)"' -DBUILD_TYPE='"dynamic"' $(BUILDINFO_C) -c -o $(BUILDINFO_O) -DNAN_BUILDINFO endif # $(CCC) $(DYNLDFLAGS) -o $@ $(NSPLUGLIB) $(PLUGAPPLIB) $(COMLIB) $(SPLIB) $(PLUGREMLIB) $(LLIBS) $(DADD) $(LOPTS) $(CCC) $(DYNLDFLAGS) -o $@ $(NSPLUGLIB) $(PLUGAPPLIB) $(COMLIB) $(SPLIB) $(PLUGREMLIB) $(LLIBS) $(DADD) $(LOPTS) /def:$(DEFFILE) @@ -602,7 +607,7 @@ endif $(DIR)/$(DEBUG_DIR)bin/npBlender3DPlugin$(SOEXT): $(NSPLUGLIB) $(PLUGAPPLIB) $(COMLIB) $(SPLIB) @echo "****> Link $@" ifdef NAN_BUILDINFO - $(CCC) $(REL_CFLAGS) -DBUILD_DATE='"$(BUILD_DATE)"' -DBUILD_TIME='"$(BUILD_TIME)"' -DBUILD_REV='"$(BUILD_REV)"' -DBUILD_PLATFORM='"$(CONFIG_GUESS)"' -DBUILD_TYPE='"dynamic"' $(BUILDINFO_C) -c -o $(BUILDINFO_O) -DNAN_BUILDINFO + $(CCC) $(CCFLAGS) $(REL_CCFLAGS) -DBUILD_DATE='"$(BUILD_DATE)"' -DBUILD_TIME='"$(BUILD_TIME)"' -DBUILD_REV='"$(BUILD_REV)"' -DBUILD_PLATFORM='"$(CONFIG_GUESS)"' -DBUILD_TYPE='"dynamic"' $(BUILDINFO_C) -c -o $(BUILDINFO_O) -DNAN_BUILDINFO endif mkdir -p $(DIR)/$(DEBUG_DIR)bin $(CCC) $(DYNLDFLAGS) -o $@ $(NSPLUGLIB) $(PLUGAPPLIB) $(COMLIB) $(SPLIB) $(PLUGREMLIB) $(LLIBS) $(DADD) $(LOPTS) @@ -613,7 +618,7 @@ endif $(DIR)/$(DEBUG_DIR)bin/npTestPlugin$(SOEXT): $(NSPLUGLIB) @echo "****> Link $@" ifdef NAN_BUILDINFO - $(CCC) $(REL_CFLAGS) -DBUILD_DATE='"$(BUILD_DATE)"' -DBUILD_TIME='"$(BUILD_TIME)"' -DBUILD_REV='"$(BUILD_REV)"' -DBUILD_PLATFORM='"$(CONFIG_GUESS)"' -DBUILD_TYPE='"dynamic"' $(BUILDINFO_C) -c -o $(BUILDINFO_O) -DNAN_BUILDINFO + $(CCC) $(CCFLAGS) $(REL_CCFLAGS) -DBUILD_DATE='"$(BUILD_DATE)"' -DBUILD_TIME='"$(BUILD_TIME)"' -DBUILD_REV='"$(BUILD_REV)"' -DBUILD_PLATFORM='"$(CONFIG_GUESS)"' -DBUILD_TYPE='"dynamic"' $(BUILDINFO_C) -c -o $(BUILDINFO_O) -DNAN_BUILDINFO endif mkdir -p $(DIR)/$(DEBUG_DIR)bin $(CCC) $(DYNLDFLAGS) -o $@ $(NSPLUGLIB) $(PLUGTESTLIB) $(LLIBS) $(DADD) $(LOPTS) diff --git a/source/blender/Makefile b/source/blender/Makefile index 6bc874c3c93..1c4ff6935b9 100644 --- a/source/blender/Makefile +++ b/source/blender/Makefile @@ -37,13 +37,17 @@ DIRS += python nodes gpu DIRS += blenfont ikplugin ifeq ($(WITH_QUICKTIME), true) - DIRS += quicktime + DIRS += quicktime endif ifeq ($(WITH_OPENJPEG), true) CFLAGS += -DWITH_OPENJPEG -I../../../../extern/libopenjpeg endif +ifeq ($(WITH_OPENCOLLADA), true) + DIRS += collada +endif + DIR = $(OCGDIR)/blender SOURCEDIR = source/blender diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index a3a1ead3924..01f863a4c2e 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -78,6 +78,12 @@ typedef struct DMGridAdjacency { int rotation[4]; } DMGridAdjacency; +typedef enum DerivedMeshType { + DM_TYPE_CDDM, + DM_TYPE_EDITMESH, + DM_TYPE_CCGDM +} DerivedMeshType; + typedef struct DerivedMesh DerivedMesh; struct DerivedMesh { /* Private DerivedMesh data, only for internal DerivedMesh use */ @@ -87,6 +93,7 @@ struct DerivedMesh { int deformedOnly; /* set by modifier stack if only deformed from original */ BVHCache bvhCache; struct GPUDrawObject *drawObject; + DerivedMeshType type; /* Misc. Queries */ @@ -202,7 +209,7 @@ struct DerivedMesh { /* Get a map of vertices to faces */ - struct ListBase *(*getFaceMap)(DerivedMesh *dm); + struct ListBase *(*getFaceMap)(struct Object *ob, DerivedMesh *dm); /* Get the BVH used for paint modes */ @@ -329,12 +336,14 @@ void DM_init_funcs(DerivedMesh *dm); * of vertices, edges and faces (doesn't allocate memory for them, just * sets up the custom data layers) */ -void DM_init(DerivedMesh *dm, int numVerts, int numEdges, int numFaces); +void DM_init(DerivedMesh *dm, DerivedMeshType type, + int numVerts, int numEdges, int numFaces); /* utility function to initialise a DerivedMesh for the desired number * of vertices, edges and faces, with a layer setup copied from source */ void DM_from_template(DerivedMesh *dm, DerivedMesh *source, + DerivedMeshType type, int numVerts, int numEdges, int numFaces); /* utility function to release a DerivedMesh's layers diff --git a/source/blender/blenkernel/BKE_anim.h b/source/blender/blenkernel/BKE_anim.h index 32c5ff81740..4862f4e5c46 100644 --- a/source/blender/blenkernel/BKE_anim.h +++ b/source/blender/blenkernel/BKE_anim.h @@ -38,14 +38,34 @@ struct Object; struct PartEff; struct Scene; struct ListBase; +struct bAnimVizSettings; +struct bMotionPath; +struct bPoseChannel; #include "DNA_object_types.h" +/* ---------------------------------------------------- */ +/* Animation Visualisation */ + +void animviz_settings_init(struct bAnimVizSettings *avs); + +void animviz_free_motionpath_cache(struct bMotionPath *mpath); +void animviz_free_motionpath(struct bMotionPath *mpath); + +struct bMotionPath *animviz_verify_motionpaths(struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan); +void animviz_calc_motionpaths(struct Scene *scene, struct Object *ob); + +/* ---------------------------------------------------- */ +/* Curve Paths */ + void free_path(struct Path *path); void calc_curvepath(struct Object *ob); int interval_test(int min, int max, int p1, int cycl); int where_on_path(struct Object *ob, float ctime, float *vec, float *dir, float *quat, float *radius); +/* ---------------------------------------------------- */ +/* Dupli-Geometry */ + struct ListBase *object_duplilist(struct Scene *sce, struct Object *ob); void free_object_duplilist(struct ListBase *lb); int count_duplilist(struct Object *ob); diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h index f302618e60d..cf8af56a5a9 100644 --- a/source/blender/blenkernel/BKE_brush.h +++ b/source/blender/blenkernel/BKE_brush.h @@ -36,6 +36,7 @@ struct Brush; struct ImBuf; struct Scene; struct wmOperator; +enum CurveMappingPreset; /* datablock functions */ struct Brush *add_brush(const char *name); @@ -54,12 +55,7 @@ int brush_clone_image_set_nr(struct Brush *brush, int nr); int brush_clone_image_delete(struct Brush *brush); /* brush curve */ -typedef enum { - BRUSH_PRESET_SHARP, - BRUSH_PRESET_SMOOTH, - BRUSH_PRESET_MAX -} BrushCurvePreset; -void brush_curve_preset(struct Brush *b, BrushCurvePreset preset); +void brush_curve_preset(struct Brush *b, /*enum CurveMappingPreset*/int preset); float brush_curve_strength_clamp(struct Brush *br, float p, const float len); float brush_curve_strength(struct Brush *br, float p, const float len); /* used for sculpt */ diff --git a/source/blender/blenkernel/BKE_colortools.h b/source/blender/blenkernel/BKE_colortools.h index c571688737a..85215592ff0 100644 --- a/source/blender/blenkernel/BKE_colortools.h +++ b/source/blender/blenkernel/BKE_colortools.h @@ -34,6 +34,13 @@ struct CurveMap; struct ImBuf; struct rctf; +typedef enum CurveMappingPreset { + CURVE_PRESET_LINE, + CURVE_PRESET_SHARP, + CURVE_PRESET_SMOOTH, + CURVE_PRESET_MAX +} CurveMappingPreset; + void floatbuf_to_srgb_byte(float *rectf, unsigned char *rectc, int x1, int x2, int y1, int y2, int w); void floatbuf_to_byte(float *rectf, unsigned char *rectc, int x1, int x2, int y1, int y2, int w); @@ -44,7 +51,7 @@ void curvemapping_set_black_white(struct CurveMapping *cumap, float *black, f void curvemap_remove(struct CurveMap *cuma, int flag); void curvemap_insert(struct CurveMap *cuma, float x, float y); -void curvemap_reset(struct CurveMap *cuma, struct rctf *clipr); +void curvemap_reset(struct CurveMap *cuma, struct rctf *clipr, CurveMappingPreset preset); void curvemap_sethandle(struct CurveMap *cuma, int type); void curvemapping_changed(struct CurveMapping *cumap, int rem_doubles); diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h index fa6b8969edb..d3457a5f5ae 100644 --- a/source/blender/blenkernel/BKE_fcurve.h +++ b/source/blender/blenkernel/BKE_fcurve.h @@ -31,6 +31,7 @@ struct FCurve; struct FModifier; struct ChannelDriver; +struct DriverVar; struct DriverTarget; struct BezTriple; @@ -40,7 +41,6 @@ struct StructRNA; /* ************** Keyframe Tools ***************** */ -// XXX this stuff is defined in BKE_ipo.h too, so maybe skip for now? typedef struct CfraElem { struct CfraElem *next, *prev; float cfra; @@ -51,13 +51,39 @@ void bezt_add_to_cfra_elem(ListBase *lb, struct BezTriple *bezt); /* ************** F-Curve Drivers ***************** */ +/* With these iterators for convenience, the variables "tarIndex" and "dtar" can be + * accessed directly from the code using them, but it is not recommended that their + * values be changed to point at other slots... + */ + +/* convenience looper over ALL driver targets for a given variable (even the unused ones) */ +#define DRIVER_TARGETS_LOOPER(dvar) \ + { \ + DriverTarget *dtar= &dvar->targets[0]; \ + int tarIndex= 0; \ + for (; tarIndex < MAX_DRIVER_TARGETS; tarIndex++, dtar++) + +/* convenience looper over USED driver targets only */ +#define DRIVER_TARGETS_USED_LOOPER(dvar) \ + { \ + DriverTarget *dtar= &dvar->targets[0]; \ + int tarIndex= 0; \ + for (; tarIndex < dvar->num_targets; tarIndex++, dtar++) + +/* tidy up for driver targets loopers */ +#define DRIVER_TARGETS_LOOPER_END \ + } + +/* ---------------------- */ + void fcurve_free_driver(struct FCurve *fcu); struct ChannelDriver *fcurve_copy_driver(struct ChannelDriver *driver); -void driver_free_target(struct ChannelDriver *driver, struct DriverTarget *dtar); -struct DriverTarget *driver_add_new_target(struct ChannelDriver *driver); +void driver_free_variable(struct ChannelDriver *driver, struct DriverVar *dvar); +void driver_change_variable_type(struct DriverVar *dvar, int type); +struct DriverVar *driver_add_new_variable(struct ChannelDriver *driver); -float driver_get_target_value(struct ChannelDriver *driver, struct DriverTarget *dtar); +float driver_get_variable_value (struct ChannelDriver *driver, struct DriverVar *dvar); /* ************** F-Curve Modifiers *************** */ diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h index 2e9ac2f65f0..9684aa1c602 100644 --- a/source/blender/blenkernel/BKE_global.h +++ b/source/blender/blenkernel/BKE_global.h @@ -146,6 +146,7 @@ typedef struct Global { #define G_FILE_GLSL_NO_EXTRA_TEX (1 << 21) /* deprecated */ #define G_FILE_IGNORE_DEPRECATION_WARNINGS (1 << 22) /* deprecated */ #define G_FILE_RECOVER (1 << 23) +#define G_FILE_RELATIVE_REMAP (1 << 24) /* G.windowstate */ #define G_WINDOWSTATE_USERDEF 0 diff --git a/source/blender/blenkernel/BKE_idprop.h b/source/blender/blenkernel/BKE_idprop.h index 9c7460851cb..7981fadccb6 100644 --- a/source/blender/blenkernel/BKE_idprop.h +++ b/source/blender/blenkernel/BKE_idprop.h @@ -82,6 +82,11 @@ void IDP_UnlinkID(struct IDProperty *prop); /*-------- Group Functions -------*/ +/* + replaces all properties with the same name in a destination group from a source group. +*/ +void IDP_ReplaceGroupInGroup(struct IDProperty *dest, struct IDProperty *src); + /*checks if a property with the same name as prop exists, and if so replaces it. Use this to preserve order!*/ void IDP_ReplaceInGroup(struct IDProperty *group, struct IDProperty *prop); diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h index 85c3c716b8b..6b8d9d1768e 100644 --- a/source/blender/blenkernel/BKE_image.h +++ b/source/blender/blenkernel/BKE_image.h @@ -47,8 +47,8 @@ void free_image(struct Image *me); void BKE_stamp_info(struct Scene *scene, struct ImBuf *ibuf); void BKE_stamp_buf(struct Scene *scene, unsigned char *rect, float *rectf, int width, int height, int channels); int BKE_write_ibuf(struct Scene *scene, struct ImBuf *ibuf, char *name, int imtype, int subimtype, int quality); -void BKE_makepicstring(struct Scene *scene, char *string, char *base, int frame, int imtype); -void BKE_add_image_extension(struct Scene *scene, char *string, int imtype); +void BKE_makepicstring(char *string, char *base, int frame, int imtype, int use_ext); +void BKE_add_image_extension(char *string, int imtype); int BKE_ftype_to_imtype(int ftype); int BKE_imtype_to_ftype(int imtype); int BKE_imtype_is_movie(int imtype); @@ -143,6 +143,9 @@ struct RenderPass *BKE_image_multilayer_index(struct RenderResult *rr, struct Im struct RenderResult *BKE_image_acquire_renderresult(struct Scene *scene, struct Image *ima); void BKE_image_release_renderresult(struct Scene *scene, struct Image *ima); +/* frees all ibufs used by any image datablocks */ +void BKE_image_free_image_ibufs(void); + /* goes over all textures that use images */ void BKE_image_free_all_textures(void); diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 3ed9ab8778e..8da732af2dd 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -174,6 +174,7 @@ struct bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node, int inte struct bNodeLink *nodeAddLink(struct bNodeTree *ntree, struct bNode *fromnode, struct bNodeSocket *fromsock, struct bNode *tonode, struct bNodeSocket *tosock); void nodeRemLink(struct bNodeTree *ntree, struct bNodeLink *link); +void nodeRemSocketLinks(struct bNodeTree *ntree, struct bNodeSocket *sock); struct bNode *nodeFindNodebyName(struct bNodeTree *ntree, const char *name); int nodeFindNode(struct bNodeTree *ntree, struct bNodeSocket *sock, struct bNode **nodep, int *sockindex); diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index 9e70251c782..d0c2052f0d6 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -62,6 +62,8 @@ void update_base_layer(struct Scene *scene, struct Object *ob); void free_object(struct Object *ob); void object_free_display(struct Object *ob); + +void object_link_modifiers(struct Object *ob, struct Object *from); void object_free_modifiers(struct Object *ob); void object_make_proxy(struct Object *ob, struct Object *target, struct Object *gob); diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index 2199240d77b..32202d9d462 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -203,6 +203,7 @@ int psys_check_enabled(struct Object *ob, struct ParticleSystem *psys); int psys_check_edited(struct ParticleSystem *psys); void psys_check_group_weights(struct ParticleSettings *part); +int psys_uses_gravity(struct ParticleSimulationData *sim); /* free */ void psys_free_settings(struct ParticleSettings *part); diff --git a/source/blender/blenkernel/BKE_sound.h b/source/blender/blenkernel/BKE_sound.h index 64ce1983e7d..8722485b97d 100644 --- a/source/blender/blenkernel/BKE_sound.h +++ b/source/blender/blenkernel/BKE_sound.h @@ -73,7 +73,7 @@ void sound_update_playing(struct bContext *C); void sound_scrub(struct bContext *C); #ifdef AUD_CAPI -AUD_Device* sound_mixdown(struct Scene *scene, AUD_Specs specs, int start, int end, float volume); +AUD_Device* sound_mixdown(struct Scene *scene, AUD_DeviceSpecs specs, int start, int end, float volume); #endif void sound_stop_all(struct bContext *C); diff --git a/source/blender/blenkernel/BKE_utildefines.h b/source/blender/blenkernel/BKE_utildefines.h index c052af775f2..77015876290 100644 --- a/source/blender/blenkernel/BKE_utildefines.h +++ b/source/blender/blenkernel/BKE_utildefines.h @@ -97,7 +97,9 @@ /* some math and copy defines */ +#ifndef SWAP #define SWAP(type, a, b) { type sw_ap; sw_ap=(a); (a)=(b); (b)=sw_ap; } +#endif #define ABS(a) ( (a)<0 ? (-(a)) : (a) ) diff --git a/source/blender/blenkernel/BKE_writeavi.h b/source/blender/blenkernel/BKE_writeavi.h index a8d38dda103..e2778ebb54c 100644 --- a/source/blender/blenkernel/BKE_writeavi.h +++ b/source/blender/blenkernel/BKE_writeavi.h @@ -40,19 +40,16 @@ struct RenderData; struct ReportList; struct Scene; -int start_avi(struct Scene *scene, struct RenderData *rd, int rectx, int recty, struct ReportList *reports); -void end_avi(void); -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 { 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, struct ReportList *reports); /* optional */ + void (*get_movie_path)(char *string, struct RenderData *rd); /* optional */ } bMovieHandle; bMovieHandle *BKE_get_movie_handle(int imtype); +void BKE_makeanimstring(char *string, struct RenderData *rd); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/BKE_writeffmpeg.h b/source/blender/blenkernel/BKE_writeffmpeg.h index 6ec8320f026..98c385ea2e1 100644 --- a/source/blender/blenkernel/BKE_writeffmpeg.h +++ b/source/blender/blenkernel/BKE_writeffmpeg.h @@ -63,6 +63,7 @@ struct Scene; extern int start_ffmpeg(struct Scene *scene, struct RenderData *rd, int rectx, int recty, struct ReportList *reports); extern void end_ffmpeg(void); extern int append_ffmpeg(struct RenderData *rd, int frame, int *pixels, int rectx, int recty, struct ReportList *reports); +void filepath_ffmpeg(char* string, struct RenderData* rd); extern void ffmpeg_set_preset(struct RenderData *rd, int preset); extern void ffmpeg_verify_image_type(struct RenderData *rd); diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index a614404dc5e..3ffa32c700d 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -184,9 +184,10 @@ void DM_init_funcs(DerivedMesh *dm) bvhcache_init(&dm->bvhCache); } -void DM_init(DerivedMesh *dm, +void DM_init(DerivedMesh *dm, DerivedMeshType type, int numVerts, int numEdges, int numFaces) { + dm->type = type; dm->numVertData = numVerts; dm->numEdgeData = numEdges; dm->numFaceData = numFaces; @@ -196,7 +197,7 @@ void DM_init(DerivedMesh *dm, dm->needsFree = 1; } -void DM_from_template(DerivedMesh *dm, DerivedMesh *source, +void DM_from_template(DerivedMesh *dm, DerivedMesh *source, DerivedMeshType type, int numVerts, int numEdges, int numFaces) { CustomData_copy(&source->vertData, &dm->vertData, CD_MASK_DERIVEDMESH, @@ -206,6 +207,7 @@ void DM_from_template(DerivedMesh *dm, DerivedMesh *source, CustomData_copy(&source->faceData, &dm->faceData, CD_MASK_DERIVEDMESH, CD_CALLOC, numFaces); + dm->type = type; dm->numVertData = numVerts; dm->numEdgeData = numEdges; dm->numFaceData = numFaces; @@ -336,16 +338,25 @@ void *DM_get_face_data(DerivedMesh *dm, int index, int type) void *DM_get_vert_data_layer(DerivedMesh *dm, int type) { + if(type == CD_MVERT) + return dm->getVertArray(dm); + return CustomData_get_layer(&dm->vertData, type); } void *DM_get_edge_data_layer(DerivedMesh *dm, int type) { + if(type == CD_MEDGE) + return dm->getEdgeArray(dm); + return CustomData_get_layer(&dm->edgeData, type); } void *DM_get_face_data_layer(DerivedMesh *dm, int type) { + if(type == CD_MFACE) + return dm->getFaceArray(dm); + return CustomData_get_layer(&dm->faceData, type); } @@ -512,56 +523,14 @@ static void emDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *us } glEnd(); } else { - GPUBuffer *buffer = NULL; - float *varray; - - if(GPU_buffer_legacy(dm)==FALSE) - buffer = GPU_buffer_alloc( sizeof(float)*3*2*emdm->em->totedge, 0 ); - - if( buffer != 0 && (varray = GPU_buffer_lock_stream( buffer )) ) { - int prevdraw = 0; - int numedges = 0; - int draw = 0; - int datatype[] = { GPU_BUFFER_INTER_V3F, GPU_BUFFER_INTER_END }; - GPU_buffer_unlock( buffer ); - GPU_interleaved_setup( buffer, datatype ); - varray = GPU_buffer_lock_stream( buffer ); - for(i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) { - if(!setDrawOptions || setDrawOptions(userData, i)) { - draw = 1; - } else { - draw = 0; - } - if( prevdraw != draw && prevdraw != 0 && numedges > 0) { - GPU_buffer_unlock( buffer ); - glDrawArrays(GL_LINES,0,numedges*2); - varray = GPU_buffer_lock_stream( buffer ); - numedges = 0; - } - if( draw != 0 ) { - VECCOPY(&varray[numedges*6],eed->v1->co); - VECCOPY(&varray[numedges*6+3],eed->v2->co); - numedges++; - } - prevdraw = draw; - } - GPU_buffer_unlock( buffer ); - if( prevdraw != 0 && numedges > 0) { - glDrawArrays(GL_LINES,0,numedges*2); - } - GPU_buffer_unbind(); - } else { - glBegin(GL_LINES); - for(i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) { - if(!setDrawOptions || setDrawOptions(userData, i)) { - glVertex3fv(eed->v1->co); - glVertex3fv(eed->v2->co); - } + glBegin(GL_LINES); + for(i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) { + if(!setDrawOptions || setDrawOptions(userData, i)) { + glVertex3fv(eed->v1->co); + glVertex3fv(eed->v2->co); } - glEnd(); } - if( buffer != 0 ) - GPU_buffer_free( buffer, 0 ); + glEnd(); } } static void emDM_drawEdges(DerivedMesh *dm, int drawLooseEdges) @@ -722,135 +691,41 @@ static void emDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *us } } } else { - GPUBuffer *buffer = 0; - float *varray; - if( setDrawOptions == 0 ) { - /* 3 floats for position, 3 for normal and times two because the faces may actually be quads instead of triangles */ - buffer = GPU_buffer_alloc( sizeof(float)*6*emdm->em->totface*3*2, 0 ); - } - if( buffer != 0 && (varray = GPU_buffer_lock_stream( buffer )) ) { - int prevdraw = 0; - int numfaces = 0; - int datatype[] = { GPU_BUFFER_INTER_V3F, GPU_BUFFER_INTER_N3F, GPU_BUFFER_INTER_END }; - GPU_buffer_unlock( buffer ); - GPU_interleaved_setup( buffer, datatype ); - glShadeModel(GL_SMOOTH); - varray = GPU_buffer_lock_stream( buffer ); - for (i=0,efa= emdm->em->faces.first; efa; i++,efa= efa->next) { - int drawSmooth = (efa->flag & ME_SMOOTH); - draw = setDrawOptions==NULL ? 1 : setDrawOptions(userData, i, &drawSmooth); - if( prevdraw != draw && prevdraw != 0 && numfaces > 0) { - if( prevdraw==2 ) { - glEnable(GL_POLYGON_STIPPLE); - glPolygonStipple(stipple_quarttone); - } - GPU_buffer_unlock( buffer ); - glDrawArrays(GL_TRIANGLES,0,numfaces*3); - if( prevdraw==2 ) { - glDisable(GL_POLYGON_STIPPLE); - } - varray = GPU_buffer_lock_stream( buffer ); - numfaces = 0; - } - if( draw != 0 ) { - if(!drawSmooth) { - VECCOPY(&varray[numfaces*18],efa->v1->co); - VECCOPY(&varray[numfaces*18+3],efa->n); - - VECCOPY(&varray[numfaces*18+6],efa->v2->co); - VECCOPY(&varray[numfaces*18+9],efa->n); - - VECCOPY(&varray[numfaces*18+12],efa->v3->co); - VECCOPY(&varray[numfaces*18+15],efa->n); - numfaces++; - if( efa->v4 ) { - VECCOPY(&varray[numfaces*18],efa->v3->co); - VECCOPY(&varray[numfaces*18+3],efa->n); - - VECCOPY(&varray[numfaces*18+6],efa->v4->co); - VECCOPY(&varray[numfaces*18+9],efa->n); - - VECCOPY(&varray[numfaces*18+12],efa->v1->co); - VECCOPY(&varray[numfaces*18+15],efa->n); - numfaces++; - } - } - else { - VECCOPY(&varray[numfaces*18],efa->v1->co); - VECCOPY(&varray[numfaces*18+3],efa->v1->no); - - VECCOPY(&varray[numfaces*18+6],efa->v2->co); - VECCOPY(&varray[numfaces*18+9],efa->v2->no); - - VECCOPY(&varray[numfaces*18+12],efa->v3->co); - VECCOPY(&varray[numfaces*18+15],efa->v3->no); - numfaces++; - if( efa->v4 ) { - VECCOPY(&varray[numfaces*18],efa->v3->co); - VECCOPY(&varray[numfaces*18+3],efa->v3->no); - - VECCOPY(&varray[numfaces*18+6],efa->v4->co); - VECCOPY(&varray[numfaces*18+9],efa->v4->no); - - VECCOPY(&varray[numfaces*18+12],efa->v1->co); - VECCOPY(&varray[numfaces*18+15],efa->v1->no); - numfaces++; - } - } - } - prevdraw = draw; - } - GPU_buffer_unlock( buffer ); - if( prevdraw != 0 && numfaces > 0) { - if( prevdraw==2 ) { + for (i=0,efa= emdm->em->faces.first; efa; i++,efa= efa->next) { + int drawSmooth = (efa->flag & ME_SMOOTH); + draw = setDrawOptions==NULL ? 1 : setDrawOptions(userData, i, &drawSmooth); + if(draw) { + if (draw==2) { /* enabled with stipple */ glEnable(GL_POLYGON_STIPPLE); - glPolygonStipple(stipple_quarttone); - } - glDrawArrays(GL_TRIANGLES,0,numfaces*3); - if( prevdraw==2 ) { - glDisable(GL_POLYGON_STIPPLE); + glPolygonStipple(stipple_quarttone); } - } - GPU_buffer_unbind(); - } else { - for (i=0,efa= emdm->em->faces.first; efa; i++,efa= efa->next) { - int drawSmooth = (efa->flag & ME_SMOOTH); - draw = setDrawOptions==NULL ? 1 : setDrawOptions(userData, i, &drawSmooth); - if(draw) { - if (draw==2) { /* enabled with stipple */ - glEnable(GL_POLYGON_STIPPLE); - glPolygonStipple(stipple_quarttone); - } - glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT); + glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT); - glBegin(efa->v4?GL_QUADS:GL_TRIANGLES); - if (!drawSmooth) { - glNormal3fv(efa->n); - glVertex3fv(efa->v1->co); - glVertex3fv(efa->v2->co); - glVertex3fv(efa->v3->co); - if(efa->v4) glVertex3fv(efa->v4->co); - } else { - glNormal3fv(efa->v1->no); - glVertex3fv(efa->v1->co); - glNormal3fv(efa->v2->no); - glVertex3fv(efa->v2->co); - glNormal3fv(efa->v3->no); - glVertex3fv(efa->v3->co); - if(efa->v4) { - glNormal3fv(efa->v4->no); - glVertex3fv(efa->v4->co); - } + glBegin(efa->v4?GL_QUADS:GL_TRIANGLES); + if (!drawSmooth) { + glNormal3fv(efa->n); + glVertex3fv(efa->v1->co); + glVertex3fv(efa->v2->co); + glVertex3fv(efa->v3->co); + if(efa->v4) glVertex3fv(efa->v4->co); + } else { + glNormal3fv(efa->v1->no); + glVertex3fv(efa->v1->co); + glNormal3fv(efa->v2->no); + glVertex3fv(efa->v2->co); + glNormal3fv(efa->v3->no); + glVertex3fv(efa->v3->co); + if(efa->v4) { + glNormal3fv(efa->v4->no); + glVertex3fv(efa->v4->co); } - glEnd(); - - if (draw==2) - glDisable(GL_POLYGON_STIPPLE); } + glEnd(); + + if (draw==2) + glDisable(GL_POLYGON_STIPPLE); } } - if( buffer != 0 ) - GPU_buffer_free( buffer, 0 ); } } @@ -1450,7 +1325,7 @@ static DerivedMesh *getEditMeshDerivedMesh(EditMesh *em, Object *ob, { EditMeshDerivedMesh *emdm = MEM_callocN(sizeof(*emdm), "emdm"); - DM_init(&emdm->dm, BLI_countlist(&em->verts), + DM_init(&emdm->dm, DM_TYPE_EDITMESH, BLI_countlist(&em->verts), BLI_countlist(&em->edges), BLI_countlist(&em->faces)); emdm->dm.getMinMax = emDM_getMinMax; diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 9e89ae77caa..a95cc7d1816 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -382,12 +382,12 @@ bPoseChannel *get_pose_channel(const bPose *pose, const char *name) if (ELEM(NULL, pose, name) || (name[0] == 0)) return NULL; - return BLI_findstring(&pose->chanbase, name, offsetof(bPoseChannel, name)); + return BLI_findstring(&((bPose *)pose)->chanbase, name, offsetof(bPoseChannel, name)); } /* Use with care, not on Armature poses but for temporal ones */ /* (currently used for action constraints and in rebuild_pose) */ -bPoseChannel *verify_pose_channel(bPose* pose, const char* name) +bPoseChannel *verify_pose_channel(bPose *pose, const char *name) { bPoseChannel *chan; @@ -455,10 +455,10 @@ const char *get_ikparam_name(bPose *pose) void copy_pose (bPose **dst, bPose *src, int copycon) { bPose *outPose; - bPoseChannel *pchan; + bPoseChannel *pchan; ListBase listb; - if (!src){ + if (!src) { *dst=NULL; return; } @@ -482,7 +482,8 @@ void copy_pose (bPose **dst, bPose *src, int copycon) if (copycon) { copy_constraints(&listb, &pchan->constraints); // copy_constraints NULLs listb pchan->constraints= listb; - pchan->path= NULL; + pchan->path= NULL; // XXX remove this line when the new motionpaths are ready... (depreceated code) + pchan->mpath= NULL; /* motion paths should not get copied yet... */ } if(pchan->prop) { @@ -491,7 +492,7 @@ void copy_pose (bPose **dst, bPose *src, int copycon) } /* for now, duplicate Bone Groups too when doing this */ - if(copycon) + if (copycon) BLI_duplicatelist(&outPose->agroups, &src->agroups); *dst=outPose; @@ -532,12 +533,20 @@ void init_pose_ikparam(bPose *pose) void free_pose_channel(bPoseChannel *pchan) { - if (pchan->path) + // XXX this case here will need to be removed when the new motionpaths are ready + if (pchan->path) { MEM_freeN(pchan->path); - + pchan->path= NULL; + } + + if (pchan->mpath) { + animviz_free_motionpath(pchan->mpath); + pchan->mpath= NULL; + } + free_constraints(&pchan->constraints); - - if(pchan->prop) { + + if (pchan->prop) { IDP_FreeProperty(pchan->prop); MEM_freeN(pchan->prop); } @@ -550,7 +559,7 @@ void free_pose_channels(bPose *pose) if (pose->chanbase.first) { for (pchan = pose->chanbase.first; pchan; pchan=pchan->next) free_pose_channel(pchan); - + BLI_freelistN(&pose->chanbase); } } @@ -564,14 +573,14 @@ void free_pose(bPose *pose) /* free pose-groups */ if (pose->agroups.first) BLI_freelistN(&pose->agroups); - + /* free IK solver state */ BIK_clear_data(pose); - + /* free IK solver param */ if (pose->ikparam) MEM_freeN(pose->ikparam); - + /* free pose */ MEM_freeN(pose); } diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index 6b8b604cb94..507fc520a85 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -29,16 +29,22 @@ * ***** END GPL LICENSE BLOCK ***** */ +#include <stdio.h> #include <math.h> #include <string.h> #include "MEM_guardedalloc.h" + #include "BLI_blenlib.h" #include "BLI_editVert.h" #include "BLI_math.h" #include "BLI_rand.h" + #include "DNA_listBase.h" +#include "DNA_anim_types.h" +#include "DNA_action_types.h" +#include "DNA_armature_types.h" #include "DNA_curve_types.h" #include "DNA_effect_types.h" #include "DNA_group_types.h" @@ -53,6 +59,7 @@ #include "DNA_vfont_types.h" #include "BKE_anim.h" +#include "BKE_animsys.h" #include "BKE_curve.h" #include "BKE_DerivedMesh.h" #include "BKE_displist.h" @@ -60,30 +67,313 @@ #include "BKE_font.h" #include "BKE_group.h" #include "BKE_global.h" -#include "BKE_ipo.h" #include "BKE_key.h" #include "BKE_lattice.h" #include "BKE_main.h" #include "BKE_mesh.h" #include "BKE_object.h" #include "BKE_particle.h" +#include "BKE_scene.h" #include "BKE_utildefines.h" #ifdef HAVE_CONFIG_H #include <config.h> #endif +// XXX bad level call... #include "ED_mesh.h" +/* --------------------- */ +/* forward declarations */ + static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBase *duplilist, float par_space_mat[][4], int level, int animated); +/* ******************************************************************** */ +/* Animation Visualisation */ + +/* Initialise the default settings for animation visualisation */ +void animviz_settings_init(bAnimVizSettings *avs) +{ + /* sanity check */ + if (avs == NULL) + return; + + /* ghosting settings */ + avs->ghost_bc= avs->ghost_ac= 10; + + avs->ghost_sf= 1; // xxx - take from scene instead? + avs->ghost_ef= 250; // xxx - take from scene instead? + + avs->ghost_step= 1; + + + /* path settings */ + avs->path_bc= avs->path_ac= 10; + + avs->path_sf= 1; // xxx - take from scene instead? + avs->path_ef= 250; // xxx - take from scene instead? + + avs->path_viewflag= (MOTIONPATH_VIEW_KFRAS|MOTIONPATH_VIEW_KFNOS); + + avs->path_step= 1; +} + +/* ------------------- */ + +/* Free the given motion path's cache */ +void animviz_free_motionpath_cache(bMotionPath *mpath) +{ + /* sanity check */ + if (mpath == NULL) + return; + + /* free the path if necessary */ + if (mpath->points) + MEM_freeN(mpath->points); + + /* reset the relevant parameters */ + mpath->points= NULL; + mpath->length= 0; +} + +/* Free the given motion path instance and its data + * NOTE: this frees the motion path given! + */ +void animviz_free_motionpath(bMotionPath *mpath) +{ + /* sanity check */ + if (mpath == NULL) + return; + + /* free the cache first */ + animviz_free_motionpath_cache(mpath); + + /* now the instance itself */ + MEM_freeN(mpath); +} + +/* ------------------- */ + +/* Setup motion paths for the given data + * - scene: current scene (for frame ranges, etc.) + * - ob: object to add paths for (must be provided) + * - pchan: posechannel to add paths for (optional; if not provided, object-paths are assumed) + */ +bMotionPath *animviz_verify_motionpaths(Scene *scene, Object *ob, bPoseChannel *pchan) +{ + bAnimVizSettings *avs; + bMotionPath *mpath, **dst; + + /* sanity checks */ + if (ELEM(NULL, scene, ob)) + return NULL; + + /* get destination data */ + if (pchan) { + /* paths for posechannel - assume that posechannel belongs to the object */ + avs= &ob->pose->avs; + dst= &pchan->mpath; + } + else { + /* paths for object */ + avs= &ob->avs; + dst= &ob->mpath; + } + + /* if there is already a motionpath, just return that, + * but provided it's settings are ok + */ + if (*dst != NULL) { + mpath= *dst; + + /* if range is not invalid, and/or length is set ok, just return */ + if ((mpath->start_frame != mpath->end_frame) && (mpath->length > 0)) + return mpath; + } + else { + /* create a new motionpath, and assign it */ + mpath= MEM_callocN(sizeof(bMotionPath), "bMotionPath"); + *dst= mpath; + } + + /* set settings from the viz settings */ + mpath->start_frame= avs->path_sf; + mpath->end_frame= avs->path_ef; + + mpath->length= mpath->end_frame - mpath->start_frame; + + if (avs->path_bakeflag & MOTIONPATH_BAKE_HEADS) + mpath->flag |= MOTIONPATH_FLAG_BHEAD; + + /* allocate a cache */ + mpath->points= MEM_callocN(sizeof(bMotionPathVert)*mpath->length, "bMotionPathVerts"); + + /* return it */ + return mpath; +} + +/* ------------------- */ + +/* Motion path needing to be baked (mpt) */ +typedef struct MPathTarget { + struct MPathTarget *next, *prev; + + bMotionPath *mpath; /* motion path in question */ + + Object *ob; /* source object */ + bPoseChannel *pchan; /* source posechannel (if applicable) */ +} MPathTarget; + +/* ........ */ + +/* get list of motion paths to be baked (assumes the list is ready to be used) */ +static void motionpaths_get_bake_targets(Object *ob, ListBase *targets) +{ + MPathTarget *mpt; + + /* object itself first */ + if ((ob->avs.recalc & ANIMVIZ_RECALC_PATHS) && (ob->mpath)) { + /* new target for object */ + mpt= MEM_callocN(sizeof(MPathTarget), "MPathTarget Ob"); + BLI_addtail(targets, mpt); + + mpt->mpath= ob->mpath; + mpt->ob= ob; + } + + /* bones */ + if ((ob->pose) && (ob->pose->avs.recalc & ANIMVIZ_RECALC_PATHS)) { + bArmature *arm= ob->data; + bPoseChannel *pchan; + + for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { + if ((pchan->bone) && (arm->layer & pchan->bone->layer) && (pchan->mpath)) { + /* new target for bone */ + mpt= MEM_callocN(sizeof(MPathTarget), "MPathTarget PoseBone"); + BLI_addtail(targets, mpt); + + mpt->mpath= pchan->mpath; + mpt->ob= ob; + mpt->pchan= pchan; + } + } + } +} + +/* perform baking for the targets on the current frame */ +static void motionpaths_calc_bake_targets(Scene *scene, ListBase *targets) +{ + MPathTarget *mpt; + + /* for each target, check if it can be baked on the current frame */ + for (mpt= targets->first; mpt; mpt= mpt->next) { + bMotionPath *mpath= mpt->mpath; + bMotionPathVert *mpv; + + /* current frame must be within the range the cache works for */ + if (IN_RANGE(CFRA, mpath->start_frame, mpath->end_frame) == 0) + continue; + + /* get the relevant cache vert to write to */ + mpv= mpath->points + (CFRA - mpath->start_frame); + + /* pose-channel or object path baking? */ + if (mpt->pchan) { + /* heads or tails */ + if (mpath->flag & MOTIONPATH_FLAG_BHEAD) { + VECCOPY(mpv->co, mpt->pchan->pose_head); + } + else { + VECCOPY(mpv->co, mpt->pchan->pose_tail); + } + + /* result must be in worldspace */ + mul_m4_v3(mpt->ob->obmat, mpv->co); + } + else { + /* worldspace object location */ + VECCOPY(mpv->co, mpt->ob->obmat[3]); + } + } +} + +/* ........ */ + +/* Perform baking of the given object's and/or its bones' transforms to motion paths + * - scene: current scene + * - ob: object whose flagged motionpaths should get calculated + * - recalc: whether we need to + */ +// TODO: include reports pointer? +void animviz_calc_motionpaths(Scene *scene, Object *ob) +{ + ListBase targets = {NULL, NULL}; + MPathTarget *mpt; + int sfra, efra; + int cfra; + + /* sanity checks */ + if (ob == NULL) + return; + + /* get motion paths to affect */ + motionpaths_get_bake_targets(ob, &targets); + + if (targets.first == NULL) + return; + + /* set frame values */ + cfra = CFRA; + sfra = efra = cfra; + + for (mpt= targets.first; mpt; mpt= mpt->next) { + /* try to increase area to do (only as much as needed) */ + sfra= MIN2(sfra, mpt->mpath->start_frame); + efra= MAX2(efra, mpt->mpath->end_frame); + } + if (efra <= sfra) return; + + /* calculate path over requested range */ + for (CFRA=sfra; CFRA<=efra; CFRA++) { + /* do all updates + * - if this is too slow, resort to using a more efficient way + * that doesn't force complete update, but for now, this is the + * most accurate way! + */ + scene_update_for_newframe(scene, ob->lay); // XXX is the layer flag too restrictive? + + /* perform baking for targets */ + motionpaths_calc_bake_targets(scene, &targets); + } + + /* reset original environment */ + CFRA= cfra; + scene_update_for_newframe(scene, ob->lay); // XXX is the layer flag too restrictive? + + // TODO: make an API call for this too? + ob->avs.recalc &= ~ANIMVIZ_RECALC_PATHS; + if (ob->pose) + ob->pose->avs.recalc &= ~ANIMVIZ_RECALC_PATHS; + + /* free temp data */ + BLI_freelistN(&targets); +} + +/* ******************************************************************** */ +/* Curve Paths - for curve deforms and/or curve following */ + +/* free curve path data + * NOTE: frees the path itself! + */ void free_path(Path *path) { if(path->data) MEM_freeN(path->data); MEM_freeN(path); } - +/* calculate a curve-deform path for a curve + * - only called from displist.c -> makeDispListCurveTypes + */ void calc_curvepath(Object *ob) { BevList *bl; @@ -96,7 +386,6 @@ void calc_curvepath(Object *ob) float fac, d=0, fac1, fac2; int a, tot, cycl=0; - /* in a path vertices are with equal differences: path->len = number of verts */ /* NOW WITH BEVELCURVE!!! */ @@ -143,7 +432,7 @@ void calc_curvepath(Object *ob) } path->totdist= *fp; - + /* the path verts in path->data */ /* now also with TILT value */ pp= path->data = (PathPoint *)MEM_callocN(sizeof(PathPoint)*4*path->len, "pathdata"); // XXX - why *4? - in 2.4x each element was 4 and the size was 16, so better leave for now - Campbell @@ -155,7 +444,7 @@ void calc_curvepath(Object *ob) maxdist= dist+tot; fac= 1.0f/((float)path->len-1.0f); fac = fac * path->totdist; - + for(a=0; a<path->len; a++) { d= ((float)a)*fac; @@ -175,7 +464,7 @@ void calc_curvepath(Object *ob) fac2= *(fp)-d; fac1= fac2/fac1; fac2= 1.0f-fac1; - + interp_v3_v3v3(pp->vec, bevp->vec, bevpn->vec, fac2); pp->vec[3]= fac1*bevp->alfa + fac2*bevpn->alfa; pp->radius= fac1*bevp->radius + fac2*bevpn->radius; @@ -188,11 +477,12 @@ void calc_curvepath(Object *ob) MEM_freeN(dist); } + +/* is this only used internally?*/ int interval_test(int min, int max, int p1, int cycl) { - if(cycl) { - if( p1 < min) + if(p1 < min) p1= ((p1 -min) % (max-min+1)) + max+1; else if(p1 > max) p1= ((p1 -min) % (max-min+1)) + min; @@ -204,8 +494,11 @@ int interval_test(int min, int max, int p1, int cycl) return p1; } -/* warning, *vec needs FOUR items! */ -/* ctime is normalized range <0-1> */ + +/* calculate the deformation implied by the curve path at a given parametric position, and returns whether this operation succeeded + * - *vec needs FOUR items! + * - ctime is normalized range <0-1> + */ int where_on_path(Object *ob, float ctime, float *vec, float *dir, float *quat, float *radius) /* returns OK */ { Curve *cu; @@ -305,7 +598,8 @@ int where_on_path(Object *ob, float ctime, float *vec, float *dir, float *quat, return 1; } -/* ****************** DUPLICATOR ************** */ +/* ******************************************************************** */ +/* Dupli-Geometry */ static DupliObject *new_dupli_object(ListBase *lb, Object *ob, float mat[][4], int lay, int index, int type, int animated) { @@ -407,7 +701,7 @@ static void frames_duplilist(ListBase *lb, Scene *scene, Object *ob, int level, enable_cu_speed= 1; } -struct vertexDupliData { +typedef struct vertexDupliData { ID *id; /* scene or group, for recursive loops */ int level; int animated; @@ -417,12 +711,14 @@ struct vertexDupliData { Scene *scene; Object *ob, *par; float (*orco)[3]; -}; +} vertexDupliData; + +/* ------------- */ static void vertex_dupli__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s) { DupliObject *dob; - struct vertexDupliData *vdd= userData; + vertexDupliData *vdd= userData; float vec[3], q2[4], mat[3][3], tmat[4][4], obmat[4][4]; VECCOPY(vec, co); @@ -466,7 +762,7 @@ static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, fl Mesh *me= par->data; Base *base = NULL; DerivedMesh *dm; - struct vertexDupliData vdd; + vertexDupliData vdd; Scene *sce = NULL; Group *group = NULL; GroupObject * go = NULL; @@ -1070,7 +1366,8 @@ static void font_duplilist(ListBase *lb, Scene *scene, Object *par, int level, i MEM_freeN(chartransdata); } -/* ***************************** */ +/* ------------- */ + static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBase *duplilist, float par_space_mat[][4], int level, int animated) { if((ob->transflag & OB_DUPLI)==0) diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 4f96b031daa..8b86f6a5d1f 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -319,16 +319,32 @@ static void fcurves_path_rename_fix (ID *owner_id, char *prefix, char *oldName, /* we need to check every curve... */ for (fcu= curves->first; fcu; fcu= fcu->next) { /* firstly, handle the F-Curve's own path */ - fcu->rna_path= rna_path_rename_fix(owner_id, prefix, oldName, newName, fcu->rna_path); + if (fcu->rna_path) + fcu->rna_path= rna_path_rename_fix(owner_id, prefix, oldName, newName, fcu->rna_path); /* driver? */ if (fcu->driver) { ChannelDriver *driver= fcu->driver; - DriverTarget *dtar; + DriverVar *dvar; - /* driver targets */ - for (dtar= driver->targets.first; dtar; dtar=dtar->next) { - dtar->rna_path= rna_path_rename_fix(dtar->id, prefix, oldName, newName, dtar->rna_path); + /* driver variables */ + for (dvar= driver->variables.first; dvar; dvar=dvar->next) { + /* only change the used targets, since the others will need fixing manually anyway */ + DRIVER_TARGETS_USED_LOOPER(dvar) + { + /* rename RNA path */ + if (dtar->rna_path) + dtar->rna_path= rna_path_rename_fix(dtar->id, prefix, oldName, newName, dtar->rna_path); + + /* also fix the bone-name (if applicable) */ + // XXX this has been disabled because the old/new names have padding which means this check will fail + //if ( ((dtar->id) && (GS(dtar->id->name) == ID_OB)) && + // (dtar->pchan_name[0]) && (strcmp(oldName, dtar->pchan_name)==0) ) + //{ + // BLI_strncpy(dtar->pchan_name, newName, sizeof(dtar->pchan_name)); + //} + } + DRIVER_TARGETS_LOOPER_END } } } diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index e53e4a1155b..9ae871b1dea 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -1480,8 +1480,23 @@ static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected bPose *pose= ob->pose, *frompose= from->pose; bPoseChannel *pchan, *pchanp, pchanw; bConstraint *con; + int error = 0; if (frompose==NULL) return; + + /* in some cases when rigs change, we cant synchronize + * to avoid crashing check for possible errors here */ + for (pchan= pose->chanbase.first; pchan; pchan= pchan->next) { + if (pchan->bone->layer & layer_protected) { + if(get_pose_channel(frompose, pchan->name) == NULL) { + printf("failed to sync proxy armature because '%s' is missing pose channel '%s'\n", from->id.name, pchan->name); + error = 1; + } + } + } + + if(error) + return; /* exception, armature local layer should be proxied too */ if (pose->proxy_layer) diff --git a/source/blender/blenkernel/intern/boids.c b/source/blender/blenkernel/intern/boids.c index 389009cca76..838e595d83f 100644 --- a/source/blender/blenkernel/intern/boids.c +++ b/source/blender/blenkernel/intern/boids.c @@ -557,8 +557,8 @@ static int rule_average_speed(BoidRule *rule, BoidBrainData *bbd, BoidValues *va add_v3_v3v3(bbd->wanted_co, bbd->wanted_co, vec); /* leveling */ - if(asbr->level > 0.0f) { - project_v3_v3v3(vec, bbd->wanted_co, bbd->sim->psys->part->acc); + if(asbr->level > 0.0f && psys_uses_gravity(bbd->sim)) { + project_v3_v3v3(vec, bbd->wanted_co, bbd->sim->scene->physics_settings.gravity); mul_v3_fl(vec, asbr->level); sub_v3_v3v3(bbd->wanted_co, bbd->wanted_co, vec); } @@ -574,8 +574,8 @@ static int rule_average_speed(BoidRule *rule, BoidBrainData *bbd, BoidValues *va } /* leveling */ - if(asbr->level > 0.0f) { - project_v3_v3v3(vec, bbd->wanted_co, bbd->sim->psys->part->acc); + if(asbr->level > 0.0f && psys_uses_gravity(bbd->sim)) { + project_v3_v3v3(vec, bbd->wanted_co, bbd->sim->scene->physics_settings.gravity); mul_v3_fl(vec, asbr->level); sub_v3_v3v3(bbd->wanted_co, bbd->wanted_co, vec); } @@ -1002,8 +1002,8 @@ void boid_brain(BoidBrainData *bbd, int p, ParticleData *pa) if(dot_v2v2(cvel, dir) > 0.95f / mul || len <= state->rule_fuzziness) { /* try to reach goal at highest point of the parabolic path */ cur_v = len_v2(pa->prev_state.vel); - z_v = sasqrt(-2.0f * bbd->part->acc[2] * bbd->wanted_co[2]); - ground_v = len_v2(bbd->wanted_co)*sasqrt(-0.5f * bbd->part->acc[2] / bbd->wanted_co[2]); + z_v = sasqrt(-2.0f * bbd->sim->scene->physics_settings.gravity[2] * bbd->wanted_co[2]); + ground_v = len_v2(bbd->wanted_co)*sasqrt(-0.5f * bbd->sim->scene->physics_settings.gravity[2] / bbd->wanted_co[2]); len = sasqrt((ground_v-cur_v)*(ground_v-cur_v) + z_v*z_v); @@ -1061,12 +1061,12 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa) pa_mass*=pa->size; /* if boids can't fly they fall to the ground */ - if((boids->options & BOID_ALLOW_FLIGHT)==0 && ELEM(bpa->data.mode, eBoidMode_OnLand, eBoidMode_Climbing)==0 && bbd->part->acc[2] != 0.0f) + if((boids->options & BOID_ALLOW_FLIGHT)==0 && ELEM(bpa->data.mode, eBoidMode_OnLand, eBoidMode_Climbing)==0 && psys_uses_gravity(bbd->sim)) bpa->data.mode = eBoidMode_Falling; if(bpa->data.mode == eBoidMode_Falling) { /* Falling boids are only effected by gravity. */ - acc[2] = bbd->part->acc[2]; + acc[2] = bbd->sim->scene->physics_settings.gravity[2]; } else { /* figure out acceleration */ @@ -1221,7 +1221,7 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa) switch(bpa->data.mode) { case eBoidMode_InAir: { - float grav[3] = {0.0f, 0.0f, bbd->part->acc[2] < 0.0f ? -1.0f : 0.0f}; + float grav[3] = {0.0f, 0.0f, bbd->sim->scene->physics_settings.gravity[2] < 0.0f ? -1.0f : 0.0f}; /* don't take forward acceleration into account (better banking) */ if(dot_v3v3(bpa->data.acc, pa->state.vel) > 0.0f) { @@ -1253,7 +1253,7 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa) } case eBoidMode_Falling: { - float grav[3] = {0.0f, 0.0f, bbd->part->acc[2] < 0.0f ? -1.0f : 0.0f}; + float grav[3] = {0.0f, 0.0f, bbd->sim->scene->physics_settings.gravity[2] < 0.0f ? -1.0f : 0.0f}; /* gather apparent gravity */ VECADDFAC(bpa->gravity, bpa->gravity, grav, dtime); diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index 667b0d50ee9..99cd6975665 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -88,7 +88,7 @@ Brush *add_brush(const char *name) brush->sculpt_tool = SCULPT_TOOL_DRAW; brush->flag |= BRUSH_SPACE; - brush_curve_preset(brush, BRUSH_PRESET_SMOOTH); + brush_curve_preset(brush, CURVE_PRESET_SMOOTH); /* enable fake user by default */ brush->id.flag |= LIB_FAKEUSER; @@ -100,19 +100,11 @@ Brush *add_brush(const char *name) Brush *copy_brush(Brush *brush) { Brush *brushn; - MTex *mtex; - int a; brushn= copy_libblock(brush); - for(a=0; a<MAX_MTEX; a++) { - mtex= brush->mtex[a]; - if(mtex) { - brushn->mtex[a]= MEM_dupallocN(mtex); - if(mtex->tex) id_us_plus((ID*)mtex->tex); - } - } - + if(brush->mtex.tex) id_us_plus((ID*)brush->mtex.tex); + brushn->curve= curvemapping_copy(brush->curve); /* enable fake user by default */ @@ -127,17 +119,8 @@ Brush *copy_brush(Brush *brush) /* not brush itself */ void free_brush(Brush *brush) { - MTex *mtex; - int a; - - for(a=0; a<MAX_MTEX; a++) { - mtex= brush->mtex[a]; - if(mtex) { - if(mtex->tex) mtex->tex->id.us--; - MEM_freeN(mtex); - } - } - + if(brush->mtex.tex) brush->mtex.tex->id.us--; + curvemapping_free(brush->curve); } @@ -242,7 +225,7 @@ void brush_toggled_fake_user(Brush *brush) } } -void brush_curve_preset(Brush *b, BrushCurvePreset preset) +void brush_curve_preset(Brush *b, /*CurveMappingPreset*/int preset) { CurveMap *cm = NULL; @@ -250,53 +233,16 @@ void brush_curve_preset(Brush *b, BrushCurvePreset preset) b->curve = curvemapping_add(1, 0, 0, 1, 1); cm = b->curve->cm; - - if(cm->curve) - MEM_freeN(cm->curve); - - if(preset == BRUSH_PRESET_SHARP) - cm->totpoint= 3; - if(preset == BRUSH_PRESET_SMOOTH) - cm->totpoint= 4; - if(preset == BRUSH_PRESET_MAX) - cm->totpoint= 2; - - - cm->curve= MEM_callocN(cm->totpoint*sizeof(CurveMapPoint), "curve points"); cm->flag &= ~CUMA_EXTEND_EXTRAPOLATE; - if(preset == BRUSH_PRESET_SHARP) { - cm->curve[0].x= 0; - cm->curve[0].y= 1; - cm->curve[1].x= 0.33; - cm->curve[1].y= 0.33; - cm->curve[2].x= 1; - cm->curve[2].y= 0; - } - else if(preset == BRUSH_PRESET_SMOOTH) { - cm->curve[0].x= 0; - cm->curve[0].y= 1; - cm->curve[1].x= 0.25; - cm->curve[1].y= 0.92; - cm->curve[2].x= 0.75; - cm->curve[2].y= 0.08; - cm->curve[3].x= 1; - cm->curve[3].y= 0; - } - else if(preset == BRUSH_PRESET_MAX) { - cm->curve[0].x= 0; - cm->curve[0].y= 1; - cm->curve[1].x= 1; - cm->curve[1].y= 1; - } - + curvemap_reset(cm, &b->curve->clipr, preset); curvemapping_changed(b->curve, 0); } static MTex *brush_active_texture(Brush *brush) { - if(brush && brush->texact >= 0) - return brush->mtex[brush->texact]; + if(brush) + return &brush->mtex; return NULL; } @@ -304,8 +250,7 @@ int brush_texture_set_nr(Brush *brush, int nr) { ID *idtest, *id=NULL; - if(brush->mtex[brush->texact]) - id= (ID *)brush->mtex[brush->texact]->tex; + id= (ID *)brush->mtex.tex; idtest= (ID*)BLI_findlink(&G.main->tex, nr-1); if(idtest==0) { /* new tex */ @@ -316,13 +261,7 @@ int brush_texture_set_nr(Brush *brush, int nr) if(idtest!=id) { brush_texture_delete(brush); - if(brush->mtex[brush->texact]==NULL) { - brush->mtex[brush->texact]= add_mtex(); - brush->mtex[brush->texact]->r = 1.0f; - brush->mtex[brush->texact]->g = 1.0f; - brush->mtex[brush->texact]->b = 1.0f; - } - brush->mtex[brush->texact]->tex= (Tex*)idtest; + brush->mtex.tex= (Tex*)idtest; id_us_plus(idtest); return 1; @@ -333,16 +272,10 @@ int brush_texture_set_nr(Brush *brush, int nr) int brush_texture_delete(Brush *brush) { - if(brush->mtex[brush->texact]) { - if(brush->mtex[brush->texact]->tex) - brush->mtex[brush->texact]->tex->id.us--; - MEM_freeN(brush->mtex[brush->texact]); - brush->mtex[brush->texact]= NULL; + if(brush->mtex.tex) + brush->mtex.tex->id.us--; - return 1; - } - - return 0; + return 1; } int brush_clone_image_set_nr(Brush *brush, int nr) @@ -383,7 +316,7 @@ void brush_check_exists(Brush **brush, const char *name) /* Brush Sampling */ void brush_sample_tex(Brush *brush, float *xy, float *rgba) { - MTex *mtex= brush->mtex[brush->texact]; + MTex *mtex= &brush->mtex; if (mtex && mtex->tex) { float co[3], tin, tr, tg, tb, ta; @@ -741,7 +674,7 @@ static void brush_painter_refresh_cache(BrushPainter *painter, float *pos) { Brush *brush= painter->brush; BrushPainterCache *cache= &painter->cache; - MTex *mtex= brush->mtex[brush->texact]; + MTex *mtex= &brush->mtex; int size; short flt; @@ -976,7 +909,7 @@ float brush_curve_strength(Brush *br, float p, const float len) unsigned int *brush_gen_texture_cache(Brush *br, int half_side) { unsigned int *texcache = NULL; - MTex *mtex = br->mtex[br->texact]; + MTex *mtex = &br->mtex; TexResult texres; int hasrgb, ix, iy; int side = half_side * 2; diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 66c39c6571a..e9a1021a203 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -177,13 +177,15 @@ static void cdDM_getVertNo(DerivedMesh *dm, int index, float no_r[3]) no_r[2] = no[2]/32767.f; } -static ListBase *cdDM_getFaceMap(DerivedMesh *dm) +static ListBase *cdDM_getFaceMap(Object *ob, DerivedMesh *dm) { CDDerivedMesh *cddm = (CDDerivedMesh*) dm; - if(!cddm->fmap) { - create_vert_face_map(&cddm->fmap, &cddm->fmap_mem, cddm->mface, - dm->getNumVerts(dm), dm->getNumFaces(dm)); + if(!cddm->fmap && ob->type == OB_MESH) { + Mesh *me= ob->data; + + create_vert_face_map(&cddm->fmap, &cddm->fmap_mem, me->mface, + me->totvert, me->totface); } return cddm->fmap; @@ -1404,7 +1406,7 @@ DerivedMesh *CDDM_new(int numVerts, int numEdges, int numFaces) CDDerivedMesh *cddm = cdDM_create("CDDM_new dm"); DerivedMesh *dm = &cddm->dm; - DM_init(dm, numVerts, numEdges, numFaces); + DM_init(dm, DM_TYPE_CDDM, numVerts, numEdges, numFaces); CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts); CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges); @@ -1430,7 +1432,7 @@ DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *ob) /* this does a referenced copy, with an exception for fluidsim */ - DM_init(dm, mesh->totvert, mesh->totedge, mesh->totface); + DM_init(dm, DM_TYPE_CDDM, mesh->totvert, mesh->totedge, mesh->totface); dm->deformedOnly = 1; @@ -1563,7 +1565,7 @@ DerivedMesh *CDDM_copy(DerivedMesh *source) source->getFaceDataArray(source, CD_ORIGINDEX); /* this initializes dm, and copies all non mvert/medge/mface layers */ - DM_from_template(dm, source, numVerts, numEdges, numFaces); + DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces); dm->deformedOnly = source->deformedOnly; CustomData_copy_data(&source->vertData, &dm->vertData, 0, 0, numVerts); @@ -1589,7 +1591,7 @@ DerivedMesh *CDDM_from_template(DerivedMesh *source, DerivedMesh *dm = &cddm->dm; /* this does a copy of all non mvert/medge/mface layers */ - DM_from_template(dm, source, numVerts, numEdges, numFaces); + DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces); /* now add mvert/medge/mface layers */ CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts); diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index 48e42bc539f..d8975c16cc8 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -236,16 +236,54 @@ void curvemap_insert(CurveMap *cuma, float x, float y) cuma->curve= cmp; } -void curvemap_reset(CurveMap *cuma, rctf *clipr) +void curvemap_reset(CurveMap *cuma, rctf *clipr, CurveMappingPreset preset) { - cuma->totpoint= 2; - - cuma->curve[0].x= clipr->xmin; - cuma->curve[0].y= clipr->ymin; - cuma->curve[0].flag= 0; - cuma->curve[1].x= clipr->xmax; - cuma->curve[1].y= clipr->ymax; - cuma->curve[1].flag= 0; + if(cuma->curve) + MEM_freeN(cuma->curve); + + switch(preset) { + case CURVE_PRESET_LINE: cuma->totpoint= 2; break; + case CURVE_PRESET_SHARP: cuma->totpoint= 3; break; + case CURVE_PRESET_SMOOTH: cuma->totpoint= 4; break; + case CURVE_PRESET_MAX: cuma->totpoint= 2; break; + } + + cuma->curve= MEM_callocN(cuma->totpoint*sizeof(CurveMapPoint), "curve points"); + + switch(preset) { + case CURVE_PRESET_LINE: + cuma->curve[0].x= clipr->xmin; + cuma->curve[0].y= clipr->ymin; + cuma->curve[0].flag= 0; + cuma->curve[1].x= clipr->xmax; + cuma->curve[1].y= clipr->ymax; + cuma->curve[1].flag= 0; + break; + case CURVE_PRESET_SHARP: + cuma->curve[0].x= 0; + cuma->curve[0].y= 1; + cuma->curve[1].x= 0.33; + cuma->curve[1].y= 0.33; + cuma->curve[2].x= 1; + cuma->curve[2].y= 0; + break; + case CURVE_PRESET_SMOOTH: + cuma->curve[0].x= 0; + cuma->curve[0].y= 1; + cuma->curve[1].x= 0.25; + cuma->curve[1].y= 0.92; + cuma->curve[2].x= 0.75; + cuma->curve[2].y= 0.08; + cuma->curve[3].x= 1; + cuma->curve[3].y= 0; + break; + case CURVE_PRESET_MAX: + cuma->curve[0].x= 0; + cuma->curve[0].y= 1; + cuma->curve[1].x= 1; + cuma->curve[1].y= 1; + break; + } if(cuma->table) { MEM_freeN(cuma->table); @@ -725,10 +763,16 @@ void colorcorrection_do_ibuf(ImBuf *ibuf, const char *profile) } } - +/* only used for image editor curves */ void curvemapping_do_ibuf(CurveMapping *cumap, ImBuf *ibuf) { + ImBuf *tmpbuf; int pixel; + char *tmpcbuf; + float *pix_in; + float col[3]; + int stride= 4; + float *pix_out; if(ibuf==NULL) return; @@ -737,35 +781,45 @@ void curvemapping_do_ibuf(CurveMapping *cumap, ImBuf *ibuf) else if(ibuf->rect==NULL) imb_addrectImBuf(ibuf); + if (!ibuf->rect || !ibuf->rect_float) + return; + + /* work on a temp buffer, so can color manage afterwards. + * No worse off memory wise than comp nodes */ + tmpbuf = IMB_dupImBuf(ibuf); + curvemapping_premultiply(cumap, 0); - if(ibuf->rect_float && ibuf->rect) { - float *pixf= ibuf->rect_float; - float col[3]; - int stride= 4; - char *pixc= (char *)ibuf->rect; - - if(ibuf->channels) - stride= ibuf->channels; - - for(pixel= ibuf->x*ibuf->y; pixel>0; pixel--, pixf+=stride, pixc+=4) { - if(stride<3) { - col[0]= curvemap_evaluateF(cumap->cm, *pixf); - pixc[1]= pixc[2]= pixc[3]= pixc[0]= FTOCHAR(col[0]); - } - else { - curvemapping_evaluate_premulRGBF(cumap, col, pixf); - pixc[0]= FTOCHAR(col[0]); - pixc[1]= FTOCHAR(col[1]); - pixc[2]= FTOCHAR(col[2]); - if(stride>3) - pixc[3]= FTOCHAR(pixf[3]); - else - pixc[3]= 255; - } + pix_in= ibuf->rect_float; + pix_out= tmpbuf->rect_float; +// pixc= (char *)ibuf->rect; + + if(ibuf->channels) + stride= ibuf->channels; + + for(pixel= ibuf->x*ibuf->y; pixel>0; pixel--, pix_in+=stride, pix_out+=4) { + if(stride<3) { + col[0]= curvemap_evaluateF(cumap->cm, *pix_in); + + pix_out[1]= pix_out[2]= pix_out[3]= pix_out[0]= col[0]; + } + else { + curvemapping_evaluate_premulRGBF(cumap, col, pix_in); + pix_out[0]= col[0]; + pix_out[1]= col[1]; + pix_out[2]= col[2]; + if(stride>3) + pix_out[3]= pix_in[3]; + else + pix_out[3]= 1.f; } } + IMB_rect_from_float(tmpbuf); + SWAP(char *, tmpbuf->rect, ibuf->rect); + IMB_freeImBuf(tmpbuf); + + curvemapping_premultiply(cumap, 1); } diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 797fe8f7324..4de148803f8 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -1690,8 +1690,8 @@ static void sizelike_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *t if (VALID_CONS_TARGET(ct)) { float obsize[3], size[3]; - mat4_to_size( size,ct->matrix); - mat4_to_size( obsize,cob->matrix); + mat4_to_size(size, ct->matrix); + mat4_to_size(obsize, cob->matrix); if ((data->flag & SIZELIKE_X) && (obsize[0] != 0)) { if (data->flag & SIZELIKE_OFFSET) { @@ -1735,6 +1735,58 @@ static bConstraintTypeInfo CTI_SIZELIKE = { sizelike_evaluate /* evaluate */ }; +/* ----------- Copy Transforms ------------- */ + +static int translike_get_tars (bConstraint *con, ListBase *list) +{ + if (con && list) { + bTransLikeConstraint *data= con->data; + bConstraintTarget *ct; + + /* standard target-getting macro for single-target constraints */ + SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list) + + return 1; + } + + return 0; +} + +static void translike_flush_tars (bConstraint *con, ListBase *list, short nocopy) +{ + if (con && list) { + bTransLikeConstraint *data= con->data; + bConstraintTarget *ct= list->first; + + /* the following macro is used for all standard single-target constraints */ + SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy) + } +} + +static void translike_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets) +{ + bConstraintTarget *ct= targets->first; + + if (VALID_CONS_TARGET(ct)) { + /* just copy the entire transform matrix of the target */ + copy_m4_m4(cob->matrix, ct->matrix); + } +} + +static bConstraintTypeInfo CTI_TRANSLIKE = { + CONSTRAINT_TYPE_TRANSLIKE, /* type */ + sizeof(bTransLikeConstraint), /* size */ + "Copy Transforms", /* name */ + "bTransLikeConstraint", /* struct name */ + NULL, /* free data */ + NULL, /* relink data */ + NULL, /* copy data */ + NULL, /* new data */ + translike_get_tars, /* get constraint targets */ + translike_flush_tars, /* flush constraint targets */ + default_get_tarmat, /* get target matrix */ + translike_evaluate /* evaluate */ +}; /* ----------- Python Constraint -------------- */ @@ -3565,6 +3617,7 @@ static void constraints_init_typeinfo () { constraintsTypeInfo[20]= &CTI_SHRINKWRAP; /* Shrinkwrap Constraint */ constraintsTypeInfo[21]= &CTI_DAMPTRACK; /* Damped TrackTo Constraint */ constraintsTypeInfo[22]= &CTI_SPLINEIK; /* Spline IK Constraint */ + constraintsTypeInfo[23]= &CTI_TRANSLIKE; /* Copy Transforms Constraint */ } /* This function should be used for getting the appropriate type-info when only diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 2f08abd82b3..e664dd01f4d 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -68,6 +68,7 @@ #include "BKE_animsys.h" #include "BKE_action.h" #include "BKE_effect.h" +#include "BKE_fcurve.h" #include "BKE_global.h" #include "BKE_group.h" #include "BKE_key.h" @@ -316,28 +317,38 @@ static void dag_add_driver_relation(AnimData *adt, DagForest *dag, DagNode *node for (fcu= adt->drivers.first; fcu; fcu= fcu->next) { ChannelDriver *driver= fcu->driver; - DriverTarget *dtar; + DriverVar *dvar; - /* loop over targets, adding relationships as appropriate */ - for (dtar= driver->targets.first; dtar; dtar= dtar->next) { - if (dtar->id) { - if (GS(dtar->id->name)==ID_OB) { - Object *ob= (Object *)dtar->id; - - /* normal channel-drives-channel */ - node1 = dag_get_node(dag, dtar->id); - - /* check if bone... */ - if ((ob->type==OB_ARMATURE) && dtar->rna_path && strstr(dtar->rna_path, "pose.bones[")) - dag_add_relation(dag, node1, node, isdata?DAG_RL_DATA_DATA:DAG_RL_DATA_OB, "Driver"); - /* check if ob data */ - else if (dtar->rna_path && strstr(dtar->rna_path, "data.")) - dag_add_relation(dag, node1, node, isdata?DAG_RL_DATA_DATA:DAG_RL_DATA_OB, "Driver"); - /* normal */ - else - dag_add_relation(dag, node1, node, isdata?DAG_RL_OB_DATA:DAG_RL_OB_OB, "Driver"); + /* loop over variables to get the target relationships */ + for (dvar= driver->variables.first; dvar; dvar= dvar->next) { + /* only used targets */ + DRIVER_TARGETS_USED_LOOPER(dvar) + { + if (dtar->id) { + // FIXME: other data types need to be added here so that they can work! + if (GS(dtar->id->name)==ID_OB) { + Object *ob= (Object *)dtar->id; + + /* normal channel-drives-channel */ + node1 = dag_get_node(dag, dtar->id); + + /* check if bone... */ + if ((ob->type==OB_ARMATURE) && + ( ((dtar->rna_path) && strstr(dtar->rna_path, "pose.bones[")) || + ((dtar->flag & DTAR_FLAG_STRUCT_REF) && (dtar->pchan_name[0])) )) + { + dag_add_relation(dag, node1, node, isdata?DAG_RL_DATA_DATA:DAG_RL_DATA_OB, "Driver"); + } + /* check if ob data */ + else if (dtar->rna_path && strstr(dtar->rna_path, "data.")) + dag_add_relation(dag, node1, node, isdata?DAG_RL_DATA_DATA:DAG_RL_DATA_OB, "Driver"); + /* normal */ + else + dag_add_relation(dag, node1, node, isdata?DAG_RL_OB_DATA:DAG_RL_OB_OB, "Driver"); + } } } + DRIVER_TARGETS_LOOPER_END } } } diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index d5e033652a8..3ce77c8cb4f 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -41,6 +41,7 @@ #include "MEM_guardedalloc.h" #include "DNA_anim_types.h" +#include "DNA_object_types.h" #include "BLI_blenlib.h" #include "BLI_math.h" @@ -48,10 +49,12 @@ #include "BKE_fcurve.h" #include "BKE_animsys.h" +#include "BKE_action.h" #include "BKE_curve.h" #include "BKE_global.h" #include "BKE_idprop.h" +#include "BKE_object.h" #include "BKE_utildefines.h" #include "RNA_access.h" @@ -735,108 +738,31 @@ short test_time_fcurve (FCurve *fcu) /* ***************************** Drivers ********************************* */ -/* Driver API --------------------------------- */ - -/* This frees the driver target itself */ -void driver_free_target (ChannelDriver *driver, DriverTarget *dtar) -{ - /* sanity checks */ - if (dtar == NULL) - return; - - /* free target vars */ - if (dtar->rna_path) - MEM_freeN(dtar->rna_path); - - /* remove the target from the driver */ - if (driver) - BLI_freelinkN(&driver->targets, dtar); - else - MEM_freeN(dtar); -} - -/* Add a new driver target variable */ -DriverTarget *driver_add_new_target (ChannelDriver *driver) -{ - DriverTarget *dtar; - - /* sanity checks */ - if (driver == NULL) - return NULL; - - /* make a new target */ - dtar= MEM_callocN(sizeof(DriverTarget), "DriverTarget"); - BLI_addtail(&driver->targets, dtar); - - /* make the default ID-type ID_OB, since most driver targets refer to objects */ - dtar->idtype= ID_OB; - - /* give the target a 'unique' name */ - strcpy(dtar->name, "var"); - BLI_uniquename(&driver->targets, dtar, "var", '_', offsetof(DriverTarget, name), 64); - - /* return the target */ - return dtar; -} +/* Driver Variables --------------------------- */ -/* This frees the driver itself */ -void fcurve_free_driver(FCurve *fcu) -{ - ChannelDriver *driver; - DriverTarget *dtar, *dtarn; +/* TypeInfo for Driver Variables (dvti) */ +typedef struct DriverVarTypeInfo { + /* evaluation callback */ + float (*get_value)(ChannelDriver *driver, DriverVar *dvar); - /* sanity checks */ - if ELEM(NULL, fcu, fcu->driver) - return; - driver= fcu->driver; - - /* free driver targets */ - for (dtar= driver->targets.first; dtar; dtar= dtarn) { - dtarn= dtar->next; - driver_free_target(driver, dtar); - } + /* allocation of target slots */ + int num_targets; /* number of target slots required */ + char *target_names[MAX_DRIVER_TARGETS]; /* UI names that should be given to the slots */ + int target_flags[MAX_DRIVER_TARGETS]; /* flags defining the requirements for each slot */ +} DriverVarTypeInfo; -#ifndef DISABLE_PYTHON - if(driver->expr_comp) - BPY_DECREF(driver->expr_comp); -#endif - - /* free driver itself, then set F-Curve's point to this to NULL (as the curve may still be used) */ - MEM_freeN(driver); - fcu->driver= NULL; -} - -/* This makes a copy of the given driver */ -ChannelDriver *fcurve_copy_driver (ChannelDriver *driver) -{ - ChannelDriver *ndriver; - DriverTarget *dtar; - - /* sanity checks */ - if (driver == NULL) - return NULL; - - /* copy all data */ - ndriver= MEM_dupallocN(driver); - - /* copy targets */ - ndriver->targets.first= ndriver->targets.last= NULL; - BLI_duplicatelist(&ndriver->targets, &driver->targets); +/* Macro to begin definitions */ +#define BEGIN_DVAR_TYPEDEF(type) \ + { - for (dtar= ndriver->targets.first; dtar; dtar= dtar->next) { - /* make a copy of target's rna path if available */ - if (dtar->rna_path) - dtar->rna_path = MEM_dupallocN(dtar->rna_path); +/* Macro to end definitions */ +#define END_DVAR_TYPEDEF \ } - - /* return the new driver */ - return ndriver; -} -/* Driver Evaluation -------------------------- */ +/* ......... */ /* Helper function to obtain a value using RNA from the specified source (for evaluating drivers) */ -float driver_get_target_value (ChannelDriver *driver, DriverTarget *dtar) +static float dtar_get_prop_val (ChannelDriver *driver, DriverTarget *dtar) { PointerRNA id_ptr, ptr; PropertyRNA *prop; @@ -853,22 +779,18 @@ float driver_get_target_value (ChannelDriver *driver, DriverTarget *dtar) RNA_id_pointer_create(dtar->id, &id_ptr); id= dtar->id; path= dtar->rna_path; - index= dtar->array_index; /* error check for missing pointer... */ + // TODO: tag the specific target too as having issues if (id == NULL) { - printf("Error: driver doesn't have any valid target to use \n"); - if (G.f & G_DEBUG) printf("\tpath = %s [%d] \n", path, index); + printf("Error: driver has an invalid target to use \n"); + if (G.f & G_DEBUG) printf("\tpath = %s\n", path); driver->flag |= DRIVER_FLAG_INVALID; return 0.0f; } /* get property to read from, and get value as appropriate */ if (RNA_path_resolve_full(&id_ptr, path, &ptr, &prop, &index)) { - /* for now, if there is no valid index, fall back to the array-index specified separately */ - if (index == -1) - index= dtar->array_index; - switch (RNA_property_type(prop)) { case PROP_BOOLEAN: if (RNA_property_array_length(&ptr, prop)) @@ -906,39 +828,423 @@ float driver_get_target_value (ChannelDriver *driver, DriverTarget *dtar) return value; } -/* Get two PoseChannels from the targets of the given Driver */ -static void driver_get_target_pchans2 (ChannelDriver *driver, bPoseChannel **pchan1, bPoseChannel **pchan2) +/* Helper function to obtain a pointer to a Pose Channel (for evaluating drivers) */ +static bPoseChannel *dtar_get_pchan_ptr (ChannelDriver *driver, DriverTarget *dtar) { - DriverTarget *dtar; - short i = 0; + /* sanity check */ + if ELEM(NULL, driver, dtar) + return NULL; + + /* check if the ID here is a valid object */ + if ((dtar->id) && GS(dtar->id->name)) { + Object *ob= (Object *)dtar->id; + + /* get pose, and subsequently, posechannel */ + return get_pose_channel(ob->pose, dtar->pchan_name); + } + else { + /* cannot find a posechannel this way */ + return NULL; + } +} + +/* ......... */ + +/* evaluate 'single prop' driver variable */ +static float dvar_eval_singleProp (ChannelDriver *driver, DriverVar *dvar) +{ + /* just evaluate the first target slot */ + return dtar_get_prop_val(driver, &dvar->targets[0]); +} + +/* evaluate 'rotation difference' driver variable */ +static float dvar_eval_rotDiff (ChannelDriver *driver, DriverVar *dvar) +{ + bPoseChannel *pchan, *pchan2; + float q1[4], q2[4], quat[4], angle; - /* before doing anything */ - *pchan1= NULL; - *pchan2= NULL; + /* get pose channels, and check if we've got two */ + pchan= dtar_get_pchan_ptr(driver, &dvar->targets[0]); + pchan2= dtar_get_pchan_ptr(driver, &dvar->targets[1]); - /* only take the first two targets */ - for (dtar= driver->targets.first; (dtar) && (i < 2); dtar=dtar->next, i++) { - PointerRNA id_ptr, ptr; - PropertyRNA *prop; + if (ELEM(NULL, pchan, pchan2)) { + /* disable this driver, since it doesn't work correctly... */ + driver->flag |= DRIVER_FLAG_INVALID; - /* get RNA-pointer for the ID-block given in target */ - if (dtar->id) - RNA_id_pointer_create(dtar->id, &id_ptr); - else - continue; + /* check what the error was */ + if ((pchan == NULL) && (pchan2 == NULL)) + printf("Driver Evaluation Error: Rotational difference failed - first 2 targets invalid \n"); + else if (pchan == NULL) + printf("Driver Evaluation Error: Rotational difference failed - first target not valid PoseChannel \n"); + else if (pchan2 == NULL) + printf("Driver Evaluation Error: Rotational difference failed - second target not valid PoseChannel \n"); + + /* stop here... */ + return 0.0f; + } + + /* use the final posed locations */ + mat4_to_quat(q1, pchan->pose_mat); + mat4_to_quat(q2, pchan2->pose_mat); + + invert_qt(q1); + mul_qt_qtqt(quat, q1, q2); + angle = 2.0f * (saacos(quat[0])); + angle= ABS(angle); + + return (angle > M_PI) ? (float)((2.0f * M_PI) - angle) : (float)(angle); +} + +/* evaluate 'location difference' driver variable */ +// TODO: this needs to take into account space conversions... +static float dvar_eval_locDiff (ChannelDriver *driver, DriverVar *dvar) +{ + float loc1[3] = {0.0f,0.0f,0.0f}; + float loc2[3] = {0.0f,0.0f,0.0f}; + + /* get two location values */ + // NOTE: for now, these are all just worldspace + DRIVER_TARGETS_USED_LOOPER(dvar) + { + /* get pointer to loc values to store in */ + Object *ob= (Object *)dtar->id; + bPoseChannel *pchan; + float tmp_loc[3]; - /* resolve path so that we have pointer to the right posechannel */ - if (RNA_path_resolve(&id_ptr, dtar->rna_path, &ptr, &prop)) { - /* is pointer valid (i.e. pointing to an actual posechannel */ - if ((ptr.type == &RNA_PoseBone) && (ptr.data)) { - /* first or second target? */ - if (i) - *pchan1= ptr.data; - else - *pchan2= ptr.data; + /* check if this target has valid data */ + if ((ob == NULL) || (GS(dtar->id->name) != ID_OB)) { + /* invalid target, so will not have enough targets */ + driver->flag |= DRIVER_FLAG_INVALID; + return 0.0f; + } + + /* try to get posechannel */ + pchan= get_pose_channel(ob->pose, dtar->pchan_name); + + /* check if object or bone */ + if (pchan) { + /* bone */ + if ((dtar->flag & DTAR_FLAG_LOCALSPACE) == 0) { + /* convert to worldspace */ + VECCOPY(tmp_loc, pchan->pose_head); + mul_m4_v3(ob->obmat, tmp_loc); + } + else { + /* local (use transform values directly) */ + VECCOPY(tmp_loc, pchan->loc); + } + } + else { + /* object */ + if ((dtar->flag & DTAR_FLAG_LOCALSPACE) == 0) { + /* worldspace */ + VECCOPY(tmp_loc, ob->obmat[3]); + } + else { + /* local (use transform values directly) */ + VECCOPY(tmp_loc, ob->loc); } } + + /* copy the location to the right place */ + if (tarIndex) { + VECCOPY(loc2, tmp_loc); + } + else { + VECCOPY(loc1, tmp_loc); + } } + DRIVER_TARGETS_LOOPER_END + + + /* if we're still here, there should now be two targets to use, + * so just take the length of the vector between these points + */ + return len_v3v3(loc1, loc2); +} + +/* evaluate 'transform channel' driver variable */ +static float dvar_eval_transChan (ChannelDriver *driver, DriverVar *dvar) +{ + DriverTarget *dtar= &dvar->targets[0]; + Object *ob= (Object *)dtar->id; + bPoseChannel *pchan; + float mat[4][4]; + short rotOrder = 0; + + /* check if this target has valid data */ + if ((ob == NULL) || (GS(dtar->id->name) != ID_OB)) { + /* invalid target, so will not have enough targets */ + driver->flag |= DRIVER_FLAG_INVALID; + return 0.0f; + } + + /* try to get posechannel */ + pchan= get_pose_channel(ob->pose, dtar->pchan_name); + + /* check if object or bone, and get transform matrix accordingly */ + if (pchan) { + /* bone */ + rotOrder= (pchan->rotmode > 0) ? pchan->rotmode : ROT_MODE_EUL; + + if (dtar->flag & DTAR_FLAG_LOCALSPACE) + copy_m4_m4(mat, pchan->chan_mat); + else + mul_m4_m4m4(mat, pchan->pose_mat, ob->obmat); + } + else { + /* object */ + rotOrder= (ob->rotmode > 0) ? ob->rotmode : ROT_MODE_EUL; + + if (dtar->flag & DTAR_FLAG_LOCALSPACE) + object_to_mat4(ob, mat); + else + copy_m4_m4(mat, ob->obmat); + } + + /* check which transform */ + if (dtar->transChan >= MAX_DTAR_TRANSCHAN_TYPES) { + /* not valid channel */ + return 0.0f; + } + else if (dtar->transChan >= DTAR_TRANSCHAN_SCALEX) { + /* extract scale, and choose the right axis */ + float scale[3]; + + mat4_to_size(scale, mat); + return scale[dtar->transChan - DTAR_TRANSCHAN_SCALEX]; + } + else if (dtar->transChan >= DTAR_TRANSCHAN_ROTX) { + /* extract euler rotation, and choose the right axis */ + float eul[3]; + + mat4_to_eulO(eul, rotOrder, mat); + return eul[dtar->transChan - DTAR_TRANSCHAN_ROTX]; + } + else { + /* extract location and choose right axis */ + return mat[3][dtar->transChan]; + } +} + +/* ......... */ + +/* Table of Driver Varaiable Type Info Data */ +DriverVarTypeInfo dvar_types[MAX_DVAR_TYPES] = { + BEGIN_DVAR_TYPEDEF(DVAR_TYPE_SINGLE_PROP) + dvar_eval_singleProp, /* eval callback */ + 1, /* number of targets used */ + {"Property"}, /* UI names for targets */ + {0} /* flags */ + END_DVAR_TYPEDEF, + + BEGIN_DVAR_TYPEDEF(DVAR_TYPE_ROT_DIFF) + dvar_eval_rotDiff, /* eval callback */ + 2, /* number of targets used */ + {"Bone 1", "Bone 2"}, /* UI names for targets */ + {DTAR_FLAG_STRUCT_REF|DTAR_FLAG_ID_OB_ONLY, DTAR_FLAG_STRUCT_REF|DTAR_FLAG_ID_OB_ONLY} /* flags */ + END_DVAR_TYPEDEF, + + BEGIN_DVAR_TYPEDEF(DVAR_TYPE_LOC_DIFF) + dvar_eval_locDiff, /* eval callback */ + 2, /* number of targets used */ + {"Object/Bone 1", "Object/Bone 2"}, /* UI names for targets */ + {DTAR_FLAG_STRUCT_REF|DTAR_FLAG_ID_OB_ONLY, DTAR_FLAG_STRUCT_REF|DTAR_FLAG_ID_OB_ONLY} /* flags */ + END_DVAR_TYPEDEF, + + BEGIN_DVAR_TYPEDEF(DVAR_TYPE_TRANSFORM_CHAN) + dvar_eval_transChan, /* eval callback */ + 1, /* number of targets used */ + {"Object/Bone"}, /* UI names for targets */ + {DTAR_FLAG_STRUCT_REF|DTAR_FLAG_ID_OB_ONLY} /* flags */ + END_DVAR_TYPEDEF, +}; + +/* Get driver variable typeinfo */ +DriverVarTypeInfo *get_dvar_typeinfo (int type) +{ + /* check if valid type */ + if ((type >= 0) && (type < MAX_DVAR_TYPES)) + return &dvar_types[type]; + else + return NULL; +} + +/* Driver API --------------------------------- */ + +/* This frees the driver variable itself */ +void driver_free_variable (ChannelDriver *driver, DriverVar *dvar) +{ + /* sanity checks */ + if (dvar == NULL) + return; + + /* free target vars + * - need to go over all of them, not just up to the ones that are used + * currently, since there may be some lingering RNA paths from + * previous users needing freeing + */ + DRIVER_TARGETS_LOOPER(dvar) + { + /* free RNA path if applicable */ + if (dtar->rna_path) + MEM_freeN(dtar->rna_path); + } + DRIVER_TARGETS_LOOPER_END + + /* remove the variable from the driver */ + if (driver) + BLI_freelinkN(&driver->variables, dvar); + else + MEM_freeN(dvar); + +#ifndef DISABLE_PYTHON + /* since driver variables are cached, the expression needs re-compiling too */ + if(driver->type==DRIVER_TYPE_PYTHON) + driver->flag |= DRIVER_FLAG_RENAMEVAR; +#endif +} + +/* Change the type of driver variable */ +void driver_change_variable_type (DriverVar *dvar, int type) +{ + DriverVarTypeInfo *dvti= get_dvar_typeinfo(type); + + /* sanity check */ + if (ELEM(NULL, dvar, dvti)) + return; + + /* set the new settings */ + dvar->type= type; + dvar->num_targets= dvti->num_targets; + + /* make changes to the targets based on the defines for these types + * NOTE: only need to make sure the ones we're using here are valid... + */ + DRIVER_TARGETS_USED_LOOPER(dvar) + { + int flags = dvti->target_flags[tarIndex]; + + /* store the flags */ + dtar->flag = flags; + + /* object ID types only, or idtype not yet initialised*/ + if ((flags & DTAR_FLAG_ID_OB_ONLY) || (dtar->idtype == 0)) + dtar->idtype= ID_OB; + } + DRIVER_TARGETS_LOOPER_END +} + +/* Add a new driver variable */ +DriverVar *driver_add_new_variable (ChannelDriver *driver) +{ + DriverVar *dvar; + + /* sanity checks */ + if (driver == NULL) + return NULL; + + /* make a new variable */ + dvar= MEM_callocN(sizeof(DriverVar), "DriverVar"); + BLI_addtail(&driver->variables, dvar); + + /* give the variable a 'unique' name */ + strcpy(dvar->name, "var"); + BLI_uniquename(&driver->variables, dvar, "var", '_', offsetof(DriverVar, name), 64); + + /* set the default type to 'single prop' */ + driver_change_variable_type(dvar, DVAR_TYPE_SINGLE_PROP); + +#ifndef DISABLE_PYTHON + /* since driver variables are cached, the expression needs re-compiling too */ + if(driver->type==DRIVER_TYPE_PYTHON) + driver->flag |= DRIVER_FLAG_RENAMEVAR; +#endif + + /* return the target */ + return dvar; +} + +/* This frees the driver itself */ +void fcurve_free_driver(FCurve *fcu) +{ + ChannelDriver *driver; + DriverVar *dvar, *dvarn; + + /* sanity checks */ + if ELEM(NULL, fcu, fcu->driver) + return; + driver= fcu->driver; + + /* free driver targets */ + for (dvar= driver->variables.first; dvar; dvar= dvarn) { + dvarn= dvar->next; + driver_free_variable(driver, dvar); + } + +#ifndef DISABLE_PYTHON + /* free compiled driver expression */ + if (driver->expr_comp) + BPY_DECREF(driver->expr_comp); +#endif + + /* free driver itself, then set F-Curve's point to this to NULL (as the curve may still be used) */ + MEM_freeN(driver); + fcu->driver= NULL; +} + +/* This makes a copy of the given driver */ +ChannelDriver *fcurve_copy_driver (ChannelDriver *driver) +{ + ChannelDriver *ndriver; + DriverVar *dvar; + + /* sanity checks */ + if (driver == NULL) + return NULL; + + /* copy all data */ + ndriver= MEM_dupallocN(driver); + + /* copy variables */ + ndriver->variables.first= ndriver->variables.last= NULL; + BLI_duplicatelist(&ndriver->variables, &driver->variables); + + for (dvar= ndriver->variables.first; dvar; dvar= dvar->next) { + /* need to go over all targets so that we don't leave any dangling paths */ + DRIVER_TARGETS_LOOPER(dvar) + { + /* make a copy of target's rna path if available */ + if (dtar->rna_path) + dtar->rna_path = MEM_dupallocN(dtar->rna_path); + } + DRIVER_TARGETS_LOOPER_END + } + + /* return the new driver */ + return ndriver; +} + +/* Driver Evaluation -------------------------- */ + +/* Evaluate a Driver Variable to get a value that contributes to the final */ +float driver_get_variable_value (ChannelDriver *driver, DriverVar *dvar) +{ + DriverVarTypeInfo *dvti; + + /* sanity check */ + if (ELEM(NULL, driver, dvar)) + return 0.0f; + + /* call the relevant callbacks to get the variable value + * using the variable type info + */ + dvti= get_dvar_typeinfo(dvar->type); + + if (dvti && dvti->get_value) + return dvti->get_value(driver, dvar); + else + return 0.0f; } /* Evaluate an Channel-Driver to get a 'time' value to use instead of "evaltime" @@ -947,22 +1253,21 @@ static void driver_get_target_pchans2 (ChannelDriver *driver, bPoseChannel **pch */ static float evaluate_driver (ChannelDriver *driver, float evaltime) { - DriverTarget *dtar; + DriverVar *dvar; /* check if driver can be evaluated */ if (driver->flag & DRIVER_FLAG_INVALID) return 0.0f; - // TODO: the flags for individual targets need to be used too for more fine-grained support... switch (driver->type) { case DRIVER_TYPE_AVERAGE: /* average values of driver targets */ case DRIVER_TYPE_SUM: /* sum values of driver targets */ { - /* check how many targets there are first (i.e. just one?) */ - if (driver->targets.first == driver->targets.last) { + /* check how many variables there are first (i.e. just one?) */ + if (driver->variables.first == driver->variables.last) { /* just one target, so just use that */ - dtar= driver->targets.first; - return driver_get_target_value(driver, dtar); + dvar= driver->variables.first; + return driver_get_variable_value(driver, dvar); } else { /* more than one target, so average the values of the targets */ @@ -970,12 +1275,12 @@ static float evaluate_driver (ChannelDriver *driver, float evaltime) float value = 0.0f; /* loop through targets, adding (hopefully we don't get any overflow!) */ - for (dtar= driver->targets.first; dtar; dtar=dtar->next) { - value += driver_get_target_value(driver, dtar); + for (dvar= driver->variables.first; dvar; dvar=dvar->next) { + value += driver_get_variable_value(driver, dvar); tot++; } - /* return the average of these */ + /* perform operations on the total if appropriate */ if (driver->type == DRIVER_TYPE_AVERAGE) return (value / (float)tot); else @@ -984,6 +1289,39 @@ static float evaluate_driver (ChannelDriver *driver, float evaltime) } } break; + + case DRIVER_TYPE_MIN: /* smallest value */ + case DRIVER_TYPE_MAX: /* largest value */ + { + float value = 0.0f; + + /* loop through the variables, getting the values and comparing them to existing ones */ + for (dvar= driver->variables.first; dvar; dvar= dvar->next) { + /* get value */ + float tmp_val= driver_get_variable_value(driver, dvar); + + /* store this value if appropriate */ + if (dvar->prev) { + /* check if greater/smaller than the baseline */ + if (driver->type == DRIVER_TYPE_MAX) { + /* max? */ + if (tmp_val > value) + value= tmp_val; + } + else { + /* min? */ + if (tmp_val < value) + value= tmp_val; + } + } + else { + /* first item - make this the baseline for comparisons */ + value= tmp_val; + } + } + } + break; + case DRIVER_TYPE_PYTHON: /* expression */ { #ifndef DISABLE_PYTHON @@ -1001,43 +1339,6 @@ static float evaluate_driver (ChannelDriver *driver, float evaltime) #endif /* DISABLE_PYTHON*/ } break; - - - case DRIVER_TYPE_ROTDIFF: /* difference of rotations of 2 bones (should ideally be in same armature) */ - { - bPoseChannel *pchan, *pchan2; - float q1[4], q2[4], quat[4], angle; - - /* get pose channels, and check if we've got two */ - driver_get_target_pchans2(driver, &pchan, &pchan2); - if (ELEM(NULL, pchan, pchan2)) { - /* disable this driver, since it doesn't work correctly... */ - driver->flag |= DRIVER_FLAG_INVALID; - - /* check what the error was */ - if ((pchan == NULL) && (pchan2 == NULL)) - printf("Driver Evaluation Error: Rotational difference failed - first 2 targets invalid \n"); - else if (pchan == NULL) - printf("Driver Evaluation Error: Rotational difference failed - first target not valid PoseChannel \n"); - else if (pchan2 == NULL) - printf("Driver Evaluation Error: Rotational difference failed - second target not valid PoseChannel \n"); - - /* stop here... */ - return 0.0f; - } - - /* use the final posed locations */ - mat4_to_quat(q1, pchan->pose_mat); - mat4_to_quat(q2, pchan2->pose_mat); - - invert_qt(q1); - mul_qt_qtqt(quat, q1, q2); - angle = 2.0f * (saacos(quat[0])); - angle= ABS(angle); - - return (angle > M_PI) ? (float)((2.0f * M_PI) - angle) : (float)(angle); - } - break; default: { @@ -1433,9 +1734,16 @@ static float fcurve_eval_samples (FCurve *fcu, FPoint *fpts, float evaltime) cvalue= lastfpt->vec[1]; } else { + float t= (float)abs(evaltime - (int)evaltime); + /* find the one on the right frame (assume that these are spaced on 1-frame intervals) */ fpt= prevfpt + (int)(evaltime - prevfpt->vec[0]); - cvalue= fpt->vec[1]; + + /* if not exactly on the frame, perform linear interpolation with the next one */ + if (t != 0.0f) + cvalue= interpf(fpt->vec[1], (fpt+1)->vec[1], t); + else + cvalue= fpt->vec[1]; } /* return value */ diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c index 5023d87cef8..8a933ba5289 100644 --- a/source/blender/blenkernel/intern/gpencil.c +++ b/source/blender/blenkernel/intern/gpencil.c @@ -349,8 +349,10 @@ bGPDframe *gpencil_layer_getframe (bGPDlayer *gpl, int cframe, short addnew) if (gpl->actframe) { gpf= gpl->actframe; - /* do not allow any changes to layer's active frame if layer is locked */ - if (gpl->flag & GP_LAYER_LOCKED) + /* do not allow any changes to layer's active frame if layer is locked from changes + * or if the layer has been set to stay on the current frame + */ + if (gpl->flag & (GP_LAYER_LOCKED|GP_LAYER_FRAMELOCK)) return gpf; /* do not allow any changes to actframe if frame has painting tag attached to it */ if (gpf->flag & GP_FRAME_PAINT) diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c index 7e081982f24..ddfb28437a9 100644 --- a/source/blender/blenkernel/intern/idprop.c +++ b/source/blender/blenkernel/intern/idprop.c @@ -386,6 +386,31 @@ IDProperty *IDP_CopyGroup(IDProperty *prop) } /* + replaces all properties with the same name in a destination group from a source group. +*/ +void IDP_ReplaceGroupInGroup(IDProperty *dest, IDProperty *src) +{ + IDProperty *loop, *prop; + for (prop=src->data.group.first; prop; prop=prop->next) { + IDProperty *copy = IDP_CopyProperty(prop); + + for (loop=dest->data.group.first; loop; loop=loop->next) { + if (BSTR_EQ(loop->name, prop->name)) { + if (loop->next) BLI_insertlinkbefore(&dest->data.group, loop->next, copy); + else BLI_addtail(&dest->data.group, copy); + + BLI_remlink(&dest->data.group, loop); + IDP_FreeProperty(loop); + MEM_freeN(loop); + break; + } + } + + dest->len++; + BLI_addtail(&dest->data.group, copy); + } +} +/* replaces a property with the same name in a group, or adds it if the propery doesn't exist. */ diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 0452b38a2e5..f7edb2bd146 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -725,6 +725,17 @@ void BKE_image_print_memlist(void) } } +/* frees all ibufs used by any image datablocks */ +void BKE_image_free_image_ibufs(void) +{ + Image *ima; + + for(ima= G.main->image.first; ima; ima= ima->id.next) { + image_free_buffers(ima); + } + +} + void BKE_image_free_all_textures(void) { Tex *tex; @@ -883,7 +894,7 @@ int BKE_imtype_is_movie(int imtype) return 0; } -void BKE_add_image_extension(Scene *scene, char *string, int imtype) +void BKE_add_image_extension(char *string, int imtype) { char *extension=""; @@ -1397,7 +1408,7 @@ int BKE_write_ibuf(Scene *scene, ImBuf *ibuf, char *name, int imtype, int subimt BLI_make_existing_file(name); - if(scene->r.stamp & R_STAMP_ALL) + if(scene && scene->r.stamp & R_STAMP_ALL) BKE_stamp_info(scene, ibuf); ok = IMB_saveiff(ibuf, name, IB_rect | IB_zbuf | IB_zbuffloat); @@ -1409,7 +1420,7 @@ int BKE_write_ibuf(Scene *scene, ImBuf *ibuf, char *name, int imtype, int subimt } -void BKE_makepicstring(struct Scene *scene, char *string, char *base, int frame, int imtype) +void BKE_makepicstring(char *string, char *base, int frame, int imtype, int use_ext) { if (string==NULL) return; @@ -1422,8 +1433,8 @@ void BKE_makepicstring(struct Scene *scene, char *string, char *base, int frame, BLI_convertstringcode(string, G.sce); BLI_convertstringframe(string, frame); - if(scene->r.scemode & R_EXTENSION) - BKE_add_image_extension(scene, string, imtype); + if(use_ext) + BKE_add_image_extension(string, imtype); } @@ -1898,6 +1909,7 @@ static ImBuf *image_get_ibuf_multilayer(Image *ima, ImageUser *iuser) ibuf->rect_float= rpass->rect; ibuf->flags |= IB_rectfloat; ibuf->channels= rpass->channels; + ibuf->profile = IB_PROFILE_LINEAR_RGB; image_assign_ibuf(ima, ibuf, iuser?iuser->multi_index:IMA_NO_INDEX, 0); } diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index 6fc3fc547df..feb7fc3e382 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -295,10 +295,7 @@ static char *pchan_adrcodes_to_paths (int adrcode, int *array_index) *array_index= 1; return "rotation_euler"; case AC_EUL_Z: *array_index= 2; return "rotation_euler"; - - case -1: /* special case for euler-rotations used by old drivers */ - *array_index= 0; return "rotation_euler"; - + case AC_LOC_X: *array_index= 0; return "location"; case AC_LOC_Y: @@ -944,14 +941,17 @@ static char *get_rna_access (int blocktype, int adrcode, char actname[], char co strcpy(buf, ""); /* empty string */ BLI_dynstr_append(path, buf); - /* append property to path (only if applicable) */ - if (blocktype > 0) { - /* need to add dot before property if there was anything precceding this */ - if (buf[0]) - BLI_dynstr_append(path, "."); - - /* now write name of property */ - BLI_dynstr_append(path, propname); + /* need to add dot before property if there was anything precceding this */ + if (buf[0]) + BLI_dynstr_append(path, "."); + + /* now write name of property */ + BLI_dynstr_append(path, propname); + + /* if there was no array index pointer provided, add it to the path */ + if (array_index == NULL) { + sprintf(buf, "[\"%d\"]", dummy_index); + BLI_dynstr_append(path, buf); } /* convert to normal MEM_malloc'd string */ @@ -965,11 +965,40 @@ static char *get_rna_access (int blocktype, int adrcode, char actname[], char co /* *************************************************** */ /* Conversion Utilities */ +/* Convert adrcodes to driver target transform channel types */ +static short adrcode_to_dtar_transchan (short adrcode) +{ + switch (adrcode) { + case OB_LOC_X: + return DTAR_TRANSCHAN_LOCX; + case OB_LOC_Y: + return DTAR_TRANSCHAN_LOCY; + case OB_LOC_Z: + return DTAR_TRANSCHAN_LOCZ; + + case OB_ROT_X: + return DTAR_TRANSCHAN_ROTX; + case OB_ROT_Y: + return DTAR_TRANSCHAN_ROTY; + case OB_ROT_Z: + return DTAR_TRANSCHAN_ROTZ; + + case OB_SIZE_X: + return DTAR_TRANSCHAN_SCALEX; + case OB_SIZE_Y: + return DTAR_TRANSCHAN_SCALEX; + case OB_SIZE_Z: + return DTAR_TRANSCHAN_SCALEX; + + default: + return 0; + } +} + /* Convert IpoDriver to ChannelDriver - will free the old data (i.e. the old driver) */ static ChannelDriver *idriver_to_cdriver (IpoDriver *idriver) { ChannelDriver *cdriver; - DriverTarget *dtar=NULL, *dtar2=NULL; /* allocate memory for new driver */ cdriver= MEM_callocN(sizeof(ChannelDriver), "ChannelDriver"); @@ -977,85 +1006,59 @@ static ChannelDriver *idriver_to_cdriver (IpoDriver *idriver) /* if 'pydriver', just copy data across */ if (idriver->type == IPO_DRIVER_TYPE_PYTHON) { /* PyDriver only requires the expression to be copied */ - // TODO: but the expression will be useless... + // FIXME: expression will be useless due to API changes, but at least not totally lost cdriver->type = DRIVER_TYPE_PYTHON; - strcpy(cdriver->expression, idriver->name); // XXX is this safe? + if (idriver->name[0]) + BLI_strncpy(cdriver->expression, idriver->name, sizeof(cdriver->expression)); } else { - /* what to store depends on the 'blocktype' (ID_OB or ID_PO - object or posechannel) */ - if (idriver->blocktype == ID_AR) { - /* ID_PO */ + DriverVar *dvar = NULL; + DriverTarget *dtar = NULL; + + /* this should be ok for all types here... */ + cdriver->type= DRIVER_TYPE_AVERAGE; + + /* what to store depends on the 'blocktype' - object or posechannel */ + if (idriver->blocktype == ID_AR) { /* PoseChannel */ if (idriver->adrcode == OB_ROT_DIFF) { - /* Rotational Difference is a special type of driver now... */ - cdriver->type= DRIVER_TYPE_ROTDIFF; - - /* make 2 driver targets */ - dtar= driver_add_new_target(cdriver); - dtar2= driver_add_new_target(cdriver); + /* Rotational Difference requires a special type of variable */ + dvar= driver_add_new_variable(cdriver); + driver_change_variable_type(dvar, DVAR_TYPE_ROT_DIFF); - /* driver must use bones from same armature... */ - dtar->id= dtar2->id= (ID *)idriver->ob; + /* first bone target */ + dtar= &dvar->targets[0]; + dtar->id= (ID *)idriver->ob; + if (idriver->name[0]) + BLI_strncpy(dtar->pchan_name, idriver->name, 32); - /* paths for the two targets get the pointers to the relevant Pose-Channels - * - return pointers to Pose-Channels not rotation channels, as calculation code is picky - * - old bone names were stored in same var, in idriver->name - * - * - we use several hacks here - blocktype == -1 specifies that no property needs to be found, and - * providing a name for 'actname' will automatically imply Pose-Channel with name 'actname' - */ - dtar->rna_path= get_rna_access(-1, -1, idriver->name, NULL, NULL); - dtar2->rna_path= get_rna_access(-1, -1, idriver->name+DRIVER_NAME_OFFS, NULL, NULL); + /* second bone target (name was stored in same var as the first one) */ + dtar= &dvar->targets[1]; + dtar->id= (ID *)idriver->ob; + if (idriver->name[0]) // xxx... for safety + BLI_strncpy(dtar->pchan_name, idriver->name+DRIVER_NAME_OFFS, 32); } else { - /* 'standard' driver */ - cdriver->type= DRIVER_TYPE_AVERAGE; + /* only a single variable, of type 'transform channel' */ + dvar= driver_add_new_variable(cdriver); + driver_change_variable_type(dvar, DVAR_TYPE_TRANSFORM_CHAN); - /* make 1 driver target */ - dtar= driver_add_new_target(cdriver); + /* only requires a single target */ + dtar= &dvar->targets[0]; dtar->id= (ID *)idriver->ob; - - switch (idriver->adrcode) { - case OB_LOC_X: /* x,y,z location are quite straightforward */ - dtar->rna_path= get_rna_access(ID_PO, AC_LOC_X, idriver->name, NULL, &dtar->array_index); - break; - case OB_LOC_Y: - dtar->rna_path= get_rna_access(ID_PO, AC_LOC_Y, idriver->name, NULL, &dtar->array_index); - break; - case OB_LOC_Z: - dtar->rna_path= get_rna_access(ID_PO, AC_LOC_Z, idriver->name, NULL, &dtar->array_index); - break; - - case OB_SIZE_X: /* x,y,z scaling are also quite straightforward */ - dtar->rna_path= get_rna_access(ID_PO, AC_SIZE_X, idriver->name, NULL, &dtar->array_index); - break; - case OB_SIZE_Y: - dtar->rna_path= get_rna_access(ID_PO, AC_SIZE_Y, idriver->name, NULL, &dtar->array_index); - break; - case OB_SIZE_Z: - dtar->rna_path= get_rna_access(ID_PO, AC_SIZE_Z, idriver->name, NULL, &dtar->array_index); - break; - - case OB_ROT_X: /* rotation - we need to be careful with this... */ - case OB_ROT_Y: - case OB_ROT_Z: - { - /* -1 here, not rotation code, since old system didn't have eulers */ - dtar->rna_path= get_rna_access(ID_PO, -1, idriver->name, NULL, NULL); - dtar->array_index= idriver->adrcode - OB_ROT_X; - } - break; - } + if (idriver->name[0]) + BLI_strncpy(dtar->pchan_name, idriver->name, 32); + dtar->transChan= adrcode_to_dtar_transchan(idriver->adrcode); } } - else { - /* ID_OB */ - cdriver->type= DRIVER_TYPE_AVERAGE; - - /* make 1 driver target */ - dtar= driver_add_new_target(cdriver); + else { /* Object */ + /* only a single variable, of type 'transform channel' */ + dvar= driver_add_new_variable(cdriver); + driver_change_variable_type(dvar, DVAR_TYPE_TRANSFORM_CHAN); + /* only requires single target */ + dtar= &dvar->targets[0]; dtar->id= (ID *)idriver->ob; - dtar->rna_path= get_rna_access(ID_OB, idriver->adrcode, NULL, NULL, &dtar->array_index); + dtar->transChan= adrcode_to_dtar_transchan(idriver->adrcode); } } @@ -1288,14 +1291,11 @@ static void icu_to_fcurves (ListBase *groups, ListBase *list, IpoCurve *icu, cha * - need to go from degrees to radians... * - there's only really 1 target to worry about */ - if (fcu->driver && fcu->driver->targets.first) { - DriverTarget *dtar= fcu->driver->targets.first; + if (fcu->driver && fcu->driver->variables.first) { + DriverVar *dvar= fcu->driver->variables.first; + DriverTarget *dtar= &dvar->targets[0]; - /* since drivers could only be for objects, we should just check for 'rotation' being - * in the name of the path given - * - WARNING: this will break if we encounter a bone or object explictly named in that way... - */ - if ((dtar && dtar->rna_path) && strstr(dtar->rna_path, "rotation")) { + if (ELEM3(dtar->transChan, DTAR_TRANSCHAN_ROTX, DTAR_TRANSCHAN_ROTY, DTAR_TRANSCHAN_ROTZ)) { const float fac= (float)M_PI / 180.0f; dst->vec[0][0] *= fac; diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index c38cfe4ee27..ae3d201a918 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -1274,13 +1274,13 @@ void all_local(Library *lib, int untagged_only) id->newid= NULL; idn= id->next; /* id is possibly being inserted again */ - /* The check on the second line (LIB_APPEND_TAG) is done so its + /* The check on the second line (LIB_PRE_EXISTING) is done so its * possible to tag data you dont want to be made local, used for * appending data, so any libdata alredy linked wont become local * (very nasty to discover all your links are lost after appending) * */ if(id->flag & (LIB_EXTERN|LIB_INDIRECT|LIB_NEW) && - (untagged_only==0 || !(id->flag & LIB_APPEND_TAG))) + (untagged_only==0 || !(id->flag & LIB_PRE_EXISTING))) { if(lib==NULL || id->lib==lib) { id->flag &= ~(LIB_EXTERN|LIB_INDIRECT|LIB_NEW); diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index a3e0ab04991..3567c061f04 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -184,6 +184,9 @@ void init_material(Material *ma) ma->vol.shade_type = MA_VOL_SHADE_SHADED; ma->vol.shadeflag |= MA_VOL_PRECACHESHADING; ma->vol.precache_resolution = 50; + ma->vol.ms_spread = 0.2f; + ma->vol.ms_diff = 1.f; + ma->vol.ms_intensity = 1.f; ma->mode= MA_TRACEBLE|MA_SHADBUF|MA_SHADOW|MA_RAYBIAS|MA_TANGENT_STR|MA_ZTRANSP; diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index e0640a76f43..fd152c118ae 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -144,12 +144,15 @@ static int is_last_displist(Object *ob) return 0; } -static DerivedMesh *get_original_dm(Scene *scene, Object *ob, float (*vertexCos)[3], int orco) +/* returns a derived mesh if dm == NULL, for deforming modifiers that need it */ +static DerivedMesh *get_dm(Scene *scene, Object *ob, EditMesh *em, DerivedMesh *dm, float (*vertexCos)[3], int orco) { - DerivedMesh *dm= NULL; + if(dm) + return dm; if(ob->type==OB_MESH) { - dm = CDDM_from_mesh((Mesh*)(ob->data), ob); + if(em) dm= CDDM_from_editmesh(em, ob->data); + else dm = CDDM_from_mesh((Mesh*)(ob->data), ob); if(vertexCos) { CDDM_apply_vert_coords(dm, vertexCos); @@ -185,6 +188,26 @@ static DerivedMesh *get_original_dm(Scene *scene, Object *ob, float (*vertexCos) return dm; } +/* returns a cdderivedmesh if dm == NULL or is another type of derivedmesh */ +static DerivedMesh *get_cddm(Scene *scene, Object *ob, EditMesh *em, DerivedMesh *dm, float (*vertexCos)[3]) +{ + if(dm && dm->type == DM_TYPE_CDDM) + return dm; + + if(!dm) { + dm= get_dm(scene, ob, em, dm, vertexCos, 0); + } + else { + dm= CDDM_copy(dm); + CDDM_apply_vert_coords(dm, vertexCos); + } + + if(dm) + CDDM_calc_normals(dm); + + return dm; +} + /***/ static int noneModifier_isDisabled(ModifierData *md, int userRenderParams) @@ -3770,37 +3793,26 @@ static void displaceModifier_deformVerts( ModifierData *md, Object *ob, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc) { - DerivedMesh *dm; - - if(derivedData) dm = CDDM_copy(derivedData); - else if(ob->type==OB_MESH) dm = CDDM_from_mesh(ob->data, ob); - else return; - - CDDM_apply_vert_coords(dm, vertexCos); - CDDM_calc_normals(dm); + DerivedMesh *dm= get_cddm(md->scene, ob, NULL, derivedData, vertexCos); displaceModifier_do((DisplaceModifierData *)md, ob, dm, vertexCos, numVerts); - dm->release(dm); + if(dm != derivedData) + dm->release(dm); } static void displaceModifier_deformVertsEM( ModifierData *md, Object *ob, EditMesh *editData, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) { - DerivedMesh *dm; - - if(derivedData) dm = CDDM_copy(derivedData); - else dm = CDDM_from_editmesh(editData, ob->data); - - CDDM_apply_vert_coords(dm, vertexCos); - CDDM_calc_normals(dm); + DerivedMesh *dm= get_cddm(md->scene, ob, editData, derivedData, vertexCos); displaceModifier_do((DisplaceModifierData *)md, ob, dm, vertexCos, numVerts); - dm->release(dm); + if(dm != derivedData) + dm->release(dm); } /* UVProject */ @@ -4328,7 +4340,7 @@ static void smoothModifier_do( fac = smd->fac; facm = 1 - fac; - medges = CDDM_get_edges(dm); + medges = dm->getEdgeArray(dm); numDMEdges = dm->getNumEdges(dm); defgrp_index = -1; @@ -4447,36 +4459,26 @@ static void smoothModifier_deformVerts( ModifierData *md, Object *ob, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc) { - DerivedMesh *dm; - - if(derivedData) dm = CDDM_copy(derivedData); - else dm = CDDM_from_mesh(ob->data, ob); - - CDDM_apply_vert_coords(dm, vertexCos); - CDDM_calc_normals(dm); + DerivedMesh *dm= get_dm(md->scene, ob, NULL, derivedData, NULL, 0); smoothModifier_do((SmoothModifierData *)md, ob, dm, vertexCos, numVerts); - dm->release(dm); + if(dm != derivedData) + dm->release(dm); } static void smoothModifier_deformVertsEM( ModifierData *md, Object *ob, EditMesh *editData, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) { - DerivedMesh *dm; - - if(derivedData) dm = CDDM_copy(derivedData); - else dm = CDDM_from_editmesh(editData, ob->data); - - CDDM_apply_vert_coords(dm, vertexCos); - CDDM_calc_normals(dm); + DerivedMesh *dm= get_dm(md->scene, ob, editData, derivedData, NULL, 0); smoothModifier_do((SmoothModifierData *)md, ob, dm, vertexCos, numVerts); - dm->release(dm); + if(dm != derivedData) + dm->release(dm); } /* Cast */ @@ -5027,38 +5029,34 @@ static void castModifier_deformVerts( ModifierData *md, Object *ob, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc) { - DerivedMesh *dm = derivedData; + DerivedMesh *dm = get_dm(md->scene, ob, NULL, derivedData, NULL, 0); CastModifierData *cmd = (CastModifierData *)md; - if (!dm && ob->type == OB_MESH) - dm = CDDM_from_mesh(ob->data, ob); - if (cmd->type == MOD_CAST_TYPE_CUBOID) { castModifier_cuboid_do(cmd, ob, dm, vertexCos, numVerts); } else { /* MOD_CAST_TYPE_SPHERE or MOD_CAST_TYPE_CYLINDER */ castModifier_sphere_do(cmd, ob, dm, vertexCos, numVerts); } - if (!derivedData && dm) dm->release(dm); + if(dm != derivedData) + dm->release(dm); } static void castModifier_deformVertsEM( ModifierData *md, Object *ob, EditMesh *editData, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) { - DerivedMesh *dm = derivedData; + DerivedMesh *dm = get_dm(md->scene, ob, editData, derivedData, NULL, 0); CastModifierData *cmd = (CastModifierData *)md; - if (!dm && ob->type == OB_MESH) - dm = CDDM_from_editmesh(editData, ob->data); - if (cmd->type == MOD_CAST_TYPE_CUBOID) { castModifier_cuboid_do(cmd, ob, dm, vertexCos, numVerts); } else { /* MOD_CAST_TYPE_SPHERE or MOD_CAST_TYPE_CYLINDER */ castModifier_sphere_do(cmd, ob, dm, vertexCos, numVerts); } - if (!derivedData && dm) dm->release(dm); + if(dm != derivedData) + dm->release(dm); } /* Wave */ @@ -5429,45 +5427,36 @@ static void waveModifier_deformVerts( ModifierData *md, Object *ob, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc) { - DerivedMesh *dm; + DerivedMesh *dm= derivedData; WaveModifierData *wmd = (WaveModifierData *)md; - if(!wmd->texture && !wmd->defgrp_name[0] && !(wmd->flag & MOD_WAVE_NORM)) - dm = derivedData; - else if(derivedData) dm = derivedData; - else if(ob->type == OB_MESH) dm = CDDM_from_mesh(ob->data, ob); - else return; - - if(wmd->flag & MOD_WAVE_NORM) { - CDDM_apply_vert_coords(dm, vertexCos); - CDDM_calc_normals(dm); - } + if(wmd->flag & MOD_WAVE_NORM) + dm= get_cddm(md->scene, ob, NULL, dm, vertexCos); + else if(wmd->texture || wmd->defgrp_name[0]) + dm= get_dm(md->scene, ob, NULL, dm, NULL, 0); waveModifier_do(wmd, md->scene, ob, dm, vertexCos, numVerts); - if(dm != derivedData) dm->release(dm); + if(dm != derivedData) + dm->release(dm); } static void waveModifier_deformVertsEM( ModifierData *md, Object *ob, EditMesh *editData, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) { - DerivedMesh *dm; + DerivedMesh *dm= derivedData; WaveModifierData *wmd = (WaveModifierData *)md; - if(!wmd->texture && !wmd->defgrp_name[0] && !(wmd->flag & MOD_WAVE_NORM)) - dm = derivedData; - else if(derivedData) dm = CDDM_copy(derivedData); - else dm = CDDM_from_editmesh(editData, ob->data); - - if(wmd->flag & MOD_WAVE_NORM) { - CDDM_apply_vert_coords(dm, vertexCos); - CDDM_calc_normals(dm); - } + if(wmd->flag & MOD_WAVE_NORM) + dm= get_cddm(md->scene, ob, editData, dm, vertexCos); + else if(wmd->texture || wmd->defgrp_name[0]) + dm= get_dm(md->scene, ob, editData, dm, NULL, 0); waveModifier_do(wmd, md->scene, ob, dm, vertexCos, numVerts); - if(dm != derivedData) dm->release(dm); + if(dm != derivedData) + dm->release(dm); } /* Armature */ @@ -6289,18 +6278,12 @@ static void smokeModifier_deformVerts( float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc) { SmokeModifierData *smd = (SmokeModifierData*) md; - DerivedMesh *dm = NULL; - - if(derivedData) dm = derivedData; - else if(ob->type == OB_MESH) dm = CDDM_from_mesh(ob->data, ob); - else return; - - CDDM_apply_vert_coords(dm, vertexCos); - CDDM_calc_normals(dm); + DerivedMesh *dm = dm= get_cddm(md->scene, ob, NULL, derivedData, vertexCos); smokeModifier_do(smd, md->scene, ob, dm, useRenderParams, isFinalCalc); - if(dm != derivedData) dm->release(dm); + if(dm != derivedData) + dm->release(dm); } static int smokeModifier_dependsOnTime(ModifierData *md) @@ -6701,7 +6684,7 @@ static void surfaceModifier_deformVerts( /* if possible use/create DerivedMesh */ if(derivedData) surmd->dm = CDDM_copy(derivedData); - else surmd->dm = get_original_dm(md->scene, ob, NULL, 0); + else surmd->dm = get_dm(md->scene, ob, NULL, NULL, NULL, 0); if(!ob->pd) { @@ -6866,7 +6849,10 @@ static void particleSystemModifier_freeData(ModifierData *md) psmd->dm=0; } - psmd->psys->flag |= PSYS_DELETE; + /* ED_object_modifier_remove may have freed this first before calling + * modifier_free (which calls this function) */ + if(psmd->psys) + psmd->psys->flag |= PSYS_DELETE; } static void particleSystemModifier_copyData(ModifierData *md, ModifierData *target) { @@ -6941,7 +6927,7 @@ static void particleSystemModifier_deformVerts( return; if(dm==0) { - dm= get_original_dm(md->scene, ob, vertexCos, 1); + dm= get_dm(md->scene, ob, NULL, NULL, vertexCos, 1); if(!dm) return; @@ -8342,7 +8328,7 @@ static void meshdeformModifier_do( /* if we don't have one computed, use derivedmesh from data * without any modifiers */ if(!cagedm) { - cagedm= get_original_dm(md->scene, mmd->object, NULL, 0); + cagedm= get_dm(md->scene, mmd->object, NULL, NULL, NULL, 0); if(cagedm) cagedm->needsFree= 1; } @@ -8478,14 +8464,10 @@ static void meshdeformModifier_deformVerts( ModifierData *md, Object *ob, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc) { - DerivedMesh *dm; - - if (!derivedData) { - dm= get_original_dm(md->scene, ob, NULL, 0); - if (dm == NULL) return; - } - else dm= derivedData; + DerivedMesh *dm= get_dm(md->scene, ob, NULL, derivedData, NULL, 0);; + if(!dm) + return; modifier_vgroup_cache(md, vertexCos); /* if next modifier needs original vertices */ @@ -8622,52 +8604,31 @@ static void shrinkwrapModifier_foreachObjectLink(ModifierData *md, Object *ob, O static void shrinkwrapModifier_deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc) { - DerivedMesh *dm = NULL; + DerivedMesh *dm = derivedData; CustomDataMask dataMask = shrinkwrapModifier_requiredDataMask(ob, md); - /* We implement requiredDataMask but thats not really usefull since mesh_calc_modifiers pass a NULL derivedData or without the modified vertexs applied */ + /* ensure we get a CDDM with applied vertex coords */ if(dataMask) - { - if(derivedData) dm = CDDM_copy(derivedData); - else if(ob->type==OB_MESH) dm = CDDM_from_mesh(ob->data, ob); - else if(ob->type==OB_LATTICE) dm = NULL; - else return; - - if(dm != NULL && (dataMask & (1<<CD_MVERT))) - { - CDDM_apply_vert_coords(dm, vertexCos); - CDDM_calc_normals(dm); - } - } + dm= get_cddm(md->scene, ob, NULL, dm, vertexCos); shrinkwrapModifier_deform((ShrinkwrapModifierData*)md, md->scene, ob, dm, vertexCos, numVerts); - if(dm) + if(dm != derivedData) dm->release(dm); } static void shrinkwrapModifier_deformVertsEM(ModifierData *md, Object *ob, EditMesh *editData, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) { - DerivedMesh *dm = NULL; + DerivedMesh *dm = derivedData; CustomDataMask dataMask = shrinkwrapModifier_requiredDataMask(ob, md); + /* ensure we get a CDDM with applied vertex coords */ if(dataMask) - { - if(derivedData) dm = CDDM_copy(derivedData); - else if(ob->type==OB_MESH) dm = CDDM_from_editmesh(editData, ob->data); - else if(ob->type==OB_LATTICE) dm = NULL; - else return; - - if(dm != NULL && (dataMask & (1<<CD_MVERT))) - { - CDDM_apply_vert_coords(dm, vertexCos); - CDDM_calc_normals(dm); - } - } + dm= get_cddm(md->scene, ob, editData, dm, vertexCos); shrinkwrapModifier_deform((ShrinkwrapModifierData*)md, md->scene, ob, dm, vertexCos, numVerts); - if(dm) + if(dm != derivedData) dm->release(dm); } @@ -8736,54 +8697,33 @@ static void simpledeformModifier_updateDepgraph(ModifierData *md, DagForest *for static void simpledeformModifier_deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc) { - DerivedMesh *dm = NULL; + DerivedMesh *dm = derivedData; CustomDataMask dataMask = simpledeformModifier_requiredDataMask(ob, md); - /* We implement requiredDataMask but thats not really usefull since mesh_calc_modifiers pass a NULL derivedData or without the modified vertexs applied */ + /* we implement requiredDataMask but thats not really usefull since + mesh_calc_modifiers pass a NULL derivedData */ if(dataMask) - { - if(derivedData) dm = CDDM_copy(derivedData); - else if(ob->type==OB_MESH) dm = CDDM_from_mesh(ob->data, ob); - else if(ob->type==OB_LATTICE) dm = NULL; - else return; - - if(dm != NULL && (dataMask & CD_MVERT)) - { - CDDM_apply_vert_coords(dm, vertexCos); - CDDM_calc_normals(dm); - } - } + dm= get_dm(md->scene, ob, NULL, dm, NULL, 0); SimpleDeformModifier_do((SimpleDeformModifierData*)md, ob, dm, vertexCos, numVerts); - if(dm) + if(dm != derivedData) dm->release(dm); - } static void simpledeformModifier_deformVertsEM(ModifierData *md, Object *ob, EditMesh *editData, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) { - DerivedMesh *dm = NULL; + DerivedMesh *dm = derivedData; CustomDataMask dataMask = simpledeformModifier_requiredDataMask(ob, md); - /* We implement requiredDataMask but thats not really usefull since mesh_calc_modifiers pass a NULL derivedData or without the modified vertexs applied */ + /* we implement requiredDataMask but thats not really usefull since + mesh_calc_modifiers pass a NULL derivedData */ if(dataMask) - { - if(derivedData) dm = CDDM_copy(derivedData); - else if(ob->type==OB_MESH) dm = CDDM_from_editmesh(editData, ob->data); - else if(ob->type==OB_LATTICE) dm = NULL; - else return; - - if(dm != NULL && (dataMask & CD_MVERT)) - { - CDDM_apply_vert_coords(dm, vertexCos); - CDDM_calc_normals(dm); - } - } + dm= get_dm(md->scene, ob, editData, dm, NULL, 0); SimpleDeformModifier_do((SimpleDeformModifierData*)md, ob, dm, vertexCos, numVerts); - if(dm) + if(dm != derivedData) dm->release(dm); } @@ -9248,7 +9188,7 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti = INIT_TYPE(Solidify); mti->type = eModifierTypeType_Constructive; mti->flags = eModifierTypeFlag_AcceptsMesh - //| eModifierTypeFlag_SupportsMapping + | eModifierTypeFlag_SupportsMapping | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode; mti->initData = solidifyModifier_initData; diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 84ef4fb6d1c..b7991d0c589 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -531,20 +531,6 @@ bNode *nodeMakeGroupFromSelected(bNodeTree *ntree) node->locx-= 0.5f*(min[0]+max[0]); node->locy-= 0.5f*(min[1]+max[1]); - /* set selin and selout of the nodetree */ - for(sock= node->inputs.first; sock; sock= sock->next) { - if(sock->flag & SOCK_SEL) { - ngroup->selin= sock; - break; - } - } - for(sock= node->outputs.first; sock; sock= sock->next) { - if(sock->flag & SOCK_SEL) { - ngroup->selout= sock; - break; - } - } - /* set socket own_index to zero since it can still have a value * from being in a group before, otherwise it doesn't get a unique * index in group_verify_own_indices */ @@ -1063,6 +1049,18 @@ void nodeRemLink(bNodeTree *ntree, bNodeLink *link) MEM_freeN(link); } +void nodeRemSocketLinks(bNodeTree *ntree, bNodeSocket *sock) +{ + bNodeLink *link, *next; + + for(link= ntree->links.first; link; link= next) { + next= link->next; + if(link->fromsock==sock || link->tosock==sock) { + nodeRemLink(ntree, link); + } + } +} + bNodeTree *ntreeAddTree(int type) { @@ -1122,28 +1120,6 @@ bNodeTree *ntreeCopyTree(bNodeTree *ntree, int internal_select) node->flag &= ~(NODE_SELECT|NODE_ACTIVE); nnode->flag |= NODE_SELECT; } - - /* deselect original sockets */ - for(sock= node->inputs.first; sock; sock= sock->next) { - if(sock->flag & SOCK_SEL) sock->flag&= ~SOCK_SEL; - } - for(sock= node->outputs.first; sock; sock= sock->next) { - if(sock->flag & SOCK_SEL) sock->flag&= ~SOCK_SEL; - } - - /* set tree selin and selout to new sockets */ - for(sock= nnode->inputs.first; sock; sock= sock->next) { - if(sock->flag & SOCK_SEL) { - ntree->selin= sock; - break; - } - } - for(sock= nnode->outputs.first; sock; sock= sock->next) { - if(sock->flag & SOCK_SEL) { - ntree->selout= sock; - break; - } - } } if(node==last) break; } diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 24d5b9cd882..762ad2432b0 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -167,9 +167,9 @@ void object_free_particlesystems(Object *ob) { while(ob->particlesystem.first){ ParticleSystem *psys = ob->particlesystem.first; - + BLI_remlink(&ob->particlesystem,psys); - + psys_free(ob,psys); } } @@ -194,9 +194,9 @@ void object_free_modifiers(Object *ob) { while (ob->modifiers.first) { ModifierData *md = ob->modifiers.first; - + BLI_remlink(&ob->modifiers, md); - + modifier_free(md); } @@ -207,6 +207,27 @@ void object_free_modifiers(Object *ob) object_free_softbody(ob); } +void object_link_modifiers(struct Object *ob, struct Object *from) +{ + ModifierData *md; + object_free_modifiers(ob); + + for (md=from->modifiers.first; md; md=md->next) { + ModifierData *nmd = NULL; + + if(ELEM4(md->type, eModifierType_Hook, eModifierType_Softbody, eModifierType_ParticleInstance, eModifierType_Collision)) continue; + + nmd = modifier_new(md->type); + modifier_copyData(md, nmd); + BLI_addtail(&ob->modifiers, nmd); + } + + copy_object_particlesystems(from, ob); + copy_object_softbody(from, ob); + + // TODO: smoke?, cloth? +} + /* here we will collect all local displist stuff */ /* also (ab)used in depsgraph */ void object_free_display(Object *ob) @@ -283,6 +304,8 @@ void free_object(Object *ob) BLI_freelistN(&ob->defbase); if(ob->pose) free_pose(ob->pose); + if(ob->mpath) + animviz_free_motionpath(ob->mpath); free_properties(&ob->prop); object_free_modifiers(ob); @@ -332,6 +355,7 @@ void unlink_object(Scene *scene, Object *ob) unlink_actuators(&ob->actuators); /* check all objects: parents en bevels and fields, also from libraries */ + // FIXME: need to check all animation blocks (drivers) obt= G.main->object.first; while(obt) { if(obt->proxy==ob) @@ -982,7 +1006,7 @@ Object *add_only_object(int type, char *name) ob->quat[0]= ob->dquat[0]= 1.0f; /* rotation locks should be 4D for 4 component rotations by default... */ ob->protectflag = OB_LOCK_ROT4D; - + unit_m4(ob->constinv); unit_m4(ob->parentinv); unit_m4(ob->obmat); @@ -1021,6 +1045,9 @@ Object *add_only_object(int type, char *name) ob->fluidsimSettings = NULL; ob->pc_ids.first = ob->pc_ids.last = NULL; + + /* Animation Visualisation defaults */ + animviz_settings_init(&ob->avs); return ob; } @@ -1473,13 +1500,18 @@ void object_make_proxy(Object *ob, Object *target, Object *gob) for (fcu= ob->adt->drivers.first; fcu; fcu= fcu->next) { ChannelDriver *driver= fcu->driver; - DriverTarget *dtar; + DriverVar *dvar; - for (dtar= driver->targets.first; dtar; dtar= dtar->next) { - if ((Object *)dtar->id == target) - dtar->id= (ID *)ob; - else - id_lib_extern((ID *)dtar->id); + for (dvar= driver->variables.first; dvar; dvar= dvar->next) { + /* all drivers */ + DRIVER_TARGETS_LOOPER(dvar) + { + if ((Object *)dtar->id == target) + dtar->id= (ID *)ob; + else + id_lib_extern((ID *)dtar->id); + } + DRIVER_TARGETS_LOOPER_END } } } diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 992f63520ab..41ca5e1804a 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -361,6 +361,10 @@ void psys_check_group_weights(ParticleSettings *part) BLI_freelistN(&part->dupliweights); } } +int psys_uses_gravity(ParticleSimulationData *sim) +{ + return sim->scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY && sim->psys->part && sim->psys->part->effector_weights->global_gravity != 0.0f; +} /************************************************/ /* Freeing stuff */ /************************************************/ diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index bf8721fd0b0..27e0c632a81 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -2332,7 +2332,7 @@ static void apply_particle_forces(ParticleSimulationData *sim, int p, float dfra mul_v3_fl(force,1.0f/pa_mass); /* add global acceleration (gravitation) */ - if(sim->scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY + if(psys_uses_gravity(sim) /* normal gravity is too strong for hair so it's disabled by default */ && (part->type != PART_HAIR || part->effector_weights->flag & EFF_WEIGHT_DO_HAIR)) { float gravity[3]; @@ -2895,7 +2895,9 @@ static void deflect_particle(ParticleSimulationData *sim, int p, float dfra, flo } else { VECCOPY(pa->state.co, col.co2); - VECCOPY(pa->state.vel, vel); + /* Stickness to surface */ + normalize_v3(nor_vec); + VECADDFAC(pa->state.vel, vel, nor_vec, -pd->pdef_stickness); } } deflections++; diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index aa81cea79f5..926f7fde14d 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -1694,7 +1694,19 @@ static void input_preprocess(Scene *scene, Sequence *seq, TStripElem *se, int cf if(seq->flag & SEQ_MAKE_FLOAT) { if (!se->ibuf->rect_float) { - IMB_float_from_rect(se->ibuf); + if (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) { + IMB_float_from_rect(se->ibuf); + } else { + int profile = IB_PROFILE_NONE; + + /* no color management: + * don't disturb the existing profiles */ + SWAP(int, se->ibuf->profile, profile); + + IMB_float_from_rect(se->ibuf); + + SWAP(int, se->ibuf->profile, profile); + } } if (se->ibuf->rect) { imb_freerectImBuf(se->ibuf); @@ -2094,7 +2106,7 @@ static void do_build_seq_ibuf(Scene *scene, Sequence * seq, TStripElem *se, int doseq= scene->r.scemode & R_DOSEQ; scene->r.scemode &= ~R_DOSEQ; - RE_BlenderFrame(re, sce, + RE_BlenderFrame(re, sce, NULL, seq->sfra+se->nr+seq->anim_startofs); if(rendering) @@ -3792,7 +3804,7 @@ Sequence *sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo info = AUD_getInfo(sound->handle); - if (info.specs.format == AUD_FORMAT_INVALID) { + if (info.specs.channels == AUD_CHANNELS_INVALID) { sound_delete(C, sound); //if(op) // BKE_report(op->reports, RPT_ERROR, "Unsupported audio format"); diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index 74c6afdc018..3232e2677b5 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -40,7 +40,7 @@ void sound_disable() void sound_init() { - AUD_Specs specs; + AUD_DeviceSpecs specs; int device, buffersize; device = U.audiodevice; @@ -455,7 +455,7 @@ void sound_scrub(struct bContext *C) } } -AUD_Device* sound_mixdown(struct Scene *scene, AUD_Specs specs, int start, int end, float volume) +AUD_Device* sound_mixdown(struct Scene *scene, AUD_DeviceSpecs specs, int start, int end, float volume) { AUD_Device* mixdown = AUD_openReadDevice(specs); SoundHandle *handle; diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index 072a665e0e9..3997f83ed49 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -2227,7 +2227,8 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, MFace *mface = NULL; FaceVertWeight *qweight, *tweight; - DM_from_template(&ccgdm->dm, dm, ccgSubSurf_getNumFinalVerts(ss), + DM_from_template(&ccgdm->dm, dm, DM_TYPE_CCGDM, + ccgSubSurf_getNumFinalVerts(ss), ccgSubSurf_getNumFinalEdges(ss), ccgSubSurf_getNumFinalFaces(ss)); diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index 818e6195049..c60001db314 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -703,11 +703,9 @@ void make_local_texture(Tex *tex) } br= G.main->brush.first; while(br) { - for(a=0; a<MAX_MTEX; a++) { - if(br->mtex[a] && br->mtex[a]->tex==tex) { - if(br->id.lib) lib= 1; - else local= 1; - } + if(br->mtex.tex==tex) { + if(br->id.lib) lib= 1; + else local= 1; } br= br->id.next; } @@ -762,13 +760,11 @@ void make_local_texture(Tex *tex) } br= G.main->brush.first; while(br) { - for(a=0; a<MAX_MTEX; a++) { - if(br->mtex[a] && br->mtex[a]->tex==tex) { - if(br->id.lib==0) { - br->mtex[a]->tex= texn; - texn->id.us++; - tex->id.us--; - } + if(br->mtex.tex==tex) { + if(br->id.lib==0) { + br->mtex.tex= texn; + texn->id.us++; + tex->id.us--; } } br= br->id.next; @@ -904,10 +900,6 @@ int give_active_mtex(ID *id, MTex ***mtex_ar, short *act) *mtex_ar= ((Lamp *)id)->mtex; if(act) *act= (((Lamp *)id)->texact); break; - case ID_BR: - *mtex_ar= ((Brush *)id)->mtex; - if(act) *act= (((Brush *)id)->texact); - break; default: *mtex_ar = NULL; if(act) *act= 0; @@ -932,9 +924,6 @@ void set_active_mtex(ID *id, short act) case ID_LA: ((Lamp *)id)->texact= act; break; - case ID_BR: - ((Brush *)id)->texact= act; - break; } } @@ -1016,35 +1005,18 @@ void set_current_world_texture(World *wo, Tex *newtex) Tex *give_current_brush_texture(Brush *br) { - MTex *mtex= NULL; - Tex *tex= NULL; - - if(br) { - mtex= br->mtex[(int)(br->texact)]; - if(mtex) tex= mtex->tex; - } - - return tex; + return br->mtex.tex; } void set_current_brush_texture(Brush *br, Tex *newtex) { - int act= br->texact; - - if(br->mtex[act] && br->mtex[act]->tex) - id_us_min(&br->mtex[act]->tex->id); + if(br->mtex.tex) + id_us_min(&br->mtex.tex->id); if(newtex) { - if(!br->mtex[act]) - br->mtex[act]= add_mtex(); - - br->mtex[act]->tex= newtex; + br->mtex.tex= newtex; id_us_plus(&newtex->id); } - else if(br->mtex[act]) { - MEM_freeN(br->mtex[act]); - br->mtex[act]= NULL; - } } /* ------------------------------------------------------------------------- */ diff --git a/source/blender/blenkernel/intern/writeavi.c b/source/blender/blenkernel/intern/writeavi.c index ec3d1185179..9ff5ee00bfb 100644 --- a/source/blender/blenkernel/intern/writeavi.c +++ b/source/blender/blenkernel/intern/writeavi.c @@ -45,6 +45,11 @@ #include "BKE_writeavi.h" #include "AVI_avi.h" +/* callbacks */ +static int start_avi(Scene *scene, RenderData *rd, int rectx, int recty, ReportList *reports); +static void end_avi(void); +static int append_avi(RenderData *rd, int frame, int *pixels, int rectx, int recty, ReportList *reports); +static void filepath_avi(char *string, RenderData *rd); /* ********************** general blender movie support ***************************** */ @@ -67,6 +72,7 @@ bMovieHandle *BKE_get_movie_handle(int imtype) mh.append_movie= append_avi; mh.end_movie= end_avi; mh.get_next_frame = NULL; + mh.get_movie_path = filepath_avi; /* do the platform specific handles */ #ifdef __sgi @@ -86,6 +92,7 @@ bMovieHandle *BKE_get_movie_handle(int imtype) mh.start_movie= start_qt; mh.append_movie= append_qt; mh.end_movie= end_qt; + mh.get_movie_path = filepath_qt; } #endif #ifdef WITH_FFMPEG @@ -93,6 +100,7 @@ bMovieHandle *BKE_get_movie_handle(int imtype) mh.start_movie = start_ffmpeg; mh.append_movie = append_ffmpeg; mh.end_movie = end_ffmpeg; + mh.get_movie_path = filepath_ffmpeg; } #endif if (imtype == R_FRAMESERVER) { @@ -111,7 +119,7 @@ bMovieHandle *BKE_get_movie_handle(int imtype) static AviMovie *avi=NULL; static int sframe; -void makeavistring (RenderData *rd, char *string) +static void filepath_avi (char *string, RenderData *rd) { char txt[64]; @@ -128,7 +136,7 @@ void makeavistring (RenderData *rd, char *string) } } -int start_avi(Scene *scene, RenderData *rd, int rectx, int recty, ReportList *reports) +static int start_avi(Scene *scene, RenderData *rd, int rectx, int recty, ReportList *reports) { int x, y; char name[256]; @@ -136,7 +144,7 @@ int start_avi(Scene *scene, RenderData *rd, int rectx, int recty, ReportList *re int quality; double framerate; - makeavistring(rd, name); + filepath_avi(name, rd); sframe = (rd->sfra); x = rectx; @@ -174,7 +182,7 @@ int start_avi(Scene *scene, RenderData *rd, int rectx, int recty, ReportList *re return 1; } -int append_avi(RenderData *rd, int frame, int *pixels, int rectx, int recty, ReportList *reports) +static int append_avi(RenderData *rd, int frame, int *pixels, int rectx, int recty, ReportList *reports) { unsigned int *rt1, *rt2, *rectot; int x, y; @@ -218,3 +226,12 @@ void end_avi(void) avi= NULL; } +/* similar to BKE_makepicstring() */ +void BKE_makeanimstring(char *string, RenderData *rd) +{ + bMovieHandle *mh= BKE_get_movie_handle(rd->imtype); + if(mh->get_movie_path) + mh->get_movie_path(string, rd); + else + string[0]= '\0'; +} diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index 417679417e4..920ff255bcc 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -75,7 +75,6 @@ #endif extern void do_init_ffmpeg(); -static void makeffmpegstring(RenderData* rd, char* string); static int ffmpeg_type = 0; static int ffmpeg_codec = CODEC_ID_MPEG4; @@ -638,7 +637,7 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report do_init_ffmpeg(); /* Determine the correct filename */ - makeffmpegstring(rd, name); + filepath_ffmpeg(name, rd); fprintf(stderr, "Starting output to %s(ffmpeg)...\n" " Using type=%d, codec=%d, audio_codec=%d,\n" " video_bitrate=%d, audio_bitrate=%d,\n" @@ -772,7 +771,7 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report ********************************************************************** */ /* Get the output filename-- similar to the other output formats */ -static void makeffmpegstring(RenderData* rd, char* string) { +void filepath_ffmpeg(char* string, RenderData* rd) { // XXX quick define, solve! #define FILE_MAXDIR 256 @@ -832,7 +831,7 @@ int start_ffmpeg(struct Scene *scene, RenderData *rd, int rectx, int recty, Repo if(ffmpeg_multiplex_audio && audio_stream) { AVCodecContext* c = get_codec_from_stream(audio_stream); - AUD_Specs specs; + AUD_DeviceSpecs specs; specs.channels = c->channels; specs.format = AUD_FORMAT_S16; specs.rate = rd->ffcodecdata.audio_mixrate; diff --git a/source/blender/blenlib/BLI_bpath.h b/source/blender/blenlib/BLI_bpath.h index 874c8c7828c..730e3eda283 100644 --- a/source/blender/blenlib/BLI_bpath.h +++ b/source/blender/blenlib/BLI_bpath.h @@ -47,11 +47,13 @@ struct BPathIterator { void (*setpath_callback)(struct BPathIterator *, char *); void (*getpath_callback)(struct BPathIterator *, char *); + char* base_path; /* base path, the directry the blend file is in - normally G.sce */ + /* only for seq data */ struct BPathIteratorSeqData seqdata; }; -void BLI_bpathIterator_init (struct BPathIterator *bpi); +void BLI_bpathIterator_init (struct BPathIterator *bpi, char *base_path); void BLI_bpathIterator_free (struct BPathIterator *bpi); char* BLI_bpathIterator_getLib (struct BPathIterator *bpi); char* BLI_bpathIterator_getName (struct BPathIterator *bpi); @@ -66,7 +68,7 @@ void BLI_bpathIterator_setPath (struct BPathIterator *bpi, char *path); /* high level funcs */ /* creates a text file with missing files if there are any */ -void checkMissingFiles(char *txtname ); -void makeFilesRelative(char *txtname, int *tot, int *changed, int *failed, int *linked); -void makeFilesAbsolute(char *txtname, int *tot, int *changed, int *failed, int *linked); -void findMissingFiles(char *str); +void checkMissingFiles(char *basepath, ReportList *reports); +void makeFilesRelative(char *basepath, ReportList *reports); +void makeFilesAbsolute(char *basepath, ReportList *reports); +void findMissingFiles(char *basepath, char *str); diff --git a/source/blender/blenlib/BLI_math_color.h b/source/blender/blenlib/BLI_math_color.h index 7444e01c3a6..2123765643e 100644 --- a/source/blender/blenlib/BLI_math_color.h +++ b/source/blender/blenlib/BLI_math_color.h @@ -74,6 +74,9 @@ void linearrgb_to_srgb_v3_v3(float *col_to, float *col_from); int constrain_rgb(float *r, float *g, float *b); void minmax_rgb(short c[3]); +void rgb_byte_to_float(char *in, float *out); +void rgb_float_to_byte(float *in, char *out); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h index e676001fba5..f650a55d8ad 100644 --- a/source/blender/blenlib/BLI_math_geom.h +++ b/source/blender/blenlib/BLI_math_geom.h @@ -111,6 +111,8 @@ int isect_axial_line_tri_v3(int axis, float co1[3], float co2[3], int isect_aabb_aabb_v3(float min1[3], float max1[3], float min2[3], float max2[3]); +int clip_line_plane(float clipco[3], float plane[4], float co[3]); + /****************************** Interpolation ********************************/ /* tri or quad, d can be NULL */ @@ -121,6 +123,8 @@ void interp_weights_poly_v3(float w[], float v[][3], int n, float p[3]); void interp_cubic_v3(float x[3], float v[3], float x1[3], float v1[3], float x2[3], float v2[3], float t); +int interp_sparse_array(float *array, int list_size, float invalid); + void barycentric_transform(float pt_tar[3], float const pt_src[3], const float tri_tar_p1[3], const float tri_tar_p2[3], const float tri_tar_p3[3], const float tri_src_p1[3], const float tri_src_p2[3], const float tri_src_p3[3]); diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h index 4dbef4ef07c..4719a835788 100644 --- a/source/blender/blenlib/BLI_math_vector.h +++ b/source/blender/blenlib/BLI_math_vector.h @@ -72,11 +72,13 @@ MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3]); MINLINE void mul_v2_fl(float r[2], float f); MINLINE void mul_v3_fl(float r[3], float f); MINLINE void mul_v3_v3fl(float r[3], float a[3], float f); +MINLINE void mul_v2_v2(float r[2], const float a[2]); MINLINE void mul_v3_v3(float r[3], float a[3]); MINLINE void mul_v3_v3v3(float r[3], float a[3], float b[3]); MINLINE void madd_v3_v3fl(float r[3], float a[3], float f); MINLINE void madd_v3_v3v3(float r[3], float a[3], float b[3]); +MINLINE void madd_v2_v2v2fl(float r[2], const float a[2], const float b[2], const float f); MINLINE void madd_v3_v3v3fl(float r[3], float a[3], float b[3], float f); MINLINE void madd_v3_v3v3v3(float r[3], float a[3], float b[3], float c[3]); diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index 3f4b9fbae25..eebff8dfaef 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -302,6 +302,8 @@ static BVHNode *bvh_medianof3(BVHNode **a, int lo, int mid, int hi, int axis) // return a[mid]; } } + +#if 0 /* * Quicksort algorithm modified for Introsort */ @@ -332,7 +334,7 @@ static void sort(BVHNode **a0, int begin, int end, int axis) bvh_insertionsort(a, begin, end, axis); } } -#if 0 + static void sort_along_axis(BVHTree *tree, int start, int end, int axis) { sort(tree->nodes, start, end, axis); diff --git a/source/blender/blenlib/intern/bpath.c b/source/blender/blenlib/intern/bpath.c index 0df9d9b8db3..626c6ee8443 100644 --- a/source/blender/blenlib/intern/bpath.c +++ b/source/blender/blenlib/intern/bpath.c @@ -52,7 +52,7 @@ #include "DNA_sound_types.h" #include "DNA_scene_types.h" /* to get the current frame */ #include "DNA_sequence_types.h" -#include "DNA_text_types.h" +#include "DNA_windowmanager_types.h" #include "BLI_blenlib.h" #include "BLI_bpath.h" @@ -61,7 +61,6 @@ #include "BKE_image.h" /* so we can check the image's type */ #include "BKE_main.h" /* so we can access G.main->*.first */ #include "BKE_sequencer.h" -#include "BKE_text.h" /* for writing to a textblock */ #include "BKE_utildefines.h" //XXX #include "BIF_screen.h" /* only for wait cursor */ @@ -86,19 +85,21 @@ enum BPathTypes { BPATH_DONE }; -void BLI_bpathIterator_init( struct BPathIterator *bpi ) { +void BLI_bpathIterator_init( struct BPathIterator *bpi, char *base_path ) { bpi->type = BPATH_IMAGE; bpi->data = NULL; bpi->getpath_callback = NULL; bpi->setpath_callback = NULL; - /* Sequencer spesific */ + /* Sequencer specific */ bpi->seqdata.totseq = 0; bpi->seqdata.seq = 0; bpi->seqdata.seqar = NULL; bpi->seqdata.scene = NULL; + bpi->base_path= base_path ? base_path : G.sce; + BLI_bpathIterator_step(bpi); } @@ -134,7 +135,7 @@ void BLI_bpathIterator_getPathExpanded( struct BPathIterator *bpi, char *path_ex if (libpath) { /* check the files location relative to its library path */ BLI_convertstringcode(path_expanded, libpath); } else { /* local data, use the blend files path */ - BLI_convertstringcode(path_expanded, G.sce); + BLI_convertstringcode(path_expanded, bpi->base_path); } } char* BLI_bpathIterator_getLib( struct BPathIterator *bpi) { @@ -413,186 +414,157 @@ int BLI_bpathIterator_isDone( struct BPathIterator *bpi) { } /* include the path argument */ -static void bpathToText(Text *btxt, struct BPathIterator *bpi) +static void bpath_as_report(struct BPathIterator *bpi, const char *message, ReportList *reports) { + char *prefix; char *name; char path_expanded[FILE_MAXDIR*2]; + if(reports==NULL) + return; + switch(BLI_bpathIterator_getType(bpi)) { case BPATH_IMAGE: - txt_insert_buf( btxt, "Image \"" ); + prefix= "Image"; break; case BPATH_SOUND: - txt_insert_buf( btxt, "Sound \"" ); + prefix= "Sound"; break; case BPATH_FONT: - txt_insert_buf( btxt, "Font \"" ); + prefix= "Font"; break; case BPATH_LIB: - txt_insert_buf( btxt, "Library \"" ); + prefix= "Library"; break; case BPATH_SEQ: - txt_insert_buf( btxt, "Sequence \"" ); + prefix= "Sequence"; break; default: - txt_insert_buf( btxt, "Unknown \"" ); + prefix= "Unknown"; break; } name = BLI_bpathIterator_getName(bpi); - - if (name) { - txt_insert_buf( btxt, name ); - } - txt_insert_buf( btxt, "\" " ); - BLI_bpathIterator_getPathExpanded(bpi, path_expanded); - - txt_insert_buf( btxt, path_expanded ); - txt_insert_buf( btxt, "\n" ); - txt_move_eof( btxt, 0 ); + + if(reports) { + if (name) BKE_reportf("%s \"%s\", \"%s\": %s", prefix, name, path_expanded, message); + else BKE_reportf("%s \"%s\": %s", prefix, path_expanded, message); + } + } /* high level function */ -void checkMissingFiles( char *txtname ) { - Text *btxt = NULL; +void checkMissingFiles(char *basepath, ReportList *reports) { struct BPathIterator bpi; /* be sure there is low chance of the path being too short */ char filepath_expanded[FILE_MAXDIR*2]; - BLI_bpathIterator_init(&bpi); + BLI_bpathIterator_init(&bpi, basepath); while (!BLI_bpathIterator_isDone(&bpi)) { BLI_bpathIterator_getPathExpanded( &bpi, filepath_expanded ); - if (!BLI_exists(filepath_expanded)) { - if (!btxt) { - btxt = add_empty_text( "missing_files.log" ); - if (txtname) { - BLI_strncpy(txtname, btxt->id.name+2, 24); - } - } - bpathToText(btxt, &bpi); - } + if (!BLI_exists(filepath_expanded)) + bpath_as_report(&bpi, "file not found", reports); + BLI_bpathIterator_step(&bpi); } BLI_bpathIterator_free(&bpi); } /* dont log any errors at the moment, should probably do this */ -void makeFilesRelative(char *txtname, int *tot, int *changed, int *failed, int *linked) { +void makeFilesRelative(char *basepath, ReportList *reports) { + int tot= 0, changed= 0, failed= 0, linked= 0; struct BPathIterator bpi; char filepath[FILE_MAX], *libpath; /* be sure there is low chance of the path being too short */ char filepath_relative[(FILE_MAXDIR * 2) + FILE_MAXFILE]; - Text *btxt = NULL; - - *tot = *changed = *failed = *linked = 0; - - BLI_bpathIterator_init(&bpi); + BLI_bpathIterator_init(&bpi, basepath); while (!BLI_bpathIterator_isDone(&bpi)) { BLI_bpathIterator_getPath(&bpi, filepath); libpath = BLI_bpathIterator_getLib(&bpi); if(strncmp(filepath, "//", 2)) { if (libpath) { /* cant make relative if we are library - TODO, LOG THIS */ - (*linked)++; + linked++; } else { /* local data, use the blend files path */ BLI_strncpy(filepath_relative, filepath, sizeof(filepath_relative)); /* Important BLI_cleanup_dir runs before the path is made relative * because it wont work for paths that start with "//../" */ - BLI_cleanup_file(G.sce, filepath_relative); /* fix any /foo/../foo/ */ - BLI_makestringcode(G.sce, filepath_relative); + BLI_cleanup_file(bpi.base_path, filepath_relative); /* fix any /foo/../foo/ */ + BLI_makestringcode(bpi.base_path, filepath_relative); /* be safe and check the length */ if (BLI_bpathIterator_getPathMaxLen(&bpi) <= strlen(filepath_relative)) { - if (!btxt) { - btxt = add_empty_text( "missing_no_rel.log" ); - if (txtname) { - BLI_strncpy(txtname, btxt->id.name+2, 24); - } - } - bpathToText(btxt, &bpi); - (*failed)++; + bpath_as_report(&bpi, "couldn't make path relative (too long)", reports); + failed++; } else { if(strncmp(filepath_relative, "//", 2)==0) { BLI_bpathIterator_setPath(&bpi, filepath_relative); - (*changed)++; + changed++; } else { - if (!btxt) { - btxt = add_empty_text( "missing_no_rel.log" ); - if (txtname) { - BLI_strncpy(txtname, btxt->id.name+2, 24); - } - } - bpathToText(btxt, &bpi); - (*failed)++; + bpath_as_report(&bpi, "couldn't make path relative", reports); + failed++; } } } } BLI_bpathIterator_step(&bpi); - (*tot)++; + tot++; } BLI_bpathIterator_free(&bpi); + + if(reports) + BKE_reportf(reports, failed ? RPT_ERROR : RPT_INFO, "Total files %i|Changed %i|Failed %i|Linked %i", tot, changed, failed, linked); } /* dont log any errors at the moment, should probably do this - * Verry similar to makeFilesRelative - keep in sync! */ -void makeFilesAbsolute(char *txtname, int *tot, int *changed, int *failed, int *linked) { +void makeFilesAbsolute(char *basepath, ReportList *reports) +{ + int tot= 0, changed= 0, failed= 0, linked= 0; + struct BPathIterator bpi; char filepath[FILE_MAX], *libpath; /* be sure there is low chance of the path being too short */ char filepath_absolute[(FILE_MAXDIR * 2) + FILE_MAXFILE]; - Text *btxt = NULL; - - *tot = *changed = *failed = *linked = 0; - - BLI_bpathIterator_init(&bpi); + BLI_bpathIterator_init(&bpi, basepath); while (!BLI_bpathIterator_isDone(&bpi)) { BLI_bpathIterator_getPath(&bpi, filepath); libpath = BLI_bpathIterator_getLib(&bpi); if(strncmp(filepath, "//", 2)==0) { if (libpath) { /* cant make absolute if we are library - TODO, LOG THIS */ - (*linked)++; + linked++; } else { /* get the expanded path and check it is relative or too long */ BLI_bpathIterator_getPathExpanded( &bpi, filepath_absolute ); - BLI_cleanup_file(G.sce, filepath_absolute); /* fix any /foo/../foo/ */ + BLI_cleanup_file(bpi.base_path, filepath_absolute); /* fix any /foo/../foo/ */ /* to be safe, check the length */ if (BLI_bpathIterator_getPathMaxLen(&bpi) <= strlen(filepath_absolute)) { - if (!btxt) { - btxt = add_empty_text( "missing_no_abs.log" ); - if (txtname) { - BLI_strncpy(txtname, btxt->id.name+2, 24); - } - } - bpathToText(btxt, &bpi); - (*failed)++; + bpath_as_report(&bpi, "couldn't make absolute (too long)", reports); + failed++; } else { if(strncmp(filepath_absolute, "//", 2)) { BLI_bpathIterator_setPath(&bpi, filepath_absolute); - (*changed)++; + changed++; } else { - if (!btxt) { - btxt = add_empty_text( "missing_no_abs.log" ); - if (txtname) { - BLI_strncpy(txtname, btxt->id.name+2, 24); - } - } - bpathToText(btxt, &bpi); - (*failed)++; + bpath_as_report(&bpi, "couldn't make absolute", reports); + failed++; } } } } BLI_bpathIterator_step(&bpi); - (*tot)++; + tot++; } BLI_bpathIterator_free(&bpi); + + if(reports) + BKE_reportf(reports, failed ? RPT_ERROR : RPT_INFO, "Total files %i|Changed %i|Failed %i|Linked %i", tot, changed, failed, linked); } @@ -651,7 +623,7 @@ static int findFileRecursive(char *filename_new, const char *dirname, const char } /* high level function - call from fileselector */ -void findMissingFiles(char *str) { +void findMissingFiles(char *basepath, char *str) { struct BPathIterator bpi; /* be sure there is low chance of the path being too short */ @@ -665,7 +637,7 @@ void findMissingFiles(char *str) { BLI_split_dirfile_basic(str, dirname, NULL); - BLI_bpathIterator_init(&bpi); + BLI_bpathIterator_init(&bpi, basepath); while (!BLI_bpathIterator_isDone(&bpi)) { BLI_bpathIterator_getPath(&bpi, filepath); @@ -699,7 +671,7 @@ void findMissingFiles(char *str) { } else { /* copy the found path into the old one */ if (G.relbase_valid) - BLI_makestringcode(G.sce, filename_new); + BLI_makestringcode(bpi.base_path, filename_new); BLI_bpathIterator_setPath( &bpi, filename_new ); } diff --git a/source/blender/blenlib/intern/math_color.c b/source/blender/blenlib/intern/math_color.c index 6dbd9c1381f..a4bd11a4bc8 100644 --- a/source/blender/blenlib/intern/math_color.c +++ b/source/blender/blenlib/intern/math_color.c @@ -274,6 +274,26 @@ void cpack_to_rgb(unsigned int col, float *r, float *g, float *b) *b /= 255.0f; } +void rgb_byte_to_float(char *in, float *out) +{ + out[0]= ((float)in[0]) / 255.0f; + out[1]= ((float)in[1]) / 255.0f; + out[2]= ((float)in[2]) / 255.0f; +} + +void rgb_float_to_byte(float *in, char *out) +{ + int r, g, b; + + r= (int)(in[0] * 255.0); + g= (int)(in[1] * 255.0); + b= (int)(in[2] * 255.0); + + out[0]= (char)((r <= 0)? 0 : (r >= 255)? 255 : r); + out[1]= (char)((g <= 0)? 0 : (g >= 255)? 255 : g); + out[2]= (char)((b <= 0)? 0 : (b >= 255)? 255 : b); +} + /* ********************************* color transforms ********************************* */ diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c index 470e5d71a45..a80f999cdbb 100644 --- a/source/blender/blenlib/intern/math_geom.c +++ b/source/blender/blenlib/intern/math_geom.c @@ -32,6 +32,7 @@ #include "BLI_math.h" #include "BLI_memarena.h" +#include "MEM_guardedalloc.h" /********************************** Polygons *********************************/ @@ -1245,6 +1246,55 @@ int isect_point_tri_prism_v3(float p[3], float v1[3], float v2[3], float v3[3]) return 1; } +int clip_line_plane(float p1[3], float p2[3], float plane[4]) +{ + float dp[3], n[3], div, t, pc[3]; + + copy_v3_v3(n, plane); + sub_v3_v3v3(dp, p2, p1); + div= dot_v3v3(dp, n); + + if(div == 0.0f) /* parallel */ + return 1; + + t= -(dot_v3v3(p1, n) + plane[3])/div; + + if(div > 0.0f) { + /* behind plane, completely clipped */ + if(t >= 1.0f) { + zero_v3(p1); + zero_v3(p2); + return 0; + } + + /* intersect plane */ + if(t > 0.0f) { + madd_v3_v3v3fl(pc, p1, dp, t); + copy_v3_v3(p1, pc); + return 1; + } + + return 1; + } + else { + /* behind plane, completely clipped */ + if(t <= 0.0f) { + zero_v3(p1); + zero_v3(p2); + return 0; + } + + /* intersect plane */ + if(t < 1.0f) { + madd_v3_v3v3fl(pc, p1, dp, t); + copy_v3_v3(p2, pc); + return 1; + } + + return 1; + } +} + /****************************** Interpolation ********************************/ static float tri_signed_area(float *v1, float *v2, float *v3, int i, int j) @@ -1408,6 +1458,85 @@ void barycentric_transform(float pt_tar[3], float const pt_src[3], madd_v3_v3v3fl(pt_tar, pt_tar, no_tar, (z_ofs_src / area_src) * area_tar); } +/* given an array with some invalid values this function interpolates valid values + * replacing the invalid ones */ +int interp_sparse_array(float *array, int list_size, float skipval) +{ + int found_invalid = 0; + int found_valid = 0; + int i; + + for (i=0; i < list_size; i++) { + if(array[i] == skipval) + found_invalid= 1; + else + found_valid= 1; + } + + if(found_valid==0) { + return -1; + } + else if (found_invalid==0) { + return 0; + } + else { + /* found invalid depths, interpolate */ + float valid_last= skipval; + int valid_ofs= 0; + + float *array_up= MEM_callocN(sizeof(float) * list_size, "interp_sparse_array up"); + float *array_down= MEM_callocN(sizeof(float) * list_size, "interp_sparse_array up"); + + int *ofs_tot_up= MEM_callocN(sizeof(int) * list_size, "interp_sparse_array tup"); + int *ofs_tot_down= MEM_callocN(sizeof(int) * list_size, "interp_sparse_array tdown"); + + for (i=0; i < list_size; i++) { + if(array[i] == skipval) { + array_up[i]= valid_last; + ofs_tot_up[i]= ++valid_ofs; + } + else { + valid_last= array[i]; + valid_ofs= 0; + } + } + + valid_last= skipval; + valid_ofs= 0; + + for (i=list_size-1; i >= 0; i--) { + if(array[i] == skipval) { + array_down[i]= valid_last; + ofs_tot_down[i]= ++valid_ofs; + } + else { + valid_last= array[i]; + valid_ofs= 0; + } + } + + /* now blend */ + for (i=0; i < list_size; i++) { + if(array[i] == skipval) { + if(array_up[i] != skipval && array_down[i] != skipval) { + array[i]= ((array_up[i] * ofs_tot_down[i]) + (array_down[i] * ofs_tot_up[i])) / (float)(ofs_tot_down[i] + ofs_tot_up[i]); + } else if (array_up[i] != skipval) { + array[i]= array_up[i]; + } else if (array_down[i] != skipval) { + array[i]= array_down[i]; + } + } + } + + MEM_freeN(array_up); + MEM_freeN(array_down); + + MEM_freeN(ofs_tot_up); + MEM_freeN(ofs_tot_down); + } + + return 1; +} /* Mean value weights - smooth interpolation weights for polygons with * more than 3 vertices */ diff --git a/source/blender/blenlib/intern/math_vector_inline.c b/source/blender/blenlib/intern/math_vector_inline.c index 8b09cb86d3a..86a0d0f49a1 100644 --- a/source/blender/blenlib/intern/math_vector_inline.c +++ b/source/blender/blenlib/intern/math_vector_inline.c @@ -145,6 +145,12 @@ MINLINE void mul_v3_v3fl(float r[3], float a[3], float f) r[2]= a[2]*f; } +MINLINE void mul_v2_v2(float r[2], const float a[2]) +{ + r[0] *= a[0]; + r[1] *= a[1]; +} + MINLINE void mul_v3_v3(float r[3], float a[3]) { r[0] *= a[0]; @@ -166,6 +172,12 @@ MINLINE void madd_v3_v3v3(float r[3], float a[3], float b[3]) r[2] += a[2]*b[2]; } +MINLINE void madd_v2_v2v2fl(float r[2], const float a[2], const float b[2], const float f) +{ + r[0] = a[0] + b[0]*f; + r[1] = a[1] + b[1]*f; +} + MINLINE void madd_v3_v3v3fl(float r[3], float a[3], float b[3], float f) { r[0] = a[0] + b[0]*f; diff --git a/source/blender/blenlib/intern/pbvh.c b/source/blender/blenlib/intern/pbvh.c index 6f33fab2571..0133017eb4d 100644 --- a/source/blender/blenlib/intern/pbvh.c +++ b/source/blender/blenlib/intern/pbvh.c @@ -633,6 +633,12 @@ static PBVHNode *pbvh_iter_next(PBVHIter *iter) /* pop node */ iter->stacksize--; node= iter->stack[iter->stacksize].node; + + /* on a mesh with no faces this can happen + * can remove this check if we know meshes have at least 1 face */ + if(node==NULL) + return NULL; + revisiting= iter->stack[iter->stacksize].revisiting; /* revisiting node already checked */ @@ -694,6 +700,11 @@ void BLI_pbvh_search_gather(PBVH *bvh, pbvh_iter_end(&iter); + if(tot == 0 && array) { + MEM_freeN(array); + array= NULL; + } + *r_array= array; *r_tot= tot; } diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index e3b4908df84..c1138bc1031 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -106,6 +106,7 @@ #include "BLI_storage_types.h" // for relname flags #include "BKE_animsys.h" +#include "BKE_anim.h" #include "BKE_action.h" #include "BKE_armature.h" #include "BKE_brush.h" @@ -1531,22 +1532,13 @@ static void direct_link_curvemapping(FileData *fd, CurveMapping *cumap) static void lib_link_brush(FileData *fd, Main *main) { Brush *brush; - MTex *mtex; - int a; /* only link ID pointers */ for(brush= main->brush.first; brush; brush= brush->id.next) { if(brush->id.flag & LIB_NEEDLINK) { brush->id.flag -= LIB_NEEDLINK; - brush->clone.image= newlibadr_us(fd, brush->id.lib, brush->clone.image); - - for(a=0; a<MAX_MTEX; a++) { - mtex= brush->mtex[a]; - if(mtex) - mtex->tex= newlibadr_us(fd, brush->id.lib, mtex->tex); - } - + brush->mtex.tex= newlibadr_us(fd, brush->id.lib, brush->mtex.tex); brush->clone.image= newlibadr_us(fd, brush->id.lib, brush->clone.image); } } @@ -1555,17 +1547,13 @@ static void lib_link_brush(FileData *fd, Main *main) static void direct_link_brush(FileData *fd, Brush *brush) { /* brush itself has been read */ - int a; - - for(a=0; a<MAX_MTEX; a++) - brush->mtex[a]= newdataadr(fd, brush->mtex[a]); /* fallof curve */ brush->curve= newdataadr(fd, brush->curve); if(brush->curve) direct_link_curvemapping(fd, brush->curve); else - brush_curve_preset(brush, BRUSH_PRESET_SHARP); + brush_curve_preset(brush, CURVE_PRESET_SHARP); } static void direct_link_script(FileData *fd, Script *script) @@ -1711,10 +1699,19 @@ static void lib_link_fcurves(FileData *fd, ID *id, ListBase *list) /* driver data */ if (fcu->driver) { ChannelDriver *driver= fcu->driver; - DriverTarget *dtar; + DriverVar *dvar; - for (dtar= driver->targets.first; dtar; dtar= dtar->next) - dtar->id= newlibadr(fd, id->lib, dtar->id); + for (dvar= driver->variables.first; dvar; dvar= dvar->next) { + DRIVER_TARGETS_LOOPER(dvar) + { + /* only relink if still used */ + if (tarIndex < dvar->num_targets) + dtar->id= newlibadr(fd, id->lib, dtar->id); + else + dtar->id= NULL; + } + DRIVER_TARGETS_LOOPER_END + } } /* modifiers */ @@ -1782,12 +1779,21 @@ static void direct_link_fcurves(FileData *fd, ListBase *list) fcu->driver= newdataadr(fd, fcu->driver); if (fcu->driver) { ChannelDriver *driver= fcu->driver; - DriverTarget *dtar; + DriverVar *dvar; - /* relink targets and their paths */ - link_list(fd, &driver->targets); - for (dtar= driver->targets.first; dtar; dtar= dtar->next) - dtar->rna_path= newdataadr(fd, dtar->rna_path); + /* relink variables, targets and their paths */ + link_list(fd, &driver->variables); + for (dvar= driver->variables.first; dvar; dvar= dvar->next) { + DRIVER_TARGETS_LOOPER(dvar) + { + /* only relink the targets being used */ + if (tarIndex < dvar->num_targets) + dtar->rna_path= newdataadr(fd, dtar->rna_path); + else + dtar->rna_path= NULL; + } + DRIVER_TARGETS_LOOPER_END + } } /* modifiers */ @@ -1981,6 +1987,19 @@ static void direct_link_animdata(FileData *fd, AnimData *adt) adt->actstrip= NULL; } +/* ************ READ MOTION PATHS *************** */ + +/* direct data for cache */ +static void direct_link_motionpath(FileData *fd, bMotionPath *mpath) +{ + /* sanity check */ + if (mpath == NULL) + return; + + /* relink points cache */ + mpath->points= newdataadr(fd, mpath->points); +} + /* ************ READ NODE TREE *************** */ /* singe node tree (also used for material/scene trees), ntree is not NULL */ @@ -2110,23 +2129,7 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree) link->fromsock= newdataadr(fd, link->fromsock); link->tosock= newdataadr(fd, link->tosock); } - - /* set selin and selout */ - for(node= ntree->nodes.first; node; node= node->next) { - for(sock= node->inputs.first; sock; sock= sock->next) { - if(sock->flag & SOCK_SEL) { - ntree->selin= sock; - break; - } - } - for(sock= node->outputs.first; sock; sock= sock->next) { - if(sock->flag & SOCK_SEL) { - ntree->selout= sock; - break; - } - } - } - + /* type verification is in lib-link */ } @@ -2288,6 +2291,13 @@ static void lib_link_constraints(FileData *fd, ID *id, ListBase *conlist) data->tar = newlibadr(fd, id->lib, data->tar); } break; + case CONSTRAINT_TYPE_TRANSLIKE: + { + bTransLikeConstraint *data; + data= ((bTransLikeConstraint*)con->data); + data->tar = newlibadr(fd, id->lib, data->tar); + } + break; case CONSTRAINT_TYPE_NULL: break; } @@ -3756,6 +3766,7 @@ static void direct_link_pose(FileData *fd, bPose *pose) pchan->bone= NULL; pchan->parent= newdataadr(fd, pchan->parent); pchan->child= newdataadr(fd, pchan->child); + pchan->custom_tx= newdataadr(fd, pchan->custom_tx); direct_link_constraints(fd, &pchan->constraints); @@ -3763,6 +3774,10 @@ static void direct_link_pose(FileData *fd, bPose *pose) if (pchan->prop) IDP_DirectLinkProperty(pchan->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + pchan->mpath= newdataadr(fd, pchan->mpath); + if (pchan->mpath) + direct_link_motionpath(fd, pchan->mpath); + pchan->iktree.first= pchan->iktree.last= NULL; pchan->path= NULL; } @@ -3975,6 +3990,10 @@ static void direct_link_object(FileData *fd, Object *ob) ob->pose= newdataadr(fd, ob->pose); direct_link_pose(fd, ob->pose); + + ob->mpath= newdataadr(fd, ob->mpath); + if (ob->mpath) + direct_link_motionpath(fd, ob->mpath); link_list(fd, &ob->defbase); // XXX depreceated - old animation system <<< @@ -4165,7 +4184,7 @@ static void composite_patch(bNodeTree *ntree, Scene *scene) bNode *node; for(node= ntree->nodes.first; node; node= node->next) - if(node->id==NULL && ELEM3(node->type, CMP_NODE_R_LAYERS, CMP_NODE_COMPOSITE, CMP_NODE_DEFOCUS)) + if(node->id==NULL && ELEM4(node->type, CMP_NODE_R_LAYERS, CMP_NODE_COMPOSITE, CMP_NODE_DEFOCUS, CMP_NODE_OUTPUT_FILE)) node->id= &scene->id; } @@ -10311,10 +10330,88 @@ static void do_versions(FileData *fd, Library *lib, Main *main) if (1) { Scene *sce; + Object *ob; + Brush *brush; + Material *ma; + /* game engine changes */ for(sce = main->scene.first; sce; sce = sce->id.next) { sce->gm.eyeseparation = 0.10; } + + /* anim viz changes */ + for (ob= main->object.first; ob; ob= ob->id.next) { + /* initialise object defaults */ + animviz_settings_init(&ob->avs); + + /* if armature, copy settings for pose from armature data + * performing initialisation where appropriate + */ + if (ob->pose && ob->data) { + bArmature *arm= newlibadr(fd, lib, ob->data); + if(arm) { /* XXX - why does this fail in some cases? */ + bAnimVizSettings *avs= &ob->pose->avs; + + /* ghosting settings ---------------- */ + /* ranges */ + avs->ghost_bc= avs->ghost_ac= arm->ghostep; + + avs->ghost_sf= arm->ghostsf; + avs->ghost_ef= arm->ghostef; + + /* type */ + avs->ghost_type= arm->ghosttype; + + /* stepsize */ + avs->ghost_step= arm->ghostsize; + if (avs->ghost_step == 0) + avs->ghost_step= 1; + + /* path settings --------------------- */ + /* ranges */ + avs->path_bc= arm->pathbc; + avs->path_ac= arm->pathac; + + avs->path_sf= arm->pathsf; + avs->path_ef= arm->pathef; + + /* flags */ + if (arm->pathflag & ARM_PATH_FNUMS) + avs->path_viewflag |= MOTIONPATH_VIEW_FNUMS; + if (arm->pathflag & ARM_PATH_KFRAS) + avs->path_viewflag |= MOTIONPATH_VIEW_KFRAS; + if (arm->pathflag & ARM_PATH_KFNOS) + avs->path_viewflag |= MOTIONPATH_VIEW_KFNOS; + + /* bake flags */ + if (arm->pathflag & ARM_PATH_HEADS) + avs->path_bakeflag |= MOTIONPATH_BAKE_HEADS; + + /* type */ + if (arm->pathflag & ARM_PATH_ACFRA) + avs->path_type = MOTIONPATH_TYPE_ACFRA; + + /* stepsize */ + avs->path_step= arm->pathsize; + if (avs->path_step == 0) + avs->path_step= 1; + } + } + } + + /* brush texture changes */ + for (brush= main->brush.first; brush; brush= brush->id.next) { + default_mtex(&brush->mtex); + } + + for (ma= main->mat.first; ma; ma= ma->id.next) { + if (ma->vol.ms_spread < 0.0001f) { + ma->vol.ms_spread = 0.2f; + ma->vol.ms_diff = 1.f; + ma->vol.ms_intensity = 1.f; + } + } + } /* WATCH IT!!!: pointers from libdata have not been converted yet here! */ @@ -10681,10 +10778,16 @@ static void expand_fcurves(FileData *fd, Main *mainvar, ListBase *list) /* Driver targets if there is a driver */ if (fcu->driver) { ChannelDriver *driver= fcu->driver; - DriverTarget *dtar; + DriverVar *dvar; - for (dtar= driver->targets.first; dtar; dtar= dtar->next) - expand_doit(fd, mainvar, dtar->id); + for (dvar= driver->variables.first; dvar; dvar= dvar->next) { + DRIVER_TARGETS_LOOPER(dvar) + { + // TODO: only expand those that are going to get used? + expand_doit(fd, mainvar, dtar->id); + } + DRIVER_TARGETS_LOOPER_END + } } /* F-Curve Modifiers */ @@ -10813,11 +10916,7 @@ static void expand_texture(FileData *fd, Main *mainvar, Tex *tex) static void expand_brush(FileData *fd, Main *mainvar, Brush *brush) { - int a; - - for(a=0; a<MAX_MTEX; a++) - if(brush->mtex[a]) - expand_doit(fd, mainvar, brush->mtex[a]->tex); + expand_doit(fd, mainvar, brush->mtex.tex); expand_doit(fd, mainvar, brush->clone.image); } @@ -11083,6 +11182,12 @@ static void expand_constraints(FileData *fd, Main *mainvar, ListBase *lb) expand_doit(fd, mainvar, data->tar); } break; + case CONSTRAINT_TYPE_TRANSLIKE: + { + bTransLikeConstraint *data = (bTransLikeConstraint*)curcon->data; + expand_doit(fd, mainvar, data->tar); + } + break; default: break; } @@ -11497,8 +11602,8 @@ static void give_base_to_objects(Main *mainvar, Scene *sce, Library *lib, int is if we are appending, but this object wasnt just added allong with a group, then this is alredy used indirectly in the scene somewhere else and we didnt just append it. - (ob->id.flag & LIB_APPEND_TAG)==0 means that this is a newly appended object - Campbell */ - if (is_group_append==0 || (ob->id.flag & LIB_APPEND_TAG)==0) { + (ob->id.flag & LIB_PRE_EXISTING)==0 means that this is a newly appended object - Campbell */ + if (is_group_append==0 || (ob->id.flag & LIB_PRE_EXISTING)==0) { int do_it= 0; @@ -11524,6 +11629,36 @@ static void give_base_to_objects(Main *mainvar, Scene *sce, Library *lib, int is } } +/* when *lib set, it also does objects that were in the appended group */ +static void give_base_to_groups(Main *mainvar, Scene *scene) +{ + Group *group; + + /* give all objects which are LIB_INDIRECT a base, or for a group when *lib has been set */ + for(group= mainvar->group.first; group; group= group->id.next) { + if(((group->id.flag & LIB_INDIRECT)==0 && (group->id.flag & LIB_PRE_EXISTING)==0)) { + Base *base; + + /* add_object(...) messes with the selection */ + Object *ob= add_only_object(OB_EMPTY, group->id.name+2); + ob->type= OB_EMPTY; + ob->lay= scene->lay; + + /* assign the base */ + base= scene_add_base(scene, ob); + base->flag |= SELECT; + base->object->flag= base->flag; + ob->recalc |= OB_RECALC; + scene->basact= base; + + /* assign the group */ + ob->dup_group= group; + ob->transflag |= OB_DUPLIGROUP; + rename_id(&ob->id, group->id.name+2); + VECCOPY(ob->loc, scene->cursor); + } + } +} static void append_named_part(const bContext *C, Main *mainl, FileData *fd, char *name, int idcode, short flag) { @@ -11725,7 +11860,11 @@ static void library_append_end(const bContext *C, Main *mainl, FileData **fd, in give_base_to_objects(mainvar, scene, NULL, 0); } else { give_base_to_objects(mainvar, scene, mainl->curlib, 1); - } + } + + if (flag & FILE_GROUP_INSTANCE) { + give_base_to_groups(mainvar, scene); + } } else { give_base_to_objects(mainvar, scene, NULL, 0); } diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index c5365195d06..d8bb140186c 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -145,6 +145,7 @@ Any case: direct data is ALWAYS after the lib block #include "MEM_guardedalloc.h" // MEM_freeN #include "BLI_blenlib.h" #include "BLI_linklist.h" +#include "BLI_bpath.h" #include "BKE_action.h" #include "BKE_blender.h" @@ -932,22 +933,27 @@ static void write_fcurves(WriteData *wd, ListBase *fcurves) /* driver data */ if (fcu->driver) { ChannelDriver *driver= fcu->driver; - DriverTarget *dtar; + DriverVar *dvar; /* don't save compiled python bytecode */ void *expr_comp= driver->expr_comp; driver->expr_comp= NULL; - + writestruct(wd, DATA, "ChannelDriver", 1, driver); driver->expr_comp= expr_comp; /* restore */ - - /* targets */ - for (dtar= driver->targets.first; dtar; dtar= dtar->next) { - writestruct(wd, DATA, "DriverTarget", 1, dtar); + + + /* variables */ + for (dvar= driver->variables.first; dvar; dvar= dvar->next) { + writestruct(wd, DATA, "DriverVar", 1, dvar); - if (dtar->rna_path) - writedata(wd, DATA, strlen(dtar->rna_path)+1, dtar->rna_path); + DRIVER_TARGETS_USED_LOOPER(dvar) + { + if (dtar->rna_path) + writedata(wd, DATA, strlen(dtar->rna_path)+1, dtar->rna_path); + } + DRIVER_TARGETS_LOOPER_END } } @@ -1058,6 +1064,19 @@ static void write_animdata(WriteData *wd, AnimData *adt) write_nladata(wd, &adt->nla_tracks); } +static void write_motionpath(WriteData *wd, bMotionPath *mpath) +{ + /* sanity checks */ + if (mpath == NULL) + return; + + /* firstly, just write the motionpath struct */ + writestruct(wd, DATA, "bMotionPath", 1, mpath); + + /* now write the array of data */ + writestruct(wd, DATA, "bMotionPathVert", mpath->length, mpath->points); +} + static void write_constraints(WriteData *wd, ListBase *conlist) { bConstraint *con; @@ -1120,6 +1139,8 @@ static void write_pose(WriteData *wd, bPose *pose) write_constraints(wd, &chan->constraints); + write_motionpath(wd, chan->mpath); + /* prevent crashes with autosave, when a bone duplicated in editmode has not yet been assigned to its posechannel */ if (chan->bone) chan->selectflag= chan->bone->flag & BONE_SELECTED; /* gets restored on read, for library armatures */ @@ -1252,6 +1273,7 @@ static void write_objects(WriteData *wd, ListBase *idbase) write_pose(wd, ob->pose); write_defgroups(wd, &ob->defbase); write_constraints(wd, &ob->constraints); + write_motionpath(wd, ob->mpath); writestruct(wd, DATA, "PartDeflect", 1, ob->pd); writestruct(wd, DATA, "SoftBody", 1, ob->soft); @@ -2308,16 +2330,12 @@ static void write_nodetrees(WriteData *wd, ListBase *idbase) static void write_brushes(WriteData *wd, ListBase *idbase) { Brush *brush; - int a; for(brush=idbase->first; brush; brush= brush->id.next) { if(brush->id.us>0 || wd->current) { writestruct(wd, ID_BR, "Brush", 1, brush); if (brush->id.properties) IDP_WriteProperty(brush->id.properties, wd); - for(a=0; a<MAX_MTEX; a++) - if(brush->mtex[a]) - writestruct(wd, DATA, "MTex", 1, brush->mtex[a]); - + if(brush->curve) write_curvemapping(wd, brush->curve); } @@ -2448,9 +2466,29 @@ int BLO_write_file(Main *mainvar, char *dir, int write_flags, ReportList *report return 0; } + if(write_flags & G_FILE_RELATIVE_REMAP) { + char dir1[FILE_MAXDIR+FILE_MAXFILE]; + char dir2[FILE_MAXDIR+FILE_MAXFILE]; + BLI_split_dirfile_basic(dir, dir1, NULL); + BLI_split_dirfile_basic(mainvar->name, dir2, NULL); + + /* just incase there is some subtle difference */ + BLI_cleanup_dir(mainvar->name, dir1); + BLI_cleanup_dir(mainvar->name, dir2); + + if(strcmp(dir1, dir2)==0) + write_flags &= ~G_FILE_RELATIVE_REMAP; + else + makeFilesAbsolute(G.sce, NULL); + + } + BLI_make_file_string(G.sce, userfilename, BLI_gethome(), ".B25.blend"); write_user_block= BLI_streq(dir, userfilename); + if(write_flags & G_FILE_RELATIVE_REMAP) + makeFilesRelative(dir, NULL); /* note, making relative to something OTHER then G.sce */ + err= write_file_handle(mainvar, file, NULL,NULL, write_user_block, write_flags); close(file); diff --git a/source/blender/collada/DocumentExporter.cpp b/source/blender/collada/DocumentExporter.cpp index d2543423097..ef36a2eea9a 100644 --- a/source/blender/collada/DocumentExporter.cpp +++ b/source/blender/collada/DocumentExporter.cpp @@ -21,6 +21,7 @@ extern "C" { #include "BKE_DerivedMesh.h" #include "BKE_fcurve.h" +#include "BKE_animsys.h" #include "BLI_path_util.h" #include "BLI_fileops.h" #include "ED_keyframing.h" @@ -36,6 +37,7 @@ extern "C" #include "BKE_armature.h" #include "BKE_image.h" #include "BKE_utildefines.h" +#include "BKE_object.h" #include "BLI_math.h" #include "BLI_string.h" @@ -198,6 +200,12 @@ static std::string get_camera_id(Object *ob) return translate_id(id_name(ob)) + "-camera"; } +std::string get_joint_id(Bone *bone, Object *ob_arm) +{ + return translate_id(id_name(ob_arm) + "_" + bone->name); +} + + /* Utilities to avoid code duplication. Definition can take some time to understand, but they should be useful. @@ -851,11 +859,6 @@ private: return ob_arm; } - std::string get_joint_id(Bone *bone, Object *ob_arm) - { - return translate_id(id_name(ob_arm) + "_" + bone->name); - } - std::string get_joint_sid(Bone *bone) { char name[100]; @@ -1538,9 +1541,23 @@ public: if (t->mapto & MAP_REF) { ep.setReflective(createTexture(ima, uvname, sampler)); } + // alpha if (t->mapto & MAP_ALPHA) { ep.setTransparent(createTexture(ima, uvname, sampler)); } + // extension: + // Normal map --> Must be stored with <extra> tag as different technique, + // since COLLADA doesn't support normal maps, even in current COLLADA 1.5. + if (t->mapto & MAP_NORM) { + COLLADASW::Texture texture(key); + texture.setTexcoord(uvname); + texture.setSampler(*sampler); + // technique FCOLLADA, with the <bump> tag, is most likely the best understood, + // most widespread de-facto standard. + texture.setProfileName("FCOLLADA"); + texture.setChildElementName("bump"); + ep.setExtraTechniqueColorOrTexture(COLLADASW::ColorOrTexture(texture)); + } } // performs the actual writing ep.addProfileElements(); @@ -1720,9 +1737,9 @@ public: class AnimationExporter: COLLADASW::LibraryAnimations { Scene *scene; - std::map<bActionGroup*, std::vector<FCurve*> > fcurves_actionGroup_map; - std::map<bActionGroup*, std::vector<FCurve*> > rotfcurves_actionGroup_map; + public: + AnimationExporter(COLLADASW::StreamWriter *sw): COLLADASW::LibraryAnimations(sw) {} void exportAnimations(Scene *sce) @@ -1736,17 +1753,278 @@ public: closeLibrary(); } - // create <animation> for each transform axis + // called for each exported object + void operator() (Object *ob) + { + if (!ob->adt || !ob->adt->action) return; + + FCurve *fcu = (FCurve*)ob->adt->action->curves.first; + + if (ob->type == OB_ARMATURE) { + if (!ob->data) return; + + bArmature *arm = (bArmature*)ob->data; + for (Bone *bone = (Bone*)arm->bonebase.first; bone; bone = bone->next) + write_bone_animation(ob, bone); + } + else { + while (fcu) { + // TODO "rotation_quaternion" is also possible for objects (although euler is default) + if ((!strcmp(fcu->rna_path, "location") || !strcmp(fcu->rna_path, "scale")) || + (!strcmp(fcu->rna_path, "rotation_euler") && ob->rotmode == ROT_MODE_EUL)) + dae_animation(fcu, id_name(ob)); + + fcu = fcu->next; + } + } + } + +protected: + + void dae_animation(FCurve *fcu, std::string ob_name) + { + const char *axis_names[] = {"X", "Y", "Z"}; + const char *axis_name = NULL; + char anim_id[200]; + char anim_name[200]; + + if (fcu->array_index < 3) + axis_name = axis_names[fcu->array_index]; + + BLI_snprintf(anim_id, sizeof(anim_id), "%s.%s.%s", (char*)translate_id(ob_name).c_str(), + fcu->rna_path, axis_names[fcu->array_index]); + BLI_snprintf(anim_name, sizeof(anim_name), "%s.%s.%s", + (char*)ob_name.c_str(), fcu->rna_path, axis_names[fcu->array_index]); + + // check rna_path is one of: rotation, scale, location + + openAnimation(anim_id, anim_name); + + // create input source + std::string input_id = create_source_from_fcurve(Sampler::INPUT, fcu, anim_id, axis_name); + + // create output source + std::string output_id = create_source_from_fcurve(Sampler::OUTPUT, fcu, anim_id, axis_name); + + // create interpolations source + std::string interpolation_id = create_interpolation_source(fcu->totvert, anim_id, axis_name); + + std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX; + COLLADASW::LibraryAnimations::Sampler sampler(sampler_id); + std::string empty; + sampler.addInput(Sampler::INPUT, COLLADABU::URI(empty, input_id)); + sampler.addInput(Sampler::OUTPUT, COLLADABU::URI(empty, output_id)); + + // this input is required + sampler.addInput(Sampler::INTERPOLATION, COLLADABU::URI(empty, interpolation_id)); + + addSampler(sampler); + + std::string target = translate_id(ob_name) + + "/" + get_transform_sid(fcu->rna_path, -1, axis_name); + addChannel(COLLADABU::URI(empty, sampler_id), target); + + closeAnimation(); + } + + void write_bone_animation(Object *ob_arm, Bone *bone) + { + if (!ob_arm->adt) + return; + + for (int i = 0; i < 3; i++) + sample_and_write_bone_animation(ob_arm, bone, i); + + for (Bone *child = (Bone*)bone->childbase.first; child; child = child->next) + write_bone_animation(ob_arm, child); + } + + void sample_and_write_bone_animation(Object *ob_arm, Bone *bone, int transform_type) + { + bArmature *arm = (bArmature*)ob_arm->data; + int flag = arm->flag; + std::vector<float> fra; + char prefix[256]; + + BLI_snprintf(prefix, sizeof(prefix), "pose.bones[\"%s\"]", bone->name); + + bPoseChannel *pchan = get_pose_channel(ob_arm->pose, bone->name); + if (!pchan) + return; + + switch (transform_type) { + case 0: + find_rotation_frames(ob_arm, fra, prefix, pchan->rotmode); + break; + case 1: + find_frames(ob_arm, fra, prefix, "scale"); + break; + case 2: + find_frames(ob_arm, fra, prefix, "location"); + break; + default: + return; + } - float convert_time(float frame) { + // exit rest position + if (flag & ARM_RESTPOS) { + arm->flag &= ~ARM_RESTPOS; + where_is_pose(scene, ob_arm); + } + + if (fra.size()) { + float *v = (float*)MEM_callocN(sizeof(float) * 3 * fra.size(), "temp. anim frames"); + sample_animation(v, fra, transform_type, bone, ob_arm); + + if (transform_type == 0) { + // write x, y, z curves separately if it is rotation + float *c = (float*)MEM_callocN(sizeof(float) * fra.size(), "temp. anim frames"); + for (int i = 0; i < 3; i++) { + for (int j = 0; j < fra.size(); j++) + c[j] = v[j * 3 + i]; + + dae_bone_animation(fra, c, transform_type, i, id_name(ob_arm), bone->name); + } + MEM_freeN(c); + } + else { + // write xyz at once if it is location or scale + dae_bone_animation(fra, v, transform_type, -1, id_name(ob_arm), bone->name); + } + + MEM_freeN(v); + } + + // restore restpos + if (flag & ARM_RESTPOS) + arm->flag = flag; + where_is_pose(scene, ob_arm); + } + + void sample_animation(float *v, std::vector<float> &frames, int type, Bone *bone, Object *ob_arm) + { + bPoseChannel *pchan, *parchan = NULL; + bPose *pose = ob_arm->pose; + + pchan = get_pose_channel(pose, bone->name); + + if (!pchan) + return; + + parchan = pchan->parent; + + enable_fcurves(ob_arm->adt->action, bone->name); + + std::vector<float>::iterator it; + for (it = frames.begin(); it != frames.end(); it++) { + float mat[4][4], ipar[4][4]; + + float ctime = bsystem_time(scene, ob_arm, *it, 0.0f); + + BKE_animsys_evaluate_animdata(&ob_arm->id, ob_arm->adt, *it, ADT_RECALC_ANIM); + where_is_pose_bone(scene, ob_arm, pchan, ctime); + + // compute bone local mat + if (bone->parent) { + invert_m4_m4(ipar, parchan->pose_mat); + mul_m4_m4m4(mat, pchan->pose_mat, ipar); + } + else + copy_m4_m4(mat, pchan->pose_mat); + + switch (type) { + case 0: + mat4_to_eul(v, mat); + break; + case 1: + mat4_to_size(v, mat); + break; + case 2: + copy_v3_v3(v, mat[3]); + break; + } + + v += 3; + } + + enable_fcurves(ob_arm->adt->action, NULL); + } + + // dae_bone_animation -> add_bone_animation + // (blend this into dae_bone_animation) + void dae_bone_animation(std::vector<float> &fra, float *v, int tm_type, int axis, std::string ob_name, std::string bone_name) + { + const char *axis_names[] = {"X", "Y", "Z"}; + const char *axis_name = NULL; + char anim_id[200]; + char anim_name[200]; + bool is_rot = tm_type == 0; + + if (!fra.size()) + return; + + char rna_path[200]; + BLI_snprintf(rna_path, sizeof(rna_path), "pose.bones[\"%s\"].%s", bone_name.c_str(), + tm_type == 0 ? "rotation_quaternion" : (tm_type == 1 ? "scale" : "location")); + + if (axis > -1) + axis_name = axis_names[axis]; + + std::string transform_sid = get_transform_sid(NULL, tm_type, axis_name); + + BLI_snprintf(anim_id, sizeof(anim_id), "%s.%s.%s", (char*)translate_id(ob_name).c_str(), + (char*)translate_id(bone_name).c_str(), (char*)transform_sid.c_str()); + BLI_snprintf(anim_name, sizeof(anim_name), "%s.%s.%s", + (char*)ob_name.c_str(), (char*)bone_name.c_str(), (char*)transform_sid.c_str()); + + // TODO check rna_path is one of: rotation, scale, location + + openAnimation(anim_id, anim_name); + + // create input source + std::string input_id = create_source_from_vector(Sampler::INPUT, fra, is_rot, anim_id, axis_name); + + // create output source + std::string output_id; + if (axis == -1) + output_id = create_xyz_source(v, fra.size(), anim_id); + else + output_id = create_source_from_array(Sampler::OUTPUT, v, fra.size(), is_rot, anim_id, axis_name); + + // create interpolations source + std::string interpolation_id = create_interpolation_source(fra.size(), anim_id, axis_name); + + std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX; + COLLADASW::LibraryAnimations::Sampler sampler(sampler_id); + std::string empty; + sampler.addInput(Sampler::INPUT, COLLADABU::URI(empty, input_id)); + sampler.addInput(Sampler::OUTPUT, COLLADABU::URI(empty, output_id)); + + // TODO create in/out tangents source + + // this input is required + sampler.addInput(Sampler::INTERPOLATION, COLLADABU::URI(empty, interpolation_id)); + + addSampler(sampler); + + std::string target = translate_id(ob_name + "_" + bone_name) + "/" + transform_sid; + addChannel(COLLADABU::URI(empty, sampler_id), target); + + closeAnimation(); + } + + float convert_time(float frame) + { return FRA2TIME(frame); } - float convert_angle(float angle) { + float convert_angle(float angle) + { return COLLADABU::Math::Utils::radToDegF(angle); } - std::string get_semantic_suffix(Sampler::Semantic semantic) { + std::string get_semantic_suffix(Sampler::Semantic semantic) + { switch(semantic) { case Sampler::INPUT: return INPUT_SOURCE_ID_SUFFIX; @@ -1763,17 +2041,25 @@ public: } void add_source_parameters(COLLADASW::SourceBase::ParameterNameList& param, - Sampler::Semantic semantic, bool rotation, const char *axis) { + Sampler::Semantic semantic, bool is_rot, const char *axis) + { switch(semantic) { case Sampler::INPUT: param.push_back("TIME"); break; case Sampler::OUTPUT: - if (rotation) { + if (is_rot) { param.push_back("ANGLE"); } else { - param.push_back(axis); + if (axis) { + param.push_back(axis); + } + else { + param.push_back("X"); + param.push_back("Y"); + param.push_back("Z"); + } } break; case Sampler::IN_TANGENT: @@ -1808,7 +2094,7 @@ public: } } - std::string create_source(Sampler::Semantic semantic, FCurve *fcu, std::string& anim_id, const char *axis_name) + std::string create_source_from_fcurve(Sampler::Semantic semantic, FCurve *fcu, const std::string& anim_id, const char *axis_name) { std::string source_id = anim_id + get_semantic_suffix(semantic); @@ -1842,26 +2128,28 @@ public: return source_id; } - std::string create_interpolation_source(FCurve *fcu, std::string& anim_id, const char *axis_name) + std::string create_source_from_array(Sampler::Semantic semantic, float *v, int tot, bool is_rot, const std::string& anim_id, const char *axis_name) { - std::string source_id = anim_id + get_semantic_suffix(Sampler::INTERPOLATION); - - //bool is_rotation = !strcmp(fcu->rna_path, "rotation"); + std::string source_id = anim_id + get_semantic_suffix(semantic); - COLLADASW::NameSource source(mSW); + COLLADASW::FloatSourceF source(mSW); source.setId(source_id); source.setArrayId(source_id + ARRAY_ID_SUFFIX); - source.setAccessorCount(fcu->totvert); + source.setAccessorCount(tot); source.setAccessorStride(1); COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); - param.push_back("INTERPOLATION"); + add_source_parameters(param, semantic, is_rot, axis_name); source.prepareToAppendValues(); - for (int i = 0; i < fcu->totvert; i++) { - // XXX - source.appendValues(LINEAR_NAME); + for (int i = 0; i < tot; i++) { + float val = v[i]; + if (semantic == Sampler::INPUT) + val = convert_time(val); + else if (is_rot) + val = convert_angle(val); + source.appendValues(val); } source.finish(); @@ -1869,258 +2157,161 @@ public: return source_id; } - std::string get_transform_sid(char *rna_path, const char *axis_name) + std::string create_source_from_vector(Sampler::Semantic semantic, std::vector<float> &fra, bool is_rot, const std::string& anim_id, const char *axis_name) { - // if (!strcmp(rna_path, "rotation")) -// return std::string(rna_path) + axis_name; - -// return std::string(rna_path) + "." + axis_name; - std::string new_rna_path; - - if (strstr(rna_path, "rotation")) { - new_rna_path = "rotation"; - return new_rna_path + axis_name; - } - else if (strstr(rna_path, "location")) { - new_rna_path = strstr(rna_path, "location"); - return new_rna_path + "." + axis_name; - } - else if (strstr(rna_path, "scale")) { - new_rna_path = strstr(rna_path, "scale"); - return new_rna_path + "." + axis_name; - } - return NULL; - } + std::string source_id = anim_id + get_semantic_suffix(semantic); - void add_animation(FCurve *fcu, std::string ob_name) - { - const char *axis_names[] = {"X", "Y", "Z"}; - const char *axis_name = NULL; - char c_anim_id[100]; // careful! - char c_anim_name[100]; // careful! + COLLADASW::FloatSourceF source(mSW); + source.setId(source_id); + source.setArrayId(source_id + ARRAY_ID_SUFFIX); + source.setAccessorCount(fra.size()); + source.setAccessorStride(1); - if (fcu->array_index < 3) - axis_name = axis_names[fcu->array_index]; - - BLI_snprintf(c_anim_id, sizeof(c_anim_id), "%s.%s.%s", (char*)translate_id(ob_name).c_str(), - fcu->rna_path, axis_names[fcu->array_index]); - std::string anim_id(c_anim_id); - BLI_snprintf(c_anim_name, sizeof(c_anim_name), "%s.%s.%s", - (char*)ob_name.c_str(), fcu->rna_path, axis_names[fcu->array_index]); - std::string anim_name = c_anim_name; + COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); + add_source_parameters(param, semantic, is_rot, axis_name); - // check rna_path is one of: rotation, scale, location + source.prepareToAppendValues(); - openAnimation(anim_id, anim_name); + std::vector<float>::iterator it; + for (it = fra.begin(); it != fra.end(); it++) { + float val = *it; + if (semantic == Sampler::INPUT) + val = convert_time(val); + else if (is_rot) + val = convert_angle(val); + source.appendValues(val); + } - // create input source - std::string input_id = create_source(Sampler::INPUT, fcu, anim_id, axis_name); + source.finish(); - // create output source - std::string output_id = create_source(Sampler::OUTPUT, fcu, anim_id, axis_name); + return source_id; + } - // create interpolations source - std::string interpolation_id = create_interpolation_source(fcu, anim_id, axis_name); + // only used for sources with OUTPUT semantic + std::string create_xyz_source(float *v, int tot, const std::string& anim_id) + { + Sampler::Semantic semantic = Sampler::OUTPUT; + std::string source_id = anim_id + get_semantic_suffix(semantic); - std::string sampler_id = anim_id + SAMPLER_ID_SUFFIX; - COLLADASW::LibraryAnimations::Sampler sampler(sampler_id); - std::string empty; - sampler.addInput(Sampler::INPUT, COLLADABU::URI(empty, input_id)); - sampler.addInput(Sampler::OUTPUT, COLLADABU::URI(empty, output_id)); + COLLADASW::FloatSourceF source(mSW); + source.setId(source_id); + source.setArrayId(source_id + ARRAY_ID_SUFFIX); + source.setAccessorCount(tot); + source.setAccessorStride(3); + + COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); + add_source_parameters(param, semantic, false, NULL); - // this input is required - sampler.addInput(Sampler::INTERPOLATION, COLLADABU::URI(empty, interpolation_id)); + source.prepareToAppendValues(); - addSampler(sampler); + for (int i = 0; i < tot; i++) { + source.appendValues(*v, *(v + 1), *(v + 2)); + v += 3; + } - std::string target = translate_id(ob_name) - + "/" + get_transform_sid(fcu->rna_path, axis_name); - addChannel(COLLADABU::URI(empty, sampler_id), target); + source.finish(); - closeAnimation(); + return source_id; } - - void add_bone_animation(FCurve *fcu, std::string ob_name, std::string bone_name) + + std::string create_interpolation_source(int tot, const std::string& anim_id, const char *axis_name) { - const char *axis_names[] = {"X", "Y", "Z"}; - const char *axis_name = NULL; - char c_anim_id[100]; // careful! - char c_anim_name[100]; // careful! + std::string source_id = anim_id + get_semantic_suffix(Sampler::INTERPOLATION); - if (fcu->array_index < 3) - axis_name = axis_names[fcu->array_index]; - - std::string transform_sid = get_transform_sid(fcu->rna_path, axis_name); + COLLADASW::NameSource source(mSW); + source.setId(source_id); + source.setArrayId(source_id + ARRAY_ID_SUFFIX); + source.setAccessorCount(tot); + source.setAccessorStride(1); - BLI_snprintf(c_anim_id, sizeof(c_anim_id), "%s.%s.%s", (char*)translate_id(ob_name).c_str(), - (char*)translate_id(bone_name).c_str(), (char*)transform_sid.c_str()); - std::string anim_id(c_anim_id); - BLI_snprintf(c_anim_name, sizeof(c_anim_name), "%s.%s.%s", - (char*)ob_name.c_str(), (char*)bone_name.c_str(), (char*)transform_sid.c_str()); - std::string anim_name(c_anim_name); - - // check rna_path is one of: rotation, scale, location - - openAnimation(anim_id, anim_name); - - // create input source - std::string input_id = create_source(Sampler::INPUT, fcu, anim_id, axis_name); + COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); + param.push_back("INTERPOLATION"); - // create output source - std::string output_id = create_source(Sampler::OUTPUT, fcu, anim_id, axis_name); + source.prepareToAppendValues(); - // create interpolations source - std::string interpolation_id = create_interpolation_source(fcu, anim_id, axis_name); + for (int i = 0; i < tot; i++) { + source.appendValues(LINEAR_NAME); + } - std::string sampler_id = anim_id + SAMPLER_ID_SUFFIX; - COLLADASW::LibraryAnimations::Sampler sampler(sampler_id); - std::string empty; - sampler.addInput(Sampler::INPUT, COLLADABU::URI(empty, input_id)); - sampler.addInput(Sampler::OUTPUT, COLLADABU::URI(empty, output_id)); + source.finish(); - // this input is required - sampler.addInput(Sampler::INTERPOLATION, COLLADABU::URI(empty, interpolation_id)); + return source_id; + } - addSampler(sampler); + std::string get_transform_sid(char *rna_path, int tm_type, const char *axis_name) + { + if (rna_path) { + char *name = extract_transform_name(rna_path); - std::string target = translate_id(ob_name + "_" + bone_name) + "/" + transform_sid; - addChannel(COLLADABU::URI(empty, sampler_id), target); + if (strstr(name, "rotation")) + return std::string("rotation") + axis_name; + else if (!strcmp(name, "location") || !strcmp(name, "scale")) + return std::string(name); + } + else { + if (tm_type == 0) + return std::string("rotation") + axis_name; + else + return tm_type == 1 ? "scale" : "location"; + } - closeAnimation(); + return NULL; } - - FCurve *create_fcurve(int array_index, char *rna_path) + + char *extract_transform_name(char *rna_path) { - FCurve *fcu = (FCurve*)MEM_callocN(sizeof(FCurve), "FCurve"); - - fcu->flag = (FCURVE_VISIBLE|FCURVE_AUTO_HANDLES|FCURVE_SELECTED); - fcu->rna_path = BLI_strdupn(rna_path, strlen(rna_path)); - fcu->array_index = array_index; - return fcu; - } - - void create_bezt(FCurve *fcu, float frame, float output) - { - BezTriple bez; - memset(&bez, 0, sizeof(BezTriple)); - bez.vec[1][0] = frame; - bez.vec[1][1] = output; - bez.ipo = U.ipo_new; /* use default interpolation mode here... */ - bez.f1 = bez.f2 = bez.f3 = SELECT; - bez.h1 = bez.h2 = HD_AUTO; - insert_bezt_fcurve(fcu, &bez, 0); - calchandles_fcurve(fcu); + char *dot = strrchr(rna_path, '.'); + return dot ? (dot + 1) : rna_path; } - - void change_quat_to_eul(Object *ob, bActionGroup *grp, char *grpname) + + void find_frames(Object *ob, std::vector<float> &fra, const char *prefix, const char *tm_name) { - std::vector<FCurve*> &rot_fcurves = rotfcurves_actionGroup_map[grp]; - - FCurve *quatcu[4] = {NULL, NULL, NULL, NULL}; - int i; - - for (i = 0; i < rot_fcurves.size(); i++) - quatcu[rot_fcurves[i]->array_index] = rot_fcurves[i]; - - char *rna_path = rot_fcurves[0]->rna_path; - - FCurve *eulcu[3] = { - create_fcurve(0, rna_path), - create_fcurve(1, rna_path), - create_fcurve(2, rna_path) - }; - - for (i = 0; i < 4; i++) { - - FCurve *cu = quatcu[i]; - - if (!cu) continue; - - for (int j = 0; j < cu->totvert; j++) { - float frame = cu->bezt[j].vec[1][0]; - - float quat[4] = { - quatcu[0] ? evaluate_fcurve(quatcu[0], frame) : 0.0f, - quatcu[1] ? evaluate_fcurve(quatcu[1], frame) : 0.0f, - quatcu[2] ? evaluate_fcurve(quatcu[2], frame) : 0.0f, - quatcu[3] ? evaluate_fcurve(quatcu[3], frame) : 0.0f - }; - - float eul[3]; - - quat_to_eul( eul,quat); - - for (int k = 0; k < 3; k++) - create_bezt(eulcu[k], frame, eul[k]); + FCurve *fcu= (FCurve*)ob->adt->action->curves.first; + + for (; fcu; fcu = fcu->next) { + if (prefix && strncmp(prefix, fcu->rna_path, strlen(prefix))) + continue; + + char *name = extract_transform_name(fcu->rna_path); + if (!strcmp(name, tm_name)) { + for (int i = 0; i < fcu->totvert; i++) { + float f = fcu->bezt[i].vec[1][0]; + if (std::find(fra.begin(), fra.end(), f) == fra.end()) + fra.push_back(f); + } } } - - for (i = 0; i < 3; i++) { - add_bone_animation(eulcu[i], id_name(ob), std::string(grpname)); - free_fcurve(eulcu[i]); - } } - // called for each exported object - void operator() (Object *ob) + void find_rotation_frames(Object *ob, std::vector<float> &fra, const char *prefix, int rotmode) { - if (!ob->adt || !ob->adt->action) return; - - FCurve *fcu = (FCurve*)ob->adt->action->curves.first; - - if (ob->type == OB_ARMATURE) { - - while (fcu) { - - if (strstr(fcu->rna_path, ".rotation")) - rotfcurves_actionGroup_map[fcu->grp].push_back(fcu); - else fcurves_actionGroup_map[fcu->grp].push_back(fcu); - - fcu = fcu->next; - } - - for (bPoseChannel *pchan = (bPoseChannel*)ob->pose->chanbase.first; pchan; pchan = pchan->next) { - int i; - char *grpname = pchan->name; - bActionGroup *grp = action_groups_find_named(ob->adt->action, grpname); - - if (!grp) continue; - - // write animation for location & scaling - if (fcurves_actionGroup_map.find(grp) == fcurves_actionGroup_map.end()) continue; - - std::vector<FCurve*> &fcurves = fcurves_actionGroup_map[grp]; - for (i = 0; i < fcurves.size(); i++) - add_bone_animation(fcurves[i], id_name(ob), std::string(grpname)); - - // ... for rotation - if (rotfcurves_actionGroup_map.find(grp) == rotfcurves_actionGroup_map.end()) - continue; - - // if rotation mode is euler - no need to convert it - if (pchan->rotmode == ROT_MODE_EUL) { - - std::vector<FCurve*> &rotfcurves = rotfcurves_actionGroup_map[grp]; - - for (i = 0; i < rotfcurves.size(); i++) - add_bone_animation(rotfcurves[i], id_name(ob), std::string(grpname)); - } - - // convert rotation to euler & write animation - else change_quat_to_eul(ob, grp, grpname); + if (rotmode > 0) + find_frames(ob, fra, prefix, "rotation_euler"); + else if (rotmode == ROT_MODE_QUAT) + find_frames(ob, fra, prefix, "rotation_quaternion"); + else if (rotmode == ROT_MODE_AXISANGLE) + ; + } + + // enable fcurves driving a specific bone, disable all the rest + // if bone_name = NULL enable all fcurves + void enable_fcurves(bAction *act, char *bone_name) + { + FCurve *fcu; + char prefix[200]; + + if (bone_name) + BLI_snprintf(prefix, sizeof(prefix), "pose.bones[\"%s\"]", bone_name); + + for (fcu = (FCurve*)act->curves.first; fcu; fcu = fcu->next) { + if (bone_name) { + if (!strncmp(fcu->rna_path, prefix, strlen(prefix))) + fcu->flag &= ~FCURVE_DISABLED; + else + fcu->flag |= FCURVE_DISABLED; } - } - else { - while (fcu) { - - if (!strcmp(fcu->rna_path, "location") || - !strcmp(fcu->rna_path, "scale") || - !strcmp(fcu->rna_path, "rotation_euler")) { - - add_animation(fcu, id_name(ob)); - } - - fcu = fcu->next; + else { + fcu->flag &= ~FCURVE_DISABLED; } } } @@ -2192,3 +2383,12 @@ void DocumentExporter::exportCurrentScene(Scene *sce, const char* filename) void DocumentExporter::exportScenes(const char* filename) { } + +/* + +NOTES: + +* AnimationExporter::sample_animation enables all curves on armature, this is undesirable for a user + + */ + diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp index 575160ff84e..26e95c378a6 100644 --- a/source/blender/collada/DocumentImporter.cpp +++ b/source/blender/collada/DocumentImporter.cpp @@ -43,6 +43,8 @@ extern "C" #include "ED_armature.h" #include "ED_mesh.h" // ED_vgroup_vert_add, ... #include "ED_anim_api.h" +#include "ED_object.h" + #include "WM_types.h" #include "WM_api.h" @@ -82,6 +84,7 @@ extern "C" #include "DNA_mesh_types.h" #include "DNA_material_types.h" #include "DNA_scene_types.h" +#include "DNA_modifier_types.h" #include "MEM_guardedalloc.h" @@ -497,20 +500,24 @@ private: void link_armature(bContext *C, Object *ob, std::map<COLLADAFW::UniqueId, COLLADAFW::Node*>& joint_by_uid, TransformReader *tm) { + Object workob; + Scene *scene = CTX_data_scene(C); + + ModifierData *md = ED_object_modifier_add(NULL, scene, ob, NULL, eModifierType_Armature); + ((ArmatureModifierData *)md)->object = ob_arm; + tm->decompose(bind_shape_matrix, ob->loc, ob->rot, NULL, ob->size); ob->parent = ob_arm; - ob->partype = PARSKEL; + ob->partype = PAROBJECT; + + what_does_parent(scene, ob, &workob); + invert_m4_m4(ob->parentinv, workob.obmat); + ob->recalc |= OB_RECALC_OB|OB_RECALC_DATA; ((bArmature*)ob_arm->data)->deformflag = ARM_DEF_VGROUP; - // we need armature matrix here... where do we get it from I wonder... - // root node/joint? or node with <instance_controller>? - float parmat[4][4]; - unit_m4(parmat); - invert_m4_m4(ob->parentinv, parmat); - // create all vertex groups std::vector<JointData>::iterator it; int joint_index; @@ -551,7 +558,7 @@ private: } } - DAG_scene_sort(CTX_data_scene(C)); + DAG_scene_sort(scene); DAG_ids_flush_update(0); WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL); } @@ -624,6 +631,9 @@ private: if (parent && totchild == 1) { copy_v3_v3(parent->tail, bone->head); + // not setting BONE_CONNECTED because this would lock child bone location with respect to parent + // bone->flag |= BONE_CONNECTED; + // XXX increase this to prevent "very" small bones? const float epsilon = 0.000001f; @@ -2430,7 +2440,7 @@ public: Bone *bone = get_named_bone((bArmature*)ob->data, bone_name); if (!bone) { - fprintf(stderr, "cannot find bone \"%s\"", bone_name); + fprintf(stderr, "cannot find bone \"%s\"\n", bone_name); #ifdef ARMATURE_TEST return NULL; #else @@ -2773,9 +2783,14 @@ public: // use bind matrix if available or calc "current" world mat if (!armature_importer->get_joint_bind_mat(m, node)) { - float temp[4][4]; - get_node_mat(temp, node, NULL, NULL); - mul_m4_m4m4(m, temp, par); + if (par) { + float temp[4][4]; + get_node_mat(temp, node, NULL, NULL); + mul_m4_m4m4(m, temp, par); + } + else { + get_node_mat(m, node, NULL, NULL); + } } COLLADAFW::NodePointerArray& children = node->getChildNodes(); diff --git a/source/blender/collada/Makefile b/source/blender/collada/Makefile new file mode 100644 index 00000000000..29a731dbcb2 --- /dev/null +++ b/source/blender/collada/Makefile @@ -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) 2008 Blender Foundation. +# All rights reserved. +# +# Contributor(s): none yet. +# +# ***** END GPL LICENSE BLOCK ***** +# +# + +LIBNAME = bf_collada +DIR = $(OCGDIR)/blender/bf_collada + +include nan_compile.mk + +CCFLAGS += $(LEVEL_1_C_WARNINGS) + +CPPFLAGS += -I../makesdna -I../blenlib -I../blenkernel -I../editors/include +CPPFLAGS += -I../windowmanager -I../makesrna +CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include +CPPFLAGS += -I$(BF_OPENCOLLADA)/include/COLLADABaseUtils +CPPFLAGS += -I$(BF_OPENCOLLADA)/include/COLLADAFrameWork +CPPFLAGS += -I$(BF_OPENCOLLADA)/include/COLLADAStreamWriter +CPPFLAGS += -I$(BF_OPENCOLLADA)/include/COLLADASaxFrameworkLoader diff --git a/source/blender/editors/CMakeLists.txt b/source/blender/editors/CMakeLists.txt index b9027578482..0572c85ac08 100644 --- a/source/blender/editors/CMakeLists.txt +++ b/source/blender/editors/CMakeLists.txt @@ -90,10 +90,9 @@ IF(WIN32) SET(INC ${INC} ${PTHREADS_INC}) ENDIF(WIN32) -# TODO buildinfo -IF(BF_BUILDINFO) +IF(WITH_BUILDINFO) ADD_DEFINITIONS(-DNAN_BUILDINFO) -ENDIF(BF_BUILDINFO) +ENDIF(WITH_BUILDINFO) BLENDERLIB_NOLIST(bf_editors "${SRC}" "${INC}") diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c index aa0fcab3e36..0f19da0e6bd 100644 --- a/source/blender/editors/animation/anim_channels_defines.c +++ b/source/blender/editors/animation/anim_channels_defines.c @@ -120,6 +120,13 @@ extern void gl_round_box_shade(int mode, float minx, float miny, float maxx, flo /* Draw Backdrop ---------------------------------- */ +/* get backdrop color for top-level widgets (Scene and Object only) */ +static void acf_generic_root_color(bAnimContext *ac, bAnimListElem *ale, float *color) +{ + /* darker blue for top-level widgets */ + UI_GetThemeColor3fv(TH_DOPESHEET_CHANNELOB, color); +} + /* backdrop for top-level widgets (Scene and Object only) */ static void acf_generic_root_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc) { @@ -127,38 +134,48 @@ static void acf_generic_root_backdrop(bAnimContext *ac, bAnimListElem *ale, floa View2D *v2d= &ac->ar->v2d; short expanded= ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_EXPAND) != 0; short offset= (acf->get_offset) ? acf->get_offset(ac, ale) : 0; + float color[3]; - /* darker blue for top-level widgets */ - UI_ThemeColor(TH_DOPESHEET_CHANNELOB); + /* set backdrop drawing color */ + acf->get_backdrop_color(ac, ale, color); + glColor3fv(color); /* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */ uiSetRoundBox((expanded)? (1):(1|8)); gl_round_box(GL_POLYGON, offset, yminc, v2d->cur.xmax+EXTRA_SCROLL_PAD, ymaxc, 8); } + +/* get backdrop color for data expanders under top-level Scene/Object */ +static void acf_generic_dataexpand_color(bAnimContext *ac, bAnimListElem *ale, float *color) +{ + /* lighter color than top-level widget */ + UI_GetThemeColor3fv(TH_DOPESHEET_CHANNELSUBOB, color); +} + /* backdrop for data expanders under top-level Scene/Object */ static void acf_generic_dataexpand_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc) { bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale); View2D *v2d= &ac->ar->v2d; short offset= (acf->get_offset) ? acf->get_offset(ac, ale) : 0; + float color[3]; - /* lighter color than top-level widget */ - UI_ThemeColor(TH_DOPESHEET_CHANNELSUBOB); + /* set backdrop drawing color */ + acf->get_backdrop_color(ac, ale, color); + glColor3fv(color); /* no rounded corner - just rectangular box */ glRectf(offset, yminc, v2d->cur.xmax+EXTRA_SCROLL_PAD, ymaxc); } -/* backdrop for generic channels */ -static void acf_generic_channel_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc) +/* get backdrop color for generic channels */ +static void acf_generic_channel_color(bAnimContext *ac, bAnimListElem *ale, float *color) { bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale); - View2D *v2d= &ac->ar->v2d; SpaceAction *saction = NULL; bActionGroup *grp = NULL; short indent= (acf->get_indent_level) ? acf->get_indent_level(ac, ale) : 0; - short offset= (acf->get_offset) ? acf->get_offset(ac, ale) : 0; /* get context info needed... */ if ((ac->sa) && (ac->sa->spacetype == SPACE_ACTION)) @@ -188,10 +205,27 @@ static void acf_generic_channel_backdrop(bAnimContext *ac, bAnimListElem *ale, f VECCOPY(cp, grp->cs.active); } - glColor3ub(cp[0], cp[1], cp[2]); + /* copy the colors over, transforming from bytes to floats */ + rgb_byte_to_float(cp, color); + } + else { + // FIXME: what happens when the indention is 1 greater than what it should be (due to grouping)? + int colOfs= 20 - 20*indent; + UI_GetThemeColorShade3fv(TH_HEADER, colOfs, color); } - else // FIXME: what happens when the indention is 1 greater than what it should be (due to grouping)? - UI_ThemeColorShade(TH_HEADER, ((indent==0)?20: (indent==1)?-20: -40)); +} + +/* backdrop for generic channels */ +static void acf_generic_channel_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc) +{ + bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale); + View2D *v2d= &ac->ar->v2d; + short offset= (acf->get_offset) ? acf->get_offset(ac, ale) : 0; + float color[3]; + + /* set backdrop drawing color */ + acf->get_backdrop_color(ac, ale, color); + glColor3fv(color); /* no rounded corners - just rectangular box */ glRectf(offset, yminc, v2d->cur.xmax+EXTRA_SCROLL_PAD, ymaxc); @@ -348,13 +382,23 @@ static short acf_generic_dataexpand_setting_valid(bAnimContext *ac, bAnimListEle /* Animation Summary ----------------------------------- */ +/* get backdrop color for summary widget */ +static void acf_summary_color(bAnimContext *ac, bAnimListElem *ale, float *color) +{ + // FIXME: hardcoded color - same as the 'action' line in NLA + glColor3f(0.8f, 0.2f, 0.0f); // reddish color +} + /* backdrop for summary widget */ static void acf_summary_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc) { + bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale); View2D *v2d= &ac->ar->v2d; + float color[3]; - // FIXME: hardcoded color - same as the 'action' line in NLA - glColor3f(0.8f, 0.2f, 0.0f); // reddish color + /* set backdrop drawing color */ + acf->get_backdrop_color(ac, ale, color); + glColor3fv(color); /* rounded corners on LHS only * - top and bottom @@ -424,6 +468,7 @@ static void *acf_summary_setting_ptr(bAnimListElem *ale, int setting, short *typ /* all animation summary (DopeSheet only) type define */ static bAnimChannelType ACF_SUMMARY = { + acf_summary_color, /* backdrop color */ acf_summary_backdrop, /* backdrop */ acf_generic_indention_0, /* indent level */ NULL, /* offset */ @@ -522,6 +567,7 @@ static void *acf_scene_setting_ptr(bAnimListElem *ale, int setting, short *type) /* scene type define */ static bAnimChannelType ACF_SCENE = { + acf_generic_root_color, /* backdrop color */ acf_generic_root_backdrop, /* backdrop */ acf_generic_indention_0, /* indent level */ NULL, /* offset */ @@ -641,6 +687,7 @@ static void *acf_object_setting_ptr(bAnimListElem *ale, int setting, short *type /* object type define */ static bAnimChannelType ACF_OBJECT = { + acf_generic_root_color, /* backdrop color */ acf_generic_root_backdrop, /* backdrop */ acf_generic_indention_0, /* indent level */ NULL, /* offset */ @@ -655,6 +702,16 @@ static bAnimChannelType ACF_OBJECT = /* Group ------------------------------------------- */ +/* get backdrop color for group widget */ +static void acf_group_color(bAnimContext *ac, bAnimListElem *ale, float *color) +{ + /* highlight only for action group channels */ + if (ale->flag & AGRP_ACTIVE) + UI_GetThemeColorShade3fv(TH_GROUP_ACTIVE, 10, color); + else + UI_GetThemeColorShade3fv(TH_GROUP, 20, color); +} + /* backdrop for group widget */ static void acf_group_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc) { @@ -662,12 +719,11 @@ static void acf_group_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc View2D *v2d= &ac->ar->v2d; short expanded= ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_EXPAND) != 0; short offset= (acf->get_offset) ? acf->get_offset(ac, ale) : 0; + float color[3]; - /* only for action group channels */ - if (ale->flag & AGRP_ACTIVE) - UI_ThemeColorShade(TH_GROUP_ACTIVE, 10); - else - UI_ThemeColorShade(TH_GROUP, 20); + /* set backdrop drawing color */ + acf->get_backdrop_color(ac, ale, color); + glColor3fv(color); /* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */ uiSetRoundBox((expanded)? (1):(1|8)); @@ -738,6 +794,7 @@ static void *acf_group_setting_ptr(bAnimListElem *ale, int setting, short *type) /* group type define */ static bAnimChannelType ACF_GROUP = { + acf_group_color, /* backdrop color */ acf_group_backdrop, /* backdrop */ acf_generic_indention_0, /* indent level */ acf_generic_group_offset, /* offset */ @@ -821,6 +878,7 @@ static void *acf_fcurve_setting_ptr(bAnimListElem *ale, int setting, short *type /* fcurve type define */ static bAnimChannelType ACF_FCURVE = { + acf_generic_channel_color, /* backdrop color */ acf_generic_channel_backdrop, /* backdrop */ acf_generic_indention_flexible, /* indent level */ // xxx rename this to f-curves only? acf_generic_group_offset, /* offset */ @@ -902,6 +960,7 @@ static void *acf_fillactd_setting_ptr(bAnimListElem *ale, int setting, short *ty /* object action expander type define */ static bAnimChannelType ACF_FILLACTD = { + acf_generic_dataexpand_color, /* backdrop color */ acf_generic_dataexpand_backdrop,/* backdrop */ acf_generic_indention_1, /* indent level */ acf_generic_basic_offset, /* offset */ @@ -977,6 +1036,7 @@ static void *acf_filldrivers_setting_ptr(bAnimListElem *ale, int setting, short /* drivers expander type define */ static bAnimChannelType ACF_FILLDRIVERS = { + acf_generic_dataexpand_color, /* backdrop color */ acf_generic_dataexpand_backdrop,/* backdrop */ acf_generic_indention_1, /* indent level */ acf_generic_basic_offset, /* offset */ @@ -1020,6 +1080,7 @@ static int acf_fillmatd_setting_flag(int setting, short *neg) /* materials expander type define */ static bAnimChannelType ACF_FILLMATD= { + acf_generic_dataexpand_color, /* backdrop color */ acf_generic_dataexpand_backdrop,/* backdrop */ acf_generic_indention_1, /* indent level */ acf_generic_basic_offset, /* offset */ @@ -1063,6 +1124,7 @@ static int acf_fillpartd_setting_flag(int setting, short *neg) /* particles expander type define */ static bAnimChannelType ACF_FILLPARTD= { + acf_generic_dataexpand_color, /* backdrop color */ acf_generic_dataexpand_backdrop,/* backdrop */ acf_generic_indention_1, /* indent level */ acf_generic_basic_offset, /* offset */ @@ -1142,6 +1204,7 @@ static void *acf_dsmat_setting_ptr(bAnimListElem *ale, int setting, short *type) /* material expander type define */ static bAnimChannelType ACF_DSMAT= { + acf_generic_channel_color, /* backdrop color */ acf_generic_channel_backdrop, /* backdrop */ acf_generic_indention_0, /* indent level */ acf_dsmat_offset, /* offset */ @@ -1215,6 +1278,7 @@ static void *acf_dslam_setting_ptr(bAnimListElem *ale, int setting, short *type) /* lamp expander type define */ static bAnimChannelType ACF_DSLAM= { + acf_generic_dataexpand_color, /* backdrop color */ acf_generic_dataexpand_backdrop,/* backdrop */ acf_generic_indention_1, /* indent level */ acf_generic_basic_offset, /* offset */ @@ -1288,6 +1352,7 @@ static void *acf_dscam_setting_ptr(bAnimListElem *ale, int setting, short *type) /* camera expander type define */ static bAnimChannelType ACF_DSCAM= { + acf_generic_dataexpand_color, /* backdrop color */ acf_generic_dataexpand_backdrop,/* backdrop */ acf_generic_indention_1, /* indent level */ acf_generic_basic_offset, /* offset */ @@ -1371,6 +1436,7 @@ static void *acf_dscur_setting_ptr(bAnimListElem *ale, int setting, short *type) /* curve expander type define */ static bAnimChannelType ACF_DSCUR= { + acf_generic_dataexpand_color, /* backdrop color */ acf_generic_dataexpand_backdrop,/* backdrop */ acf_generic_indention_1, /* indent level */ acf_generic_basic_offset, /* offset */ @@ -1444,6 +1510,7 @@ static void *acf_dsskey_setting_ptr(bAnimListElem *ale, int setting, short *type /* shapekey expander type define */ static bAnimChannelType ACF_DSSKEY= { + acf_generic_dataexpand_color, /* backdrop color */ acf_generic_dataexpand_backdrop,/* backdrop */ acf_generic_indention_1, /* indent level */ acf_generic_basic_offset, /* offset */ @@ -1517,6 +1584,7 @@ static void *acf_dswor_setting_ptr(bAnimListElem *ale, int setting, short *type) /* world expander type define */ static bAnimChannelType ACF_DSWOR= { + acf_generic_dataexpand_color, /* backdrop color */ acf_generic_dataexpand_backdrop,/* backdrop */ acf_generic_indention_1, /* indent level */ acf_generic_basic_offset, /* offset */ @@ -1590,6 +1658,7 @@ static void *acf_dspart_setting_ptr(bAnimListElem *ale, int setting, short *type /* particle expander type define */ static bAnimChannelType ACF_DSPART= { + acf_generic_dataexpand_color, /* backdrop color */ acf_generic_dataexpand_backdrop,/* backdrop */ acf_generic_indention_1, /* indent level */ acf_generic_basic_offset, /* offset */ @@ -1663,6 +1732,7 @@ static void *acf_dsmball_setting_ptr(bAnimListElem *ale, int setting, short *typ /* metaball expander type define */ static bAnimChannelType ACF_DSMBALL= { + acf_generic_dataexpand_color, /* backdrop color */ acf_generic_dataexpand_backdrop,/* backdrop */ acf_generic_indention_1, /* indent level */ acf_generic_basic_offset, /* offset */ @@ -1736,6 +1806,7 @@ static void *acf_dsarm_setting_ptr(bAnimListElem *ale, int setting, short *type) /* metaball expander type define */ static bAnimChannelType ACF_DSARM= { + acf_generic_dataexpand_color, /* backdrop color */ acf_generic_dataexpand_backdrop,/* backdrop */ acf_generic_indention_1, /* indent level */ acf_generic_basic_offset, /* offset */ @@ -1809,6 +1880,7 @@ static void *acf_dsntree_setting_ptr(bAnimListElem *ale, int setting, short *typ /* node tree expander type define */ static bAnimChannelType ACF_DSNTREE= { + acf_generic_dataexpand_color, /* backdrop color */ acf_generic_dataexpand_backdrop,/* backdrop */ acf_generic_indention_1, /* indent level */ // XXX this only works for compositing acf_generic_basic_offset, /* offset */ @@ -1882,6 +1954,7 @@ static void *acf_dsmesh_setting_ptr(bAnimListElem *ale, int setting, short *type /* node tree expander type define */ static bAnimChannelType ACF_DSMESH= { + acf_generic_dataexpand_color, /* backdrop color */ acf_generic_dataexpand_backdrop,/* backdrop */ acf_generic_indention_1, /* indent level */ // XXX this only works for compositing acf_generic_basic_offset, /* offset */ @@ -1969,6 +2042,7 @@ static void *acf_shapekey_setting_ptr(bAnimListElem *ale, int setting, short *ty /* shapekey expander type define */ static bAnimChannelType ACF_SHAPEKEY= { + acf_generic_channel_color, /* backdrop color */ acf_generic_channel_backdrop, /* backdrop */ acf_generic_indention_0, /* indent level */ acf_generic_basic_offset, /* offset */ @@ -2314,6 +2388,7 @@ void ANIM_channel_setting_set (bAnimContext *ac, bAnimListElem *ale, int setting void ANIM_channel_draw (bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc) { bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale); + View2D *v2d= &ac->ar->v2d; short selected, offset; float y, ymid, ytext; @@ -2411,6 +2486,66 @@ void ANIM_channel_draw (bAnimContext *ac, bAnimListElem *ale, float yminc, float offset += 3; UI_DrawString(offset, ytext, name); } + + /* step 6) draw backdrops behidn mute+protection toggles + (sliders) ....................... */ + /* reset offset - now goes from RHS of panel */ + offset = 0; + + // TODO: when drawing sliders, make those draw instead of these toggles if not enough space + + if (v2d) { + short draw_sliders = 0; + float color[3]; + + /* get and set backdrop color */ + acf->get_backdrop_color(ac, ale, color); + glColor3fv(color); + + /* check if we need to show the sliders */ + if ((ac->sa) && ELEM(ac->spacetype, SPACE_ACTION, SPACE_IPO)) { + switch (ac->spacetype) { + case SPACE_ACTION: + { + SpaceAction *saction= (SpaceAction *)ac->sa->spacedata.first; + draw_sliders= (saction->flag & SACTION_SLIDERS); + } + break; + case SPACE_IPO: + { + SpaceIpo *sipo= (SpaceIpo *)ac->sa->spacedata.first; + draw_sliders= (sipo->flag & SIPO_SLIDERS); + } + break; + } + } + + /* check if there's enough space for the toggles if the sliders are drawn too */ + if ( !(draw_sliders) || ((v2d->mask.xmax-v2d->mask.xmin) > ACHANNEL_BUTTON_WIDTH/2) ) { + /* protect... */ + if (acf->has_setting(ac, ale, ACHANNEL_SETTING_PROTECT)) + offset += ICON_WIDTH; + /* mute... */ + if (acf->has_setting(ac, ale, ACHANNEL_SETTING_MUTE)) + offset += ICON_WIDTH; + } + + /* draw slider + * - even if we can draw sliders for this view, we must also check that the channel-type supports them + * (only only F-Curves really can support them for now) + * - slider should start before the toggles (if they're visible) to keep a clean line down the side + */ + if ((draw_sliders) && ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_SHAPEKEY)) { + /* adjust offset */ + offset += SLIDER_WIDTH; + } + + + /* finally draw a backdrop rect behind these + * - starts from the point where the first toggle/slider starts, + * - ends past the space that might be reserved for a scroller + */ + glRectf(v2d->cur.xmax-(float)offset, yminc, v2d->cur.xmax+EXTRA_SCROLL_PAD, ymaxc); + } } /* ------------------ */ @@ -2421,14 +2556,15 @@ static void achannel_setting_widget_cb(bContext *C, void *poin, void *poin2) WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN_EDIT, NULL); } -/* callback for visiblility-toggle widget settings - perform value flushing (Graph Editor only) */ -static void achannel_setting_visible_widget_cb(bContext *C, void *ale_npoin, void *dummy_poin) +/* callback for widget settings that need flushing */ +static void achannel_setting_flush_widget_cb(bContext *C, void *ale_npoin, void *setting_wrap) { bAnimListElem *ale_setting= (bAnimListElem *)ale_npoin; bAnimContext ac; ListBase anim_data = {NULL, NULL}; int filter; - short vizOn = 0; + int setting = GET_INT_FROM_POINTER(setting_wrap); + short on = 0; /* send notifiers before doing anything else... */ WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN_EDIT, NULL); @@ -2440,10 +2576,10 @@ static void achannel_setting_visible_widget_cb(bContext *C, void *ale_npoin, voi /* verify that we have a channel to operate on, and that it has all we need */ if (ale_setting) { /* check if the setting is on... */ - vizOn= ANIM_channel_setting_get(&ac, ale_setting, ACHANNEL_SETTING_VISIBLE); + on= ANIM_channel_setting_get(&ac, ale_setting, setting); - /* vizOn == -1 means setting not found... */ - if (vizOn == -1) + /* on == -1 means setting not found... */ + if (on == -1) return; } else @@ -2457,7 +2593,7 @@ static void achannel_setting_visible_widget_cb(bContext *C, void *ale_npoin, voi ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); /* call API method to flush the setting */ - ANIM_visibility_flush_anim_channels(&ac, &anim_data, ale_setting, vizOn); + ANIM_flush_setting_anim_channels(&ac, &anim_data, ale_setting, setting, on); /* free temp data */ BLI_freelistN(&anim_data); @@ -2635,11 +2771,19 @@ static void draw_setting_widget (bAnimContext *ac, bAnimListElem *ale, bAnimChan /* set call to send relevant notifiers and/or perform type-specific updates */ if (but) { - /* 'visibility' toggles for Graph Editor need special flushing */ - if (setting == ACHANNEL_SETTING_VISIBLE) - uiButSetNFunc(but, achannel_setting_visible_widget_cb, MEM_dupallocN(ale), 0); - else - uiButSetFunc(but, achannel_setting_widget_cb, NULL, NULL); + switch (setting) { + /* settings needing flushing up/down hierarchy */ + case ACHANNEL_SETTING_VISIBLE: /* Graph Editor - 'visibility' toggles */ + case ACHANNEL_SETTING_PROTECT: /* General - protection flags */ + case ACHANNEL_SETTING_MUTE: /* General - muting flags */ + uiButSetNFunc(but, achannel_setting_flush_widget_cb, MEM_dupallocN(ale), SET_INT_IN_POINTER(setting)); + break; + + /* no flushing */ + case ACHANNEL_SETTING_EXPAND: /* expanding - cannot flush, otherwise all would open/close at once */ + default: + uiButSetFunc(but, achannel_setting_widget_cb, NULL, NULL); + } } } } diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index ebb3136d530..530e9179474 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -364,9 +364,10 @@ void ANIM_deselect_anim_channels (void *data, short datatype, short test, short * then the channels under closed expanders get ignored... * - ale_setting: the anim channel (not in the anim_data list directly, though occuring there) * with the new state of the setting that we want flushed up/down the hierarchy - * - vizOn: whether the visibility setting has been enabled or disabled + * - setting: type of setting to set + * - on: whether the visibility setting has been enabled or disabled */ -void ANIM_visibility_flush_anim_channels (bAnimContext *ac, ListBase *anim_data, bAnimListElem *ale_setting, short vizOn) +void ANIM_flush_setting_anim_channels (bAnimContext *ac, ListBase *anim_data, bAnimListElem *ale_setting, int setting, short on) { bAnimListElem *ale, *match=NULL; int prevLevel=0, matchLevel=0; @@ -394,13 +395,22 @@ void ANIM_visibility_flush_anim_channels (bAnimContext *ac, ListBase *anim_data, * - we define the level as simply being the offset for the start of the channel */ matchLevel= (acf->get_offset)? acf->get_offset(ac, ale_setting) : 0; + prevLevel= matchLevel; } /* flush up? - * - only flush up if the current state is now enabled + * + * For Visibility: + * - only flush up if the current state is now enabled (positive 'on' state is default) * (otherwise, it's too much work to force the parents to be inactive too) + * + * For everything else: + * - only flush up if the current state is now disabled (negative 'off' state is default) + * (otherwise, it's too much work to force the parents to be active too) */ - if (vizOn) { + if ( ((setting == ACHANNEL_SETTING_VISIBLE) && on) || + ((setting != ACHANNEL_SETTING_VISIBLE) && on==0) ) + { /* go backwards in the list, until the highest-ranking element (by indention has been covered) */ for (ale= match->prev; ale; ale= ale->prev) { bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale); @@ -416,7 +426,7 @@ void ANIM_visibility_flush_anim_channels (bAnimContext *ac, ListBase *anim_data, * when toggling visibility of F-Curves, gets flushed), flush the new status... */ if (level < prevLevel) - ANIM_channel_setting_set(ac, ale, ACHANNEL_SETTING_VISIBLE, vizOn); + ANIM_channel_setting_set(ac, ale, setting, on); /* however, if the level is 'greater than' (i.e. less important than the previous channel, * stop searching, since we've already reached the bottom of another hierarchy */ @@ -444,7 +454,7 @@ void ANIM_visibility_flush_anim_channels (bAnimContext *ac, ListBase *anim_data, * flush the new status... */ if (level > matchLevel) - ANIM_channel_setting_set(ac, ale, ACHANNEL_SETTING_VISIBLE, vizOn); + ANIM_channel_setting_set(ac, ale, setting, on); /* however, if the level is 'less than or equal to' the channel that was changed, * (i.e. the current channel is as important if not more important than the changed channel) * then we should stop, since we've found the last one of the children we should flush @@ -1054,7 +1064,7 @@ static int animchannels_visibility_set_exec(bContext *C, wmOperator *op) ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_ADD); /* now, also flush selection status up/down as appropriate */ - ANIM_visibility_flush_anim_channels(&ac, &all_data, ale, 1); + ANIM_flush_setting_anim_channels(&ac, &all_data, ale, ACHANNEL_SETTING_VISIBLE, 1); } BLI_freelistN(&anim_data); @@ -1128,7 +1138,7 @@ static int animchannels_visibility_toggle_exec(bContext *C, wmOperator *op) ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_VISIBLE, vis); /* now, also flush selection status up/down as appropriate */ - ANIM_visibility_flush_anim_channels(&ac, &all_data, ale, (vis == ACHANNEL_SETFLAG_ADD)); + ANIM_flush_setting_anim_channels(&ac, &all_data, ale, ACHANNEL_SETTING_VISIBLE, (vis == ACHANNEL_SETFLAG_ADD)); } /* cleanup */ diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c index 4cc3a8d343f..7d1ddda1c6d 100644 --- a/source/blender/editors/animation/anim_markers.c +++ b/source/blender/editors/animation/anim_markers.c @@ -120,7 +120,7 @@ void ED_markers_get_minmax (ListBase *markers, short sel, float *first, float *l int selcount = 0; /* sanity check */ - printf("markers = %p - %p, %p \n", markers, markers->first, markers->last); + //printf("markers = %p - %p, %p \n", markers, markers->first, markers->last); if (markers == NULL) { *first = 0.0f; *last = 0.0f; @@ -240,9 +240,8 @@ static void draw_marker(View2D *v2d, TimeMarker *marker, int cfra, int flag) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); /* vertical line - dotted */ - // NOTE: currently only used for sequencer #ifdef DURIAN_CAMERA_SWITCH - if (marker->camera || flag & DRAW_MARKERS_LINES) { + if ((marker->camera) || (flag & DRAW_MARKERS_LINES)) { #else if (flag & DRAW_MARKERS_LINES) { #endif @@ -252,10 +251,10 @@ static void draw_marker(View2D *v2d, TimeMarker *marker, int cfra, int flag) glColor4ub(255, 255, 255, 96); else glColor4ub(0, 0, 0, 96); - + glBegin(GL_LINES); glVertex2f((xpos*xscale)+0.5f, 12.0f); - glVertex2f((xpos*xscale)+0.5f, 34.0f*yscale); /* a bit lazy but we know it cant be greater then 34 strips high */ + glVertex2f((xpos*xscale)+0.5f, (v2d->cur.ymax+12.0f)*yscale); glEnd(); setlinestyle(0); @@ -351,7 +350,7 @@ static int ed_marker_add(bContext *C, wmOperator *op) marker = MEM_callocN(sizeof(TimeMarker), "TimeMarker"); marker->flag= SELECT; marker->frame= frame; - sprintf(marker->name, "Frame %d", frame); // XXX - temp code only + sprintf(marker->name, "F_%02d", frame); // XXX - temp code only BLI_addtail(markers, marker); WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL); diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c index 59e52c0d489..b816ffbe905 100644 --- a/source/blender/editors/animation/drivers.c +++ b/source/blender/editors/animation/drivers.c @@ -404,8 +404,7 @@ static int add_driver_button_exec (bContext *C, wmOperator *op) /* send updates */ DAG_ids_flush_update(0); - /* for now, only send ND_KEYS for KeyingSets */ - WM_event_add_notifier(C, ND_KEYS, NULL); // XXX + WM_event_add_notifier(C, NC_ANIMATION|ND_FCURVES_ORDER, NULL); // XXX } return (success)? OPERATOR_FINISHED: OPERATOR_CANCELLED; @@ -468,8 +467,7 @@ static int remove_driver_button_exec (bContext *C, wmOperator *op) /* send updates */ DAG_ids_flush_update(0); - /* for now, only send ND_KEYS for KeyingSets */ - WM_event_add_notifier(C, ND_KEYS, NULL); // XXX + WM_event_add_notifier(C, NC_ANIMATION|ND_FCURVES_ORDER, NULL); // XXX } return (success)? OPERATOR_FINISHED: OPERATOR_CANCELLED; diff --git a/source/blender/editors/animation/keyframes_edit.c b/source/blender/editors/animation/keyframes_edit.c index b3b0d6308a7..828ff9792be 100644 --- a/source/blender/editors/animation/keyframes_edit.c +++ b/source/blender/editors/animation/keyframes_edit.c @@ -455,11 +455,11 @@ void ANIM_editkeyframes_refresh(bAnimContext *ac) filter= ANIMFILTER_CURVESONLY; ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - /* loop over ipo-curves that are likely to have been edited, and check them */ + /* loop over F-Curves that are likely to have been edited, and check them */ for (ale= anim_data.first; ale; ale= ale->next) { FCurve *fcu= ale->key_data; - /* make sure keyframes in F-curve are all in order, and handles are in valid positions */ + /* make sure keyframes in F-Curve are all in order, and handles are in valid positions */ sort_time_fcurve(fcu); testhandles_fcurve(fcu); } @@ -936,7 +936,6 @@ static short select_bezier_invert(BeztEditData *bed, BezTriple *bezt) return 0; } -// NULL BeztEditFunc ANIM_editkeyframes_select(short selectmode) { switch (selectmode) { diff --git a/source/blender/editors/animation/keyframes_general.c b/source/blender/editors/animation/keyframes_general.c index fb9d4d53b0f..a1ff940e8b9 100644 --- a/source/blender/editors/animation/keyframes_general.c +++ b/source/blender/editors/animation/keyframes_general.c @@ -67,21 +67,26 @@ /* **************************************************** */ -/* Only delete the nominated keyframe from provided ipo-curve. +/* Only delete the nominated keyframe from provided F-Curve. * Not recommended to be used many times successively. For that - * there is delete_ipo_keys(). + * there is delete_fcurve_keys(). */ void delete_fcurve_key(FCurve *fcu, int index, short do_recalc) { - /* firstly check that index is valid */ - if (index < 0) - index *= -1; + /* sanity check */ if (fcu == NULL) return; - if (index >= fcu->totvert) + + /* verify the index: + * 1) cannot be greater than the number of available keyframes + * 2) negative indices are for specifying a value from the end of the array + */ + if (abs(index) >= fcu->totvert) return; + else if (index < 0) + index += fcu->totvert; - /* Delete this key */ + /* Delete this keyframe */ memmove(&fcu->bezt[index], &fcu->bezt[index+1], sizeof(BezTriple)*(fcu->totvert-index-1)); fcu->totvert--; @@ -250,7 +255,7 @@ void clean_fcurve(FCurve *fcu, float thresh) /* ---------------- */ -/* temp struct used for smooth_ipo */ +/* temp struct used for smooth_fcurve */ typedef struct tSmooth_Bezt { float *h1, *h2, *h3; /* bezt->vec[0,1,2][1] */ } tSmooth_Bezt; diff --git a/source/blender/editors/armature/poseSlide.c b/source/blender/editors/armature/poseSlide.c index 7ceb50057ce..0e066b112b0 100644 --- a/source/blender/editors/armature/poseSlide.c +++ b/source/blender/editors/armature/poseSlide.c @@ -417,7 +417,7 @@ static void pose_slide_apply_quat (tPoseSlideOp *pso, tPChanFCurveLink *pfl) float cframe; /* get the path to use - this should be quaternion rotations only (needs care) */ - path= BLI_sprintfN("%s.%s", pfl->pchan_path, "rotation"); + path= BLI_sprintfN("%s.%s", pfl->pchan_path, "rotation_quaternion"); /* get the current frame number */ cframe= (float)pso->cframe; @@ -463,6 +463,19 @@ static void pose_slide_apply_quat (tPoseSlideOp *pso, tPChanFCurveLink *pfl) /* just perform the interpol between quat_prev and quat_next using pso->percentage as a guide */ interp_qt_qtqt(pchan->quat, quat_prev, quat_next, pso->percentage); } + else if (pso->mode == POSESLIDE_PUSH) { + float quat_diff[4], quat_orig[4]; + + /* calculate the delta transform from the previous to the current */ + // TODO: investigate ways to favour one transform more? + sub_qt_qtqt(quat_diff, pchan->quat, quat_prev); + + /* make a copy of the original rotation */ + QUATCOPY(quat_orig, pchan->quat); + + /* increase the original by the delta transform, by an amount determined by percentage */ + add_qt_qtqt(pchan->quat, quat_orig, quat_diff, pso->percentage); + } else { float quat_interp[4], quat_orig[4]; int iters= (int)ceil(10.0f*pso->percentage); // TODO: maybe a sensitivity ctrl on top of this is needed @@ -475,11 +488,8 @@ static void pose_slide_apply_quat (tPoseSlideOp *pso, tPChanFCurveLink *pfl) /* make a copy of the original rotation */ QUATCOPY(quat_orig, pchan->quat); - /* tricky interpolations - mode-dependent blending between original and new */ - if (pso->mode == POSESLIDE_RELAX) // xxx this was the original code, so should work fine - interp_qt_qtqt(pchan->quat, quat_orig, quat_interp, 1.0f/6.0f); - else // I'm just guessing here... - interp_qt_qtqt(pchan->quat, quat_orig, quat_interp, 6.0f/5.0f); + /* tricky interpolations - blending between original and new */ + interp_qt_qtqt(pchan->quat, quat_orig, quat_interp, 1.0f/6.0f); } } } @@ -612,22 +622,15 @@ static int pose_slide_invoke_common (bContext *C, wmOperator *op, tPoseSlideOp * /* cancel if no keyframes found... */ if (pso->keys.root) { ActKeyColumn *ak; + float cframe= (float)pso->cframe; /* firstly, check if the current frame is a keyframe... */ - ak= (ActKeyColumn *)BLI_dlrbTree_search_exact(&pso->keys, compare_ak_cfraPtr, &pso->cframe); + ak= (ActKeyColumn *)BLI_dlrbTree_search_exact(&pso->keys, compare_ak_cfraPtr, &cframe); if (ak == NULL) { /* current frame is not a keyframe, so search */ - ActKeyColumn *pk= (ActKeyColumn *)BLI_dlrbTree_search_prev(&pso->keys, compare_ak_cfraPtr, &pso->cframe); - ActKeyColumn *nk= (ActKeyColumn *)BLI_dlrbTree_search_next(&pso->keys, compare_ak_cfraPtr, &pso->cframe); - - /* check if we found good keyframes */ - if ((pk == nk) && (pk != NULL)) { - if (pk->cfra < pso->cframe) - nk= nk->next; - else if (nk->cfra > pso->cframe) - pk= pk->prev; - } + ActKeyColumn *pk= (ActKeyColumn *)BLI_dlrbTree_search_prev(&pso->keys, compare_ak_cfraPtr, &cframe); + ActKeyColumn *nk= (ActKeyColumn *)BLI_dlrbTree_search_next(&pso->keys, compare_ak_cfraPtr, &cframe); /* new set the frames */ /* prev frame */ diff --git a/source/blender/editors/armature/poseobject.c b/source/blender/editors/armature/poseobject.c index aeb42142abd..df5f551fb0c 100644 --- a/source/blender/editors/armature/poseobject.c +++ b/source/blender/editors/armature/poseobject.c @@ -227,6 +227,7 @@ void ED_pose_recalculate_paths(bContext *C, Scene *scene, Object *ob) if ((pchan->bone) && (arm->layer & pchan->bone->layer)) { if (pchan->path) { /* if the pathsf and pathef aren't initialised, abort! */ + // XXX can now have negative frames, so this check needs improvement if (ELEM(0, pchan->pathsf, pchan->pathef)) return; diff --git a/source/blender/editors/gpencil/gpencil_buttons.c b/source/blender/editors/gpencil/gpencil_buttons.c index 5deffbabb77..59ad4124a95 100644 --- a/source/blender/editors/gpencil/gpencil_buttons.c +++ b/source/blender/editors/gpencil/gpencil_buttons.c @@ -119,13 +119,13 @@ static void gp_drawui_layer (uiLayout *layout, bGPdata *gpd, bGPDlayer *gpl) box= uiLayoutBox(layout); row= uiLayoutRow(box, 0); + uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_EXPAND); block= uiLayoutGetBlock(row); // err... uiBlockSetEmboss(block, UI_EMBOSSN); /* left-align ............................... */ - subrow= uiLayoutRow(row, 1); - uiLayoutSetAlignment(subrow, UI_LAYOUT_ALIGN_LEFT); + subrow= uiLayoutRow(row, 0); /* active */ icon= (gpl->flag & GP_LAYER_ACTIVE) ? ICON_RADIOBUT_ON : ICON_RADIOBUT_OFF; @@ -168,6 +168,11 @@ static void gp_drawui_layer (uiLayout *layout, bGPdata *gpd, bGPDlayer *gpl) /* visibility button */ uiItemR(subrow, "", ICON_RESTRICT_VIEW_OFF, &ptr, "hide", 0); + /* frame locking */ + // TODO: this needs its own icons... + icon= (gpl->flag & GP_LAYER_FRAMELOCK) ? ICON_RENDER_STILL : ICON_RENDER_ANIMATION; + uiItemR(subrow, "", icon, &ptr, "frame_lock", 0); + uiBlockSetEmboss(block, UI_EMBOSS); /* name */ @@ -189,7 +194,6 @@ static void gp_drawui_layer (uiLayout *layout, bGPdata *gpd, bGPDlayer *gpl) box= uiLayoutBox(layout); split= uiLayoutSplit(box, 0.5f, 0); - /* draw settings ---------------------------------- */ /* left column ..................... */ col= uiLayoutColumn(split, 0); @@ -229,7 +233,7 @@ static void draw_gpencil_panel (bContext *C, uiLayout *layout, bGPdata *gpd, Poi { PointerRNA gpd_ptr; bGPDlayer *gpl; - uiLayout *col; + uiLayout *col, *row; /* make new PointerRNA for Grease Pencil block */ RNA_id_pointer_create((ID *)gpd, &gpd_ptr); @@ -254,12 +258,21 @@ static void draw_gpencil_panel (bContext *C, uiLayout *layout, bGPdata *gpd, Poi } /* draw gpd drawing settings first ------------------------------------- */ - col= uiLayoutColumn(layout, 0); + col= uiLayoutColumn(layout, 1); /* label */ uiItemL(col, "Drawing Settings:", 0); /* 'stick to view' option */ - uiItemR(col, NULL, 0, &gpd_ptr, "view_space_draw", 0); + row= uiLayoutRow(col, 1); + uiItemEnumR_string(row, NULL, 0, &gpd_ptr, "draw_mode", "VIEW"); + uiItemEnumR_string(row, NULL, 0, &gpd_ptr, "draw_mode", "CURSOR"); + row= uiLayoutRow(col, 1); + uiItemEnumR_string(row, NULL, 0, &gpd_ptr, "draw_mode", "SURFACE"); + uiItemEnumR_string(row, NULL, 0, &gpd_ptr, "draw_mode", "STROKE"); + + row= uiLayoutRow(col, 0); + uiLayoutSetActive(row, (gpd->flag & (GP_DATA_DEPTH_STROKE|GP_DATA_DEPTH_VIEW)) ? 1:0); + uiItemR(row, NULL, 0, &gpd_ptr, "use_stroke_endpoints", 0); } diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index 3f9e3e04411..371e73cfb9b 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -155,15 +155,7 @@ static int gpencil_draw_poll (bContext *C) static int gpencil_project_check (tGPsdata *p) { bGPdata *gpd= p->gpd; - - if( (gpd->sbuffer_sflag & GP_STROKE_3DSPACE) && - (p->scene->toolsettings->snap_mode==SCE_SNAP_MODE_FACE) && - (p->scene->toolsettings->snap_flag & SCE_SNAP_PROJECT) ) - { - return 1; - } - - return 0; + return ((gpd->sbuffer_sflag & GP_STROKE_3DSPACE) && (p->gpd->flag & (GP_DATA_DEPTH_VIEW | GP_DATA_DEPTH_STROKE))) ? 1:0; } /* ******************************************* */ @@ -220,13 +212,13 @@ static short gp_stroke_filtermval (tGPsdata *p, int mval[2], int pmval[2]) /* convert screen-coordinates to buffer-coordinates */ // XXX this method needs a total overhaul! -static void gp_stroke_convertcoords (tGPsdata *p, short mval[], float out[]) +static void gp_stroke_convertcoords (tGPsdata *p, short mval[], float out[], float *depth) { bGPdata *gpd= p->gpd; /* in 3d-space - pt->x/y/z are 3 side-by-side floats */ if (gpd->sbuffer_sflag & GP_STROKE_3DSPACE) { - if(gpencil_project_check(p) && (view_autodist_simple(p->ar, mval, out))) { + if(gpencil_project_check(p) && (view_autodist_simple(p->ar, mval, out, 0, depth))) { /* projecting onto 3D-Geometry * - nothing more needs to be done here, since view_autodist_simple() has already done it */ @@ -466,6 +458,8 @@ static void gp_stroke_newfrombuffer (tGPsdata *p) bGPDspoint *pt; tGPspoint *ptc; int i, totelem; + /* since strokes are so fine, when using their depth we need a margin otherwise they might get missed */ + int depth_margin = (p->gpd->flag & GP_DATA_DEPTH_STROKE) ? 4 : 0; /* get total number of points to allocate space for * - drawing straight-lines only requires the endpoints @@ -501,7 +495,7 @@ static void gp_stroke_newfrombuffer (tGPsdata *p) ptc= gpd->sbuffer; /* convert screen-coordinates to appropriate coordinates (and store them) */ - gp_stroke_convertcoords(p, &ptc->x, &pt->x); + gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL); /* copy pressure */ pt->pressure= ptc->pressure; @@ -514,23 +508,79 @@ static void gp_stroke_newfrombuffer (tGPsdata *p) ptc= ((tGPspoint *)gpd->sbuffer) + (gpd->sbuffer_size - 1); /* convert screen-coordinates to appropriate coordinates (and store them) */ - gp_stroke_convertcoords(p, &ptc->x, &pt->x); + gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL); /* copy pressure */ pt->pressure= ptc->pressure; } } else { + float *depth_arr= NULL; + + /* get an array of depths, far depths are blended */ + if(gpencil_project_check(p)) { + short mval[2]; + int interp_depth = 0; + int found_depth = 0; + + depth_arr= MEM_mallocN(sizeof(float) * gpd->sbuffer_size, "depth_points"); + + for (i=0, ptc=gpd->sbuffer; i < gpd->sbuffer_size; i++, ptc++, pt++) { + mval[0]= ptc->x; mval[1]= ptc->y; + if(view_autodist_depth(p->ar, mval, depth_margin, depth_arr+i) == 0) + interp_depth= TRUE; + else + found_depth= TRUE; + } + + if(found_depth==FALSE) { + /* eeh... not much we can do.. :/, ignore depth in this case, use the 3D cursor */ + for (i=gpd->sbuffer_size-1; i >= 0; i--) + depth_arr[i] = 0.9999f; + } + else { + if(p->gpd->flag & GP_DATA_DEPTH_STROKE_ENDPOINTS) { + /* remove all info between the valid endpoints */ + int first_valid = 0; + int last_valid = 0; + + for (i=0; i < gpd->sbuffer_size; i++) + if(depth_arr[i] != FLT_MAX) + break; + first_valid= i; + + for (i=gpd->sbuffer_size-1; i >= 0; i--) + if(depth_arr[i] != FLT_MAX) + break; + last_valid= i; + + /* invalidate non-endpoints, so only blend between first and last */ + for (i=first_valid+1; i < last_valid; i++) + depth_arr[i]= FLT_MAX; + + interp_depth= TRUE; + } + + if(interp_depth) { + interp_sparse_array(depth_arr, gpd->sbuffer_size, FLT_MAX); + } + } + } + + + pt= gps->points; + /* convert all points (normal behaviour) */ - for (i=0, ptc=gpd->sbuffer; i < gpd->sbuffer_size && ptc; i++, ptc++) { + for (i=0, ptc=gpd->sbuffer; i < gpd->sbuffer_size && ptc; i++, ptc++, pt++) { /* convert screen-coordinates to appropriate coordinates (and store them) */ - gp_stroke_convertcoords(p, &ptc->x, &pt->x); + gp_stroke_convertcoords(p, &ptc->x, &pt->x, depth_arr ? depth_arr+i:NULL); /* copy pressure */ pt->pressure= ptc->pressure; - - pt++; } + + if(depth_arr) + MEM_freeN(depth_arr); } /* add stroke to frame */ @@ -1141,7 +1191,7 @@ static void gpencil_draw_exit (bContext *C, wmOperator *op) /* need to restore the original projection settings before packing up */ view3d_operator_needs_opengl(C); - view_autodist_init(p->scene, p->ar, v3d); + view_autodist_init(p->scene, p->ar, v3d, (p->gpd->flag & GP_DATA_DEPTH_STROKE) ? 1:0); } gp_paint_cleanup(p); diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index c34885fbe6b..531751a609e 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -327,6 +327,8 @@ typedef enum eAnimChannel_Settings { /* Drawing, mouse handling, and flag setting behaviour... */ typedef struct bAnimChannelType { /* drawing */ + /* get RGB color that is used to draw the majority of the backdrop */ + void (*get_backdrop_color)(bAnimContext *ac, bAnimListElem *ale, float *color); /* draw backdrop strip for channel */ void (*draw_backdrop)(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc); /* get depth of indention (relative to the depth channel is nested at) */ @@ -334,7 +336,6 @@ typedef struct bAnimChannelType { /* get offset in pixels for the start of the channel (in addition to the indent depth) */ short (*get_offset)(bAnimContext *ac, bAnimListElem *ale); - /* get name (for channel lists) */ void (*name)(bAnimListElem *ale, char *name); /* get icon (for channel lists) */ @@ -385,9 +386,10 @@ void ANIM_channel_setting_set(bAnimContext *ac, bAnimListElem *ale, int setting, * then the channels under closed expanders get ignored... * - ale_setting: the anim channel (not in the anim_data list directly, though occuring there) * with the new state of the setting that we want flushed up/down the hierarchy - * - vizOn: whether the visibility setting has been enabled or disabled + * - setting: type of setting to set + * - on: whether the visibility setting has been enabled or disabled */ -void ANIM_visibility_flush_anim_channels(bAnimContext *ac, ListBase *anim_data, bAnimListElem *ale_setting, short vizOn); +void ANIM_flush_setting_anim_channels(bAnimContext *ac, ListBase *anim_data, bAnimListElem *ale_setting, int setting, short on); /* Deselect all animation channels */ diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index 66c32b06f95..174447c0f9f 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -85,8 +85,6 @@ int *mesh_get_x_mirror_faces(struct Object *ob, struct EditMesh *em); int join_mesh_exec(struct bContext *C, struct wmOperator *op); int join_mesh_shapes_exec(struct bContext *C, struct wmOperator *op); -void objects_bake_render(struct Scene *scene, short event, char **error_msg); - /* mesh_ops.c */ void ED_operatortypes_mesh(void); void ED_operatormacros_mesh(void); diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index de5a9fe4e07..a7879c7b70d 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -127,8 +127,9 @@ unsigned int view3d_sample_backbuf(struct ViewContext *vc, int x, int y); int view_autodist(struct Scene *scene, struct ARegion *ar, struct View3D *v3d, short *mval, float mouse_worldloc[3]); /* only draw so view_autodist_simple can be called many times after */ -int view_autodist_init(struct Scene *scene, struct ARegion *ar, struct View3D *v3d); -int view_autodist_simple(struct ARegion *ar, short *mval, float mouse_worldloc[3]); +int view_autodist_init(struct Scene *scene, struct ARegion *ar, struct View3D *v3d, int mode); +int view_autodist_simple(struct ARegion *ar, short *mval, float mouse_worldloc[3], int margin, float *force_depth); +int view_autodist_depth(struct ARegion *ar, short *mval, int margin, float *depth); /* select */ #define MAXPICKBUF 10000 diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 77a8ea8e912..0b7499b947a 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -126,11 +126,12 @@ typedef struct uiLayout uiLayout; #define UI_TEXT_LEFT 64 #define UI_ICON_LEFT 128 #define UI_ICON_SUBMENU 256 +#define UI_ICON_PREVIEW 512 /* control for button type block */ -#define UI_MAKE_TOP 512 -#define UI_MAKE_DOWN 1024 -#define UI_MAKE_LEFT 2048 -#define UI_MAKE_RIGHT 4096 +#define UI_MAKE_TOP 1024 +#define UI_MAKE_DOWN 2048 +#define UI_MAKE_LEFT 4096 +#define UI_MAKE_RIGHT 8192 /* button align flag, for drawing groups together */ #define UI_BUT_ALIGN (15<<14) @@ -427,6 +428,7 @@ struct PointerRNA *uiButGetOperatorPtrRNA(uiBut *but); #define UI_ID_FAKE_USER 256 #define UI_ID_PIN 512 #define UI_ID_BROWSE_RENDER 1024 +#define UI_ID_PREVIEWS 2048 #define UI_ID_FULL (UI_ID_RENAME|UI_ID_BROWSE|UI_ID_ADD_NEW|UI_ID_OPEN|UI_ID_ALONE|UI_ID_DELETE|UI_ID_LOCAL) typedef void (*uiIDPoinFuncFP)(struct bContext *C, char *str, struct ID **idpp); @@ -451,10 +453,9 @@ uiBut *uiDefIconTextBlockBut(uiBlock *block, uiBlockCreateFunc func, void *arg, uiBut *uiDefKeyevtButS(uiBlock *block, int retval, char *str, short x1, short y1, short x2, short y2, short *spoin, char *tip); uiBut *uiDefHotKeyevtButS(uiBlock *block, int retval, char *str, short x1, short y1, short x2, short y2, short *keypoin, short *modkeypoin, char *tip); -uiBut *uiDefSearchBut(uiBlock *block, void *arg, int retval, int icon, int maxlen, short x1, short y1, short x2, short y2, char *tip); +uiBut *uiDefSearchBut(uiBlock *block, void *arg, int retval, int icon, int maxlen, short x1, short y1, short x2, short y2, float a1, float a2, char *tip); void uiBlockPickerButtons(struct uiBlock *block, float *col, float *hsv, float *old, char *hexcol, char mode, short retval); -void uiBlockColorbandButtons(struct uiBlock *block, struct ColorBand *coba, struct rctf *butr, int event); uiBut *uiDefAutoButR(uiBlock *block, struct PointerRNA *ptr, struct PropertyRNA *prop, int index, char *name, int icon, int x1, int y1, int x2, int y2); void uiDefAutoButsRNA(const struct bContext *C, uiLayout *layout, struct PointerRNA *ptr, int columns); @@ -641,6 +642,8 @@ void uiTemplateHeader(uiLayout *layout, struct bContext *C, int menus); void uiTemplateDopeSheetFilter(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr); void uiTemplateID(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, char *propname, char *newop, char *openop, char *unlinkop); +void uiTemplateIDPreview(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, char *propname, + char *newop, char *openop, char *unlinkop, int rows, int cols); void uiTemplateAnyID(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, char *propname, char *proptypename, char *text); void uiTemplatePathBuilder(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, char *propname, @@ -649,7 +652,8 @@ uiLayout *uiTemplateModifier(uiLayout *layout, struct PointerRNA *ptr); uiLayout *uiTemplateConstraint(uiLayout *layout, struct PointerRNA *ptr); void uiTemplatePreview(uiLayout *layout, struct ID *id, struct ID *parent, struct MTex *slot); void uiTemplateColorRamp(uiLayout *layout, struct PointerRNA *ptr, char *propname, int expand); -void uiTemplateCurveMapping(uiLayout *layout, struct PointerRNA *ptr, char *propname, int type, int levels); +void uiTemplateCurveMapping(uiLayout *layout, struct PointerRNA *ptr, char *propname, int type, int levels, int brush); +void uiTemplateColorWheel(uiLayout *layout, struct PointerRNA *ptr, char *propname, int value_slider); void uiTemplateTriColorSet(uiLayout *layout, struct PointerRNA *ptr, char *propname); void uiTemplateLayers(uiLayout *layout, struct PointerRNA *ptr, char *propname, PointerRNA *used_ptr, char *used_propname, int active_layer); diff --git a/source/blender/editors/include/UI_interface_icons.h b/source/blender/editors/include/UI_interface_icons.h index afe6a2b9dcb..69e75d0e7c4 100644 --- a/source/blender/editors/include/UI_interface_icons.h +++ b/source/blender/editors/include/UI_interface_icons.h @@ -55,7 +55,9 @@ int UI_icon_get_width(int icon_id); int UI_icon_get_height(int icon_id); void UI_icon_draw(float x, float y, int icon_id); -void UI_icon_draw_preview(float x, float y, int icon_id, int nocreate); +void UI_icon_draw_preview(float x, float y, int icon_id); +void UI_icon_draw_preview_aspect(float x, float y, int icon_id, float aspect); +void UI_icon_draw_preview_aspect_size(float x, float y, int icon_id, float aspect, int size); void UI_icon_draw_aspect(float x, float y, int icon_id, float aspect, float alpha); void UI_icon_draw_aspect_color(float x, float y, int icon_id, float aspect, float *rgb); diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h index 1ae3634c73b..787a39591c7 100644 --- a/source/blender/editors/include/UI_resources.h +++ b/source/blender/editors/include/UI_resources.h @@ -236,6 +236,8 @@ int UI_GetThemeValue(int colorid); // get three color values, scaled to 0.0-1.0 range void UI_GetThemeColor3fv(int colorid, float *col); +// get the color, range 0.0-1.0, complete with shading offset +void UI_GetThemeColorShade3fv(int colorid, int offset, float *col); // get the 3 or 4 byte values void UI_GetThemeColor3ubv(int colorid, char *col); diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 88b9c7819fd..5c91a91e447 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -1116,7 +1116,6 @@ void ui_get_but_vectorf(uiBut *but, float *vec) if(but->editvec) { VECCOPY(vec, but->editvec); - return; } if(but->rnaprop) { @@ -1152,7 +1151,6 @@ void ui_set_but_vectorf(uiBut *but, float *vec) if(but->editvec) { VECCOPY(but->editvec, vec); - return; } if(but->rnaprop) { @@ -3171,9 +3169,10 @@ uiBut *uiDefHotKeyevtButS(uiBlock *block, int retval, char *str, short x1, short /* arg is pointer to string/name, use uiButSetSearchFunc() below to make this work */ -uiBut *uiDefSearchBut(uiBlock *block, void *arg, int retval, int icon, int maxlen, short x1, short y1, short x2, short y2, char *tip) +/* here a1 and a2, if set, control thumbnail preview rows/cols */ +uiBut *uiDefSearchBut(uiBlock *block, void *arg, int retval, int icon, int maxlen, short x1, short y1, short x2, short y2, float a1, float a2, char *tip) { - uiBut *but= ui_def_but(block, SEARCH_MENU, retval, "", x1, y1, x2, y2, arg, 0.0, maxlen, 0.0, 0.0, tip); + uiBut *but= ui_def_but(block, SEARCH_MENU, retval, "", x1, y1, x2, y2, arg, 0.0, maxlen, a1, a2, tip); but->icon= (BIFIconID) icon; but->flag|= UI_HAS_ICON; diff --git a/source/blender/editors/interface/interface_anim.c b/source/blender/editors/interface/interface_anim.c index acfd48e0269..e35ffade342 100644 --- a/source/blender/editors/interface/interface_anim.c +++ b/source/blender/editors/interface/interface_anim.c @@ -168,7 +168,7 @@ void uiAnimContextProperty(const bContext *C, struct PointerRNA *ptr, struct Pro if(ar) { for(block=ar->uiblocks.first; block; block=block->next) { for(but=block->buttons.first; but; but= but->next) { - if(but->active && but->rnapoin.id.data) { + if((but->active || but->flag & UI_BUT_LAST_ACTIVE) && but->rnapoin.id.data) { *ptr= but->rnapoin; *prop= but->rnaprop; *index= but->rnaindex; diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index fa5d60a20f6..916a48b7442 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -402,11 +402,7 @@ static void ui_apply_but_BUTM(bContext *C, uiBut *but, uiHandleButtonData *data) static void ui_apply_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data) { - if(but->type == COL) { - if(but->a1 != -1) // this is not a color picker (weak!) - ui_set_but_vectorf(but, data->vec); - } - else if(ELEM3(but->type, MENU, ICONROW, ICONTEXTROW)) + if(ELEM3(but->type, MENU, ICONROW, ICONTEXTROW)) ui_set_but_val(but, data->value); ui_check_but(but); @@ -2586,6 +2582,7 @@ static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, wm but->hsv[2]= CLAMPIS(but->hsv[2]+0.05f, 0.0f, 1.0f); hsv_to_rgb(but->hsv[0], but->hsv[1], but->hsv[2], data->vec, data->vec+1, data->vec+2); + ui_set_but_vectorf(but, data->vec); button_activate_state(C, but, BUTTON_STATE_EXIT); ui_apply_button(C, but->block, but, data, 1); @@ -2694,6 +2691,7 @@ static int ui_do_but_NORMAL(bContext *C, uiBlock *block, uiBut *but, uiHandleBut static int ui_numedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, int mx, int my) { + float rgb[3], hsv[3]; float x, y; int changed= 1; int color_profile = but->block->color_profile; @@ -2702,6 +2700,9 @@ static int ui_numedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, int mx, if (RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) color_profile = BLI_PR_NONE; } + + ui_get_but_vectorf(but, rgb); + rgb_to_hsv(rgb[0], rgb[1], rgb[2], hsv, hsv+1, hsv+2); /* relative position within box */ x= ((float)mx-but->x1)/(but->x2-but->x1); @@ -2710,31 +2711,35 @@ static int ui_numedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, int mx, CLAMP(y, 0.0, 1.0); if(but->a1==0) { - but->hsv[0]= x; - but->hsv[2]= y; + hsv[2]= x; + hsv[1]= y; } else if(but->a1==1) { - but->hsv[0]= x; - but->hsv[1]= y; + hsv[0]= x; + hsv[2]= y; } else if(but->a1==2) { - but->hsv[2]= x; - but->hsv[1]= y; + hsv[0]= x; + hsv[1]= y; } else if(but->a1==3) { - but->hsv[0]= x; + hsv[0]= x; } - else { + else if(but->a1==4) { + hsv[1]= x; + } + else if(but->a1==5) { + hsv[2]= x; + } + else if (but->a1==9){ /* vertical 'value' strip */ - but->hsv[2]= y; + hsv[2]= y; if (color_profile) - but->hsv[2] = srgb_to_linearrgb(but->hsv[2]); + hsv[2] = srgb_to_linearrgb(hsv[2]); } - ui_set_but_hsv(but); // converts to rgb - - // update button values and strings - ui_update_block_buts_hsv(but->block, but->hsv); + hsv_to_rgb(hsv[0], hsv[1], hsv[2], rgb, rgb+1, rgb+2); + ui_set_but_vectorf(but, rgb); data->draglastx= mx; data->draglasty= my; @@ -2766,7 +2771,12 @@ static int ui_do_but_HSVCUBE(bContext *C, uiBlock *block, uiBut *but, uiHandleBu } } else if(data->state == BUTTON_STATE_NUM_EDITING) { - if(event->type == MOUSEMOVE) { + if(event->type == ESCKEY) { + data->cancel= 1; + data->escapecancel= 1; + button_activate_state(C, but, BUTTON_STATE_EXIT); + } + else if(event->type == MOUSEMOVE) { if(mx!=data->draglastx || my!=data->draglasty) { if(ui_numedit_but_HSVCUBE(but, data, mx, my)) ui_numedit_apply(C, block, but, data); @@ -2785,16 +2795,18 @@ static int ui_numedit_but_HSVCIRCLE(uiBut *but, uiHandleButtonData *data, int mx { rcti rect; int changed= 1; - + float rgb[3], hsv[3]; + rect.xmin= but->x1; rect.xmax= but->x2; rect.ymin= but->y1; rect.ymax= but->y2; - ui_hsvcircle_vals_from_pos(but->hsv, but->hsv+1, &rect, (float)mx, (float)my); + ui_get_but_vectorf(but, rgb); + rgb_to_hsv(rgb[0], rgb[1], rgb[2], hsv, hsv+1, hsv+2); - ui_set_but_hsv(but); // converts to rgb + ui_hsvcircle_vals_from_pos(hsv, hsv+1, &rect, (float)mx, (float)my); - // update button values and strings - // XXX ui_update_block_buts_hsv(but->block, but->hsv); + hsv_to_rgb(hsv[0], hsv[1], hsv[2], rgb, rgb+1, rgb+2); + ui_set_but_vectorf(but, rgb); data->draglastx= mx; data->draglasty= my; @@ -2827,8 +2839,13 @@ static int ui_do_but_HSVCIRCLE(bContext *C, uiBlock *block, uiBut *but, uiHandle } } else if(data->state == BUTTON_STATE_NUM_EDITING) { + if(event->type == ESCKEY) { + data->cancel= 1; + data->escapecancel= 1; + button_activate_state(C, but, BUTTON_STATE_EXIT); + } /* XXX hardcoded keymap check.... */ - if(event->type == WHEELDOWNMOUSE) { + else if(event->type == WHEELDOWNMOUSE) { but->hsv[2]= CLAMPIS(but->hsv[2]-0.05f, 0.0f, 1.0f); ui_set_but_hsv(but); // converts to rgb ui_numedit_apply(C, block, but, data); @@ -2844,9 +2861,9 @@ static int ui_do_but_HSVCIRCLE(bContext *C, uiBlock *block, uiBut *but, uiHandle ui_numedit_apply(C, block, but, data); } } - else if(event->type==LEFTMOUSE && event->val!=KM_PRESS) + else if(event->type==LEFTMOUSE && event->val!=KM_PRESS) { button_activate_state(C, but, BUTTON_STATE_EXIT); - + } return WM_UI_HANDLER_BREAK; } @@ -3780,7 +3797,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event) retval= ui_do_but_BUT(C, but, data, event); break; case COL: - if(but->a1 == -1) // signal to prevent calling up color picker + if(but->a1 == 9) // signal to prevent calling up color picker retval= ui_do_but_EXIT(C, but, data, event); else retval= ui_do_but_BLOCK(C, but, data, event); diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index e219198da0f..43c8b0b2c74 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -940,7 +940,7 @@ static void icon_draw_size(float x, float y, int icon_id, float aspect, float al } } -void ui_id_icon_render(bContext *C, ID *id) +void ui_id_icon_render(bContext *C, ID *id, int preview) { PreviewImage *pi = BKE_previewimg_get(id); @@ -948,13 +948,17 @@ void ui_id_icon_render(bContext *C, ID *id) if ((pi->changed[0] ||!pi->rect[0])) /* changed only ever set by dynamic icons */ { /* create the preview rect if necessary */ - icon_set_image(C, id, pi, 0); + + icon_set_image(C, id, pi, 0); /* icon size */ + if (preview) + icon_set_image(C, id, pi, 1); /* preview size */ + pi->changed[0] = 0; } } } -int ui_id_icon_get(bContext *C, ID *id) +int ui_id_icon_get(bContext *C, ID *id, int preview) { int iconid= 0; @@ -968,7 +972,7 @@ int ui_id_icon_get(bContext *C, ID *id) case ID_LA: /* fall through */ iconid= BKE_icon_getid(id); /* checks if not exists, or changed */ - ui_id_icon_render(C, id); + ui_id_icon_render(C, id, preview); break; default: break; @@ -1004,8 +1008,18 @@ void UI_icon_draw_size(float x, float y, int size, int icon_id, float alpha) icon_draw_size(x, y, icon_id, 1.0f, alpha, NULL, 0, size, 1); } -void UI_icon_draw_preview(float x, float y, int icon_id, int nocreate) +void UI_icon_draw_preview(float x, float y, int icon_id) +{ + icon_draw_mipmap(x, y, icon_id, 1.0f, 1.0f, PREVIEW_MIPMAP_LARGE, 0); +} + +void UI_icon_draw_preview_aspect(float x, float y, int icon_id, float aspect) +{ + icon_draw_mipmap(x, y, icon_id, aspect, 1.0f, PREVIEW_MIPMAP_LARGE, 0); +} + +void UI_icon_draw_preview_aspect_size(float x, float y, int icon_id, float aspect, int size) { - icon_draw_mipmap(x, y, icon_id, 1.0f, 1.0f, PREVIEW_MIPMAP_LARGE, nocreate); + icon_draw_size(x, y, icon_id, aspect, 1.0f, NULL, PREVIEW_MIPMAP_LARGE, size, 0); } diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 02808f9c2e7..aec48b5c7c7 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -348,7 +348,6 @@ extern void ui_set_but_soft_range(uiBut *but, double value); extern void ui_check_but(uiBut *but); extern int ui_is_but_float(uiBut *but); extern int ui_is_but_unit(uiBut *but); -extern void ui_update_block_buts_hsv(uiBlock *block, float *hsv); extern void ui_bounds_block(uiBlock *block); extern void ui_block_translate(uiBlock *block, int x, int y); @@ -378,7 +377,7 @@ struct uiPopupBlockHandle { int butretval; int menuretval; float retvalue; - float retvec[3]; + float retvec[4]; }; uiBlock *ui_block_func_COL(struct bContext *C, uiPopupBlockHandle *handle, void *arg_but); @@ -450,13 +449,14 @@ struct ThemeUI; void ui_widget_color_init(struct ThemeUI *tui); void ui_draw_menu_item(struct uiFontStyle *fstyle, rcti *rect, char *name, int iconid, int state); +void ui_draw_preview_item(struct uiFontStyle *fstyle, rcti *rect, char *name, int iconid, int state); /* interface_style.c */ void uiStyleInit(void); /* interface_icons.c */ -void ui_id_icon_render(struct bContext *C, struct ID *id); -int ui_id_icon_get(struct bContext *C, struct ID *id); +void ui_id_icon_render(struct bContext *C, struct ID *id, int preview); +int ui_id_icon_get(struct bContext *C, struct ID *id, int preview); /* resources.c */ void init_userdef_do_versions(void); diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index e512c1f6bf8..57102f4ad50 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -388,28 +388,28 @@ static void ui_item_array(uiLayout *layout, uiBlock *block, char *name, int icon } } else if(subtype == PROP_MATRIX) { - /* matrix layout */ + int totdim, dim_size[3]; /* 3 == RNA_MAX_ARRAY_DIMENSION */ int row, col; uiBlockSetCurLayout(block, uiLayoutAbsolute(layout, 1)); - len= ceil(sqrt(len)); - - h /= len; - w /= len; + totdim= RNA_property_array_dimension(ptr, prop, dim_size); + if (totdim != 2) return; /* only 2D matrices supported in UI so far */ + + w /= dim_size[0]; + h /= dim_size[1]; - // XXX test for(a=0; a<len; a++) { - col= a%len; - row= a/len; - - but= uiDefAutoButR(block, ptr, prop, a, "", 0, x + w*col, y+(row-a-1)*UI_UNIT_Y, w, UI_UNIT_Y); + col= a % dim_size[0]; + row= a / dim_size[0]; + + but= uiDefAutoButR(block, ptr, prop, a, "", 0, x + w*col, y+(dim_size[1]*UI_UNIT_Y)-(row*UI_UNIT_Y), w, UI_UNIT_Y); if(slider && but->type==NUM) but->type= NUMSLI; } } else { - if(ELEM(subtype, PROP_COLOR, PROP_COLOR_GAMMA)) + if(ELEM(subtype, PROP_COLOR, PROP_COLOR_GAMMA) && !expand) uiDefAutoButR(block, ptr, prop, -1, "", 0, 0, 0, w, UI_UNIT_Y); if(!ELEM(subtype, PROP_COLOR, PROP_COLOR_GAMMA) || expand) { @@ -911,7 +911,7 @@ void uiItemFullR(uiLayout *layout, char *name, int icon, PointerRNA *ptr, Proper name= (char*)RNA_property_ui_name(prop); if(!icon) icon= RNA_property_ui_icon(prop); - + if(ELEM4(type, PROP_INT, PROP_FLOAT, PROP_STRING, PROP_POINTER)) name= ui_item_name_add_colon(name, namestr); else if(type == PROP_BOOLEAN && len && index == RNA_NO_INDEX) @@ -1115,7 +1115,7 @@ static void rna_search_cb(const struct bContext *C, void *arg_but, char *str, ui continue; if(RNA_struct_is_ID(itemptr.type)) - iconid= ui_id_icon_get((bContext*)C, itemptr.data); + iconid= ui_id_icon_get((bContext*)C, itemptr.data, 0); name= RNA_struct_name_get_alloc(&itemptr, NULL, 0); diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c index 25bfaf3d682..268f6d6e648 100644 --- a/source/blender/editors/interface/interface_ops.c +++ b/source/blender/editors/interface/interface_ops.c @@ -40,6 +40,7 @@ #include "DNA_view2d_types.h" #include "BLI_blenlib.h" +#include "BLI_math_color.h" #include "BKE_context.h" #include "BKE_utildefines.h" @@ -59,6 +60,142 @@ /* ********************************************************** */ +typedef struct Eyedropper { + PointerRNA ptr; + PropertyRNA *prop; + int index; +} Eyedropper; + +static int eyedropper_init(bContext *C, wmOperator *op) +{ + Eyedropper *eye; + + op->customdata= eye= MEM_callocN(sizeof(Eyedropper), "Eyedropper"); + + uiAnimContextProperty(C, &eye->ptr, &eye->prop, &eye->index); + + return (eye->ptr.data && eye->prop && RNA_property_editable(&eye->ptr, eye->prop)); +} + +static void eyedropper_exit(bContext *C, wmOperator *op) +{ + WM_cursor_restore(CTX_wm_window(C)); + + if(op->customdata) + MEM_freeN(op->customdata); + op->customdata= NULL; +} + +static int eyedropper_cancel(bContext *C, wmOperator *op) +{ + eyedropper_exit(C, op); + return OPERATOR_CANCELLED; +} + +static void eyedropper_sample(bContext *C, Eyedropper *eye, short mx, short my) +{ + float col[3]; + + glReadBuffer(GL_FRONT); + glReadPixels(mx, my, 1, 1, GL_RGB, GL_FLOAT, col); + glReadBuffer(GL_BACK); + + if(RNA_property_type(eye->prop) == PROP_FLOAT) { + + if (RNA_property_array_length(&eye->ptr, eye->prop) < 3) return; + + /* convert from screen (srgb) space to linear rgb space */ + if (RNA_property_subtype(eye->prop) == PROP_COLOR) + srgb_to_linearrgb_v3_v3(col, col); + + RNA_property_float_set_array(&eye->ptr, eye->prop, col); + + RNA_property_update(C, &eye->ptr, eye->prop); + } +} + +/* main modal status check */ +static int eyedropper_modal(bContext *C, wmOperator *op, wmEvent *event) +{ + Eyedropper *eye = (Eyedropper *)op->customdata; + + switch(event->type) { + case ESCKEY: + case RIGHTMOUSE: + return eyedropper_cancel(C, op); + case LEFTMOUSE: + if(event->val==KM_RELEASE) { + eyedropper_sample(C, eye, event->x, event->y); + eyedropper_exit(C, op); + return OPERATOR_FINISHED; + } + break; + } + + return OPERATOR_RUNNING_MODAL; +} + +/* Modal Operator init */ +static int eyedropper_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + /* init */ + if (eyedropper_init(C, op)) { + WM_cursor_modal(CTX_wm_window(C), BC_EYEDROPPER_CURSOR); + + /* add temp handler */ + WM_event_add_modal_handler(C, op); + + return OPERATOR_RUNNING_MODAL; + } else { + eyedropper_exit(C, op); + return OPERATOR_CANCELLED; + } +} + +/* Repeat operator */ +static int eyedropper_exec (bContext *C, wmOperator *op) +{ + /* init */ + if (eyedropper_init(C, op)) { + + /* do something */ + + /* cleanup */ + eyedropper_exit(C, op); + + return OPERATOR_FINISHED; + } else { + return OPERATOR_CANCELLED; + } +} + +static int eyedropper_poll(bContext *C) +{ + if (!CTX_wm_window(C)) return 0; + else return 1; +} + +void UI_OT_eyedropper(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Eyedropper"; + ot->idname= "UI_OT_eyedropper"; + ot->description= "Sample a color from the Blender Window to store in a property"; + + /* api callbacks */ + ot->invoke= eyedropper_invoke; + ot->modal= eyedropper_modal; + ot->cancel= eyedropper_cancel; + ot->exec= eyedropper_exec; + ot->poll= eyedropper_poll; + + /* flags */ + ot->flag= OPTYPE_BLOCKING; + + /* properties */ +} + + /* Copy Data Path Operator ------------------------ */ static int copy_data_path_button_exec(bContext *C, wmOperator *op) @@ -140,7 +277,7 @@ void UI_OT_reset_default_button(wmOperatorType *ot) /* identifiers */ ot->name= "Reset to Default Value"; ot->idname= "UI_OT_reset_default_button"; - ot->description= "Copy the RNA data path for this property to the clipboard."; + ot->description= "Reset this property's value to its default value"; /* callbacks */ ot->poll= reset_default_button_poll; @@ -248,6 +385,7 @@ void UI_OT_copy_to_selected_button(wmOperatorType *ot) void UI_buttons_operatortypes(void) { + WM_operatortype_append(UI_OT_eyedropper); WM_operatortype_append(UI_OT_copy_data_path_button); WM_operatortype_append(UI_OT_reset_default_button); WM_operatortype_append(UI_OT_copy_to_selected_button); diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index 8ebfed21dcc..6bc4e7b0b65 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -547,6 +547,8 @@ typedef struct uiSearchboxData { uiSearchItems items; int active; /* index in items array */ int noback; /* when menu opened with enough space for this */ + int preview; /* draw thumbnail previews, rather than list */ + int prv_rows, prv_cols; } uiSearchboxData; #define SEARCH_ITEMS 10 @@ -628,14 +630,34 @@ static void ui_searchbox_select(bContext *C, ARegion *ar, uiBut *but, int step) static void ui_searchbox_butrect(rcti *rect, uiSearchboxData *data, int itemnr) { - int buth= (data->bbox.ymax-data->bbox.ymin - 2*MENU_TOP)/SEARCH_ITEMS; - - *rect= data->bbox; - rect->xmin= data->bbox.xmin + 3.0f; - rect->xmax= data->bbox.xmax - 3.0f; - - rect->ymax= data->bbox.ymax - MENU_TOP - itemnr*buth; - rect->ymin= rect->ymax - buth; + /* thumbnail preview */ + if (data->preview) { + int buth = (data->bbox.ymax - data->bbox.ymin - 2*MENU_TOP) / data->prv_rows; + int butw = (data->bbox.xmax - data->bbox.xmin) / data->prv_cols; + int row, col; + + *rect= data->bbox; + + col = itemnr % data->prv_cols; + row = itemnr / data->prv_cols; + + rect->xmin += col * butw; + rect->xmax = rect->xmin + butw; + + rect->ymax = data->bbox.ymax - (row * buth); + rect->ymin = rect->ymax - buth; + } + /* list view */ + else { + int buth= (data->bbox.ymax-data->bbox.ymin - 2*MENU_TOP)/SEARCH_ITEMS; + + *rect= data->bbox; + rect->xmin= data->bbox.xmin + 3.0f; + rect->xmax= data->bbox.xmax - 3.0f; + + rect->ymax= data->bbox.ymax - MENU_TOP - itemnr*buth; + rect->ymin= rect->ymax - buth; + } } @@ -799,27 +821,55 @@ static void ui_searchbox_region_draw(const bContext *C, ARegion *ar) if(data->items.totitem) { rcti rect; int a; + + if (data->preview) { + /* draw items */ + for(a=0; a<data->items.totitem; a++) { + ui_searchbox_butrect(&rect, data, a); - /* draw items */ - for(a=0; a<data->items.totitem; a++) { - ui_searchbox_butrect(&rect, data, a); + /* widget itself */ + if (data->preview) + ui_draw_preview_item(&data->fstyle, &rect, data->items.names[a], data->items.icons[a], (a+1)==data->active?UI_ACTIVE:0); + else + ui_draw_menu_item(&data->fstyle, &rect, data->items.names[a], data->items.icons[a], (a+1)==data->active?UI_ACTIVE:0); + } - /* widget itself */ - ui_draw_menu_item(&data->fstyle, &rect, data->items.names[a], data->items.icons[a], (a+1)==data->active?UI_ACTIVE:0); + /* indicate more */ + if(data->items.more) { + ui_searchbox_butrect(&rect, data, data->items.maxitem-1); + glEnable(GL_BLEND); + UI_icon_draw(rect.xmax-18, rect.ymin-7, ICON_TRIA_DOWN); + glDisable(GL_BLEND); + } + if(data->items.offset) { + ui_searchbox_butrect(&rect, data, 0); + glEnable(GL_BLEND); + UI_icon_draw(rect.xmin, rect.ymax-9, ICON_TRIA_UP); + glDisable(GL_BLEND); + } - } - /* indicate more */ - if(data->items.more) { - ui_searchbox_butrect(&rect, data, data->items.maxitem-1); - glEnable(GL_BLEND); - UI_icon_draw((rect.xmax-rect.xmin)/2, rect.ymin-9, ICON_TRIA_DOWN); - glDisable(GL_BLEND); - } - if(data->items.offset) { - ui_searchbox_butrect(&rect, data, 0); - glEnable(GL_BLEND); - UI_icon_draw((rect.xmax-rect.xmin)/2, rect.ymax-7, ICON_TRIA_UP); - glDisable(GL_BLEND); + } else { + /* draw items */ + for(a=0; a<data->items.totitem; a++) { + ui_searchbox_butrect(&rect, data, a); + + /* widget itself */ + ui_draw_menu_item(&data->fstyle, &rect, data->items.names[a], data->items.icons[a], (a+1)==data->active?UI_ACTIVE:0); + + } + /* indicate more */ + if(data->items.more) { + ui_searchbox_butrect(&rect, data, data->items.maxitem-1); + glEnable(GL_BLEND); + UI_icon_draw((rect.xmax-rect.xmin)/2, rect.ymin-9, ICON_TRIA_DOWN); + glDisable(GL_BLEND); + } + if(data->items.offset) { + ui_searchbox_butrect(&rect, data, 0); + glEnable(GL_BLEND); + UI_icon_draw((rect.xmax-rect.xmin)/2, rect.ymax-7, ICON_TRIA_UP); + glDisable(GL_BLEND); + } } } } @@ -830,7 +880,7 @@ static void ui_searchbox_region_free(ARegion *ar) int a; /* free search data */ - for(a=0; a<SEARCH_ITEMS; a++) + for(a=0; a<data->items.maxitem; a++) MEM_freeN(data->items.names[a]); MEM_freeN(data->items.names); MEM_freeN(data->items.pointers); @@ -876,8 +926,13 @@ ARegion *ui_searchbox_create(bContext *C, ARegion *butregion, uiBut *but) if(but->block->flag & UI_BLOCK_LOOP) data->noback= 1; - /* compute position */ + if (but->a1 > 0 && but->a2 > 0) { + data->preview = 1; + data->prv_rows = but->a1; + data->prv_cols = but->a2; + } + /* compute position */ if(but->block->flag & UI_BLOCK_LOOP) { /* this case is search menu inside other menu */ /* we copy region size */ @@ -972,13 +1027,17 @@ ARegion *ui_searchbox_create(bContext *C, ARegion *butregion, uiBut *but) ED_region_tag_redraw(ar); /* prepare search data */ - data->items.maxitem= SEARCH_ITEMS; + if (data->preview) { + data->items.maxitem= data->prv_rows * data->prv_cols; + } else { + data->items.maxitem= SEARCH_ITEMS; + } data->items.maxstrlen= but->hardmax; data->items.totitem= 0; - data->items.names= MEM_callocN(SEARCH_ITEMS*sizeof(void *), "search names"); - data->items.pointers= MEM_callocN(SEARCH_ITEMS*sizeof(void *), "search pointers"); - data->items.icons= MEM_callocN(SEARCH_ITEMS*sizeof(int), "search icons"); - for(x1=0; x1<SEARCH_ITEMS; x1++) + data->items.names= MEM_callocN(data->items.maxitem*sizeof(void *), "search names"); + data->items.pointers= MEM_callocN(data->items.maxitem*sizeof(void *), "search pointers"); + data->items.icons= MEM_callocN(data->items.maxitem*sizeof(int), "search icons"); + for(x1=0; x1<data->items.maxitem; x1++) data->items.names[x1]= MEM_callocN(but->hardmax+1, "search pointers"); return ar; @@ -1476,15 +1535,6 @@ static void ui_warp_pointer(short x, short y) #define DPICK 6.0 #define BPICK 24.0 -#define UI_PALETTE_TOT 16 -/* note; in tot+1 the old color is stored */ -static float palette[UI_PALETTE_TOT+1][3]= { -{0.93, 0.83, 0.81}, {0.88, 0.89, 0.73}, {0.69, 0.81, 0.57}, {0.51, 0.76, 0.64}, -{0.37, 0.56, 0.61}, {0.33, 0.29, 0.55}, {0.46, 0.21, 0.51}, {0.40, 0.12, 0.18}, -{1.0, 1.0, 1.0}, {0.85, 0.85, 0.85}, {0.7, 0.7, 0.7}, {0.56, 0.56, 0.56}, -{0.42, 0.42, 0.42}, {0.28, 0.28, 0.28}, {0.14, 0.14, 0.14}, {0.0, 0.0, 0.0} -}; - /* for picker, while editing hsv */ void ui_set_but_hsv(uiBut *but) { @@ -1494,50 +1544,37 @@ void ui_set_but_hsv(uiBut *but) ui_set_but_vectorf(but, col); } -static void update_picker_hex(uiBlock *block, float *rgb) +/* also used by small picker, be careful with name checks below... */ +void ui_update_block_buts_rgb(uiBlock *block, float *rgb) { uiBut *bt; - char col[16]; + float hsv[3]; - sprintf(col, "%02X%02X%02X", (unsigned int)(rgb[0]*255.0), (unsigned int)(rgb[1]*255.0), (unsigned int)(rgb[2]*255.0)); + rgb_to_hsv(rgb[0], rgb[1], rgb[2], hsv, hsv+1, hsv+2); // this updates button strings, is hackish... but button pointers are on stack of caller function - for(bt= block->buttons.first; bt; bt= bt->next) { - if(strcmp(bt->str, "Hex: ")==0) + if (bt->rnaprop) { + + ui_set_but_vectorf(bt, rgb); + + } + else if(strcmp(bt->str, "Hex: ")==0) { + char col[16]; + + sprintf(col, "%02X%02X%02X", (unsigned int)(rgb[0]*255.0), (unsigned int)(rgb[1]*255.0), (unsigned int)(rgb[2]*255.0)); + strcpy(bt->poin, col); - - ui_check_but(bt); - } -} - -/* also used by small picker, be careful with name checks below... */ -void ui_update_block_buts_hsv(uiBlock *block, float *hsv) -{ - uiBut *bt; - float r, g, b; - float rgb[3]; - - // this updates button strings, is hackish... but button pointers are on stack of caller function - hsv_to_rgb(hsv[0], hsv[1], hsv[2], &r, &g, &b); - - rgb[0] = r; rgb[1] = g; rgb[2] = b; - update_picker_hex(block, rgb); - - for(bt= block->buttons.first; bt; bt= bt->next) { - if(ELEM(bt->type, HSVCUBE, HSVCIRCLE)) { - VECCOPY(bt->hsv, hsv); - ui_set_but_hsv(bt); } else if(bt->str[1]==' ') { if(bt->str[0]=='R') { - ui_set_but_val(bt, r); + ui_set_but_val(bt, rgb[0]); } else if(bt->str[0]=='G') { - ui_set_but_val(bt, g); + ui_set_but_val(bt, rgb[1]); } else if(bt->str[0]=='B') { - ui_set_but_val(bt, b); + ui_set_but_val(bt, rgb[2]); } else if(bt->str[0]=='H') { ui_set_but_val(bt, hsv[0]); @@ -1554,315 +1591,62 @@ void ui_update_block_buts_hsv(uiBlock *block, float *hsv) } } -static void ui_update_block_buts_hex(uiBlock *block, char *hexcol) -{ - uiBut *bt; - float r=0, g=0, b=0; - float h, s, v; - - - // this updates button strings, is hackish... but button pointers are on stack of caller function - hex_to_rgb(hexcol, &r, &g, &b); - rgb_to_hsv(r, g, b, &h, &s, &v); - - for(bt= block->buttons.first; bt; bt= bt->next) { - if(bt->type==HSVCUBE) { - bt->hsv[0] = h; - bt->hsv[1] = s; - bt->hsv[2] = v; - ui_set_but_hsv(bt); - } - else if(bt->str[1]==' ') { - if(bt->str[0]=='R') { - ui_set_but_val(bt, r); - } - else if(bt->str[0]=='G') { - ui_set_but_val(bt, g); - } - else if(bt->str[0]=='B') { - ui_set_but_val(bt, b); - } - else if(bt->str[0]=='H') { - ui_set_but_val(bt, h); - } - else if(bt->str[0]=='S') { - ui_set_but_val(bt, s); - } - else if(bt->str[0]=='V') { - ui_set_but_val(bt, v); - } - } - - ui_check_but(bt); - } -} - -/* bt1 is palette but, col1 is original color */ -/* callback to copy from/to palette */ -static void do_palette_cb(bContext *C, void *bt1, void *col1) +static void do_picker_rna_cb(bContext *C, void *bt1, void *unused) { - wmWindow *win= CTX_wm_window(C); - uiBut *but1= (uiBut *)bt1; - uiPopupBlockHandle *popup= but1->block->handle; - float *col= (float *)col1; - float *fp, hsv[3]; + uiBut *but= (uiBut *)bt1; + uiPopupBlockHandle *popup= but->block->handle; + PropertyRNA *prop = but->rnaprop; + PointerRNA ptr = but->rnapoin; + float rgb[4]; - fp= (float *)but1->poin; - - if(win->eventstate->ctrl) { - VECCOPY(fp, col); - } - else { - VECCOPY(col, fp); + if (prop) { + RNA_property_float_get_array(&ptr, prop, rgb); + ui_update_block_buts_rgb(but->block, rgb); } - rgb_to_hsv(col[0], col[1], col[2], hsv, hsv+1, hsv+2); - ui_update_block_buts_hsv(but1->block, hsv); - update_picker_hex(but1->block, col); - - if(popup) - popup->menuretval= UI_RETURN_UPDATE; -} - -static void do_hsv_cb(bContext *C, void *bt1, void *unused) -{ - uiBut *but1= (uiBut *)bt1; - uiPopupBlockHandle *popup= but1->block->handle; - if(popup) popup->menuretval= UI_RETURN_UPDATE; } -/* bt1 is num but, hsv1 is pointer to original color in hsv space*/ -/* callback to handle changes in num-buts in picker */ -static void do_palette1_cb(bContext *C, void *bt1, void *hsv1) +static void do_hsv_rna_cb(bContext *C, void *bt1, void *hsv_arg) { - uiBut *but1= (uiBut *)bt1; - uiPopupBlockHandle *popup= but1->block->handle; - float *hsv= (float *)hsv1; - float *fp= NULL; + uiBut *but= (uiBut *)bt1; + uiPopupBlockHandle *popup= but->block->handle; + float *hsv = (float *)hsv_arg; + float rgb[3]; - if(but1->str[1]==' ') { - if(but1->str[0]=='R') fp= (float *)but1->poin; - else if(but1->str[0]=='G') fp= ((float *)but1->poin)-1; - else if(but1->str[0]=='B') fp= ((float *)but1->poin)-2; - } - if(fp) { - rgb_to_hsv(fp[0], fp[1], fp[2], hsv, hsv+1, hsv+2); - } - ui_update_block_buts_hsv(but1->block, hsv); - - if(popup) - popup->menuretval= UI_RETURN_UPDATE; -} - -/* bt1 is num but, col1 is pointer to original color */ -/* callback to handle changes in num-buts in picker */ -static void do_palette2_cb(bContext *C, void *bt1, void *col1) -{ - uiBut *but1= (uiBut *)bt1; - uiPopupBlockHandle *popup= but1->block->handle; - float *rgb= (float *)col1; - float *fp= NULL; + hsv_to_rgb(hsv[0], hsv[1], hsv[2], rgb, rgb+1, rgb+2); - if(but1->str[1]==' ') { - if(but1->str[0]=='H') fp= (float *)but1->poin; - else if(but1->str[0]=='S') fp= ((float *)but1->poin)-1; - else if(but1->str[0]=='V') fp= ((float *)but1->poin)-2; - } - if(fp) { - hsv_to_rgb(fp[0], fp[1], fp[2], rgb, rgb+1, rgb+2); - } - ui_update_block_buts_hsv(but1->block, fp); - - if(popup) - popup->menuretval= UI_RETURN_UPDATE; -} - -static void do_palette_hex_cb(bContext *C, void *bt1, void *hexcl) -{ - uiBut *but1= (uiBut *)bt1; - uiPopupBlockHandle *popup= but1->block->handle; - char *hexcol= (char *)hexcl; + ui_update_block_buts_rgb(but->block, rgb); - ui_update_block_buts_hex(but1->block, hexcol); - if(popup) popup->menuretval= UI_RETURN_UPDATE; } -/* used for both 3d view and image window */ -static void do_palette_sample_cb(bContext *C, void *bt1, void *col1) /* frontbuf */ -{ - /* XXX 2.50 this should become an operator? */ -#if 0 - uiBut *but1= (uiBut *)bt1; - uiBut *but; - float tempcol[4]; - int x=0, y=0; - short mval[2]; - float hsv[3]; - short capturing; - int oldcursor; - Window *win; - unsigned short dev; - - oldcursor=get_cursor(); - win=winlay_get_active_window(); - - while (get_mbut() & L_MOUSE) UI_wait_for_statechange(); - - SetBlenderCursor(BC_EYEDROPPER_CURSOR); - - /* loop and wait for a mouse click */ - capturing = TRUE; - while(capturing) { - char ascii; - short val; - - dev = extern_qread_ext(&val, &ascii); - - if(dev==INPUTCHANGE) break; - if(get_mbut() & R_MOUSE) break; - else if(get_mbut() & L_MOUSE) { - uiGetMouse(mywinget(), mval); - x= mval[0]; y= mval[1]; - - capturing = FALSE; - break; - } - else if(dev==ESCKEY) break; - } - window_set_cursor(win, oldcursor); - - if(capturing) return; - - if(x<0 || y<0) return; - - /* if we've got a glick, use OpenGL to sample the color under the mouse pointer */ - glReadBuffer(GL_FRONT); - glReadPixels(x, y, 1, 1, GL_RGBA, GL_FLOAT, tempcol); - glReadBuffer(GL_BACK); - - /* and send that color back to the picker */ - rgb_to_hsv(tempcol[0], tempcol[1], tempcol[2], hsv, hsv+1, hsv+2); - ui_update_block_buts_hsv(but1->block, hsv); - update_picker_hex(but1->block, tempcol); - - for (but= but1->block->buttons.first; but; but= but->next) { - ui_check_but(but); - ui_draw_but(but); - } - - but= but1->block->buttons.first; - ui_block_flush_back(but->block); -#endif -} - -/* color picker, Gimp version. mode: 'f' = floating panel, 'p' = popup */ -/* col = read/write to, hsv/old/hexcol = memory for temporal use */ -void uiBlockPickerButtons(uiBlock *block, float *col, float *hsv, float *old, char *hexcol, char mode, short retval) +static void do_hex_rna_cb(bContext *C, void *bt1, void *hexcl) { - uiBut *bt; - float h, offs; - int a; - - VECCOPY(old, col); // old color stored there, for palette_cb to work - - // the cube intersection - bt= uiDefButF(block, HSVCUBE, retval, "", 0,DPICK+BPICK,FPICK,FPICK, col, 0.0, 0.0, 2, 0, ""); - uiButSetFunc(bt, do_hsv_cb, bt, NULL); - - bt= uiDefButF(block, HSVCUBE, retval, "", 0,0,FPICK,BPICK, col, 0.0, 0.0, 3, 0, ""); - uiButSetFunc(bt, do_hsv_cb, bt, NULL); - - // palette - - bt=uiDefButF(block, COL, retval, "", FPICK+DPICK, 0, BPICK,BPICK, old, 0.0, 0.0, -1, 0, "Old color, click to restore"); - uiButSetFunc(bt, do_palette_cb, bt, col); - uiDefButF(block, COL, retval, "", FPICK+DPICK, BPICK+DPICK, BPICK,60-BPICK-DPICK, col, 0.0, 0.0, -1, 0, "Active color"); - - h= (DPICK+BPICK+FPICK-64)/(UI_PALETTE_TOT/2.0); - uiBlockBeginAlign(block); - for(a= -1+UI_PALETTE_TOT/2; a>=0; a--) { - bt= uiDefButF(block, COL, retval, "", FPICK+DPICK, 65.0+(float)a*h, BPICK/2, h, palette[a+UI_PALETTE_TOT/2], 0.0, 0.0, -1, 0, "Click to choose, hold CTRL to store in palette"); - uiButSetFunc(bt, do_palette_cb, bt, col); - bt= uiDefButF(block, COL, retval, "", FPICK+DPICK+BPICK/2, 65.0+(float)a*h, BPICK/2, h, palette[a], 0.0, 0.0, -1, 0, "Click to choose, hold CTRL to store in palette"); - uiButSetFunc(bt, do_palette_cb, bt, col); - } - uiBlockEndAlign(block); - - // buttons - rgb_to_hsv(col[0], col[1], col[2], hsv, hsv+1, hsv+2); - sprintf(hexcol, "%02X%02X%02X", (unsigned int)(col[0]*255.0), (unsigned int)(col[1]*255.0), (unsigned int)(col[2]*255.0)); - - offs= FPICK+2*DPICK+BPICK; - - /* note; made this a TOG now, with NULL pointer. Is because BUT now gets handled with a afterfunc */ - bt= uiDefIconTextBut(block, TOG, UI_RETURN_OK, ICON_EYEDROPPER, "Sample", offs+55, 170, 85, 20, NULL, 0, 0, 0, 0, "Sample the color underneath the following mouse click (ESC or RMB to cancel)"); - uiButSetFunc(bt, do_palette_sample_cb, bt, col); - uiButSetFlag(bt, UI_TEXT_LEFT); - - bt= uiDefBut(block, TEX, retval, "Hex: ", offs, 140, 140, 20, hexcol, 0, 8, 0, 0, "Hex triplet for color (#RRGGBB)"); - uiButSetFunc(bt, do_palette_hex_cb, bt, hexcol); - - uiBlockBeginAlign(block); - bt= uiDefButF(block, NUMSLI, retval, "R ", offs, 110, 140,20, col, 0.0, 1.0, 10, 3, ""); - uiButSetFunc(bt, do_palette1_cb, bt, hsv); - bt= uiDefButF(block, NUMSLI, retval, "G ", offs, 90, 140,20, col+1, 0.0, 1.0, 10, 3, ""); - uiButSetFunc(bt, do_palette1_cb, bt, hsv); - bt= uiDefButF(block, NUMSLI, retval, "B ", offs, 70, 140,20, col+2, 0.0, 1.0, 10, 3, ""); - uiButSetFunc(bt, do_palette1_cb, bt, hsv); + uiBut *but= (uiBut *)bt1; + uiPopupBlockHandle *popup= but->block->handle; + char *hexcol= (char *)hexcl; + float rgb[3]; - uiBlockBeginAlign(block); - bt= uiDefButF(block, NUMSLI, retval, "H ", offs, 40, 140,20, hsv, 0.0, 1.0, 10, 3, ""); - uiButSetFunc(bt, do_palette2_cb, bt, col); - bt= uiDefButF(block, NUMSLI, retval, "S ", offs, 20, 140,20, hsv+1, 0.0, 1.0, 10, 3, ""); - uiButSetFunc(bt, do_palette2_cb, bt, col); - bt= uiDefButF(block, NUMSLI, retval, "V ", offs, 0, 140,20, hsv+2, 0.0, 1.0, 10, 3, ""); - uiButSetFunc(bt, do_palette2_cb, bt, col); - uiBlockEndAlign(block); -} - -/* bt1 is num but, hsv1 is pointer to original color in hsv space*/ -/* callback to handle changes */ -static void do_picker_small_cb(bContext *C, void *bt1, void *hsv1) -{ - uiBut *but1= (uiBut *)bt1; - uiPopupBlockHandle *popup= but1->block->handle; - float *hsv= (float *)hsv1; - float *fp= NULL; + hex_to_rgb(hexcol, rgb, rgb+1, rgb+2); - fp= (float *)but1->poin; - rgb_to_hsv(fp[0], fp[1], fp[2], hsv, hsv+1, hsv+2); - - ui_update_block_buts_hsv(but1->block, hsv); + ui_update_block_buts_rgb(but->block, rgb); if(popup) popup->menuretval= UI_RETURN_UPDATE; } -/* picker sizes S hsize, F full size, D spacer, B button/pallette height */ -#define SPICK1 150.0 -#define DPICK1 6.0 - -/* only the color, a HS circle and V slider */ -static void uiBlockPickerSmall(uiBlock *block, float *col, float *hsv, float *old, char *hexcol, char mode, short retval) +static void close_popup_cb(bContext *C, void *bt1, void *arg) { - uiBut *bt; + uiBut *but= (uiBut *)bt1; + uiPopupBlockHandle *popup= but->block->handle; - VECCOPY(old, col); // old color stored there, for palette_cb to work - - /* HS circle */ - bt= uiDefButF(block, HSVCIRCLE, retval, "", 0, 0,SPICK1,SPICK1, col, 0.0, 0.0, 0, 0, ""); - uiButSetFunc(bt, do_picker_small_cb, bt, hsv); - - /* value */ - bt= uiDefButF(block, HSVCUBE, retval, "", SPICK1+DPICK1,0,14,SPICK1, col, 0.0, 0.0, 4, 0, ""); - uiButSetFunc(bt, do_picker_small_cb, bt, hsv); + if(popup) + popup->menuretval= UI_RETURN_OK; } - static void picker_new_hide_reveal(uiBlock *block, short colormode) { uiBut *bt; @@ -1891,20 +1675,62 @@ static void do_picker_new_mode_cb(bContext *C, void *bt1, void *colv) { uiBut *bt= bt1; short colormode= ui_get_but_val(bt); - picker_new_hide_reveal(bt->block, colormode); } +/* picker sizes S hsize, F full size, D spacer, B button/pallette height */ +#define SPICK1 150.0 +#define DPICK1 6.0 + +#define PICKER_H 150 +#define PICKER_W 150 +#define PICKER_SPACE 6 +#define PICKER_BAR 14 + +#define PICKER_TOTAL_W (PICKER_W+PICKER_SPACE+PICKER_BAR) + +static void circle_picker(uiBlock *block, PointerRNA *ptr, const char *propname) +{ + uiBut *bt; + + /* HS circle */ + bt= uiDefButR(block, HSVCIRCLE, 0, "", 0, 0, PICKER_H, PICKER_W, ptr, propname, -1, 0.0, 0.0, 0, 0, ""); + uiButSetFunc(bt, do_picker_rna_cb, bt, NULL); + + /* value */ + uiDefButR(block, HSVCUBE, 0, "", PICKER_W+PICKER_SPACE,0,PICKER_BAR,PICKER_H, ptr, propname, -1, 0.0, 0.0, 9, 0, ""); + uiButSetFunc(bt, do_picker_rna_cb, bt, NULL); +} + + +static void square_picker(uiBlock *block, PointerRNA *ptr, const char *propname, int type) +{ + uiBut *bt; + int bartype = type + 3; + + /* HS square */ + bt= uiDefButR(block, HSVCUBE, 0, "", 0, PICKER_BAR+PICKER_SPACE, PICKER_TOTAL_W, PICKER_H, ptr, propname, -1, 0.0, 0.0, type, 0, ""); + uiButSetFunc(bt, do_picker_rna_cb, bt, NULL); + + /* value */ + uiDefButR(block, HSVCUBE, 0, "", 0, 0, PICKER_TOTAL_W, PICKER_BAR, ptr, propname, -1, 0.0, 0.0, bartype, 0, ""); + uiButSetFunc(bt, do_picker_rna_cb, bt, NULL); +} + /* a HS circle, V slider, rgb/hsv/hex sliders */ -static void uiBlockPickerNew(uiBlock *block, float *col, float *hsv, float *old, char *hexcol, char mode, short retval) +static void uiBlockPicker(uiBlock *block, float *rgb, PointerRNA *ptr, PropertyRNA *prop) { static short colormode= 0; /* temp? 0=rgb, 1=hsv, 2=hex */ uiBut *bt; - int width; + int width, butwidth; static char tip[50]; + static float hsv[3]; + static char hexcol[128]; + const char *propname = RNA_property_identifier(prop); - VECCOPY(old, col); // old color stored there, for palette_cb to work + width= PICKER_TOTAL_W; + butwidth = width - UI_UNIT_X - 10; /* existence of profile means storage is in linear colour space, with display correction */ if (block->color_profile == BLI_PR_NONE) @@ -1912,50 +1738,63 @@ static void uiBlockPickerNew(uiBlock *block, float *col, float *hsv, float *old, else sprintf(tip, "Value in Linear RGB Color Space"); - /* HS circle */ - bt= uiDefButF(block, HSVCIRCLE, retval, "", 0, 0,SPICK1,SPICK1, col, 0.0, 0.0, 0, 0, ""); - uiButSetFunc(bt, do_picker_small_cb, bt, hsv); - - /* value */ - bt= uiDefButF(block, HSVCUBE, retval, "", SPICK1+DPICK1,0,14,SPICK1, col, 0.0, 0.0, 4, 0, ""); - uiButSetFunc(bt, do_picker_small_cb, bt, hsv); + RNA_property_float_get_array(ptr, prop, rgb); + rgb_to_hsv(rgb[0], rgb[1], rgb[2], hsv, hsv+1, hsv+2); + + switch (U.color_picker_type) { + case USER_CP_CIRCLE: + circle_picker(block, ptr, propname); + break; + case USER_CP_SQUARE_SV: + square_picker(block, ptr, propname, 0); + break; + case USER_CP_SQUARE_HS: + square_picker(block, ptr, propname, 1); + break; + case USER_CP_SQUARE_HV: + square_picker(block, ptr, propname, 2); + break; + } /* mode */ - width= (SPICK1+DPICK1+14)/3; uiBlockBeginAlign(block); - bt= uiDefButS(block, ROW, retval, "RGB", 0, -30, width, 19, &colormode, 0.0, 0.0, 0, 0, ""); - uiButSetFunc(bt, do_picker_new_mode_cb, bt, col); - bt= uiDefButS(block, ROW, retval, "HSV", width, -30, width, 19, &colormode, 0.0, 1.0, 0, 0, ""); + bt= uiDefButS(block, ROW, 0, "RGB", 0, -30, width/3, UI_UNIT_Y, &colormode, 0.0, 0.0, 0, 0, ""); + uiButSetFunc(bt, do_picker_new_mode_cb, bt, rgb); + bt= uiDefButS(block, ROW, 0, "HSV", width/3, -30, width/3, UI_UNIT_Y, &colormode, 0.0, 1.0, 0, 0, ""); uiButSetFunc(bt, do_picker_new_mode_cb, bt, hsv); - bt= uiDefButS(block, ROW, retval, "Hex", 2*width, -30, width, 19, &colormode, 0.0, 2.0, 0, 0, ""); + bt= uiDefButS(block, ROW, 0, "Hex", 2*width/3, -30, width/3, UI_UNIT_Y, &colormode, 0.0, 2.0, 0, 0, ""); uiButSetFunc(bt, do_picker_new_mode_cb, bt, hexcol); uiBlockEndAlign(block); - - /* sliders or hex */ - width= (SPICK1+DPICK1+14); - rgb_to_hsv(col[0], col[1], col[2], hsv, hsv+1, hsv+2); - sprintf(hexcol, "%02X%02X%02X", (unsigned int)(col[0]*255.0), (unsigned int)(col[1]*255.0), (unsigned int)(col[2]*255.0)); + bt= uiDefIconButO(block, BUT, "UI_OT_eyedropper", WM_OP_INVOKE_DEFAULT, ICON_EYEDROPPER, butwidth+10, -60, UI_UNIT_X, UI_UNIT_Y, NULL); + uiButSetFunc(bt, close_popup_cb, bt, NULL); + + /* RGB values */ uiBlockBeginAlign(block); - bt= uiDefButF(block, NUMSLI, 0, "R ", 0, -60, width, 19, col, 0.0, 1.0, 10, 3, tip); - uiButSetFunc(bt, do_palette1_cb, bt, hsv); - bt= uiDefButF(block, NUMSLI, 0, "G ", 0, -80, width, 19, col+1, 0.0, 1.0, 10, 3, tip); - uiButSetFunc(bt, do_palette1_cb, bt, hsv); - bt= uiDefButF(block, NUMSLI, 0, "B ", 0, -100, width, 19, col+2, 0.0, 1.0, 10, 3, tip); - uiButSetFunc(bt, do_palette1_cb, bt, hsv); - uiBlockEndAlign(block); - + bt= uiDefButR(block, NUMSLI, 0, "R ", 0, -60, butwidth, UI_UNIT_Y, ptr, propname, 0, 0.0, 0.0, 0, 0, ""); + uiButSetFunc(bt, do_picker_rna_cb, bt, NULL); + bt= uiDefButR(block, NUMSLI, 0, "G ", 0, -80, butwidth, UI_UNIT_Y, ptr, propname, 1, 0.0, 0.0, 0, 0, ""); + uiButSetFunc(bt, do_picker_rna_cb, bt, NULL); + bt= uiDefButR(block, NUMSLI, 0, "B ", 0, -100, butwidth, UI_UNIT_Y, ptr, propname, 2, 0.0, 0.0, 0, 0, ""); + uiButSetFunc(bt, do_picker_rna_cb, bt, NULL); + // could use uiItemFullR(col, "", 0, ptr, prop, -1, 0, UI_ITEM_R_EXPAND|UI_ITEM_R_SLIDER); + // but need to use uiButSetFunc for updating other fake buttons + + /* HSV values */ uiBlockBeginAlign(block); - bt= uiDefButF(block, NUMSLI, 0, "H ", 0, -60, width, 19, hsv, 0.0, 1.0, 10, 3, ""); - uiButSetFunc(bt, do_palette2_cb, bt, col); - bt= uiDefButF(block, NUMSLI, 0, "S ", 0, -80, width, 19, hsv+1, 0.0, 1.0, 10, 3, ""); - uiButSetFunc(bt, do_palette2_cb, bt, col); - bt= uiDefButF(block, NUMSLI, 0, "V ", 0, -100, width, 19, hsv+2, 0.0, 1.0, 10, 3, ""); - uiButSetFunc(bt, do_palette2_cb, bt, col); + bt= uiDefButF(block, NUMSLI, 0, "H ", 0, -60, butwidth, UI_UNIT_Y, hsv, 0.0, 1.0, 10, 3, ""); + uiButSetFunc(bt, do_hsv_rna_cb, bt, hsv); + bt= uiDefButF(block, NUMSLI, 0, "S ", 0, -80, butwidth, UI_UNIT_Y, hsv+1, 0.0, 1.0, 10, 3, ""); + uiButSetFunc(bt, do_hsv_rna_cb, bt, hsv); + bt= uiDefButF(block, NUMSLI, 0, "V ", 0, -100, butwidth, UI_UNIT_Y, hsv+2, 0.0, 1.0, 10, 3, ""); + uiButSetFunc(bt, do_hsv_rna_cb, bt, hsv); uiBlockEndAlign(block); + + rgb_to_hsv(rgb[0], rgb[1], rgb[2], hsv, hsv+1, hsv+2); + sprintf(hexcol, "%02X%02X%02X", (unsigned int)(rgb[0]*255.0), (unsigned int)(rgb[1]*255.0), (unsigned int)(rgb[2]*255.0)); - bt= uiDefBut(block, TEX, 0, "Hex: ", 0, -80, width, 19, hexcol, 0, 8, 0, 0, "Hex triplet for color (#RRGGBB)"); - uiButSetFunc(bt, do_palette_hex_cb, bt, hexcol); + bt= uiDefBut(block, TEX, 0, "Hex: ", 0, -60, butwidth, UI_UNIT_Y, hexcol, 0, 8, 0, 0, "Hex triplet for color (#RRGGBB)"); + uiButSetFunc(bt, do_hex_rna_cb, bt, hexcol); picker_new_hide_reveal(block, colormode); } @@ -1986,7 +1825,7 @@ static int ui_picker_small_wheel(const bContext *C, uiBlock *block, wmEvent *eve ui_set_but_vectorf(but, col); - ui_update_block_buts_hsv(block, but->hsv); + ui_update_block_buts_rgb(block, col); if(popup) popup->menuretval= UI_RETURN_UPDATE; @@ -1999,15 +1838,11 @@ static int ui_picker_small_wheel(const bContext *C, uiBlock *block, wmEvent *eve uiBlock *ui_block_func_COL(bContext *C, uiPopupBlockHandle *handle, void *arg_but) { - wmWindow *win= CTX_wm_window(C); // XXX temp, needs to become keymap to detect type? uiBut *but= arg_but; uiBlock *block; - static float hsvcol[3], oldcol[3]; - static char hexcol[128]; block= uiBeginBlock(C, handle->region, "colorpicker", UI_EMBOSS); - /* XXX ideally the colour picker buttons would reference the rna property itself */ if (but->rnaprop) { if (RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) { block->color_profile = BLI_PR_NONE; @@ -2017,26 +1852,12 @@ uiBlock *ui_block_func_COL(bContext *C, uiPopupBlockHandle *handle, void *arg_bu uiBlockSetFlag(block, UI_BLOCK_MOVEMOUSE_QUIT); VECCOPY(handle->retvec, but->editvec); - if(win->eventstate->shift) { - uiBlockPickerButtons(block, handle->retvec, hsvcol, oldcol, hexcol, 'p', 0); - block->flag= UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_KEEP_OPEN; - uiBoundsBlock(block, 3); - } - else if(win->eventstate->alt) { - uiBlockPickerSmall(block, handle->retvec, hsvcol, oldcol, hexcol, 'p', 0); - block->flag= UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_RET_1|UI_BLOCK_OUT_1; - uiBoundsBlock(block, 10); - - block->block_event_func= ui_picker_small_wheel; - } - else { - uiBlockPickerNew(block, handle->retvec, hsvcol, oldcol, hexcol, 'p', 0); - block->flag= UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_KEEP_OPEN; - uiBoundsBlock(block, 10); - - block->block_event_func= ui_picker_small_wheel; - } + + uiBlockPicker(block, handle->retvec, &but->rnapoin, but->rnaprop); + block->flag= UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_KEEP_OPEN; + uiBoundsBlock(block, 10); + block->block_event_func= ui_picker_small_wheel; /* and lets go */ block->direction= UI_TOP; @@ -2044,90 +1865,6 @@ uiBlock *ui_block_func_COL(bContext *C, uiPopupBlockHandle *handle, void *arg_bu return block; } -/* ******************** Color band *************** */ - -static int vergcband(const void *a1, const void *a2) -{ - const CBData *x1=a1, *x2=a2; - - if( x1->pos > x2->pos ) return 1; - else if( x1->pos < x2->pos) return -1; - return 0; -} - -static void colorband_pos_cb(bContext *C, void *coba_v, void *unused_v) -{ - ColorBand *coba= coba_v; - int a; - - if(coba->tot<2) return; - - for(a=0; a<coba->tot; a++) coba->data[a].cur= a; - qsort(coba->data, coba->tot, sizeof(CBData), vergcband); - for(a=0; a<coba->tot; a++) { - if(coba->data[a].cur==coba->cur) { - /* if(coba->cur!=a) addqueue(curarea->win, REDRAW, 0); */ /* button cur */ - coba->cur= a; - break; - } - } -} - -static void colorband_add_cb(bContext *C, void *coba_v, void *unused_v) -{ - ColorBand *coba= coba_v; - - if(coba->tot < MAXCOLORBAND-1) coba->tot++; - coba->cur= coba->tot-1; - - colorband_pos_cb(C, coba, NULL); -// BIF_undo_push("Add colorband"); - -} - -static void colorband_del_cb(bContext *C, void *coba_v, void *unused_v) -{ - ColorBand *coba= coba_v; - int a; - - if(coba->tot<2) return; - - for(a=coba->cur; a<coba->tot; a++) { - coba->data[a]= coba->data[a+1]; - } - if(coba->cur) coba->cur--; - coba->tot--; - -// BIF_undo_push("Delete colorband"); -// BIF_preview_changed(ID_TE); -} - -void uiBlockColorbandButtons(uiBlock *block, ColorBand *coba, rctf *butr, int event) -{ - CBData *cbd; - uiBut *bt; - float unit= (butr->xmax-butr->xmin)/14.0f; - float xs= butr->xmin; - - cbd= coba->data + coba->cur; - - uiBlockBeginAlign(block); - uiDefButF(block, COL, event, "", xs,butr->ymin+20.0f,2.0f*unit,20, &(cbd->r), 0, 0, 0, 0, ""); - uiDefButF(block, NUM, event, "A:", xs+2.0f*unit,butr->ymin+20.0f,4.0f*unit,20, &(cbd->a), 0.0f, 1.0f, 10, 2, ""); - bt= uiDefBut(block, BUT, event, "Add", xs+6.0f*unit,butr->ymin+20.0f,2.0f*unit,20, NULL, 0, 0, 0, 0, "Adds a new color position to the colorband"); - uiButSetFunc(bt, colorband_add_cb, coba, NULL); - bt= uiDefBut(block, BUT, event, "Del", xs+8.0f*unit, butr->ymin+20.0f, 2.0f*unit, 20, NULL, 0, 0, 0, 0, "Deletes the active position"); - uiButSetFunc(bt, colorband_del_cb, coba, NULL); - - uiDefButS(block, MENU, event, "Interpolation %t|Ease %x1|Cardinal %x3|Linear %x0|B-Spline %x2|Constant %x4", - xs + 10.0f*unit, butr->ymin+20.0f, unit*4.0f, 20, &coba->ipotype, 0.0, 0.0, 0, 0, "Sets interpolation type"); - - uiDefBut(block, BUT_COLORBAND, event, "", xs, butr->ymin, butr->xmax-butr->xmin, 20.0f, coba, 0, 0, 0, 0, ""); - uiBlockEndAlign(block); - -} - - /************************ Popup Menu Memory ****************************/ static int ui_popup_menu_hash(char *str) diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index a2b926003a7..5852f8f8873 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -33,6 +33,7 @@ #include "BLI_string.h" +#include "BKE_colortools.h" #include "BKE_context.h" #include "BKE_icons.h" #include "BKE_global.h" @@ -122,6 +123,7 @@ typedef struct TemplateID { PropertyRNA *prop; ListBase *idlb; + int prv_rows, prv_cols; } TemplateID; /* Search browse menu, assign */ @@ -150,7 +152,7 @@ static void id_search_cb(const bContext *C, void *arg_template, char *str, uiSea /* ID listbase */ for(id= lb->first; id; id= id->next) { if(BLI_strcasestr(id->name+2, str)) { - iconid= ui_id_icon_get((bContext*)C, id); + iconid= ui_id_icon_get((bContext*)C, id, 0); if(!uiSearchItemAdd(items, id->name+2, id, iconid)) break; @@ -180,11 +182,26 @@ static uiBlock *id_search_menu(bContext *C, ARegion *ar, void *arg_litem) block= uiBeginBlock(C, ar, "_popup", UI_EMBOSS); uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_RET_1); - /* fake button, it holds space for search items */ - uiDefBut(block, LABEL, 0, "", 10, 15, 150, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL); - - but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, 256, 10, 0, 150, 19, ""); - uiButSetSearchFunc(but, id_search_cb, &template, id_search_call_cb, idptr.data); + /* preview thumbnails */ + if (template.prv_rows > 0 && template.prv_cols > 0) { + int w = 96 * template.prv_cols; + int h = 96 * template.prv_rows + 20; + + /* fake button, it holds space for search items */ + uiDefBut(block, LABEL, 0, "", 10, 15, w, h, NULL, 0, 0, 0, 0, NULL); + + but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, 256, 10, 0, w, 19, template.prv_rows, template.prv_cols, ""); + uiButSetSearchFunc(but, id_search_cb, &template, id_search_call_cb, idptr.data); + } + /* list view */ + else { + /* fake button, it holds space for search items */ + uiDefBut(block, LABEL, 0, "", 10, 15, 150, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL); + + but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, 256, 10, 0, 150, 19, 0, 0, ""); + uiButSetSearchFunc(but, id_search_cb, &template, id_search_call_cb, idptr.data); + } + uiBoundsBlock(block, 6); uiBlockSetDirection(block, UI_DOWN); @@ -293,9 +310,10 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event) } } -static void template_ID(bContext *C, uiBlock *block, TemplateID *template, StructRNA *type, int flag, char *newop, char *openop, char *unlinkop) +static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, StructRNA *type, int flag, char *newop, char *openop, char *unlinkop) { uiBut *but; + uiBlock *block; PointerRNA idptr; ListBase *lb; ID *id, *idfrom; @@ -305,11 +323,27 @@ static void template_ID(bContext *C, uiBlock *block, TemplateID *template, Struc idfrom= template->ptr.id.data; lb= template->idlb; + block= uiLayoutGetBlock(layout); uiBlockBeginAlign(block); if(idptr.type) type= idptr.type; + if(flag & UI_ID_PREVIEWS) { + + but= uiDefBlockButN(block, id_search_menu, MEM_dupallocN(template), "", 0, 0, UI_UNIT_X*6, UI_UNIT_Y*6, "Browse ID data"); + if(type) { + but->icon= RNA_struct_ui_icon(type); + if (id) but->icon = ui_id_icon_get(C, id, 1); + uiButSetFlag(but, UI_HAS_ICON|UI_ICON_PREVIEW); + } + if((idfrom && idfrom->lib)) + uiButSetFlag(but, UI_BUT_DISABLED); + + + uiLayoutRow(layout, 1); + } else + if(flag & UI_ID_BROWSE) { but= uiDefBlockButN(block, id_search_menu, MEM_dupallocN(template), "", 0, 0, UI_UNIT_X*1.6, UI_UNIT_Y, "Browse ID data"); if(type) { @@ -412,10 +446,9 @@ static void template_ID(bContext *C, uiBlock *block, TemplateID *template, Struc uiBlockEndAlign(block); } -void uiTemplateID(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname, char *newop, char *openop, char *unlinkop) +static void ui_template_id(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname, char *newop, char *openop, char *unlinkop, int previews, int prv_rows, int prv_cols) { TemplateID *template; - uiBlock *block; PropertyRNA *prop; StructRNA *type; int flag; @@ -430,14 +463,18 @@ void uiTemplateID(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname template= MEM_callocN(sizeof(TemplateID), "TemplateID"); template->ptr= *ptr; template->prop= prop; - + template->prv_rows = prv_rows; + template->prv_cols = prv_cols; + flag= UI_ID_BROWSE|UI_ID_RENAME|UI_ID_DELETE; if(newop) flag |= UI_ID_ADD_NEW; if(openop) flag |= UI_ID_OPEN; - + if(previews) + flag |= UI_ID_PREVIEWS; + type= RNA_property_pointer_type(ptr, prop); template->idlb= wich_libbase(CTX_data_main(C), RNA_type_to_ID_code(type)); @@ -446,11 +483,21 @@ void uiTemplateID(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname */ if(template->idlb) { uiLayoutRow(layout, 1); - block= uiLayoutGetBlock(layout); - template_ID(C, block, template, type, flag, newop, openop, unlinkop); + template_ID(C, layout, template, type, flag, newop, openop, unlinkop); } MEM_freeN(template); + +} + +void uiTemplateID(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname, char *newop, char *openop, char *unlinkop) +{ + ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, 0, 0, 0); +} + +void uiTemplateIDPreview(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname, char *newop, char *openop, char *unlinkop, int rows, int cols) +{ + ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, 1, rows, cols); } /************************ ID Chooser Template ***************************/ @@ -1402,7 +1449,7 @@ static void colorband_buttons_large(uiLayout *layout, uiBlock *block, ColorBand if(coba->tot) { CBData *cbd= coba->data + coba->cur; -#if 1 + /* better to use rna so we can animate them */ PointerRNA ptr; RNA_pointer_create(cb->ptr.id.data, &RNA_ColorRampElement, cbd, &ptr); @@ -1410,15 +1457,6 @@ static void colorband_buttons_large(uiLayout *layout, uiBlock *block, ColorBand //uiItemR(layout, NULL, 0, &ptr, "position", 0); bt= uiDefButF(block, NUM, 0, "Pos:", 0+xoffs,40+yoffs,100, 20, &cbd->pos, 0.0, 1.0, 10, 0, "The position of the active color stop"); uiButSetNFunc(bt, colorband_pos_cb, MEM_dupallocN(cb), coba); - -#else - bt= uiDefButF(block, NUM, 0, "Pos:", 0+xoffs,40+yoffs,100, 20, &cbd->pos, 0.0, 1.0, 10, 0, "The position of the active color stop"); - uiButSetNFunc(bt, colorband_pos_cb, MEM_dupallocN(cb), coba); - bt= uiDefButF(block, COL, 0, "", 110+xoffs,40+yoffs,80,20, &(cbd->r), 0, 0, 0, B_BANDCOL, "The color value for the active color stop"); - uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL); - bt= uiDefButF(block, NUMSLI, 0, "A ", 200+xoffs,40+yoffs,100,20, &cbd->a, 0.0, 1.0, 10, 0, "The alpha value of the active color stop"); - uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL); -#endif } } @@ -1437,16 +1475,9 @@ static void colorband_buttons_small(uiLayout *layout, uiBlock *block, ColorBand if(coba->tot) { CBData *cbd= coba->data + coba->cur; -#if 1 PointerRNA ptr; RNA_pointer_create(cb->ptr.id.data, &RNA_ColorRampElement, cbd, &ptr); uiItemR(layout, "", 0, &ptr, "color", 0); -#else - bt= uiDefButF(block, COL, 0, "", xs+4.0f*unit,butr->ymin+20.0f,2.0f*unit,20, &(cbd->r), 0, 0, 0, B_BANDCOL, "The color value for the active color stop"); - uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL); - bt= uiDefButF(block, NUMSLI, 0, "A:", xs+6.0f*unit,butr->ymin+20.0f,4.0f*unit,20, &(cbd->a), 0.0f, 1.0f, 10, 2, "The alpha value of the active color stop"); - uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL); -#endif } bt= uiDefButS(block, MENU, 0, "Interpolation %t|Ease %x1|Cardinal %x3|Linear %x0|B-Spline %x2|Constant %x4", @@ -1606,8 +1637,8 @@ static void curvemap_tools_dofunc(bContext *C, void *cumap_v, int event) CurveMap *cuma= cumap->cm+cumap->cur; switch(event) { - case 0: - curvemap_reset(cuma, &cumap->clipr); + case 0: /* reset */ + curvemap_reset(cuma, &cumap->clipr, CURVE_PRESET_LINE); curvemapping_changed(cumap, 0); break; case 1: @@ -1629,6 +1660,10 @@ static void curvemap_tools_dofunc(bContext *C, void *cumap_v, int event) cuma->flag |= CUMA_EXTEND_EXTRAPOLATE; curvemapping_changed(cumap, 0); break; + case 6: /* reset smooth */ + curvemap_reset(cuma, &cumap->clipr, CURVE_PRESET_SMOOTH); + curvemapping_changed(cumap, 0); + break; } ED_region_tag_redraw(CTX_wm_region(C)); } @@ -1655,6 +1690,26 @@ static uiBlock *curvemap_tools_func(bContext *C, struct ARegion *ar, void *cumap return block; } +static uiBlock *curvemap_brush_tools_func(bContext *C, struct ARegion *ar, void *cumap_v) +{ + uiBlock *block; + short yco= 0, menuwidth=120; + + block= uiBeginBlock(C, ar, "curvemap_tools_func", UI_EMBOSS); + uiBlockSetButmFunc(block, curvemap_tools_dofunc, cumap_v); + + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Reset View", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Vector Handle", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Auto Handle", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Reset Curve", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 6, ""); + + uiBlockSetDirection(block, UI_RIGHT); + uiTextBoundsBlock(block, 50); + + uiEndBlock(C, block); + return block; +} + static void curvemap_buttons_redraw(bContext *C, void *arg1, void *arg2) { ED_region_tag_redraw(CTX_wm_region(C)); @@ -1666,7 +1721,7 @@ static void curvemap_buttons_reset(bContext *C, void *cb_v, void *cumap_v) int a; for(a=0; a<CM_TOT; a++) - curvemap_reset(cumap->cm+a, &cumap->clipr); + curvemap_reset(cumap->cm+a, &cumap->clipr, CURVE_PRESET_LINE); cumap->black[0]=cumap->black[1]=cumap->black[2]= 0.0f; cumap->white[0]=cumap->white[1]=cumap->white[2]= 1.0f; @@ -1678,7 +1733,7 @@ static void curvemap_buttons_reset(bContext *C, void *cb_v, void *cumap_v) } /* still unsure how this call evolves... we use labeltype for defining what curve-channels to show */ -static void curvemap_buttons_layout(uiLayout *layout, PointerRNA *ptr, char labeltype, int levels, RNAUpdateCb *cb) +static void curvemap_buttons_layout(uiLayout *layout, PointerRNA *ptr, char labeltype, int levels, int brush, RNAUpdateCb *cb) { CurveMapping *cumap= ptr->data; uiLayout *row, *sub, *split; @@ -1746,7 +1801,11 @@ static void curvemap_buttons_layout(uiLayout *layout, PointerRNA *ptr, char labe bt= uiDefIconBut(block, BUT, 0, ICON_ZOOMOUT, 0, 0, dx, 14, NULL, 0.0, 0.0, 0.0, 0.0, "Zoom out"); uiButSetFunc(bt, curvemap_buttons_zoom_out, cumap, NULL); - bt= uiDefIconBlockBut(block, curvemap_tools_func, cumap, 0, ICON_MODIFIER, 0, 0, dx, 18, "Tools"); + if(brush) + bt= uiDefIconBlockBut(block, curvemap_brush_tools_func, cumap, 0, ICON_MODIFIER, 0, 0, dx, 18, "Tools"); + else + bt= uiDefIconBlockBut(block, curvemap_tools_func, cumap, 0, ICON_MODIFIER, 0, 0, dx, 18, "Tools"); + uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL); if(cumap->flag & CUMA_DO_CLIP) icon= ICON_CLIPUV_HLT; else icon= ICON_CLIPUV_DEHLT; @@ -1779,7 +1838,7 @@ static void curvemap_buttons_layout(uiLayout *layout, PointerRNA *ptr, char labe uiBlockSetNFunc(block, NULL, NULL, NULL); } -void uiTemplateCurveMapping(uiLayout *layout, PointerRNA *ptr, char *propname, int type, int levels) +void uiTemplateCurveMapping(uiLayout *layout, PointerRNA *ptr, char *propname, int type, int levels, int brush) { RNAUpdateCb *cb; PropertyRNA *prop= RNA_struct_find_property(ptr, propname); @@ -1796,11 +1855,47 @@ void uiTemplateCurveMapping(uiLayout *layout, PointerRNA *ptr, char *propname, i cb->ptr= *ptr; cb->prop= prop; - curvemap_buttons_layout(layout, &cptr, type, levels, cb); + curvemap_buttons_layout(layout, &cptr, type, levels, brush, cb); MEM_freeN(cb); } +/********************* ColorWheel Template ************************/ + +#define WHEEL_SIZE 100 + +void uiTemplateColorWheel(uiLayout *layout, PointerRNA *ptr, char *propname, int value_slider) +{ + PropertyRNA *prop= RNA_struct_find_property(ptr, propname); + uiBlock *block= uiLayoutGetBlock(layout); + uiLayout *col, *row; + uiBut *but; + + if (!prop) { + printf("uiTemplateColorWheel: property not found: %s\n", propname); + return; + } + + col = uiLayoutColumn(layout, 0); + row= uiLayoutRow(col, 1); + + uiDefButR(block, HSVCIRCLE, 0, "", 0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, propname, -1, 0.0, 0.0, 0, 0, ""); + + uiItemS(row); + + if (value_slider) + uiDefButR(block, HSVCUBE, 0, "", WHEEL_SIZE+6, 0, 14, WHEEL_SIZE, ptr, propname, -1, 0.0, 0.0, 9, 0, ""); + + /* maybe a switch for this? + row= uiLayoutRow(col, 0); + if(ELEM(RNA_property_subtype(prop), PROP_COLOR, PROP_COLOR_GAMMA) && RNA_property_array_length(ptr, prop) == 4) { + but= uiDefAutoButR(block, ptr, prop, 3, "A:", 0, 0, 0, WHEEL_SIZE+20, UI_UNIT_Y); + } + */ + +} + + /********************* TriColor (ThemeWireColorSet) Template ************************/ void uiTemplateTriColorSet(uiLayout *layout, PointerRNA *ptr, char *propname) @@ -1944,7 +2039,7 @@ static int list_item_icon_get(bContext *C, PointerRNA *itemptr, int rnaicon) /* get icon from ID */ if(id) { - icon= ui_id_icon_get(C, id); + icon= ui_id_icon_get(C, id, 1); if(icon) return icon; @@ -1998,6 +2093,11 @@ static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, Pointe uiBlockSetEmboss(block, UI_EMBOSS); uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, ptr, "use_textures", i, 0, 0, 0, 0, NULL); } + else if(RNA_struct_is_a(itemptr->type, &RNA_SceneRenderLayer)) { + uiItemL(sub, name, icon); + uiBlockSetEmboss(block, UI_EMBOSS); + uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "enabled", 0, 0, 0, 0, 0, NULL); + } else if(itemptr->type == &RNA_ShapeKey) { ob= (Object*)activeptr->data; @@ -2245,7 +2345,7 @@ void uiTemplateOperatorSearch(uiLayout *layout) block= uiLayoutGetBlock(layout); uiBlockSetCurLayout(block, layout); - but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 0, 0, UI_UNIT_X*6, UI_UNIT_Y, ""); + but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 0, 0, UI_UNIT_X*6, UI_UNIT_Y, 0, 0, ""); uiButSetSearchFunc(but, operator_search_cb, NULL, operator_call_cb, NULL); } diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 4c9698974b4..82c79c32c6c 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -695,6 +695,27 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol) /* *********************** text/icon ************************************** */ +#define PREVIEW_PAD 4 + +static void widget_draw_preview(BIFIconID icon, float aspect, float alpha, rcti *rect) +{ + int w, h, x, y, size; + + /* only display previews for actual preview images .. ? */ + if (icon < BIFICONID_LAST) + return; + + w = rect->xmax - rect->xmin; + h = rect->ymax - rect->ymin; + size = MIN2(w, h); + size -= PREVIEW_PAD*2; /* padding */ + + x = rect->xmin + w/2 - size/2; + y = rect->ymin + h/2 - size/2; + + UI_icon_draw_preview_aspect_size(x, y, icon, aspect, size); +} + /* icons have been standardized... and this call draws in untransformed coordinates */ #define ICON_HEIGHT 16.0f @@ -704,6 +725,11 @@ static void widget_draw_icon(uiBut *but, BIFIconID icon, float alpha, rcti *rect int xs=0, ys=0; float aspect, height; + if (but->flag & UI_ICON_PREVIEW) { + widget_draw_preview(icon, but->block->aspect, alpha, rect); + return; + } + /* this icon doesn't need draw... */ if(icon==ICON_BLANK1 && (but->flag & UI_ICON_SUBMENU)==0) return; @@ -1512,12 +1538,12 @@ void ui_hsvcircle_vals_from_pos(float *valrad, float *valdist, rcti *rect, float *valrad= atan2(mx, my)/(2.0f*M_PI) + 0.5f; } -void ui_draw_but_HSVCIRCLE(uiBut *but, rcti *rect) +void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, rcti *rect) { /* gouraud triangle fan */ float radstep, ang= 0.0f; float centx, centy, radius; - float hsv[3], col[3], colcent[3]; + float rgb[3], hsv[3], hsvo[3], col[3], colcent[3]; int a, tot= 32; radstep= 2.0f*M_PI/(float)tot; @@ -1530,9 +1556,11 @@ void ui_draw_but_HSVCIRCLE(uiBut *but, rcti *rect) radius= (float)(rect->xmax - rect->xmin)/2; /* color */ - VECCOPY(hsv, but->hsv); - hsv[0]= hsv[1]= 0.0f; - hsv_to_rgb(hsv[0], hsv[1], hsv[2], colcent, colcent+1, colcent+2); + ui_get_but_vectorf(but, rgb); + rgb_to_hsv(rgb[0], rgb[1], rgb[2], hsv, hsv+1, hsv+2); + copy_v3_v3(hsvo, hsv); + + hsv_to_rgb(0.f, 0.f, hsv[2], colcent, colcent+1, colcent+2); glShadeModel(GL_SMOOTH); @@ -1558,15 +1586,15 @@ void ui_draw_but_HSVCIRCLE(uiBut *but, rcti *rect) glTranslatef(centx, centy, 0.0f); glEnable(GL_BLEND); glEnable(GL_LINE_SMOOTH ); - glColor3f(0.0f, 0.0f, 0.0f); + glColor3ubv((unsigned char*)wcol->outline); glutil_draw_lined_arc(0.0f, M_PI*2.0, radius, tot); glDisable(GL_BLEND); glDisable(GL_LINE_SMOOTH ); glPopMatrix(); /* cursor */ - ang= 2.0f*M_PI*but->hsv[0] + 0.5f*M_PI; - radius= but->hsv[1]*radius; + ang= 2.0f*M_PI*hsvo[0] + 0.5f*M_PI; + radius= hsvo[1]*radius; ui_hsv_cursor(centx + cos(-ang)*radius, centy + sin(-ang)*radius); } @@ -1577,46 +1605,63 @@ void ui_draw_but_HSVCIRCLE(uiBut *but, rcti *rect) static void ui_draw_but_HSVCUBE(uiBut *but, rcti *rect) { int a; - float h,s,v; + float rgb[3], h,s,v; float dx, dy, sx1, sx2, sy, x=0.0f, y=0.0f; float col0[4][3]; // left half, rect bottom to top float col1[4][3]; // right half, rect bottom to top - h= but->hsv[0]; - s= but->hsv[1]; - v= but->hsv[2]; + ui_get_but_vectorf(but, rgb); + rgb_to_hsv(rgb[0], rgb[1], rgb[2], &h, &s, &v); /* draw series of gouraud rects */ glShadeModel(GL_SMOOTH); - if(but->a1==0) { // H and V vary + + if(but->a1==0) { // S and V vary + hsv_to_rgb(h, 0.0, 0.0, &col1[0][0], &col1[0][1], &col1[0][2]); + hsv_to_rgb(h, 0.333, 0.0, &col1[1][0], &col1[1][1], &col1[1][2]); + hsv_to_rgb(h, 0.666, 0.0, &col1[2][0], &col1[2][1], &col1[2][2]); + hsv_to_rgb(h, 1.0, 0.0, &col1[3][0], &col1[3][1], &col1[3][2]); + x= v; y= s; + } + else if(but->a1==1) { // H and V vary hsv_to_rgb(0.0, s, 0.0, &col1[0][0], &col1[0][1], &col1[0][2]); hsv_to_rgb(0.0, s, 0.333, &col1[1][0], &col1[1][1], &col1[1][2]); hsv_to_rgb(0.0, s, 0.666, &col1[2][0], &col1[2][1], &col1[2][2]); hsv_to_rgb(0.0, s, 1.0, &col1[3][0], &col1[3][1], &col1[3][2]); x= h; y= v; } - else if(but->a1==1) { // H and S vary + else if(but->a1==2) { // H and S vary hsv_to_rgb(0.0, 0.0, v, &col1[0][0], &col1[0][1], &col1[0][2]); hsv_to_rgb(0.0, 0.333, v, &col1[1][0], &col1[1][1], &col1[1][2]); hsv_to_rgb(0.0, 0.666, v, &col1[2][0], &col1[2][1], &col1[2][2]); hsv_to_rgb(0.0, 1.0, v, &col1[3][0], &col1[3][1], &col1[3][2]); x= h; y= s; } - else if(but->a1==2) { // S and V vary - hsv_to_rgb(h, 0.0, 0.0, &col1[0][0], &col1[0][1], &col1[0][2]); - hsv_to_rgb(h, 0.333, 0.0, &col1[1][0], &col1[1][1], &col1[1][2]); - hsv_to_rgb(h, 0.666, 0.0, &col1[2][0], &col1[2][1], &col1[2][2]); - hsv_to_rgb(h, 1.0, 0.0, &col1[3][0], &col1[3][1], &col1[3][2]); - x= v; y= s; - } - else if(but->a1==3) { // only hue slider + else if(but->a1==3) { // only H hsv_to_rgb(0.0, 1.0, 1.0, &col1[0][0], &col1[0][1], &col1[0][2]); VECCOPY(col1[1], col1[0]); VECCOPY(col1[2], col1[0]); VECCOPY(col1[3], col1[0]); x= h; y= 0.5; } + else if(but->a1==4) { // only S + hsv_to_rgb(1.0, 0.0, 1.0, &col1[1][0], &col1[1][1], &col1[1][2]); + VECCOPY(col1[0], col1[1]); + VECCOPY(col1[2], col1[1]); + VECCOPY(col1[3], col1[1]); + x= s; y= 0.5; + } + else if(but->a1==5) { // only V + hsv_to_rgb(1.0, 1.0, 0.0, &col1[2][0], &col1[2][1], &col1[2][2]); + VECCOPY(col1[0], col1[2]); + VECCOPY(col1[1], col1[2]); + VECCOPY(col1[3], col1[2]); + x= v; y= 0.5; + } + + + /* old below */ for(dx=0.0; dx<1.0; dx+= 0.05) { // previous color @@ -1626,30 +1671,42 @@ static void ui_draw_but_HSVCUBE(uiBut *but, rcti *rect) VECCOPY(col0[3], col1[3]); // new color - if(but->a1==0) { // H and V vary + if(but->a1==0) { // S and V vary + hsv_to_rgb(h, 0.0, dx, &col1[0][0], &col1[0][1], &col1[0][2]); + hsv_to_rgb(h, 0.333, dx, &col1[1][0], &col1[1][1], &col1[1][2]); + hsv_to_rgb(h, 0.666, dx, &col1[2][0], &col1[2][1], &col1[2][2]); + hsv_to_rgb(h, 1.0, dx, &col1[3][0], &col1[3][1], &col1[3][2]); + } + else if(but->a1==1) { // H and V vary hsv_to_rgb(dx, s, 0.0, &col1[0][0], &col1[0][1], &col1[0][2]); hsv_to_rgb(dx, s, 0.333, &col1[1][0], &col1[1][1], &col1[1][2]); hsv_to_rgb(dx, s, 0.666, &col1[2][0], &col1[2][1], &col1[2][2]); hsv_to_rgb(dx, s, 1.0, &col1[3][0], &col1[3][1], &col1[3][2]); } - else if(but->a1==1) { // H and S vary + else if(but->a1==2) { // H and S vary hsv_to_rgb(dx, 0.0, v, &col1[0][0], &col1[0][1], &col1[0][2]); hsv_to_rgb(dx, 0.333, v, &col1[1][0], &col1[1][1], &col1[1][2]); hsv_to_rgb(dx, 0.666, v, &col1[2][0], &col1[2][1], &col1[2][2]); hsv_to_rgb(dx, 1.0, v, &col1[3][0], &col1[3][1], &col1[3][2]); } - else if(but->a1==2) { // S and V vary - hsv_to_rgb(h, 0.0, dx, &col1[0][0], &col1[0][1], &col1[0][2]); - hsv_to_rgb(h, 0.333, dx, &col1[1][0], &col1[1][1], &col1[1][2]); - hsv_to_rgb(h, 0.666, dx, &col1[2][0], &col1[2][1], &col1[2][2]); - hsv_to_rgb(h, 1.0, dx, &col1[3][0], &col1[3][1], &col1[3][2]); - } else if(but->a1==3) { // only H hsv_to_rgb(dx, 1.0, 1.0, &col1[0][0], &col1[0][1], &col1[0][2]); VECCOPY(col1[1], col1[0]); VECCOPY(col1[2], col1[0]); VECCOPY(col1[3], col1[0]); } + else if(but->a1==4) { // only S + hsv_to_rgb(h, dx, 1.0, &col1[1][0], &col1[1][1], &col1[1][2]); + VECCOPY(col1[0], col1[1]); + VECCOPY(col1[2], col1[1]); + VECCOPY(col1[3], col1[1]); + } + else if(but->a1==5) { // only V + hsv_to_rgb(h, 1.0, dx, &col1[2][0], &col1[2][1], &col1[2][2]); + VECCOPY(col1[0], col1[2]); + VECCOPY(col1[1], col1[2]); + VECCOPY(col1[3], col1[2]); + } // rect sx1= rect->xmin + dx*(rect->xmax-rect->xmin); @@ -1695,7 +1752,7 @@ static void ui_draw_but_HSV_v(uiBut *but, rcti *rect) uiWidgetBase wtb; float rad= 0.5f*(rect->xmax - rect->xmin); float x, y; - float v = but->hsv[2]; + float rgb[3], hsv[3], v; int color_profile = but->block->color_profile; if (but->rnaprop) { @@ -1704,6 +1761,10 @@ static void ui_draw_but_HSV_v(uiBut *but, rcti *rect) } } + ui_get_but_vectorf(but, rgb); + rgb_to_hsv(rgb[0], rgb[1], rgb[2], hsv, hsv+1, hsv+2); + v = hsv[2]; + if (color_profile) v = linearrgb_to_srgb(v); @@ -2558,14 +2619,14 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct break; case HSVCUBE: - if(but->a1==4) // vertical V slider, uses new widget draw now + if(but->a1==9) // vertical V slider, uses new widget draw now ui_draw_but_HSV_v(but, rect); else // other HSV pickers... ui_draw_but_HSVCUBE(but, rect); break; case HSVCIRCLE: - ui_draw_but_HSVCIRCLE(but, rect); + ui_draw_but_HSVCIRCLE(but, &tui->wcol_regular, rect); break; case BUT_COLORBAND: @@ -2692,3 +2753,25 @@ void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, char *name, int iconid, } } +void ui_draw_preview_item(uiFontStyle *fstyle, rcti *rect, char *name, int iconid, int state) +{ + rcti trect = *rect; + + uiWidgetType *wt= widget_type(UI_WTYPE_MENU_ITEM); + + wt->state(wt, state); + wt->draw(&wt->wcol, rect, 0, 0); + + widget_draw_preview(iconid, 1.f, 1.f, rect); + + if (state == UI_ACTIVE) + glColor3ubv((unsigned char*)wt->wcol.text); + else + glColor3ubv((unsigned char*)wt->wcol.text_sel); + + trect.xmin += 0; + trect.xmax = trect.xmin + BLF_width(name) + 10; + trect.ymin += 10; + trect.ymax = trect.ymin + BLF_height(name); + uiStyleFontDraw(fstyle, &trect, name); +} diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index 47bbbd9292c..15513daa624 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -782,6 +782,26 @@ void UI_GetThemeColor3fv(int colorid, float *col) col[2]= ((float)cp[2])/255.0; } +// get the color, range 0.0-1.0, complete with shading offset +void UI_GetThemeColorShade3fv(int colorid, int offset, float *col) +{ + int r, g, b; + char *cp; + + cp= UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid); + + r= offset + (int) cp[0]; + CLAMP(r, 0, 255); + g= offset + (int) cp[1]; + CLAMP(g, 0, 255); + b= offset + (int) cp[2]; + CLAMP(b, 0, 255); + + col[0]= ((float)r)/255.0; + col[1]= ((float)g)/255.0; + col[2]= ((float)b)/255.0; +} + // get the color, in char pointer void UI_GetThemeColor3ubv(int colorid, char *col) { diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c index 7d1dc00e271..57882b7dd0d 100644 --- a/source/blender/editors/interface/view2d_ops.c +++ b/source/blender/editors/interface/view2d_ops.c @@ -236,6 +236,18 @@ static int view_pan_modal(bContext *C, wmOperator *op, wmEvent *event) break; case LEFTMOUSE: + /* switch to zoom */ + if (event->val==KM_PRESS) { + /* calculate overall delta mouse-movement for redo */ + RNA_int_set(op->ptr, "deltax", (vpd->startx - vpd->lastx)); + RNA_int_set(op->ptr, "deltay", (vpd->starty - vpd->lasty)); + + view_pan_exit(C, op); + WM_cursor_restore(CTX_wm_window(C)); + + WM_operator_name_call(C, "VIEW2D_OT_zoom", WM_OP_INVOKE_DEFAULT, NULL); + return OPERATOR_FINISHED; + } case MIDDLEMOUSE: case ESCKEY: if (event->val==KM_RELEASE) { diff --git a/source/blender/editors/mesh/editmesh_add.c b/source/blender/editors/mesh/editmesh_add.c index d7f421331e5..572cf214c6a 100644 --- a/source/blender/editors/mesh/editmesh_add.c +++ b/source/blender/editors/mesh/editmesh_add.c @@ -1265,7 +1265,7 @@ static void make_prim(Object *obedit, int type, float mat[4][4], int tot, int se EM_select_flush(em); /* flushes vertex -> edge -> face selection */ if(type!=PRIM_PLANE && type!=PRIM_MONKEY) - righthandfaces(em, 1); /* otherwise monkey has eyes in wrong direction */ + EM_recalc_normal_direction(em, 0, 0); /* otherwise monkey has eyes in wrong direction */ BKE_mesh_end_editmesh(obedit->data, em); } diff --git a/source/blender/editors/mesh/editmesh_mods.c b/source/blender/editors/mesh/editmesh_mods.c index 827b28f954b..dee831b7fd0 100644 --- a/source/blender/editors/mesh/editmesh_mods.c +++ b/source/blender/editors/mesh/editmesh_mods.c @@ -3800,8 +3800,7 @@ void MESH_OT_mark_sharp(wmOperatorType *ot) /* **************** NORMALS ************** */ -/* XXX value of select is messed up, it means two things */ -void righthandfaces(EditMesh *em, int select) /* makes faces righthand turning */ +void EM_recalc_normal_direction(EditMesh *em, int inside, int select) /* makes faces righthand turning */ { EditEdge *eed, *ed1, *ed2, *ed3, *ed4; EditFace *efa, *startvl; @@ -3893,16 +3892,12 @@ void righthandfaces(EditMesh *em, int select) /* makes faces righthand turning * cent_tri_v3(cent, startvl->v1->co, startvl->v2->co, startvl->v3->co); } /* first normal is oriented this way or the other */ - if(select) { - if(select==2) { - if(cent[0]*nor[0]+cent[1]*nor[1]+cent[2]*nor[2] > 0.0) flipface(em, startvl); - } - else { - if(cent[0]*nor[0]+cent[1]*nor[1]+cent[2]*nor[2] < 0.0) flipface(em, startvl); - } + if(inside) { + if(cent[0]*nor[0]+cent[1]*nor[1]+cent[2]*nor[2] > 0.0) flipface(em, startvl); + } + else { + if(cent[0]*nor[0]+cent[1]*nor[1]+cent[2]*nor[2] < 0.0) flipface(em, startvl); } - else if(cent[0]*nor[0]+cent[1]*nor[1]+cent[2]*nor[2] < 0.0) flipface(em, startvl); - eed= startvl->e1; if(eed->v1==startvl->v1) eed->f2= 1; @@ -4012,7 +4007,7 @@ void righthandfaces(EditMesh *em, int select) /* makes faces righthand turning * } -static int righthandfaces_exec(bContext *C, wmOperator *op) +static int normals_make_consistent_exec(bContext *C, wmOperator *op) { Object *obedit= CTX_data_edit_object(C); EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data)); @@ -4020,7 +4015,7 @@ static int righthandfaces_exec(bContext *C, wmOperator *op) /* 'standard' behaviour - check if selected, then apply relevant selection */ // XXX need other args - righthandfaces(em, RNA_boolean_get(op->ptr, "inside")); + EM_recalc_normal_direction(em, RNA_boolean_get(op->ptr, "inside"), 1); BKE_mesh_end_editmesh(obedit->data, em); @@ -4038,7 +4033,7 @@ void MESH_OT_normals_make_consistent(wmOperatorType *ot) ot->idname= "MESH_OT_normals_make_consistent"; /* api callbacks */ - ot->exec= righthandfaces_exec; + ot->exec= normals_make_consistent_exec; ot->poll= ED_operator_editmesh; /* flags */ diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h index 31e8cb16abc..94bdbdc73aa 100644 --- a/source/blender/editors/mesh/mesh_intern.h +++ b/source/blender/editors/mesh/mesh_intern.h @@ -172,7 +172,7 @@ void MESH_OT_select_nth(struct wmOperatorType *ot); extern EditEdge *findnearestedge(ViewContext *vc, int *dist); extern void EM_automerge(Scene *scene, Object *obedit, int update); void editmesh_select_by_material(EditMesh *em, int index); -void righthandfaces(EditMesh *em, int select); /* makes faces righthand turning */ +void EM_recalc_normal_direction(EditMesh *em, int inside, int select); /* makes faces righthand turning */ void EM_select_more(EditMesh *em); void selectconnected_mesh_all(EditMesh *em); void faceloop_select(EditMesh *em, EditEdge *startedge, int select); diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c index c41ac9f6550..8537d39fbd8 100644 --- a/source/blender/editors/mesh/mesh_ops.c +++ b/source/blender/editors/mesh/mesh_ops.c @@ -195,7 +195,7 @@ void ED_operatormacros_mesh(void) RNA_enum_set(otmacro->ptr, "constraint_orientation", V3D_MANIP_NORMAL); RNA_boolean_set_array(otmacro->ptr, "constraint_axis", constraint_axis); - ot= WM_operatortype_append_macro("MESH_OT_extrude_move", "Extrude", OPTYPE_UNDO|OPTYPE_REGISTER); + ot= WM_operatortype_append_macro("MESH_OT_extrude_move", "Extrude and Move", OPTYPE_UNDO|OPTYPE_REGISTER); WM_operatortype_macro_define(ot, "MESH_OT_extrude"); otmacro= WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate"); RNA_enum_set(otmacro->ptr, "proportional", 0); diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c index 1feaa2dc83a..269fc278581 100644 --- a/source/blender/editors/mesh/meshtools.c +++ b/source/blender/editors/mesh/meshtools.c @@ -76,16 +76,6 @@ #include "BKE_utildefines.h" #include "BKE_report.h" -#include "RE_pipeline.h" -#include "RE_shader_ext.h" - -#include "PIL_time.h" - -#include "IMB_imbuf_types.h" -#include "IMB_imbuf.h" - -#include "GPU_draw.h" - #include "BLO_sys_types.h" // for intptr_t support #include "ED_mesh.h" @@ -99,8 +89,6 @@ #include "mesh_intern.h" /* XXX */ -static void waitcursor(int val) {} -static void error() {} static int pupmenu() {return 0;} /* XXX */ @@ -772,7 +760,7 @@ void sort_faces(Scene *scene, View3D *v3d) #define MOC_RES 8 #define MOC_NODE_RES 8 -#define MOC_THRESH 0.0002f +#define MOC_THRESH 0.00002f typedef struct MocNode { struct MocNode *next; @@ -1132,191 +1120,3 @@ int *mesh_get_x_mirror_faces(Object *ob, EditMesh *em) return mirrorfaces; } - -/* ****************** render BAKING ********************** */ - -/* threaded break test */ -static int thread_break(void *unused) -{ - return G.afbreek; -} - -static ScrArea *biggest_image_area(bScreen *screen) -{ - ScrArea *sa, *big= NULL; - int size, maxsize= 0; - - for(sa= screen->areabase.first; sa; sa= sa->next) { - if(sa->spacetype==SPACE_IMAGE) { - size= sa->winx*sa->winy; - if(sa->winx > 10 && sa->winy > 10 && size > maxsize) { - maxsize= size; - big= sa; - } - } - } - return big; -} - - -typedef struct BakeRender { - Render *re; - struct Object *actob; - int event, tot, ready; -} BakeRender; - -static void *do_bake_render(void *bake_v) -{ - BakeRender *bkr= bake_v; - - bkr->tot= RE_bake_shade_all_selected(bkr->re, bkr->event, bkr->actob); - bkr->ready= 1; - - return NULL; -} - - -void objects_bake_render(Scene *scene, short event, char **error_msg) -{ - Object *actob= OBACT; - int active= scene->r.bake_flag & R_BAKE_TO_ACTIVE; - short prev_r_raytrace= 0, prev_wo_amb_occ= 0; - - if(event==0) event= scene->r.bake_mode; - - if(scene->r.renderer!=R_INTERN) { - *error_msg = "Bake only supported for Internal Renderer"; - return; - } - - if(active && !actob) { - *error_msg = "No active object"; - return; - } - - if(event>0) { - bScreen *screen= NULL; // XXX CTX - Render *re= RE_NewRender("_Bake View_"); - ScrArea *area= NULL; //biggest_image_area(screen); // XXX - ListBase threads; - BakeRender bkr; - int timer=0, tot; // XXX, sculptmode= G.f & G_SCULPTMODE; - -// XXX if(sculptmode) set_sculptmode(); - - if(event==1) event= RE_BAKE_ALL; - else if(event==2) event= RE_BAKE_AO; - else if(event==3) event= RE_BAKE_NORMALS; - else if(event==4) event= RE_BAKE_TEXTURE; - else if(event==5) event= RE_BAKE_DISPLACEMENT; - else event= RE_BAKE_SHADOW; - - if(event==RE_BAKE_AO) { - if(scene->world==NULL) { - *error_msg = "No world set up"; - return; - } - - /* If raytracing or AO is disabled, switch it on temporarily for baking. */ - prev_wo_amb_occ = (scene->world->mode & WO_AMB_OCC) != 0; - scene->world->mode |= WO_AMB_OCC; - } - if(event==RE_BAKE_AO || active) { - prev_r_raytrace = (scene->r.mode & R_RAYTRACE) != 0; - scene->r.mode |= R_RAYTRACE; - } - - waitcursor(1); - RE_test_break_cb(re, NULL, thread_break); - G.afbreek= 0; /* blender_test_break uses this global */ - - RE_Database_Baking(re, scene, event, (active)? actob: NULL); - - /* baking itself is threaded, cannot use test_break in threads. we also update optional imagewindow */ - - BLI_init_threads(&threads, do_bake_render, 1); - bkr.re= re; - bkr.event= event; - bkr.ready= 0; - bkr.actob= (active)? actob: NULL; - BLI_insert_thread(&threads, &bkr); - - while(bkr.ready==0) { - PIL_sleep_ms(50); - if(bkr.ready) - break; - - if (!G.background) { - blender_test_break(); - - timer++; - if(area && timer==20) { - Image *ima= RE_bake_shade_get_image(); - if(ima) ((SpaceImage *)area->spacedata.first)->image= ima; -// XX scrarea_do_windraw(area); -// myswapbuffers(); - timer= 0; - } - } - } - BLI_end_threads(&threads); - tot= bkr.tot; - - RE_Database_Free(re); - waitcursor(0); - - if(tot==0) *error_msg = "No Images found to bake to"; - else { - Image *ima; - /* force OpenGL reload and mipmap recalc */ - for(ima= G.main->image.first; ima; ima= ima->id.next) { - if(ima->ok==IMA_OK_LOADED) { - ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); - if(ibuf && (ibuf->userflags & IB_BITMAPDIRTY)) { - GPU_free_image(ima); - imb_freemipmapImBuf(ibuf); - } - } - } - } - - /* restore raytrace and AO */ - if(event==RE_BAKE_AO) - if(prev_wo_amb_occ == 0) - scene->world->mode &= ~WO_AMB_OCC; - - if(event==RE_BAKE_AO || active) - if(prev_r_raytrace == 0) - scene->r.mode &= ~R_RAYTRACE; - -// XXX if(sculptmode) set_sculptmode(); - - } -} - -/* all selected meshes with UV maps are rendered for current scene visibility */ -static void objects_bake_render_ui(Scene *scene, short event) -{ - char *error_msg = NULL; -// int is_editmode = (obedit!=NULL); - - /* Deal with editmode, this is a bit clunky but since UV's are in editmode, users are likely to bake from their */ -// XXX if (is_editmode) exit_editmode(0); - - objects_bake_render(scene, event, &error_msg); - -// XXX if (is_editmode) enter_editmode(0); - - if (error_msg) - error(error_msg); -} - -void objects_bake_render_menu(Scene *scene) -{ - short event; - - event= pupmenu("Bake Selected Meshes %t|Full Render %x1|Ambient Occlusion %x2|Normals %x3|Texture Only %x4|Displacement %x5|Shadow %x6"); - if (event < 1) return; - objects_bake_render_ui(scene, event); -} - diff --git a/source/blender/editors/object/Makefile b/source/blender/editors/object/Makefile index fd2af305d87..7c081355ed5 100644 --- a/source/blender/editors/object/Makefile +++ b/source/blender/editors/object/Makefile @@ -48,6 +48,8 @@ CPPFLAGS += -I../../makesrna CPPFLAGS += -I../../python CPPFLAGS += -I../../imbuf CPPFLAGS += -I../../ikplugin +CPPFLAGS += -I../../gpu +CPPFLAGS += -I../../render/extern/include # own include diff --git a/source/blender/editors/object/SConscript b/source/blender/editors/object/SConscript index 06d68cd1021..0a94de255cb 100644 --- a/source/blender/editors/object/SConscript +++ b/source/blender/editors/object/SConscript @@ -6,9 +6,17 @@ sources = env.Glob('*.c') incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf' incs += ' ../../windowmanager #/intern/guardedalloc' incs += ' ../../makesrna ../../python ../../ikplugin' +incs += ' ../../render/extern/include ../../gpu' # for object_bake.c defs = [] +if env['OURPLATFORM'] == 'linux2': + cflags='-pthread' + incs += ' ../../../extern/binreloc/include' + +if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc'): + incs += ' ' + env['BF_PTHREADS_INC'] + if not env['WITH_BF_PYTHON']: defs.append('DISABLE_PYTHON') diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c new file mode 100644 index 00000000000..4b02cd8e623 --- /dev/null +++ b/source/blender/editors/object/object_bake.c @@ -0,0 +1,341 @@ +/** + * $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) 2004 by Blender Foundation + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/* + meshtools.c: no editmode (violated already :), tools operating on meshes +*/ + +#include <string.h> + +#include "MEM_guardedalloc.h" + +#include "DNA_image_types.h" +#include "DNA_scene_types.h" +#include "DNA_screen_types.h" +#include "DNA_space_types.h" +#include "DNA_world_types.h" + +#include "BLI_blenlib.h" +#include "BLI_threads.h" + +#include "BKE_blender.h" +#include "BKE_context.h" +#include "BKE_global.h" +#include "BKE_image.h" +#include "BKE_main.h" +#include "BKE_object.h" +#include "BKE_utildefines.h" +#include "BKE_report.h" + +#include "RE_pipeline.h" +#include "RE_shader_ext.h" + +#include "PIL_time.h" + +#include "IMB_imbuf_types.h" +#include "IMB_imbuf.h" + +#include "GPU_draw.h" /* GPU_free_image */ + +#include "WM_api.h" +#include "WM_types.h" + + +/* ****************** render BAKING ********************** */ + +/* threaded break test */ +static int thread_break(void *unused) +{ + return G.afbreek; +} + +static ScrArea *biggest_image_area(bScreen *screen) +{ + ScrArea *sa, *big= NULL; + int size, maxsize= 0; + + for(sa= screen->areabase.first; sa; sa= sa->next) { + if(sa->spacetype==SPACE_IMAGE) { + size= sa->winx*sa->winy; + if(sa->winx > 10 && sa->winy > 10 && size > maxsize) { + maxsize= size; + big= sa; + } + } + } + return big; +} + + +typedef struct BakeRender { + Render *re; + Scene *scene; + struct Object *actob; + int tot, ready; + + ReportList *reports; + + short *stop; + short *do_update; + + ListBase threads; + + /* backup */ + short prev_wo_amb_occ; + short prev_r_raytrace; + + /* for redrawing */ + ScrArea *sa; +} BakeRender; + +/* use by exec and invoke */ +int test_bake_internal(bContext *C, ReportList *reports) +{ + Scene *scene= CTX_data_scene(C); + + if(scene->r.renderer!=R_INTERN) { + BKE_report(reports, RPT_ERROR, "Bake only supported for Internal Renderer"); + } else if((scene->r.bake_flag & R_BAKE_TO_ACTIVE) && CTX_data_active_object(C)==NULL) { + BKE_report(reports, RPT_ERROR, "No active object"); + } + else if(scene->r.bake_mode==RE_BAKE_AO && scene->world==NULL) { + BKE_report(reports, RPT_ERROR, "No world set up"); + } + else { + return 1; + } + + return 0; +} + +static void init_bake_internal(BakeRender *bkr, bContext *C) +{ + Scene *scene= CTX_data_scene(C); + + bkr->sa= biggest_image_area(CTX_wm_screen(C)); /* can be NULL */ + bkr->scene= scene; + bkr->actob= (scene->r.bake_flag & R_BAKE_TO_ACTIVE) ? OBACT : NULL; + bkr->re= RE_NewRender("_Bake View_"); + + if(scene->r.bake_mode==RE_BAKE_AO) { + /* If raytracing or AO is disabled, switch it on temporarily for baking. */ + bkr->prev_wo_amb_occ = (scene->world->mode & WO_AMB_OCC) != 0; + scene->world->mode |= WO_AMB_OCC; + } + if(scene->r.bake_mode==RE_BAKE_AO || bkr->actob) { + bkr->prev_r_raytrace = (scene->r.mode & R_RAYTRACE) != 0; + scene->r.mode |= R_RAYTRACE; + } +} + +static void finish_bake_internal(BakeRender *bkr) +{ + RE_Database_Free(bkr->re); + + /* restore raytrace and AO */ + if(bkr->scene->r.bake_mode==RE_BAKE_AO) + if(bkr->prev_wo_amb_occ == 0) + bkr->scene->world->mode &= ~WO_AMB_OCC; + + if(bkr->scene->r.bake_mode==RE_BAKE_AO || bkr->actob) + if(bkr->prev_r_raytrace == 0) + bkr->scene->r.mode &= ~R_RAYTRACE; + + if(bkr->tot) { + Image *ima; + /* force OpenGL reload and mipmap recalc */ + for(ima= G.main->image.first; ima; ima= ima->id.next) { + if(ima->ok==IMA_OK_LOADED) { + ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); + if(ibuf && (ibuf->userflags & IB_BITMAPDIRTY)) { + GPU_free_image(ima); + imb_freemipmapImBuf(ibuf); + } + } + } + } +} + +static void *do_bake_render(void *bake_v) +{ + BakeRender *bkr= bake_v; + + bkr->tot= RE_bake_shade_all_selected(bkr->re, bkr->scene->r.bake_mode, bkr->actob, NULL); + bkr->ready= 1; + + return NULL; +} + +static void bake_startjob(void *bkv, short *stop, short *do_update) +{ + BakeRender *bkr= bkv; + Scene *scene= bkr->scene; + + bkr->stop= stop; + bkr->do_update= do_update; + + RE_test_break_cb(bkr->re, NULL, thread_break); + G.afbreek= 0; /* blender_test_break uses this global */ + + RE_Database_Baking(bkr->re, scene, scene->r.bake_mode, bkr->actob); + + /* baking itself is threaded, cannot use test_break in threads. we also update optional imagewindow */ + bkr->tot= RE_bake_shade_all_selected(bkr->re, scene->r.bake_mode, bkr->actob, bkr->do_update); +} + +static void bake_update(void *bkv) +{ + BakeRender *bkr= bkv; + + if(bkr->sa && bkr->sa->spacetype==SPACE_IMAGE) { /* incase the user changed while baking */ + SpaceImage *sima= bkr->sa->spacedata.first; + sima->image= RE_bake_shade_get_image(); + } +} + +static void bake_freejob(void *bkv) +{ + BakeRender *bkr= bkv; + BLI_end_threads(&bkr->threads); + finish_bake_internal(bkr); + + if(bkr->tot==0) BKE_report(bkr->reports, RPT_ERROR, "No Images found to bake to"); + MEM_freeN(bkr); +} + +/* catch esc */ +static int objects_bake_render_modal(bContext *C, wmOperator *op, wmEvent *event) +{ + /* no running blender, remove handler and pass through */ + if(0==WM_jobs_test(CTX_wm_manager(C), CTX_data_scene(C))) + return OPERATOR_FINISHED|OPERATOR_PASS_THROUGH; + + /* running render */ + switch (event->type) { + case ESCKEY: + return OPERATOR_RUNNING_MODAL; + break; + } + return OPERATOR_PASS_THROUGH; +} + +static int objects_bake_render_invoke(bContext *C, wmOperator *op, wmEvent *_event) +{ + Scene *scene= CTX_data_scene(C); + + if(test_bake_internal(C, op->reports)==0) { + return OPERATOR_CANCELLED; + } + else { + BakeRender *bkr= MEM_callocN(sizeof(BakeRender), "render bake"); + wmJob *steve; + + init_bake_internal(bkr, C); + bkr->reports= op->reports; + + /* setup job */ + steve= WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, WM_JOB_EXCL_RENDER|WM_JOB_PRIORITY); + WM_jobs_customdata(steve, bkr, bake_freejob); + WM_jobs_timer(steve, 0.2, NC_IMAGE, 0); /* TODO - only draw bake image, can we enforce this */ + WM_jobs_callbacks(steve, bake_startjob, NULL, bake_update); + + G.afbreek= 0; + + WM_jobs_start(CTX_wm_manager(C), steve); + + WM_cursor_wait(0); + WM_event_add_notifier(C, NC_SCENE|ND_RENDER_RESULT, scene); + + /* add modal handler for ESC */ + WM_event_add_modal_handler(C, op); + } + + return OPERATOR_RUNNING_MODAL; +} + + +static int bake_image_exec(bContext *C, wmOperator *op) +{ + Scene *scene= CTX_data_scene(C); + + + if(test_bake_internal(C, op->reports)==0) { + return OPERATOR_CANCELLED; + } + else { + ListBase threads; + BakeRender bkr; + + memset(&bkr, 0, sizeof(bkr)); + + init_bake_internal(&bkr, C); + bkr.reports= op->reports; + + RE_test_break_cb(bkr.re, NULL, thread_break); + G.afbreek= 0; /* blender_test_break uses this global */ + + RE_Database_Baking(bkr.re, scene, scene->r.bake_mode, (scene->r.bake_flag & R_BAKE_TO_ACTIVE)? OBACT: NULL); + + /* baking itself is threaded, cannot use test_break in threads */ + BLI_init_threads(&threads, do_bake_render, 1); + bkr.ready= 0; + BLI_insert_thread(&threads, &bkr); + + while(bkr.ready==0) { + PIL_sleep_ms(50); + if(bkr.ready) + break; + + /* used to redraw in 2.4x but this is just for exec in 2.5 */ + if (!G.background) + blender_test_break(); + } + BLI_end_threads(&threads); + + if(bkr.tot==0) BKE_report(op->reports, RPT_ERROR, "No Images found to bake to"); + + finish_bake_internal(&bkr); + } + + WM_event_add_notifier(C, NC_SCENE|ND_RENDER_RESULT, scene); + return OPERATOR_FINISHED; +} + +void OBJECT_OT_bake_image(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Bake"; + ot->description= "Bake image textures of selected objects."; + ot->idname= "OBJECT_OT_bake_image"; + + /* api callbacks */ + ot->exec= bake_image_exec; + ot->invoke= objects_bake_render_invoke; + ot->modal= objects_bake_render_modal; +} diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index 790db0dc564..9ef1fafff82 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -1671,34 +1671,6 @@ void OBJECT_OT_shade_smooth(wmOperatorType *ot) /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; } -/* bake */ - -static int bake_image_exec(bContext *C, wmOperator *op) -{ - Scene *scene= CTX_data_scene(C); - char *error_msg= NULL; - objects_bake_render(scene, 0, &error_msg); - - if(error_msg) { - BKE_report(op->reports, RPT_ERROR, error_msg); - return OPERATOR_CANCELLED; - } - else { - WM_event_add_notifier(C, NC_SCENE|ND_RENDER_RESULT, scene); - return OPERATOR_FINISHED; - } -} - -void OBJECT_OT_bake_image(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Bake"; - ot->description= "Bake selected objects."; - ot->idname= "OBJECT_OT_bake_image"; - - /* api callbacks */ - ot->exec= bake_image_exec; -} /* ********************** */ diff --git a/source/blender/editors/object/object_group.c b/source/blender/editors/object/object_group.c index 1e5b93aa6dc..50fc5f5d2fe 100644 --- a/source/blender/editors/object/object_group.c +++ b/source/blender/editors/object/object_group.c @@ -287,8 +287,9 @@ void OBJECT_OT_group_add(wmOperatorType *ot) PropertyRNA *prop; /* identifiers */ - ot->name= "Add Group"; + ot->name= "Add to Group"; ot->idname= "OBJECT_OT_group_add"; + ot->description = "Add an object to an existing group, or create new."; /* api callbacks */ ot->exec= group_add_exec; diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h index c5bb61b4403..d47cecb762b 100644 --- a/source/blender/editors/object/object_intern.h +++ b/source/blender/editors/object/object_intern.h @@ -79,7 +79,6 @@ void OBJECT_OT_restrictview_clear(struct wmOperatorType *ot); void OBJECT_OT_proxy_make(struct wmOperatorType *ot); void OBJECT_OT_shade_smooth(struct wmOperatorType *ot); void OBJECT_OT_shade_flat(struct wmOperatorType *ot); -void OBJECT_OT_bake_image(struct wmOperatorType *ot); /* object_select.c */ void OBJECT_OT_select_all(struct wmOperatorType *ot); @@ -203,5 +202,8 @@ void OBJECT_OT_shape_key_move(struct wmOperatorType *ot); void OBJECT_OT_group_add(struct wmOperatorType *ot); void OBJECT_OT_group_remove(struct wmOperatorType *ot); +/* object_bake.c */ +void OBJECT_OT_bake_image(wmOperatorType *ot); + #endif /* ED_OBJECT_INTERN_H */ diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index 3e9b1cfe7c7..a44ad47b94f 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -165,6 +165,7 @@ int ED_object_modifier_remove(ReportList *reports, Scene *scene, Object *ob, Mod BLI_remlink(&ob->particlesystem, psmd->psys); psys_free(ob, psmd->psys); + psmd->psys= NULL; } else if(md->type == eModifierType_Softbody) { if(ob->soft) { diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index 05eab6528fd..eb2086fe95d 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -81,7 +81,6 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_restrictview_set); WM_operatortype_append(OBJECT_OT_shade_smooth); WM_operatortype_append(OBJECT_OT_shade_flat); - WM_operatortype_append(OBJECT_OT_bake_image); WM_operatortype_append(OBJECT_OT_parent_set); WM_operatortype_append(OBJECT_OT_parent_no_inverse_set); @@ -197,6 +196,8 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_hook_assign); WM_operatortype_append(OBJECT_OT_hook_reset); WM_operatortype_append(OBJECT_OT_hook_recenter); + + WM_operatortype_append(OBJECT_OT_bake_image); } void ED_operatormacros_object(void) diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index b8839360296..d4bf721e14e 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -1183,6 +1183,7 @@ enum { MAKE_LINKS_MATERIALS, MAKE_LINKS_ANIMDATA, MAKE_LINKS_DUPLIGROUP, + MAKE_LINKS_MODIFIERS }; static int make_links_data_exec(bContext *C, wmOperator *op) @@ -1235,6 +1236,10 @@ static int make_links_data_exec(bContext *C, wmOperator *op) obt->transflag |= OB_DUPLIGROUP; } break; + case MAKE_LINKS_MODIFIERS: + object_link_modifiers(obt, ob); + obt->recalc |= OB_RECALC; + break; } } } @@ -1274,6 +1279,7 @@ void OBJECT_OT_make_links_data(wmOperatorType *ot) {MAKE_LINKS_MATERIALS, "MATERIAL", 0, "Materials", ""}, {MAKE_LINKS_ANIMDATA, "ANIMATION", 0, "Animation Data", ""}, {MAKE_LINKS_DUPLIGROUP, "DUPLIGROUP", 0, "DupliGroup", ""}, + {MAKE_LINKS_MODIFIERS, "MODIFIERS", 0, "Modifiers", ""}, {0, NULL, 0, NULL, NULL}}; PropertyRNA *prop; diff --git a/source/blender/editors/object/object_shapekey.c b/source/blender/editors/object/object_shapekey.c index 99b35b998c2..226c630f2e8 100644 --- a/source/blender/editors/object/object_shapekey.c +++ b/source/blender/editors/object/object_shapekey.c @@ -260,7 +260,7 @@ void OBJECT_OT_shape_key_add(wmOperatorType *ot) ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; /* properties */ - RNA_def_boolean(ot->srna, "from_mix", 0, "From Mix", "Create the new shape key from the existing mix of keys."); + RNA_def_boolean(ot->srna, "from_mix", 1, "From Mix", "Create the new shape key from the existing mix of keys."); } static int shape_key_remove_exec(bContext *C, wmOperator *op) diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c index a16b0f2a7ac..43382562a8a 100644 --- a/source/blender/editors/object/object_transform.c +++ b/source/blender/editors/object/object_transform.c @@ -506,7 +506,6 @@ static int apply_objects_internal(bContext *C, ReportList *reports, int apply_lo mul_m4_v3(mat, bezt->vec[1]); mul_m4_v3(mat, bezt->vec[2]); bezt->radius *= scale; - bezt++; } } else { diff --git a/source/blender/editors/physics/Makefile b/source/blender/editors/physics/Makefile index 63968fdd537..e9260b66087 100644 --- a/source/blender/editors/physics/Makefile +++ b/source/blender/editors/physics/Makefile @@ -53,4 +53,10 @@ CPPFLAGS += -I../../render/extern/include # own include -CPPFLAGS += -I../include +CPPFLAGS += -I../include + +ifeq ($(OS), darwin) + ifeq ($(WITH_BF_OPENMP), true) + CPPFLAGS += -DPARALLEL=1 + endif +endif diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index eccb257dab5..8a73dc0e050 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -316,6 +316,14 @@ void PE_hide_keys_time(Scene *scene, PTCacheEdit *edit, float cfra) } } +static int pe_x_mirror(Object *ob) +{ + if(ob->type == OB_MESH) + return (((Mesh*)ob->data)->editflag & ME_EDIT_MIRROR_X); + + return 0; +} + /****************** common struct passed to callbacks ******************/ typedef struct PEData { @@ -580,25 +588,34 @@ static void foreach_mouse_hit_key(PEData *data, ForKeyMatFunc func, int selected unit_m4(mat); LOOP_VISIBLE_POINTS { - if(edit->psys && !(edit->psys->flag & PSYS_GLOBAL_HAIR)) { - psys_mat_hair_to_global(data->ob, psmd->dm, psys->part->from, psys->particles + p, mat); - invert_m4_m4(imat,mat); - } - if(pset->selectmode==SCE_SELECT_END) { /* only do end keys */ key= point->keys + point->totkey-1; - if(selected==0 || key->flag & PEK_SELECT) - if(key_inside_circle(data, data->rad, KEY_WCO, &data->dist)) + if(selected==0 || key->flag & PEK_SELECT) { + if(key_inside_circle(data, data->rad, KEY_WCO, &data->dist)) { + if(edit->psys && !(edit->psys->flag & PSYS_GLOBAL_HAIR)) { + psys_mat_hair_to_global(data->ob, psmd->dm, psys->part->from, psys->particles + p, mat); + invert_m4_m4(imat,mat); + } + func(data, mat, imat, p, point->totkey-1, key); + } + } } else { /* do all keys */ LOOP_VISIBLE_KEYS { - if(selected==0 || key->flag & PEK_SELECT) - if(key_inside_circle(data, data->rad, KEY_WCO, &data->dist)) + if(selected==0 || key->flag & PEK_SELECT) { + if(key_inside_circle(data, data->rad, KEY_WCO, &data->dist)) { + if(edit->psys && !(edit->psys->flag & PSYS_GLOBAL_HAIR)) { + psys_mat_hair_to_global(data->ob, psmd->dm, psys->part->from, psys->particles + p, mat); + invert_m4_m4(imat,mat); + } + func(data, mat, imat, p, k, key); + } + } } } } @@ -1185,7 +1202,7 @@ void PE_update_object(Scene *scene, Object *ob, int useflag) pe_iterate_lengths(scene, edit); pe_deflect_emitter(scene, ob, edit); PE_apply_lengths(scene, edit); - if(pset->flag & PE_X_MIRROR) + if(pe_x_mirror(ob)) PE_apply_mirror(ob,edit->psys); if(edit->psys) update_world_cos(ob, edit); @@ -1997,17 +2014,16 @@ static void rekey_particle_to_time(Scene *scene, Object *ob, int pa_index, float /************************* utilities **************************/ -static int remove_tagged_particles(Scene *scene, Object *ob, ParticleSystem *psys) +static int remove_tagged_particles(Scene *scene, Object *ob, ParticleSystem *psys, int mirror) { PTCacheEdit *edit = psys->edit; - ParticleEditSettings *pset= PE_settings(scene); ParticleData *pa, *npa=0, *new_pars=0; POINT_P; PTCacheEditPoint *npoint=0, *new_points=0; ParticleSystemModifierData *psmd; int i, totpart, new_totpart= psys->totpart, removed= 0; - if(pset->flag & PE_X_MIRROR) { + if(mirror) { /* mirror tags */ psmd= psys_get_modifier(ob, psys); totpart= psys->totpart; @@ -2071,14 +2087,13 @@ static int remove_tagged_particles(Scene *scene, Object *ob, ParticleSystem *psy static void remove_tagged_keys(Scene *scene, Object *ob, ParticleSystem *psys) { PTCacheEdit *edit= psys->edit; - ParticleEditSettings *pset= PE_settings(scene); ParticleData *pa; HairKey *hkey, *nhkey, *new_hkeys=0; POINT_P; KEY_K; ParticleSystemModifierData *psmd; short new_totkey; - if(pset->flag & PE_X_MIRROR) { + if(pe_x_mirror(ob)) { /* mirror key tags */ psmd= psys_get_modifier(ob, psys); @@ -2099,7 +2114,7 @@ static void remove_tagged_keys(Scene *scene, Object *ob, ParticleSystem *psys) if(new_totkey < 2) point->flag |= PEP_TAG; } - remove_tagged_particles(scene, ob, psys); + remove_tagged_particles(scene, ob, psys, pe_x_mirror(ob)); LOOP_POINTS { pa = psys->particles + p; @@ -2262,7 +2277,6 @@ static int remove_doubles_exec(bContext *C, wmOperator *op) { Scene *scene= CTX_data_scene(C); Object *ob= CTX_data_active_object(C); - ParticleEditSettings *pset=PE_settings(scene); PTCacheEdit *edit= PE_get_current(scene, ob); ParticleSystem *psys = edit->psys; ParticleSystemModifierData *psmd; @@ -2270,7 +2284,7 @@ static int remove_doubles_exec(bContext *C, wmOperator *op) KDTreeNearest nearest[10]; POINT_P; float mat[4][4], co[3], threshold= RNA_float_get(op->ptr, "threshold"); - int n, totn, removed, flag, totremoved; + int n, totn, removed, totremoved; if(psys->flag & PSYS_GLOBAL_HAIR) return OPERATOR_CANCELLED; @@ -2316,10 +2330,7 @@ static int remove_doubles_exec(bContext *C, wmOperator *op) BLI_kdtree_free(tree); /* remove tagged particles - don't do mirror here! */ - flag= pset->flag; - pset->flag &= ~PE_X_MIRROR; - remove_tagged_particles(scene, ob, psys); - pset->flag= flag; + remove_tagged_particles(scene, ob, psys, 0); totremoved += removed; } while(removed); @@ -2500,7 +2511,7 @@ static int delete_exec(bContext *C, wmOperator *op) } else if(type == DEL_PARTICLE) { foreach_selected_point(&data, set_delete_particle); - remove_tagged_particles(data.scene, data.ob, data.edit->psys); + remove_tagged_particles(data.scene, data.ob, data.edit->psys, pe_x_mirror(data.ob)); recalc_lengths(data.edit); } @@ -2603,9 +2614,11 @@ static void PE_mirror_x(Scene *scene, Object *ob, int tagged) newpa= psys->particles + totpart; newpoint= edit->points + totpart; - LOOP_VISIBLE_POINTS { + for(p=0, point=edit->points; p<totpart; p++, point++) { pa = psys->particles + p; + if(point->flag & PEP_HIDE) + continue; if(!(point->flag & PEP_TAG) || mirrorfaces[pa->num*2] == -1) continue; @@ -3097,7 +3110,7 @@ static int brush_add(PEData *data, short number) initialize_particle(&sim, pa,i); reset_particle(&sim, pa, 0.0, 1.0); point->flag |= PEP_EDIT_RECALC; - if(pset->flag & PE_X_MIRROR) + if(pe_x_mirror(ob)) point->flag |= PEP_TAG; /* signal for duplicate */ framestep= pa->lifetime/(float)(pset->totaddkey-1); @@ -3304,7 +3317,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) else foreach_point(&data, brush_cut); - removed= remove_tagged_particles(scene, ob, edit->psys); + removed= remove_tagged_particles(scene, ob, edit->psys, pe_x_mirror(ob)); if(pset->flag & PE_KEEP_LENGTHS) recalc_lengths(edit); } @@ -3403,7 +3416,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) recalc_lengths(edit); if(ELEM(pset->brushtype, PE_BRUSH_ADD, PE_BRUSH_CUT) && (added || removed)) { - if(pset->brushtype == PE_BRUSH_ADD && (pset->flag & PE_X_MIRROR)) + if(pset->brushtype == PE_BRUSH_ADD && pe_x_mirror(ob)) PE_mirror_x(scene, ob, 1); update_world_cos(ob,edit); diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index 74e1cca5579..03fe772c09b 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -717,7 +717,7 @@ void BIF_view3d_previewrender(Scene *scene, ScrArea *sa) rdata.layers.first= rdata.layers.last= NULL; rdata.renderer= R_INTERN; - RE_InitState(re, NULL, &rdata, sa->winx, sa->winy, &ri->disprect); + RE_InitState(re, NULL, &rdata, NULL, sa->winx, sa->winy, &ri->disprect); if(orth) RE_SetOrtho(re, &viewplane, clipsta, clipend); @@ -923,7 +923,7 @@ static void shader_preview_render(ShaderPreview *sp, ID *id, int split, int firs else sizex= sp->sizex; /* allocates or re-uses render result */ - RE_InitState(re, NULL, &sce->r, sizex, sp->sizey, NULL); + RE_InitState(re, NULL, &sce->r, NULL, sizex, sp->sizey, NULL); /* callbacs are cleared on GetRender() */ if(sp->pr_method==PR_BUTS_RENDER) { diff --git a/source/blender/editors/screen/CMakeLists.txt b/source/blender/editors/screen/CMakeLists.txt index ad7770e12fa..75811735d25 100644 --- a/source/blender/editors/screen/CMakeLists.txt +++ b/source/blender/editors/screen/CMakeLists.txt @@ -70,10 +70,9 @@ IF(WIN32) SET(INC ${INC} ${PTHREADS_INC}) ENDIF(WIN32) -# TODO buildinfo -IF(BF_BUILDINFO) +IF(WITH_BUILDINFO) ADD_DEFINITIONS(-DNAN_BUILDINFO) -ENDIF(BF_BUILDINFO) +ENDIF(WITH_BUILDINFO) BLENDERLIB_NOLIST(bf_editors "${SRC}" "${INC}") diff --git a/source/blender/editors/screen/Makefile b/source/blender/editors/screen/Makefile index 87ba3337caa..23c9d130eec 100644 --- a/source/blender/editors/screen/Makefile +++ b/source/blender/editors/screen/Makefile @@ -60,3 +60,8 @@ ifeq ($(WITH_OPENEXR), true) CPPFLAGS += -DWITH_OPENEXR endif +ifeq ($(OS), darwin) + ifeq ($(WITH_BF_OPENMP), true) + CPPFLAGS += -DPARALLEL=1 + endif +endif diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index d9d76e963a3..c494afac79e 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -1107,10 +1107,10 @@ void ED_area_prevspace(bContext *C, ScrArea *sa) ED_area_tag_redraw(sa); } -static char *windowtype_pup(void) +static char *editortype_pup(void) { return( - "Window type:%t" + "Editor type:%t" "|3D View %x1" "|%l" @@ -1160,9 +1160,9 @@ int ED_area_header_switchbutton(const bContext *C, uiBlock *block, int yco) int xco= 8; but= uiDefIconTextButC(block, ICONTEXTROW, 0, ICON_VIEW3D, - windowtype_pup(), xco, yco, XIC+10, YIC, + editortype_pup(), xco, yco, XIC+10, YIC, &(sa->butspacetype), 1.0, SPACEICONMAX, 0, 0, - "Displays Current Window Type. " + "Displays Current Editor Type. " "Click for menu of available types."); uiButSetFunc(but, spacefunc, NULL, NULL); diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 9db9247287c..a0df3a2360e 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -26,6 +26,7 @@ #include <math.h> #include <string.h> +#include <stddef.h> #include <GL/glew.h> @@ -2262,9 +2263,9 @@ static int header_toolbox_invoke(bContext *C, wmOperator *op, wmEvent *event) /* file browser should be fullscreen all the time, but other regions can be maximised/restored... */ if (sa->spacetype != SPACE_FILE) { if (sa->full) - uiItemO(layout, "Tile Window", 0, "SCREEN_OT_screen_full_area"); + uiItemO(layout, "Tile Area", 0, "SCREEN_OT_screen_full_area"); else - uiItemO(layout, "Maximize Window", 0, "SCREEN_OT_screen_full_area"); + uiItemO(layout, "Maximize Area", 0, "SCREEN_OT_screen_full_area"); } uiPupMenuEnd(C, pup); @@ -2815,7 +2816,7 @@ static int screen_render_exec(bContext *C, wmOperator *op) if(RNA_boolean_get(op->ptr, "animation")) RE_BlenderAnim(re, scene, scene->r.sfra, scene->r.efra, scene->r.frame_step, op->reports); else - RE_BlenderFrame(re, scene, scene->r.cfra); + RE_BlenderFrame(re, scene, NULL, scene->r.cfra); // no redraw needed, we leave state as we entered it ED_update_for_newframe(C, 1); @@ -2829,6 +2830,7 @@ typedef struct RenderJob { Scene *scene; Render *re; wmWindow *win; + SceneRenderLayer *srl; int anim; Image *image; ImageUser iuser; @@ -3041,7 +3043,7 @@ static void render_startjob(void *rjv, short *stop, short *do_update) if(rj->anim) RE_BlenderAnim(rj->re, rj->scene, rj->scene->r.sfra, rj->scene->r.efra, rj->scene->r.frame_step, rj->reports); else - RE_BlenderFrame(rj->re, rj->scene, rj->scene->r.cfra); + RE_BlenderFrame(rj->re, rj->scene, rj->srl, rj->scene->r.cfra); } /* called by render, check job 'stop' value or the global */ @@ -3077,6 +3079,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, wmEvent *event) { /* new render clears all callbacks */ Scene *scene= CTX_data_scene(C); + SceneRenderLayer *srl=NULL; Render *re; wmJob *steve; RenderJob *rj; @@ -3108,10 +3111,29 @@ static int screen_render_invoke(bContext *C, wmOperator *op, wmEvent *event) /* ensure at least 1 area shows result */ screen_set_image_output(C, event->x, event->y); + /* single layer re-render */ + if(RNA_property_is_set(op->ptr, "layer")) { + SceneRenderLayer *rl; + Scene *scn; + char scene_name[19], rl_name[RE_MAXNAME]; + + RNA_string_get(op->ptr, "layer", rl_name); + RNA_string_get(op->ptr, "scene", scene_name); + + scn = (Scene *)BLI_findstring(&CTX_data_main(C)->scene, scene_name, offsetof(ID, name) + 2); + rl = (SceneRenderLayer *)BLI_findstring(&scene->r.layers, rl_name, offsetof(SceneRenderLayer, name)); + + if (scn && rl) { + scene = scn; + srl = rl; + } + } + /* job custom data */ rj= MEM_callocN(sizeof(RenderJob), "render job"); rj->scene= scene; rj->win= CTX_wm_window(C); + rj->srl = srl; rj->anim= RNA_boolean_get(op->ptr, "animation"); rj->iuser.scene= scene; rj->iuser.ok= 1; @@ -3173,6 +3195,8 @@ static void SCREEN_OT_render(wmOperatorType *ot) ot->poll= ED_operator_screenactive; RNA_def_boolean(ot->srna, "animation", 0, "Animation", ""); + RNA_def_string(ot->srna, "layer", "", RE_MAXNAME, "Render Layer", "Single render layer to re-render"); + RNA_def_string(ot->srna, "scene", "", 19, "Scene", "Re-render single layer in this scene"); } /* ****************************** opengl render *************************** */ @@ -3295,7 +3319,7 @@ static int screen_opengl_render_init(bContext *C, wmOperator *op) /* create render and render result */ oglrender->re= RE_NewRender(scene->id.name); - RE_InitState(oglrender->re, NULL, &scene->r, sizex, sizey, NULL); + RE_InitState(oglrender->re, NULL, &scene->r, NULL, sizex, sizey, NULL); rr= RE_AcquireResultWrite(oglrender->re); if(rr->rectf==NULL) @@ -3395,7 +3419,7 @@ static int screen_opengl_render_modal(bContext *C, wmOperator *op, wmEvent *even printf("Append frame %d", scene->r.cfra); } else { - BKE_makepicstring(scene, name, scene->r.pic, scene->r.cfra, scene->r.imtype); + BKE_makepicstring(name, scene->r.pic, scene->r.cfra, scene->r.imtype, scene->r.scemode & R_EXTENSION); ok= BKE_write_ibuf(scene, ibuf, name, scene->r.imtype, scene->r.subimtype, scene->r.quality); if(ok==0) printf("write error: cannot save %s\n", name); @@ -3941,6 +3965,9 @@ void ED_keymap_screen(wmKeyConfig *keyconf) RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_offset", LEFTARROWKEY, KM_PRESS, 0, 0)->ptr, "delta", -1); RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_offset", RIGHTARROWKEY, KM_PRESS, 0, 0)->ptr, "delta", 1); + RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_offset", WHEELDOWNMOUSE, KM_PRESS, KM_ALT, 0)->ptr, "delta", 1); + RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_offset", WHEELUPMOUSE, KM_PRESS, KM_ALT, 0)->ptr, "delta", -1); + WM_keymap_add_item(keymap, "SCREEN_OT_frame_jump", DOWNARROWKEY, KM_PRESS, KM_SHIFT, 0); RNA_boolean_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_jump", RIGHTARROWKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "end", 1); RNA_boolean_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_jump", LEFTARROWKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "end", 0); diff --git a/source/blender/editors/screen/screendump.c b/source/blender/editors/screen/screendump.c index 088be194fe8..7fea28304ba 100644 --- a/source/blender/editors/screen/screendump.c +++ b/source/blender/editors/screen/screendump.c @@ -84,7 +84,7 @@ static int screenshot_exec(bContext *C, wmOperator *op) /* BKE_add_image_extension() checks for if extension was already set */ if(scene->r.scemode & R_EXTENSION) if(strlen(path)<FILE_MAXDIR+FILE_MAXFILE-5) - BKE_add_image_extension(scene, path, scene->r.imtype); + BKE_add_image_extension(path, scene->r.imtype); ibuf= IMB_allocImBuf(scd->dumpsx, scd->dumpsy, 24, 0, 0); ibuf->rect= scd->dumprect; @@ -258,7 +258,7 @@ static void screenshot_startjob(void *sjv, short *stop, short *do_update) char name[FILE_MAXDIR+FILE_MAXFILE]; int ok; - BKE_makepicstring(sj->scene, name, rd.pic, cfra, rd.imtype); + BKE_makepicstring(name, rd.pic, cfra, rd.imtype, rd.scemode & R_EXTENSION); ibuf->rect= sj->dumprect; ok= BKE_write_ibuf(sj->scene, ibuf, name, rd.imtype, rd.subimtype, rd.quality); diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index 526eb2d6661..77e90e3c7b1 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -1001,8 +1001,7 @@ static void uv_image_outset(float (*orig_uv)[2], float (*outset_uv)[2], const fl float puv[4][2]; /* pixelspace uv's */ float no1[2], no2[2], no3[2], no4[2]; /* normals */ float dir1[2], dir2[2], dir3[2], dir4[2]; - float ibuf_x_inv = 1.0f / (float)ibuf_x; - float ibuf_y_inv = 1.0f / (float)ibuf_y; + float ibuf_inv[2] = {1.0f / (float)ibuf_x, 1.0f / (float)ibuf_y}; /* make UV's in pixel space so we can */ puv[0][0] = orig_uv[0][0] * ibuf_x; @@ -1035,17 +1034,20 @@ static void uv_image_outset(float (*orig_uv)[2], float (*outset_uv)[2], const fl sub_v2_v2v2(dir3, puv[0], puv[2]); normalize_v2(dir3); } - + + /* TODO - angle_normalized_v2v2(...) * (M_PI/180.0f) + * This is incorrect. Its already given radians but without it wont work. + * need to look into a fix - campbell */ if (is_quad) { - a1 = shell_angle_to_dist(angle_normalized_v2v2(dir4, dir1)); - a2 = shell_angle_to_dist(angle_normalized_v2v2(dir1, dir2)); - a3 = shell_angle_to_dist(angle_normalized_v2v2(dir2, dir3)); - a4 = shell_angle_to_dist(angle_normalized_v2v2(dir3, dir4)); + a1 = shell_angle_to_dist(angle_normalized_v2v2(dir4, dir1) * (M_PI/180.0f)); + a2 = shell_angle_to_dist(angle_normalized_v2v2(dir1, dir2) * (M_PI/180.0f)); + a3 = shell_angle_to_dist(angle_normalized_v2v2(dir2, dir3) * (M_PI/180.0f)); + a4 = shell_angle_to_dist(angle_normalized_v2v2(dir3, dir4) * (M_PI/180.0f)); } else { - a1 = shell_angle_to_dist(angle_normalized_v2v2(dir3, dir1)); - a2 = shell_angle_to_dist(angle_normalized_v2v2(dir1, dir2)); - a3 = shell_angle_to_dist(angle_normalized_v2v2(dir2, dir3)); + a1 = shell_angle_to_dist(angle_normalized_v2v2(dir3, dir1) * (M_PI/180.0f)); + a2 = shell_angle_to_dist(angle_normalized_v2v2(dir1, dir2) * (M_PI/180.0f)); + a3 = shell_angle_to_dist(angle_normalized_v2v2(dir2, dir3) * (M_PI/180.0f)); } if (is_quad) { @@ -1065,17 +1067,10 @@ static void uv_image_outset(float (*orig_uv)[2], float (*outset_uv)[2], const fl add_v2_v2v2(outset_uv[1], puv[1], no2); add_v2_v2v2(outset_uv[2], puv[2], no3); add_v2_v2v2(outset_uv[3], puv[3], no4); - outset_uv[0][0] *= ibuf_x_inv; - outset_uv[0][1] *= ibuf_y_inv; - - outset_uv[1][0] *= ibuf_x_inv; - outset_uv[1][1] *= ibuf_y_inv; - - outset_uv[2][0] *= ibuf_x_inv; - outset_uv[2][1] *= ibuf_y_inv; - - outset_uv[3][0] *= ibuf_x_inv; - outset_uv[3][1] *= ibuf_y_inv; + mul_v2_v2(outset_uv[0], ibuf_inv); + mul_v2_v2(outset_uv[1], ibuf_inv); + mul_v2_v2(outset_uv[2], ibuf_inv); + mul_v2_v2(outset_uv[3], ibuf_inv); } else { sub_v2_v2v2(no1, dir3, dir1); @@ -1090,14 +1085,10 @@ static void uv_image_outset(float (*orig_uv)[2], float (*outset_uv)[2], const fl add_v2_v2v2(outset_uv[0], puv[0], no1); add_v2_v2v2(outset_uv[1], puv[1], no2); add_v2_v2v2(outset_uv[2], puv[2], no3); - outset_uv[0][0] *= ibuf_x_inv; - outset_uv[0][1] *= ibuf_y_inv; - - outset_uv[1][0] *= ibuf_x_inv; - outset_uv[1][1] *= ibuf_y_inv; - - outset_uv[2][0] *= ibuf_x_inv; - outset_uv[2][1] *= ibuf_y_inv; + + mul_v2_v2(outset_uv[0], ibuf_inv); + mul_v2_v2(outset_uv[1], ibuf_inv); + mul_v2_v2(outset_uv[2], ibuf_inv); } } @@ -2890,7 +2881,7 @@ static void project_paint_begin(ProjPaintState *ps) ps->is_airbrush = (ps->brush->flag & BRUSH_AIRBRUSH) ? 1 : 0; - ps->is_texbrush = (ps->brush->mtex[ps->brush->texact] && ps->brush->mtex[ps->brush->texact]->tex) ? 1 : 0; + ps->is_texbrush = (ps->brush->mtex.tex) ? 1 : 0; /* calculate vert screen coords @@ -4090,10 +4081,17 @@ static int imapaint_canvas_set(ImagePaintState *s, Image *ima) s->clonecanvas= ibuf; + /* temporarily add float rect for cloning */ if(s->canvas->rect_float && !s->clonecanvas->rect_float) { - /* temporarily add float rect for cloning */ + int profile = IB_PROFILE_NONE; + + /* Don't want to color manage, but don't disturb existing profiles */ + SWAP(int, s->clonecanvas->profile, profile); + IMB_float_from_rect(s->clonecanvas); s->clonefreefloat= 1; + + SWAP(int, s->clonecanvas->profile, profile); } else if(!s->canvas->rect_float && !s->clonecanvas->rect) IMB_rect_from_float(s->clonecanvas); diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h index 108be50267d..6bb5f432b0d 100644 --- a/source/blender/editors/sculpt_paint/paint_intern.h +++ b/source/blender/editors/sculpt_paint/paint_intern.h @@ -52,6 +52,8 @@ typedef void (*StrokeDone)(struct bContext *C, struct PaintStroke *stroke); struct PaintStroke *paint_stroke_new(struct bContext *C, StrokeGetLocation get_location, StrokeTestStart test_start, StrokeUpdateStep update_step, StrokeDone done); +void paint_stroke_free(struct PaintStroke *stroke); + int paint_stroke_modal(struct bContext *C, struct wmOperator *op, struct wmEvent *event); int paint_stroke_exec(struct bContext *C, struct wmOperator *op); struct ViewContext *paint_stroke_view_context(struct PaintStroke *stroke); diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c index 57b56da2fcd..715a41e6431 100644 --- a/source/blender/editors/sculpt_paint/paint_ops.c +++ b/source/blender/editors/sculpt_paint/paint_ops.c @@ -176,6 +176,21 @@ static void ed_keymap_paint_brush_switch(wmKeyMap *keymap, const char *path) RNA_int_set(kmi->ptr, "value", 9); } +static void ed_keymap_paint_brush_size(wmKeyMap *keymap, const char *path) +{ + wmKeyMapItem *kmi; + + kmi= WM_keymap_add_item(keymap, "WM_OT_context_set_int", LEFTBRACKETKEY, KM_PRESS, 0, 0); + RNA_string_set(kmi->ptr, "path", path); + RNA_int_set(kmi->ptr, "value", -20); + RNA_boolean_set(kmi->ptr, "relative", 1); + + kmi= WM_keymap_add_item(keymap, "WM_OT_context_set_int", RIGHTBRACKETKEY, KM_PRESS, 0, 0); + RNA_string_set(kmi->ptr, "path", path); + RNA_int_set(kmi->ptr, "value", 20); + RNA_boolean_set(kmi->ptr, "relative", 1); +} + void ED_keymap_paint(wmKeyConfig *keyconf) { wmKeyMap *keymap; @@ -205,8 +220,8 @@ void ED_keymap_paint(wmKeyConfig *keyconf) RNA_int_set(kmi->ptr, "level", -1); RNA_boolean_set(kmi->ptr, "relative", 1); - /* toggles */ ed_keymap_paint_brush_switch(keymap, "tool_settings.sculpt.active_brush_index"); + ed_keymap_paint_brush_size(keymap, "tool_settings.sculpt.brush.size"); kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", AKEY, KM_PRESS, 0, 0); RNA_string_set(kmi->ptr, "path", "tool_settings.sculpt.brush.use_anchor"); @@ -259,6 +274,7 @@ void ED_keymap_paint(wmKeyConfig *keyconf) "PAINT_OT_vertex_color_set",KKEY, KM_PRESS, KM_SHIFT, 0); ed_keymap_paint_brush_switch(keymap, "tool_settings.vertex_paint.active_brush_index"); + ed_keymap_paint_brush_size(keymap, "tool_settings.vertex_paint.brush.size"); /* Weight Paint mode */ keymap= WM_keymap_find(keyconf, "Weight Paint", 0, 0); @@ -273,6 +289,7 @@ void ED_keymap_paint(wmKeyConfig *keyconf) "PAINT_OT_weight_set", KKEY, KM_PRESS, KM_SHIFT, 0); ed_keymap_paint_brush_switch(keymap, "tool_settings.weight_paint.active_brush_index"); + ed_keymap_paint_brush_size(keymap, "tool_settings.weight_paint.brush.size"); /* Image/Texture Paint mode */ keymap= WM_keymap_find(keyconf, "Image Paint", 0, 0); @@ -286,6 +303,7 @@ void ED_keymap_paint(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "PAINT_OT_clone_cursor_set", LEFTMOUSE, KM_PRESS, KM_CTRL, 0); ed_keymap_paint_brush_switch(keymap, "tool_settings.image_paint.active_brush_index"); + ed_keymap_paint_brush_size(keymap, "tool_settings.image_paint.brush.size"); /* face-mask mode */ keymap= WM_keymap_find(keyconf, "Face Mask", 0, 0); diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index e26b1945e7f..89c5443bf99 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -237,6 +237,11 @@ PaintStroke *paint_stroke_new(bContext *C, return stroke; } +void paint_stroke_free(PaintStroke *stroke) +{ + MEM_freeN(stroke); +} + int paint_stroke_modal(bContext *C, wmOperator *op, wmEvent *event) { PaintStroke *stroke = op->customdata; diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c index b968930128a..606fae3d8bb 100644 --- a/source/blender/editors/sculpt_paint/paint_utils.c +++ b/source/blender/editors/sculpt_paint/paint_utils.c @@ -16,6 +16,7 @@ #include "BLI_math.h" #include "BKE_brush.h" +#include "BKE_colortools.h" #include "BKE_context.h" #include "BKE_DerivedMesh.h" #include "BKE_global.h" @@ -214,9 +215,9 @@ static int brush_curve_preset_poll(bContext *C) void BRUSH_OT_curve_preset(wmOperatorType *ot) { static EnumPropertyItem prop_shape_items[] = { - {BRUSH_PRESET_SHARP, "SHARP", 0, "Sharp", ""}, - {BRUSH_PRESET_SMOOTH, "SMOOTH", 0, "Smooth", ""}, - {BRUSH_PRESET_MAX, "MAX", 0, "Max", ""}, + {CURVE_PRESET_SHARP, "SHARP", 0, "Sharp", ""}, + {CURVE_PRESET_SMOOTH, "SMOOTH", 0, "Smooth", ""}, + {CURVE_PRESET_MAX, "MAX", 0, "Max", ""}, {0, NULL, 0, NULL, NULL}}; ot->name= "Preset"; @@ -228,7 +229,7 @@ void BRUSH_OT_curve_preset(wmOperatorType *ot) ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - RNA_def_enum(ot->srna, "shape", prop_shape_items, BRUSH_PRESET_SHARP, "Mode", ""); + RNA_def_enum(ot->srna, "shape", prop_shape_items, CURVE_PRESET_SMOOTH, "Mode", ""); } diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 09b99f4f43c..6671fec783e 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -614,12 +614,9 @@ static float get_texcache_pixel_bilinear(const SculptSession *ss, float u, float /* Return a multiplier for brush strength on a particular vertex. */ static float tex_strength(SculptSession *ss, Brush *br, float *point, const float len) { - MTex *tex = NULL; + MTex *tex = &br->mtex; float avg= 1; - if(br->texact >= 0) - tex = br->mtex[br->texact]; - if(!tex) { avg= 1; } @@ -917,6 +914,8 @@ static void do_mesh_smooth_brush(Sculpt *sd, SculptSession *ss, PBVHNode *node) if(sculpt_brush_test(&test, vd.co)) { float fade = tex_strength(ss, brush, vd.co, test.dist)*bstrength; float avg[3], val[3]; + + CLAMP(fade, 0.0f, 1.0f); neighbor_average(ss, avg, vd.vert_indices[vd.i]); val[0] = vd.co[0]+(avg[0]-vd.co[0])*fade; @@ -993,6 +992,8 @@ static void do_multires_smooth_brush(Sculpt *sd, SculptSession *ss, PBVHNode *no if(y == 0 || y == gridsize - 1) mul_v3_fl(avg, 2.0f); + CLAMP(fade, 0.0f, 1.0f); + val[0] = co[0]+(avg[0]-co[0])*fade; val[1] = co[1]+(avg[1]-co[1])*fade; val[2] = co[2]+(avg[2]-co[2])*fade; @@ -1016,15 +1017,15 @@ static void do_smooth_brush(Sculpt *sd, SculptSession *ss, PBVHNode **nodes, int for(n=0; n<totnode; n++) { sculpt_undo_push_node(ss, nodes[n]); - if(ss->fmap) - do_mesh_smooth_brush(sd, ss, nodes[n]); - else + if(ss->multires) do_multires_smooth_brush(sd, ss, nodes[n]); + else if(ss->fmap) + do_mesh_smooth_brush(sd, ss, nodes[n]); BLI_pbvh_node_mark_update(nodes[n]); } - if(!ss->fmap) + if(ss->multires) multires_stitch_grids(ss->ob); } } @@ -1547,7 +1548,7 @@ void sculpt_update_mesh_elements(Scene *scene, Object *ob, int need_fmap) } ss->tree = dm->getPBVH(ob, dm); - ss->fmap = (need_fmap && dm->getFaceMap)? dm->getFaceMap(dm): NULL; + ss->fmap = (need_fmap && dm->getFaceMap)? dm->getFaceMap(ob, dm): NULL; } static int sculpt_mode_poll(bContext *C) @@ -1746,7 +1747,7 @@ static void sculpt_update_cache_variants(Sculpt *sd, SculptSession *ss, struct P if(cache->first_time) cache->initial_radius = unproject_brush_radius(ss->ob, cache->vc, cache->true_location, brush->size); - if(brush->flag & BRUSH_SIZE_PRESSURE) { + if(brush->flag & BRUSH_SIZE_PRESSURE && brush->sculpt_tool != SCULPT_TOOL_GRAB) { cache->pixel_radius *= cache->pressure; cache->radius = cache->initial_radius * cache->pressure; } @@ -1800,8 +1801,12 @@ static void sculpt_update_cache_variants(Sculpt *sd, SculptSession *ss, struct P static void sculpt_stroke_modifiers_check(bContext *C, SculptSession *ss) { - if(sculpt_modifiers_active(ss->ob)) - sculpt_update_mesh_elements(CTX_data_scene(C), ss->ob, 0); // XXX brush->sculpt_tool == SCULPT_TOOL_SMOOTH); + if(sculpt_modifiers_active(ss->ob)) { + Sculpt *sd = CTX_data_tool_settings(C)->sculpt; + Brush *brush = paint_brush(&sd->paint); + + sculpt_update_mesh_elements(CTX_data_scene(C), ss->ob, brush->sculpt_tool == SCULPT_TOOL_SMOOTH); + } } typedef struct { @@ -1836,7 +1841,7 @@ int sculpt_stroke_get_location(bContext *C, struct PaintStroke *stroke, float ou ViewContext *vc = paint_stroke_view_context(stroke); SculptSession *ss= vc->obact->sculpt; StrokeCache *cache= ss->cache; - float ray_start[3], ray_normal[3]; + float ray_start[3], ray_end[3], ray_normal[3], dist; float obimat[4][4]; float mval[2] = {mouse[0] - vc->ar->winrct.xmin, mouse[1] - vc->ar->winrct.ymin}; @@ -1844,7 +1849,9 @@ int sculpt_stroke_get_location(bContext *C, struct PaintStroke *stroke, float ou sculpt_stroke_modifiers_check(C, ss); - viewray(vc->ar, vc->v3d, mval, ray_start, ray_normal); + viewline(vc->ar, vc->v3d, mval, ray_start, ray_end); + sub_v3_v3v3(ray_normal, ray_end, ray_start); + dist= normalize_v3(ray_normal); invert_m4_m4(obimat, ss->ob->obmat); mul_m4_v3(obimat, ray_start); @@ -1854,7 +1861,7 @@ int sculpt_stroke_get_location(bContext *C, struct PaintStroke *stroke, float ou srd.ss = vc->obact->sculpt; srd.ray_start = ray_start; srd.ray_normal = ray_normal; - srd.dist = FLT_MAX; + srd.dist = dist; srd.hit = 0; srd.original = (cache)? cache->original: 0; BLI_pbvh_raycast(ss->tree, sculpt_raycast_cb, &srd, @@ -2003,15 +2010,20 @@ static void sculpt_flush_update(bContext *C) } } -static int sculpt_stroke_test_start(bContext *C, struct wmOperator *op, wmEvent *event) +/* Returns whether the mouse/stylus is over the mesh (1) + or over the background (0) */ +static int over_mesh(bContext *C, struct wmOperator *op, float x, float y) { - float mouse[2] = {event->x, event->y}, location[3]; - int over_mesh; - - over_mesh = sculpt_stroke_get_location(C, op->customdata, location, mouse); + float mouse[2] = {x, y}, co[3]; + return (int)sculpt_stroke_get_location(C, op->customdata, co, mouse); +} + +static int sculpt_stroke_test_start(bContext *C, struct wmOperator *op, + wmEvent *event) +{ /* Don't start the stroke until mouse goes over the mesh */ - if(over_mesh) { + if(over_mesh(C, op, event->x, event->y)) { Object *ob = CTX_data_active_object(C); SculptSession *ss = ob->sculpt; Sculpt *sd = CTX_data_tool_settings(C)->sculpt; @@ -2069,14 +2081,27 @@ static void sculpt_stroke_done(bContext *C, struct PaintStroke *stroke) static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, wmEvent *event) { + struct PaintStroke *stroke; + int ignore_background_click; + if(!sculpt_brush_stroke_init(C, op->reports)) return OPERATOR_CANCELLED; - op->customdata = paint_stroke_new(C, sculpt_stroke_get_location, - sculpt_stroke_test_start, - sculpt_stroke_update_step, - sculpt_stroke_done); + stroke = paint_stroke_new(C, sculpt_stroke_get_location, + sculpt_stroke_test_start, + sculpt_stroke_update_step, + sculpt_stroke_done); + op->customdata = stroke; + + /* For tablet rotation */ + ignore_background_click = RNA_boolean_get(op->ptr, + "ignore_background_click"); + if(ignore_background_click && !over_mesh(C, op, event->x, event->y)) { + paint_stroke_free(stroke); + return OPERATOR_PASS_THROUGH; + } + /* add modal handler */ WM_event_add_modal_handler(C, op); @@ -2137,6 +2162,10 @@ static void SCULPT_OT_brush_stroke(wmOperatorType *ot) /* The initial 2D location of the mouse */ RNA_def_float_vector(ot->srna, "initial_mouse", 2, NULL, INT_MIN, INT_MAX, "initial_mouse", "", INT_MIN, INT_MAX); + + RNA_def_boolean(ot->srna, "ignore_background_click", 0, + "Ignore Background Click", + "Clicks on the background don't start the stroke"); } /**** Reset the copy of the mesh that is being sculpted on (currently just for the layer brush) ****/ diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c index 3b42fc7b382..d48a322f562 100644 --- a/source/blender/editors/sound/sound_ops.c +++ b/source/blender/editors/sound/sound_ops.c @@ -81,7 +81,7 @@ static int open_exec(bContext *C, wmOperator *op) info = AUD_getInfo(sound->handle); - if (info.specs.format == AUD_FORMAT_INVALID) { + if (info.specs.channels == AUD_CHANNELS_INVALID) { sound_delete(C, sound); BKE_report(op->reports, RPT_ERROR, "Unsupported audio format"); return OPERATOR_CANCELLED; diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c index e7b1dcb677d..687e7c53644 100644 --- a/source/blender/editors/space_action/action_edit.c +++ b/source/blender/editors/space_action/action_edit.c @@ -497,11 +497,11 @@ static int actkeys_insertkey_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void ACT_OT_keyframe_insert (wmOperatorType *ot) +void ACTION_OT_keyframe_insert (wmOperatorType *ot) { /* identifiers */ ot->name= "Insert Keyframes"; - ot->idname= "ACT_OT_keyframe_insert"; + ot->idname= "ACTION_OT_keyframe_insert"; ot->description= "Insert keyframes for the specified channels."; /* api callbacks */ diff --git a/source/blender/editors/space_action/action_intern.h b/source/blender/editors/space_action/action_intern.h index e45b2d05fac..166004a5742 100644 --- a/source/blender/editors/space_action/action_intern.h +++ b/source/blender/editors/space_action/action_intern.h @@ -83,7 +83,7 @@ void ACTION_OT_view_all(struct wmOperatorType *ot); void ACTION_OT_copy(struct wmOperatorType *ot); void ACTION_OT_paste(struct wmOperatorType *ot); -void ACT_OT_keyframe_insert(struct wmOperatorType *ot); +void ACTION_OT_keyframe_insert(struct wmOperatorType *ot); void ACTION_OT_duplicate(struct wmOperatorType *ot); void ACTION_OT_delete(struct wmOperatorType *ot); void ACTION_OT_clean(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_action/action_ops.c b/source/blender/editors/space_action/action_ops.c index f02974c2ea4..7792247fe81 100644 --- a/source/blender/editors/space_action/action_ops.c +++ b/source/blender/editors/space_action/action_ops.c @@ -80,7 +80,7 @@ void action_operatortypes(void) WM_operatortype_append(ACTION_OT_clean); WM_operatortype_append(ACTION_OT_delete); WM_operatortype_append(ACTION_OT_duplicate); - WM_operatortype_append(ACT_OT_keyframe_insert); + WM_operatortype_append(ACTION_OT_keyframe_insert); WM_operatortype_append(ACTION_OT_copy); WM_operatortype_append(ACTION_OT_paste); WM_operatortype_append(ACTION_OT_new); @@ -145,7 +145,7 @@ static void action_keymap_keyframes (wmKeyConfig *keyconf, wmKeyMap *keymap) WM_keymap_add_item(keymap, "ACTION_OT_delete", DELKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "ACTION_OT_duplicate", DKEY, KM_PRESS, KM_SHIFT, 0); - WM_keymap_add_item(keymap, "ACT_OT_keyframe_insert", IKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "ACTION_OT_keyframe_insert", IKEY, KM_PRESS, 0, 0); /* copy/paste */ WM_keymap_add_item(keymap, "ACTION_OT_copy", CKEY, KM_PRESS, KM_CTRL, 0); diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c index 18ba149d7ed..c4bdd3a6c5b 100644 --- a/source/blender/editors/space_buttons/buttons_context.c +++ b/source/blender/editors/space_buttons/buttons_context.c @@ -626,7 +626,7 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r Brush *br= ptr->data; if(br) - CTX_data_pointer_set(result, &br->id, &RNA_BrushTextureSlot, br->mtex[(int)br->texact]); + CTX_data_pointer_set(result, &br->id, &RNA_BrushTextureSlot, &br->mtex); } return 1; diff --git a/source/blender/editors/space_buttons/buttons_header.c b/source/blender/editors/space_buttons/buttons_header.c index 0fb7ea9283c..c9df1f76dd9 100644 --- a/source/blender/editors/space_buttons/buttons_header.c +++ b/source/blender/editors/space_buttons/buttons_header.c @@ -67,7 +67,7 @@ static void do_buttons_buttons(bContext *C, void *arg, int event) { SpaceButs *sbuts= CTX_wm_space_buts(C); - if(!sbuts) /* window type switch */ + if(!sbuts) /* editor type switch */ return; switch(event) { diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c index 7e51ee2a5e9..8d35e6ed69e 100644 --- a/source/blender/editors/space_buttons/space_buttons.c +++ b/source/blender/editors/space_buttons/space_buttons.c @@ -322,6 +322,7 @@ static void buttons_area_listener(ScrArea *sa, wmNotifier *wmn) switch(wmn->data) { case ND_SHADING: case ND_SHADING_DRAW: + case ND_NODES: /* currently works by redraws... if preview is set, it (re)starts job */ sbuts->preview= 1; break; @@ -335,6 +336,10 @@ static void buttons_area_listener(ScrArea *sa, wmNotifier *wmn) buttons_area_redraw(sa, BCONTEXT_DATA); sbuts->preview= 1; break; + case NC_BRUSH: + buttons_area_redraw(sa, BCONTEXT_TEXTURE); + sbuts->preview= 1; + break; case NC_TEXTURE: ED_area_tag_redraw(sa); sbuts->preview= 1; @@ -347,6 +352,12 @@ static void buttons_area_listener(ScrArea *sa, wmNotifier *wmn) if(wmn->action == NA_RENAME) ED_area_tag_redraw(sa); break; + case NC_ANIMATION: + switch(wmn->data) { + case ND_KEYFRAME_EDIT: + ED_area_tag_redraw(sa); + break; + } } if(wmn->data == ND_KEYS) diff --git a/source/blender/editors/space_console/console_intern.h b/source/blender/editors/space_console/console_intern.h index 92ab3eb3d0c..a90e434246f 100644 --- a/source/blender/editors/space_console/console_intern.h +++ b/source/blender/editors/space_console/console_intern.h @@ -63,7 +63,6 @@ void CONSOLE_OT_clear(struct wmOperatorType *ot); void CONSOLE_OT_history_cycle(struct wmOperatorType *ot); void CONSOLE_OT_copy(struct wmOperatorType *ot); void CONSOLE_OT_paste(struct wmOperatorType *ot); -void CONSOLE_OT_zoom(struct wmOperatorType *ot); void CONSOLE_OT_select_set(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_console/console_ops.c b/source/blender/editors/space_console/console_ops.c index e615ae8f140..76e1231b0d4 100644 --- a/source/blender/editors/space_console/console_ops.c +++ b/source/blender/editors/space_console/console_ops.c @@ -750,38 +750,6 @@ void CONSOLE_OT_paste(wmOperatorType *ot) /* properties */ } -static int zoom_exec(bContext *C, wmOperator *op) -{ - SpaceConsole *sc= CTX_wm_space_console(C); - - int delta= RNA_int_get(op->ptr, "delta"); - - sc->lheight += delta; - CLAMP(sc->lheight, 8, 32); - - ED_area_tag_redraw(CTX_wm_area(C)); - - return OPERATOR_FINISHED; -} - - -void CONSOLE_OT_zoom(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Console Zoom"; - /*optionals - - "Zoom view font." */ - ot->description= "Zoom screen area."; - ot->idname= "CONSOLE_OT_zoom"; - - /* api callbacks */ - ot->exec= zoom_exec; - ot->poll= console_poll; - - /* properties */ - RNA_def_int(ot->srna, "delta", 0, 0, INT_MAX, "Delta", "Scale the view font.", 0, 1000); -} - typedef struct SetConsoleCursor { int sel_old[2]; int sel_init; @@ -824,7 +792,7 @@ static void console_modal_select_apply(bContext *C, wmOperator *op, wmEvent *eve static void set_cursor_exit(bContext *C, wmOperator *op) { - SpaceConsole *sc= CTX_wm_space_console(C); +// SpaceConsole *sc= CTX_wm_space_console(C); SetConsoleCursor *scu= op->customdata; /* @@ -840,7 +808,7 @@ static void set_cursor_exit(bContext *C, wmOperator *op) static int console_modal_select_invoke(bContext *C, wmOperator *op, wmEvent *event) { SpaceConsole *sc= CTX_wm_space_console(C); - ARegion *ar= CTX_wm_region(C); +// ARegion *ar= CTX_wm_region(C); SetConsoleCursor *scu; op->customdata= MEM_callocN(sizeof(SetConsoleCursor), "SetConsoleCursor"); @@ -891,5 +859,5 @@ void CONSOLE_OT_select_set(wmOperatorType *ot) ot->invoke= console_modal_select_invoke; ot->modal= console_modal_select; ot->cancel= console_modal_select_cancel; - ot->poll= console_poll; + ot->poll= console_edit_poll; } diff --git a/source/blender/editors/space_console/space_console.c b/source/blender/editors/space_console/space_console.c index f4058f4eefb..e9e87a865ef 100644 --- a/source/blender/editors/space_console/space_console.c +++ b/source/blender/editors/space_console/space_console.c @@ -207,7 +207,6 @@ void console_operatortypes(void) WM_operatortype_append(CONSOLE_OT_history_cycle); WM_operatortype_append(CONSOLE_OT_copy); WM_operatortype_append(CONSOLE_OT_paste); - WM_operatortype_append(CONSOLE_OT_zoom); WM_operatortype_append(CONSOLE_OT_select_set); /* console_report.c */ @@ -223,6 +222,7 @@ void console_operatortypes(void) void console_keymap(struct wmKeyConfig *keyconf) { wmKeyMap *keymap= WM_keymap_find(keyconf, "Console", SPACE_CONSOLE, 0); + wmKeyMapItem *kmi; #ifdef __APPLE__ RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", LEFTARROWKEY, KM_PRESS, KM_OSKEY, 0)->ptr, "type", LINE_BEGIN); @@ -235,13 +235,22 @@ void console_keymap(struct wmKeyConfig *keyconf) RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", HOMEKEY, KM_PRESS, 0, 0)->ptr, "type", LINE_BEGIN); RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", ENDKEY, KM_PRESS, 0, 0)->ptr, "type", LINE_END); - RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_zoom", WHEELUPMOUSE, KM_PRESS, KM_CTRL, 0)->ptr, "delta", 1); - RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_zoom", WHEELDOWNMOUSE, KM_PRESS, KM_CTRL, 0)->ptr, "delta", -1); - - RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_zoom", PADPLUSKEY, KM_PRESS, KM_CTRL, 0)->ptr, "delta", 1); - RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_zoom", PADMINUS, KM_PRESS, KM_CTRL, 0)->ptr, "delta", -1); + kmi = WM_keymap_add_item(keymap, "WM_OT_context_cycle_int", WHEELUPMOUSE, KM_PRESS, KM_CTRL, 0); + RNA_string_set(kmi->ptr, "path", "space_data.font_size"); + RNA_boolean_set(kmi->ptr, "reverse", 0); + kmi = WM_keymap_add_item(keymap, "WM_OT_context_cycle_int", WHEELDOWNMOUSE, KM_PRESS, KM_CTRL, 0); + RNA_string_set(kmi->ptr, "path", "space_data.font_size"); + RNA_boolean_set(kmi->ptr, "reverse", 1); + + kmi = WM_keymap_add_item(keymap, "WM_OT_context_cycle_int", PADPLUSKEY, KM_PRESS, KM_CTRL, 0); + RNA_string_set(kmi->ptr, "path", "space_data.font_size"); + RNA_boolean_set(kmi->ptr, "reverse", 0); + kmi = WM_keymap_add_item(keymap, "WM_OT_context_cycle_int", PADMINUS, KM_PRESS, KM_CTRL, 0); + RNA_string_set(kmi->ptr, "path", "space_data.font_size"); + RNA_boolean_set(kmi->ptr, "reverse", 1); + RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", LEFTARROWKEY, KM_PRESS, 0, 0)->ptr, "type", PREV_CHAR); RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", RIGHTARROWKEY, KM_PRESS, 0, 0)->ptr, "type", NEXT_CHAR); diff --git a/source/blender/editors/space_file/writeimage.c b/source/blender/editors/space_file/writeimage.c index 045c790b9cd..9e8e3b7b058 100644 --- a/source/blender/editors/space_file/writeimage.c +++ b/source/blender/editors/space_file/writeimage.c @@ -102,7 +102,7 @@ static void save_rendered_image_cb_real(char *name, int confirm) /* BKE_add_image_extension() checks for if extension was already set */ if(scene->r.scemode & R_EXTENSION) if(strlen(name)<FILE_MAXDIR+FILE_MAXFILE-5) - BKE_add_image_extension(scene, name, scene->r.imtype); + BKE_add_image_extension(name, scene->r.imtype); strcpy(str, name); BLI_convertstringcode(str, G.sce); diff --git a/source/blender/editors/space_graph/Makefile b/source/blender/editors/space_graph/Makefile index e04a354fb1d..65cdf1a3ffb 100644 --- a/source/blender/editors/space_graph/Makefile +++ b/source/blender/editors/space_graph/Makefile @@ -1,3 +1,5 @@ +# -*- mode: gnumakefile; tab-width: 8; indent-tabs-mode: t; -*- +# vim: tabstop=8 # # $Id$ # @@ -37,6 +39,8 @@ CFLAGS += $(LEVEL_1_C_WARNINGS) CPPFLAGS += -I$(NAN_GLEW)/include CPPFLAGS += -I$(OPENGL_HEADERS) +CPPFLAGS += -I$(NAN_AUDASPACE)/include +CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include # not very neat.... CPPFLAGS += -I../../windowmanager @@ -47,8 +51,6 @@ CPPFLAGS += -I../../makesdna CPPFLAGS += -I../../makesrna CPPFLAGS += -I../../imbuf CPPFLAGS += -I../../python -CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include - -# own include -CPPFLAGS += -I../include +# own include +CPPFLAGS += -I../include diff --git a/source/blender/editors/space_graph/SConscript b/source/blender/editors/space_graph/SConscript index cc9812678e9..174894ddfad 100644 --- a/source/blender/editors/space_graph/SConscript +++ b/source/blender/editors/space_graph/SConscript @@ -5,5 +5,6 @@ sources = env.Glob('*.c') incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../makesrna ../../imbuf' incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include' +incs += ' #/intern/audaspace/intern' env.BlenderLib ( 'bf_editors_space_graph', sources, Split(incs), [], libtype=['core'], priority=[50] ) diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c index 3faba9bbba7..a866ebd75e2 100644 --- a/source/blender/editors/space_graph/graph_buttons.c +++ b/source/blender/editors/space_graph/graph_buttons.c @@ -264,18 +264,18 @@ static void driver_add_var_cb (bContext *C, void *driver_v, void *dummy_v) { ChannelDriver *driver= (ChannelDriver *)driver_v; - /* add a new var */ - driver_add_new_target(driver); + /* add a new variable */ + driver_add_new_variable(driver); } /* callback to remove target variable from active driver */ -static void driver_delete_var_cb (bContext *C, void *driver_v, void *dtar_v) +static void driver_delete_var_cb (bContext *C, void *driver_v, void *dvar_v) { ChannelDriver *driver= (ChannelDriver *)driver_v; - DriverTarget *dtar= (DriverTarget *)dtar_v; + DriverVar *dvar= (DriverVar *)dvar_v; - /* remove the active target */ - driver_free_target(driver, dtar); + /* remove the active variable */ + driver_free_variable(driver, dvar); } /* callback to reset the driver's flags */ @@ -301,13 +301,146 @@ static int graph_panel_drivers_poll(const bContext *C, PanelType *pt) } +/* settings for 'single property' driver variable type */ +static void graph_panel_driverVar__singleProp(const bContext *C, uiLayout *layout, ID *id, DriverVar *dvar) +{ + DriverTarget *dtar= &dvar->targets[0]; + PointerRNA dtar_ptr; + uiLayout *row, *col; + uiBlock *block; + + /* initialise RNA pointer to the target */ + RNA_pointer_create(id, &RNA_DriverTarget, dtar, &dtar_ptr); + + /* Target ID */ + row= uiLayoutRow(layout, 0); + uiTemplateAnyID(row, (bContext *)C, &dtar_ptr, "id", "id_type", "Value:"); + + /* Target Property */ + // TODO: make this less technical... + if (dtar->id) { + PointerRNA root_ptr; + + /* get pointer for resolving the property selected */ + RNA_id_pointer_create(dtar->id, &root_ptr); + + col= uiLayoutColumn(layout, 1); + block= uiLayoutGetBlock(col); + /* rna path */ + uiTemplatePathBuilder(col, (bContext *)C, &dtar_ptr, "data_path", &root_ptr, "Path"); + } +} + +/* settings for 'rotation difference' driver variable type */ +static void graph_panel_driverVar__rotDiff(const bContext *C, uiLayout *layout, ID *id, DriverVar *dvar) +{ + DriverTarget *dtar= &dvar->targets[0]; + DriverTarget *dtar2= &dvar->targets[1]; + Object *ob1 = (Object *)dtar->id; + Object *ob2 = (Object *)dtar2->id; + PointerRNA dtar_ptr, dtar2_ptr; + uiLayout *col; + + /* initialise RNA pointer to the target */ + RNA_pointer_create(id, &RNA_DriverTarget, dtar, &dtar_ptr); + RNA_pointer_create(id, &RNA_DriverTarget, dtar2, &dtar2_ptr); + + /* Bone 1 */ + col= uiLayoutColumn(layout, 1); + uiTemplateAnyID(col, (bContext *)C, &dtar_ptr, "id", "id_type", "Bone 1:"); + + if (dtar->id && ob1->pose) { + PointerRNA tar_ptr; + + RNA_pointer_create(dtar->id, &RNA_Pose, ob1->pose, &tar_ptr); + uiItemPointerR(col, "", ICON_BONE_DATA, &dtar_ptr, "bone_target", &tar_ptr, "bones"); + } + + col= uiLayoutColumn(layout, 1); + uiTemplateAnyID(col, (bContext *)C, &dtar2_ptr, "id", "id_type", "Bone 2:"); + + if (dtar2->id && ob2->pose) { + PointerRNA tar_ptr; + + RNA_pointer_create(dtar2->id, &RNA_Pose, ob2->pose, &tar_ptr); + uiItemPointerR(col, "", ICON_BONE_DATA, &dtar2_ptr, "bone_target", &tar_ptr, "bones"); + } +} + +/* settings for 'location difference' driver variable type */ +static void graph_panel_driverVar__locDiff(const bContext *C, uiLayout *layout, ID *id, DriverVar *dvar) +{ + DriverTarget *dtar= &dvar->targets[0]; + DriverTarget *dtar2= &dvar->targets[1]; + Object *ob1 = (Object *)dtar->id; + Object *ob2 = (Object *)dtar2->id; + PointerRNA dtar_ptr, dtar2_ptr; + uiLayout *col; + + /* initialise RNA pointer to the target */ + RNA_pointer_create(id, &RNA_DriverTarget, dtar, &dtar_ptr); + RNA_pointer_create(id, &RNA_DriverTarget, dtar2, &dtar2_ptr); + + /* Bone 1 */ + col= uiLayoutColumn(layout, 1); + uiTemplateAnyID(col, (bContext *)C, &dtar_ptr, "id", "id_type", "Ob/Bone 1:"); + + if (dtar->id && ob1->pose) { + PointerRNA tar_ptr; + + RNA_pointer_create(dtar->id, &RNA_Pose, ob1->pose, &tar_ptr); + uiItemPointerR(col, "", ICON_BONE_DATA, &dtar_ptr, "bone_target", &tar_ptr, "bones"); + } + + uiItemR(col, NULL, 0, &dtar_ptr, "use_local_space_transforms", 0); + + col= uiLayoutColumn(layout, 1); + uiTemplateAnyID(col, (bContext *)C, &dtar2_ptr, "id", "id_type", "Ob/Bone 2:"); + + if (dtar2->id && ob2->pose) { + PointerRNA tar_ptr; + + RNA_pointer_create(dtar2->id, &RNA_Pose, ob2->pose, &tar_ptr); + uiItemPointerR(col, "", ICON_BONE_DATA, &dtar2_ptr, "bone_target", &tar_ptr, "bones"); + } + + uiItemR(col, NULL, 0, &dtar2_ptr, "use_local_space_transforms", 0); +} + +/* settings for 'transform channel' driver variable type */ +static void graph_panel_driverVar__transChan(const bContext *C, uiLayout *layout, ID *id, DriverVar *dvar) +{ + DriverTarget *dtar= &dvar->targets[0]; + Object *ob = (Object *)dtar->id; + PointerRNA dtar_ptr; + uiLayout *col, *row; + + /* initialise RNA pointer to the target */ + RNA_pointer_create(id, &RNA_DriverTarget, dtar, &dtar_ptr); + + /* properties */ + col= uiLayoutColumn(layout, 1); + uiTemplateAnyID(col, (bContext *)C, &dtar_ptr, "id", "id_type", "Ob/Bone:"); + + if (dtar->id && ob->pose) { + PointerRNA tar_ptr; + + RNA_pointer_create(dtar->id, &RNA_Pose, ob->pose, &tar_ptr); + uiItemPointerR(col, "", ICON_BONE_DATA, &dtar_ptr, "bone_target", &tar_ptr, "bones"); + } + + row= uiLayoutRow(layout, 1); + uiItemR(row, "", 0, &dtar_ptr, "transform_type", 0); + uiItemR(row, NULL, 0, &dtar_ptr, "use_local_space_transforms", 0); +} + /* driver settings for active F-Curve (only for 'Drivers' mode) */ static void graph_panel_drivers(const bContext *C, Panel *pa) { bAnimListElem *ale; FCurve *fcu; ChannelDriver *driver; - DriverTarget *dtar; + DriverVar *dvar; PointerRNA driver_ptr; uiLayout *col; @@ -354,56 +487,57 @@ static void graph_panel_drivers(const bContext *C, Panel *pa) uiItemL(col, "ERROR: invalid target channel(s)", ICON_ERROR); } - /* add driver target variables */ + /* add driver variables */ col= uiLayoutColumn(pa->layout, 0); block= uiLayoutGetBlock(col); - but= uiDefBut(block, BUT, B_IPO_DEPCHANGE, "Add Target", 0, 0, 10*UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "Add a new target variable for this Driver"); + but= uiDefBut(block, BUT, B_IPO_DEPCHANGE, "Add Variable", 0, 0, 10*UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "Add a new target variable for this Driver"); uiButSetFunc(but, driver_add_var_cb, driver, NULL); /* loop over targets, drawing them */ - for (dtar= driver->targets.first; dtar; dtar= dtar->next) { - PointerRNA dtar_ptr; + for (dvar= driver->variables.first; dvar; dvar= dvar->next) { + PointerRNA dvar_ptr; uiLayout *box, *row; - /* panel holding the buttons */ - box= uiLayoutBox(pa->layout); - - /* first row context info for driver */ - RNA_pointer_create(ale->id, &RNA_DriverTarget, dtar, &dtar_ptr); - - row= uiLayoutRow(box, 0); - block= uiLayoutGetBlock(row); - /* variable name */ - uiItemR(row, "", 0, &dtar_ptr, "name", 0); - - /* remove button */ - but= uiDefIconBut(block, BUT, B_IPO_DEPCHANGE, ICON_X, 290, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0.0, 0.0, "Delete target variable."); - uiButSetFunc(but, driver_delete_var_cb, driver, dtar); - - - /* Target ID */ - row= uiLayoutRow(box, 0); - uiTemplateAnyID(row, (bContext *)C, &dtar_ptr, "id", "id_type", "Value:"); + /* sub-layout column for this variable's settings */ + col= uiLayoutColumn(pa->layout, 1); - /* Target Property */ - // TODO: make this less technical... - if (dtar->id) { - PointerRNA root_ptr; + /* header panel */ + box= uiLayoutBox(col); + /* first row context info for driver */ + RNA_pointer_create(ale->id, &RNA_DriverVariable, dvar, &dvar_ptr); - /* get pointer for resolving the property selected */ - RNA_id_pointer_create(dtar->id, &root_ptr); + row= uiLayoutRow(box, 0); + block= uiLayoutGetBlock(row); + /* variable name */ + uiItemR(row, "", 0, &dvar_ptr, "name", 0); + + /* remove button */ + uiBlockSetEmboss(block, UI_EMBOSSN); + but= uiDefIconBut(block, BUT, B_IPO_DEPCHANGE, ICON_X, 290, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0.0, 0.0, "Delete target variable."); + uiButSetFunc(but, driver_delete_var_cb, driver, dvar); + uiBlockSetEmboss(block, UI_EMBOSS); - col= uiLayoutColumn(box, 1); - block= uiLayoutGetBlock(col); - /* rna path */ - uiTemplatePathBuilder(col, (bContext *)C, &dtar_ptr, "data_path", &root_ptr, "Path"); + /* variable type */ + row= uiLayoutRow(box, 0); + uiItemR(row, "", 0, &dvar_ptr, "type", 0); - /* array index */ - // TODO: this needs selector which limits it to ok values - // NOTE: for for now, the array index box still gets shown when non-zero (i.e. for tweaking rigs as necessary) - if (dtar->array_index) - uiItemR(col, "Index", 0, &dtar_ptr, "array_index", 0); - } + /* variable type settings */ + box= uiLayoutBox(col); + /* controls to draw depends on the type of variable */ + switch (dvar->type) { + case DVAR_TYPE_SINGLE_PROP: /* single property */ + graph_panel_driverVar__singleProp(C, box, ale->id, dvar); + break; + case DVAR_TYPE_ROT_DIFF: /* rotational difference */ + graph_panel_driverVar__rotDiff(C, box, ale->id, dvar); + break; + case DVAR_TYPE_LOC_DIFF: /* location difference */ + graph_panel_driverVar__locDiff(C, box, ale->id, dvar); + break; + case DVAR_TYPE_TRANSFORM_CHAN: /* transform channel */ + graph_panel_driverVar__transChan(C, box, ale->id, dvar); + break; + } } /* cleanup */ diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index 8ac3f2efefb..ffc450b5368 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -36,6 +36,8 @@ #include <config.h> #endif +#include "AUD_C-API.h" + #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" @@ -990,6 +992,147 @@ void GRAPH_OT_bake (wmOperatorType *ot) // todo: add props for start/end frames } +/* ******************** Sound Bake F-Curve Operator *********************** */ +/* This operator bakes the given sound to the selected F-Curves */ + +/* ------------------- */ + +/* Custom data storage passed to the F-Sample-ing function, + * which provides the necessary info for baking the sound + */ +typedef struct tSoundBakeInfo { + float* samples; + int length; + int cfra; +} tSoundBakeInfo; + +/* ------------------- */ + +/* Sampling callback used to determine the value from the sound to + * save in the F-Curve at the specified frame + */ +static float fcurve_samplingcb_sound (FCurve *fcu, void *data, float evaltime) +{ + tSoundBakeInfo *sbi= (tSoundBakeInfo *)data; + + int position = evaltime - sbi->cfra; + if((position < 0) || (position >= sbi->length)) + return 0.0f; + + return sbi->samples[position]; +} + +/* ------------------- */ + +static int graphkeys_sound_bake_exec(bContext *C, wmOperator *op) +{ + bAnimContext ac; + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + tSoundBakeInfo sbi; + Scene *scene= NULL; + int start, end; + + char path[FILE_MAX]; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + RNA_string_get(op->ptr, "path", path); + + scene= ac.scene; /* current scene */ + + /* store necessary data for the baking steps */ + sbi.samples = AUD_readSoundBuffer(path, + RNA_float_get(op->ptr, "low"), + RNA_float_get(op->ptr, "high"), + RNA_float_get(op->ptr, "attack"), + RNA_float_get(op->ptr, "release"), + RNA_float_get(op->ptr, "threshold"), + RNA_boolean_get(op->ptr, "accumulate"), + RNA_boolean_get(op->ptr, "additive"), + RNA_boolean_get(op->ptr, "square"), + RNA_float_get(op->ptr, "sthreshold"), + FPS, &sbi.length); + + if (sbi.samples == NULL) { + BKE_report(op->reports, RPT_ERROR, "Unsupported audio format"); + return OPERATOR_CANCELLED; + } + + /* determine extents of the baking */ + sbi.cfra = start = CFRA; + end = CFRA + sbi.length - 1; + + /* filter anim channels */ + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + /* loop through all selected F-Curves, replacing its data with the sound samples */ + for (ale= anim_data.first; ale; ale= ale->next) { + FCurve *fcu= (FCurve *)ale->key_data; + + /* sample the sound */ + fcurve_store_samples(fcu, &sbi, start, end, fcurve_samplingcb_sound); + } + + /* free sample data */ + free(sbi.samples); + + /* admin and redraws */ + BLI_freelistN(&anim_data); + + /* validate keyframes after editing */ + ANIM_editkeyframes_refresh(&ac); + + /* set notifier that 'keyframes' have changed */ + WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL); + + return OPERATOR_FINISHED; +} + +static int graphkeys_sound_bake_invoke (bContext *C, wmOperator *op, wmEvent *event) +{ + bAnimContext ac; + + /* verify editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + return WM_operator_filesel(C, op, event); +} + +void GRAPH_OT_sound_bake (wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Bake Sound to F-Curves"; + ot->idname= "GRAPH_OT_sound_bake"; + ot->description= "Bakes a sound wave to selected F-Curves."; + + /* api callbacks */ + ot->invoke= graphkeys_sound_bake_invoke; + ot->exec= graphkeys_sound_bake_exec; + ot->poll= graphop_selected_fcurve_poll; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* properties */ + WM_operator_properties_filesel(ot, FOLDERFILE|SOUNDFILE|MOVIEFILE, FILE_SPECIAL); + RNA_def_float(ot->srna, "low", 0.0f, 0.0, 100000.0, "Lowest frequency", "", 0.1, 1000.00); + RNA_def_float(ot->srna, "high", 100000.0, 0.0, 100000.0, "Highest frequency", "", 0.1, 1000.00); + RNA_def_float(ot->srna, "attack", 0.005, 0.0, 2.0, "Attack time", "", 0.01, 0.1); + RNA_def_float(ot->srna, "release", 0.2, 0.0, 5.0, "Release time", "", 0.01, 0.2); + RNA_def_float(ot->srna, "threshold", 0.0, 0.0, 1.0, "Threshold", "", 0.01, 0.1); + RNA_def_boolean(ot->srna, "accumulate", 0, "Accumulate", ""); + RNA_def_boolean(ot->srna, "additive", 0, "Additive", ""); + RNA_def_boolean(ot->srna, "square", 0, "Square", ""); + RNA_def_float(ot->srna, "sthreshold", 0.1, 0.0, 1.0, "Square Threshold", "", 0.01, 0.1); +} + /* ******************** Sample Keyframes Operator *********************** */ /* This operator 'bakes' the values of the curve into new keyframes between pairs * of selected keyframes. It is useful for creating keyframes for tweaking overlap. diff --git a/source/blender/editors/space_graph/graph_intern.h b/source/blender/editors/space_graph/graph_intern.h index 87e03247353..ec6f38c93b7 100644 --- a/source/blender/editors/space_graph/graph_intern.h +++ b/source/blender/editors/space_graph/graph_intern.h @@ -100,6 +100,7 @@ void GRAPH_OT_delete(struct wmOperatorType *ot); void GRAPH_OT_clean(struct wmOperatorType *ot); void GRAPH_OT_sample(struct wmOperatorType *ot); void GRAPH_OT_bake(struct wmOperatorType *ot); +void GRAPH_OT_sound_bake(struct wmOperatorType *ot); void GRAPH_OT_smooth(struct wmOperatorType *ot); void GRAPH_OT_handle_type(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c index 295ee869979..7be2d7b3e4b 100644 --- a/source/blender/editors/space_graph/graph_ops.c +++ b/source/blender/editors/space_graph/graph_ops.c @@ -247,6 +247,7 @@ void graphedit_operatortypes(void) WM_operatortype_append(GRAPH_OT_extrapolation_type); WM_operatortype_append(GRAPH_OT_sample); WM_operatortype_append(GRAPH_OT_bake); + WM_operatortype_append(GRAPH_OT_sound_bake); WM_operatortype_append(GRAPH_OT_smooth); WM_operatortype_append(GRAPH_OT_clean); WM_operatortype_append(GRAPH_OT_delete); diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index 4811eb411ec..6b92fc3fe4f 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -389,7 +389,7 @@ static void image_panel_curves(const bContext *C, Panel *pa) levels= (ibuf->channels==4); RNA_pointer_create(&sc->id, &RNA_SpaceImageEditor, sima, &simaptr); - uiTemplateCurveMapping(pa->layout, &simaptr, "curves", 'c', levels); + uiTemplateCurveMapping(pa->layout, &simaptr, "curves", 'c', levels, 0); } ED_space_image_release_buffer(sima, lock); diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c index 46ec41eda58..ea526b13219 100644 --- a/source/blender/editors/space_image/image_draw.c +++ b/source/blender/editors/space_image/image_draw.c @@ -126,7 +126,7 @@ static void image_verify_buffer_float(SpaceImage *sima, Image *ima, ImBuf *ibuf, else { if (color_manage) { if (ima && ima->source == IMA_SRC_VIEWER) - ibuf->profile = IB_PROFILE_SRGB; + ibuf->profile = IB_PROFILE_LINEAR_RGB; } else { ibuf->profile = IB_PROFILE_NONE; } diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 897b02404ef..827b2ddeac2 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -649,7 +649,8 @@ static int open_exec(bContext *C, wmOperator *op) char str[FILE_MAX]; RNA_string_get(op->ptr, "path", str); - ima= BKE_add_image_file(str, scene->r.cfra); + /* default to frame 1 if there's no scene in context */ + ima= BKE_add_image_file(str, scene ? scene->r.cfra : 1); if(!ima) { if(op->customdata) MEM_freeN(op->customdata); @@ -784,8 +785,7 @@ static void save_image_doit(bContext *C, SpaceImage *sima, Scene *scene, wmOpera BLI_convertstringframe(name, scene->r.cfra); if(scene->r.scemode & R_EXTENSION) { - BKE_add_image_extension(scene, name, sima->imtypenr); - BKE_add_image_extension(scene, name, sima->imtypenr); + BKE_add_image_extension(name, sima->imtypenr); } /* enforce user setting for RGB or RGBA, but skip BW */ diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index a077357d03e..4622962bac5 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -290,7 +290,7 @@ static void image_listener(ScrArea *sa, wmNotifier *wmn) break; } break; - case NC_IMAGE: + case NC_IMAGE: ED_area_tag_redraw(sa); break; case NC_SPACE: diff --git a/source/blender/editors/space_info/info_ops.c b/source/blender/editors/space_info/info_ops.c index 13bcd3276af..81506d42d87 100644 --- a/source/blender/editors/space_info/info_ops.c +++ b/source/blender/editors/space_info/info_ops.c @@ -196,21 +196,12 @@ void FILE_OT_unpack_all(wmOperatorType *ot) static int make_paths_relative_exec(bContext *C, wmOperator *op) { - char txtname[24]; /* text block name */ - int tot, changed, failed, linked; - if(!G.relbase_valid) { BKE_report(op->reports, RPT_WARNING, "Can't set relative paths with an unsaved blend file."); return OPERATOR_CANCELLED; } - txtname[0] = '\0'; - makeFilesRelative(txtname, &tot, &changed, &failed, &linked); - - if(failed) - BKE_reportf(op->reports, RPT_ERROR, "Total files %i|Changed %i|Failed %i, See Text \"%s\"|Linked %i", tot, changed, failed, txtname, linked); - else - BKE_reportf(op->reports, RPT_INFO, "Total files %i|Changed %i|Failed %i|Linked %i", tot, changed, failed, linked); + makeFilesRelative(G.sce, op->reports); return OPERATOR_FINISHED; } @@ -232,22 +223,12 @@ void FILE_OT_make_paths_relative(wmOperatorType *ot) static int make_paths_absolute_exec(bContext *C, wmOperator *op) { - char txtname[24]; /* text block name */ - int tot, changed, failed, linked; - if(!G.relbase_valid) { BKE_report(op->reports, RPT_WARNING, "Can't set absolute paths with an unsaved blend file."); return OPERATOR_CANCELLED; } - txtname[0] = '\0'; - makeFilesAbsolute(txtname, &tot, &changed, &failed, &linked); - - if(failed) - BKE_reportf(op->reports, RPT_ERROR, "Total files %i|Changed %i|Failed %i, See Text \"%s\"|Linked %i", tot, changed, failed, txtname, linked); - else - BKE_reportf(op->reports, RPT_INFO, "Total files %i|Changed %i|Failed %i|Linked %i", tot, changed, failed, linked); - + makeFilesAbsolute(G.sce, op->reports); return OPERATOR_FINISHED; } @@ -273,12 +254,7 @@ static int report_missing_files_exec(bContext *C, wmOperator *op) txtname[0] = '\0'; /* run the missing file check */ - checkMissingFiles(txtname); - - if(txtname[0] == '\0') - BKE_report(op->reports, RPT_INFO, "No external files missing."); - else - BKE_reportf(op->reports, RPT_ERROR, "Missing files listed in Text \"%s\"", txtname); + checkMissingFiles(G.sce, op->reports); return OPERATOR_FINISHED; } @@ -303,7 +279,7 @@ static int find_missing_files_exec(bContext *C, wmOperator *op) char *path; path= RNA_string_get_alloc(op->ptr, "path", NULL, 0); - findMissingFiles(path); + findMissingFiles(path, G.sce); MEM_freeN(path); return OPERATOR_FINISHED; diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 30212abd4da..7f8bf2618a4 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -166,6 +166,7 @@ static void node_buts_rgb(uiLayout *layout, bContext *C, PointerRNA *ptr) RNA_property_collection_lookup_int(ptr, prop, 0, &sockptr); col = uiLayoutColumn(layout, 0); + uiTemplateColorWheel(col, &sockptr, "default_value", 1); uiItemR(col, "", 0, &sockptr, "default_value", 0); } @@ -196,7 +197,7 @@ static void node_buts_time(uiLayout *layout, bContext *C, PointerRNA *ptr) } #endif - uiTemplateCurveMapping(layout, ptr, "curve", 's', 0); + uiTemplateCurveMapping(layout, ptr, "curve", 's', 0, 0); row= uiLayoutRow(layout, 1); uiItemR(row, "Sta", 0, ptr, "start", 0); @@ -210,7 +211,7 @@ static void node_buts_colorramp(uiLayout *layout, bContext *C, PointerRNA *ptr) static void node_buts_curvevec(uiLayout *layout, bContext *C, PointerRNA *ptr) { - uiTemplateCurveMapping(layout, ptr, "mapping", 'v', 0); + uiTemplateCurveMapping(layout, ptr, "mapping", 'v', 0, 0); } static float *_sample_col= NULL; // bad bad, 2.5 will do better? @@ -231,7 +232,7 @@ static void node_buts_curvecol(uiLayout *layout, bContext *C, PointerRNA *ptr) else cumap->flag &= ~CUMA_DRAW_SAMPLE; - uiTemplateCurveMapping(layout, ptr, "mapping", 'c', 0); + uiTemplateCurveMapping(layout, ptr, "mapping", 'c', 0, 0); } static void node_buts_normal(uiLayout *layout, bContext *C, PointerRNA *ptr) @@ -545,16 +546,33 @@ static void node_composit_buts_image(uiLayout *layout, bContext *C, PointerRNA * static void node_composit_buts_renderlayers(uiLayout *layout, bContext *C, PointerRNA *ptr) { bNode *node= ptr->data; - uiLayout *col; - + uiLayout *col, *row; + PointerRNA op_ptr; + PointerRNA scn_ptr; + PropertyRNA *prop; + const char *layer_name; + char scene_name[19]; + uiTemplateID(layout, C, ptr, "scene", NULL, NULL, NULL); if(!node->id) return; col= uiLayoutColumn(layout, 0); - uiItemR(col, "", 0, ptr, "layer", 0); + row = uiLayoutRow(col, 0); + uiItemR(row, "", 0, ptr, "layer", 0); - /* XXX Missing 're-render this layer' button - needs completely new implementation */ + prop = RNA_struct_find_property(ptr, "layer"); + if (!(RNA_property_enum_identifier(C, ptr, prop, RNA_property_enum_get(ptr, prop), &layer_name))) + return; + + scn_ptr = RNA_pointer_get(ptr, "scene"); + RNA_string_get(&scn_ptr, "name", scene_name); + + WM_operator_properties_create(&op_ptr, "SCREEN_OT_render"); + RNA_string_set(&op_ptr, "layer", layer_name); + RNA_string_set(&op_ptr, "scene", scene_name); + uiItemFullO(row, "", ICON_RENDER_STILL, "SCREEN_OT_render", op_ptr.data, WM_OP_INVOKE_DEFAULT, 0); + } @@ -1251,7 +1269,7 @@ void draw_nodespace_back_pix(ARegion *ar, SpaceNode *snode, int color_manage) if(!ibuf->rect) { if(color_manage) - ibuf->profile= IB_PROFILE_SRGB; + ibuf->profile = IB_PROFILE_LINEAR_RGB; else ibuf->profile = IB_PROFILE_NONE; IMB_rect_from_float(ibuf); diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c index 59085ce19cd..4fc0d37f6a6 100644 --- a/source/blender/editors/space_node/node_draw.c +++ b/source/blender/editors/space_node/node_draw.c @@ -506,9 +506,7 @@ static void socket_circle_draw(bNodeSocket *sock, float size) /* choose color based on sock flags */ if(sock->flag & SELECT) { - if(sock->flag & SOCK_SEL) { - col[0]= 240; col[1]= 200; col[2]= 40;} - else if(sock->type==SOCK_VALUE) { + if(sock->type==SOCK_VALUE) { col[0]= 200; col[1]= 200; col[2]= 200;} else if(sock->type==SOCK_VECTOR) { col[0]= 140; col[1]= 140; col[2]= 240;} @@ -517,8 +515,6 @@ static void socket_circle_draw(bNodeSocket *sock, float size) else { col[0]= 140; col[1]= 240; col[2]= 140;} } - else if(sock->flag & SOCK_SEL) { - col[0]= 200; col[1]= 160; col[2]= 0;} else { if(sock->type==-1) { col[0]= 0; col[1]= 0; col[2]= 0;} diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index f177e1a2622..c177cb7f1f5 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -222,116 +222,6 @@ void snode_handle_recalc(bContext *C, SpaceNode *snode) WM_event_add_notifier(C, NC_TEXTURE|ND_NODES, snode->id); } -#if 0 -static int image_detect_file_sequence(int *start_p, int *frames_p, char *str) -{ - SpaceFile *sfile; - char name[FILE_MAX], head[FILE_MAX], tail[FILE_MAX], filename[FILE_MAX]; - int a, frame, totframe, found, minframe; - unsigned short numlen; - - sfile= scrarea_find_space_of_type(curarea, SPACE_FILE); - if(sfile==NULL || sfile->filelist==NULL) - return 0; - - /* find first frame */ - found= 0; - minframe= 0; - - for(a=0; a<sfile->totfile; a++) { - if(sfile->filelist[a].flags & ACTIVE) { - BLI_strncpy(name, sfile->filelist[a].relname, sizeof(name)); - frame= BLI_stringdec(name, head, tail, &numlen); - - if(!found || frame < minframe) { - BLI_strncpy(filename, name, sizeof(name)); - minframe= frame; - found= 1; - } - } - } - - /* not one frame found */ - if(!found) - return 0; - - /* counter number of following frames */ - found= 1; - totframe= 0; - - for(frame=minframe; found; frame++) { - found= 0; - BLI_strncpy(name, filename, sizeof(name)); - BLI_stringenc(name, head, tail, numlen, frame); - - for(a=0; a<sfile->totfile; a++) { - if(sfile->filelist[a].flags & ACTIVE) { - if(strcmp(sfile->filelist[a].relname, name) == 0) { - found= 1; - totframe++; - break; - } - } - } - } - - if(totframe > 1) { - BLI_strncpy(str, sfile->dir, sizeof(name)); - strcat(str, filename); - - *start_p= minframe; - *frames_p= totframe; - return 1; - } - - return 0; -} - -static void load_node_image(char *str) /* called from fileselect */ -{ - SpaceNode *snode= curarea->spacedata.first; - bNode *node= nodeGetActive(snode->edittree); - Image *ima= NULL; - ImageUser *iuser= node->storage; - char filename[FILE_MAX]; - int start=0, frames=0, sequence; - - sequence= image_detect_file_sequence(&start, &frames, filename); - if(sequence) - str= filename; - - ima= BKE_add_image_file(str); - if(ima) { - if(node->id) - node->id->us--; - - node->id= &ima->id; - id_us_plus(node->id); - - BLI_strncpy(node->name, node->id->name+2, 21); - - if(sequence) { - ima->source= IMA_SRC_SEQUENCE; - iuser->frames= frames; - iuser->offset= start-1; - } - - BKE_image_signal(ima, node->storage, IMA_SIGNAL_RELOAD); - - NodeTagChanged(snode->edittree, node); - // XXX snode_handle_recalc(C, snode); - } -} - -static void set_node_imagepath(char *str) /* called from fileselect */ -{ - SpaceNode *snode= curarea->spacedata.first; - bNode *node= nodeGetActive(snode->edittree); - BLI_strncpy(((NodeImageFile *)node->storage)->name, str, sizeof( ((NodeImageFile *)node->storage)->name )); -} - -#endif /* 0 */ - bNode *node_tree_get_editgroup(bNodeTree *nodetree) { bNode *gnode; @@ -343,136 +233,6 @@ bNode *node_tree_get_editgroup(bNodeTree *nodetree) return gnode; } -#if 0 - -/* node has to be of type 'render layers' */ -/* is a bit clumsy copying renderdata here... scene nodes use render size of current render */ -static void composite_node_render(SpaceNode *snode, bNode *node) -{ - RenderData rd; - Scene *scene= NULL; - int scemode, actlay; - - /* the button press won't show up otherwise, button hilites disabled */ - force_draw(0); - - if(node->id && node->id!=(ID *)G.scene) { - scene= G.scene; - set_scene_bg((Scene *)node->id); - rd= G.scene->r; - G.scene->r.xsch= scene->r.xsch; - G.scene->r.ysch= scene->r.ysch; - G.scene->r.size= scene->r.size; - G.scene->r.mode &= ~(R_BORDER|R_DOCOMP); - G.scene->r.mode |= scene->r.mode & R_BORDER; - G.scene->r.border= scene->r.border; - G.scene->r.cfra= scene->r.cfra; - } - - scemode= G.scene->r.scemode; - actlay= G.scene->r.actlay; - - G.scene->r.scemode |= R_SINGLE_LAYER|R_COMP_RERENDER; - G.scene->r.actlay= node->custom1; - - BIF_do_render(0); - - G.scene->r.scemode= scemode; - G.scene->r.actlay= actlay; - - node->custom2= 0; - - if(scene) { - G.scene->r= rd; - set_scene_bg(scene); - } -} - -static void composit_node_event(SpaceNode *snode, short event) -{ - - switch(event) { - case B_REDR: - // allqueue(REDRAWNODE, 1); - break; - case B_NODE_SETIMAGE: - { - bNode *node= nodeGetActive(snode->edittree); - char name[FILE_MAXDIR+FILE_MAXFILE]; - - strcpy(name, ((NodeImageFile *)node->storage)->name); - if (G.qual & LR_CTRLKEY) { - activate_imageselect(FILE_SPECIAL, "SELECT OUTPUT DIR", name, set_node_imagepath); - } else { - activate_fileselect(FILE_SPECIAL, "SELECT OUTPUT DIR", name, set_node_imagepath); - } - break; - } - case B_NODE_TREE_EXEC: - // XXX snode_handle_recalc(snode); - break; - default: - /* B_NODE_EXEC */ - { - bNode *node= BLI_findlink(&snode->edittree->nodes, event-B_NODE_EXEC); - if(node) { - NodeTagChanged(snode->edittree, node); - /* don't use NodeTagIDChanged, it gives far too many recomposites for image, scene layers, ... */ - - /* not the best implementation of the world... but we need it to work now :) */ - if(node->type==CMP_NODE_R_LAYERS && node->custom2) { - /* add event for this window (after render curarea can be changed) */ - addqueue(curarea->win, UI_BUT_EVENT, B_NODE_TREE_EXEC); - - composite_node_render(snode, node); - // XXX snode_handle_recalc(snode); - - /* add another event, a render can go fullscreen and open new window */ - addqueue(curarea->win, UI_BUT_EVENT, B_NODE_TREE_EXEC); - } - else { - node= node_tree_get_editgroup(snode->nodetree); - if(node) - NodeTagIDChanged(snode->nodetree, node->id); - - // XXX snode_handle_recalc(snode); - } - } - } - } -} - -static void texture_node_event(SpaceNode *snode, short event) -{ - switch(event) { - case B_REDR: - // allqueue(REDRAWNODE, 1); - break; - case B_NODE_LOADIMAGE: - { - bNode *node= nodeGetActive(snode->edittree); - char name[FILE_MAXDIR+FILE_MAXFILE]; - - if(node->id) - strcpy(name, ((Image *)node->id)->name); - else strcpy(name, U.textudir); - if (G.qual & LR_CTRLKEY) { - activate_imageselect(FILE_SPECIAL, "SELECT IMAGE", name, load_node_image); - } else { - activate_fileselect(FILE_SPECIAL, "SELECT IMAGE", name, load_node_image); - } - break; - } - default: - /* B_NODE_EXEC */ - ntreeTexCheckCyclics( snode->nodetree ); - // XXX snode_handle_recalc(snode); - // allqueue(REDRAWNODE, 1); - break; - } -} - -#endif /* 0 */ /* assumes nothing being done in ntree yet, sets the default in/out node */ /* called from shading buttons or header */ void ED_node_shader_default(Material *ma) @@ -663,29 +423,6 @@ void snode_set_context(SpaceNode *snode, Scene *scene) node_tree_from_ID(snode->id, &snode->nodetree, &snode->edittree, NULL); } -#if 0 -/* on activate image viewer, check if we show it */ -static void node_active_image(Image *ima) -{ - ScrArea *sa; - SpaceImage *sima= NULL; - - /* find an imagewindow showing render result */ - for(sa=G.curscreen->areabase.first; sa; sa= sa->next) { - if(sa->spacetype==SPACE_IMAGE) { - sima= sa->spacedata.first; - if(sima->image && sima->image->source!=IMA_SRC_VIEWER) - break; - } - } - if(sa && sima) { - sima->image= ima; - scrarea_queue_winredraw(sa); - scrarea_queue_headredraw(sa); - } -} -#endif /* 0 */ - void node_set_active(SpaceNode *snode, bNode *node) { nodeSetActive(snode->edittree, node); @@ -735,18 +472,9 @@ void node_set_active(SpaceNode *snode, bNode *node) /* addnode() doesnt link this yet... */ node->id= (ID *)BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node"); } - else if(node->type==CMP_NODE_IMAGE) { - // XXX -#if 0 - if(node->id) - node_active_image((Image *)node->id); -#endif - } else if(node->type==CMP_NODE_R_LAYERS) { if(node->id==NULL || node->id==(ID *)scene) { scene->r.actlay= node->custom1; - // XXX - // allqueue(REDRAWBUTSSCENE, 0); } } } @@ -808,13 +536,6 @@ void snode_make_group_editable(SpaceNode *snode, bNode *gnode) snode->edittree= snode->nodetree; ntreeSolveOrder(snode->nodetree); - - /* finally send out events for new active node */ - if(snode->treetype==NTREE_SHADER) { - // allqueue(REDRAWBUTSSHADING, 0); - - // XXX BIF_preview_changed(-1); /* temp hack to force texture preview to update */ - } } static int node_group_edit_exec(bContext *C, wmOperator *op) @@ -1139,31 +860,8 @@ void NODE_OT_resize(wmOperatorType *ot) ot->flag= OPTYPE_BLOCKING; } - -#if 0 - /* ********************** select ******************** */ -/* used in buttons to check context, also checks for edited groups */ -bNode *editnode_get_active_idnode(bNodeTree *ntree, short id_code) -{ - return nodeGetActiveID(ntree, id_code); -} - -/* used in buttons to check context, also checks for edited groups */ -Material *editnode_get_active_material(Material *ma) -{ - if(ma && ma->use_nodes && ma->nodetree) { - bNode *node= editnode_get_active_idnode(ma->nodetree, ID_MA); - if(node) - return (Material *)node->id; - else - return NULL; - } - return ma; -} -#endif /* 0 */ - /* no undo here! */ void node_deselectall(SpaceNode *snode) @@ -1215,8 +913,6 @@ static void node_link_viewer(SpaceNode *snode, bNode *tonode) link->fromnode= tonode; link->fromsock= tonode->outputs.first; NodeTagChanged(snode->edittree, node); - -// XXX snode_handle_recalc(snode); } } } @@ -1353,59 +1049,156 @@ static int node_socket_hilights(SpaceNode *snode, int in_out) /* ****************** Add *********************** */ -void snode_autoconnect(SpaceNode *snode, bNode *node_to, int flag) + +typedef struct bNodeListItem { + struct bNodeListItem *next, *prev; + struct bNode *node; +} bNodeListItem; + +int sort_nodes_locx(void *a, void *b) { - bNodeSocket *sock, *sockfrom[8]; - bNode *node, *nodefrom[8]; - int totsock= 0, socktype=0; + bNodeListItem *nli1 = (bNodeListItem *)a; + bNodeListItem *nli2 = (bNodeListItem *)b; + bNode *node1 = nli1->node; + bNode *node2 = nli2->node; + + if (node1->locx > node2->locx) + return 1; + else + return 0; +} - if(node_to==NULL || node_to->inputs.first==NULL) - return; +static int socket_is_available(bNodeTree *ntree, bNodeSocket *sock, int allow_used) +{ + if (sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL)) + return 0; - /* no inputs for node allowed (code it) */ + if (!allow_used) { + if (nodeCountSocketLinks(ntree, sock) > 0) + return 0; + } + return 1; +} - /* connect first 1 socket type now */ - for(sock= node_to->inputs.first; sock; sock= sock->next) - if(socktype<sock->type) - socktype= sock->type; +static bNodeSocket *best_socket_output(bNodeTree *ntree, bNode *node, bNodeSocket *sock_target, int allow_multiple) +{ + bNodeSocket *sock; + + /* first try to find a socket with a matching name */ + for (sock=node->outputs.first; sock; sock=sock->next) { + if (!socket_is_available(ntree, sock, allow_multiple)) + continue; + + /* check for same types */ + if (sock->type == sock_target->type) { + if (strcmp(sock->name, sock_target->name)==0) + return sock; + } + } - /* find potential sockets, max 8 should work */ - for(node= snode->edittree->nodes.first; node; node= node->next) { - if((node->flag & flag) && node!=node_to) { - for(sock= node->outputs.first; sock; sock= sock->next) { - if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) { - sockfrom[totsock]= sock; - nodefrom[totsock]= node; - totsock++; - if(totsock>7) - break; - } + /* otherwise settle for the first available socket of the right type */ + for (sock=node->outputs.first; sock; sock=sock->next) { + + if (!socket_is_available(ntree, sock, allow_multiple)) + continue; + + /* check for same types */ + if (sock->type == sock_target->type) { + return sock; + } + } + + return NULL; +} + +/* this is a bit complicated, but designed to prioritise finding + * sockets of higher types, such as image, first */ +static bNodeSocket *best_socket_input(bNodeTree *ntree, bNode *node, int num, int replace) +{ + bNodeSocket *sock; + int socktype, maxtype=0; + int a; + + for (sock=node->inputs.first; sock; sock=sock->next) { + maxtype = MAX2(sock->type, maxtype); + } + + /* find sockets of higher 'types' first (i.e. image) */ + for (socktype=maxtype; socktype >= 0; socktype--) { + for (sock=node->inputs.first; sock; sock=sock->next) { + + if (!socket_is_available(ntree, sock, replace)) { + a++; + continue; + } + + if (sock->type == socktype) { + /* increment to make sure we don't keep finding + * the same socket on every attempt running this function */ + a++; + if (a > num) + return sock; } } - if(totsock>7) - break; } + + return NULL; +} - /* now just get matching socket types and create links */ - for(sock= node_to->inputs.first; sock; sock= sock->next) { - int a; +void snode_autoconnect(SpaceNode *snode, int allow_multiple, int replace) +{ + ListBase *nodelist = MEM_callocN(sizeof(ListBase), "items_list"); + bNodeListItem *nli; + bNode *node; + int i; + + for(node= snode->edittree->nodes.first; node; node= node->next) { + if(node->flag & NODE_SELECT) { + nli = MEM_mallocN(sizeof(bNodeListItem), "temporary node list item"); + nli->node = node; + BLI_addtail(nodelist, nli); + } + } + + /* sort nodes left to right */ + BLI_sortlist(nodelist, sort_nodes_locx); + + for (nli=nodelist->first; nli; nli=nli->next) { + bNode *node_fr, *node_to; + bNodeSocket *sock_fr, *sock_to; - for(a=0; a<totsock; a++) { - if(sockfrom[a]) { - if(sock->type==sockfrom[a]->type && sock->type==socktype) { - nodeAddLink(snode->edittree, nodefrom[a], sockfrom[a], node_to, sock); - sockfrom[a]= NULL; - break; - } - } + if (nli->next == NULL) break; + + node_fr = nli->node; + node_to = nli->next->node; + + /* check over input sockets first */ + for (i=0; i<BLI_countlist(&node_to->inputs); i++) { + + /* find the best guess input socket */ + sock_to = best_socket_input(snode->edittree, node_to, i, replace); + if (!sock_to) continue; + + /* check for an appropriate output socket to connect from */ + sock_fr = best_socket_output(snode->edittree, node_fr, sock_to, allow_multiple); + if (!sock_fr) continue; + + /* then we can connect */ + if (replace) + nodeRemSocketLinks(snode->edittree, sock_to); + nodeAddLink(snode->edittree, node_fr, sock_fr, node_to, sock_to); + NodeTagChanged(snode->edittree, node_to); + break; } } ntreeSolveOrder(snode->edittree); + + BLI_freelistN(nodelist); + MEM_freeN(nodelist); } - /* can be called from menus too, but they should do own undopush and redraws */ bNode *node_add_node(SpaceNode *snode, Scene *scene, int type, float locx, float locy) { @@ -1506,24 +1299,6 @@ typedef struct NodeLinkDrag int in_out; } NodeLinkDrag; -/*static*/ void reset_sel_socket(SpaceNode *snode, int in_out) -{ - bNode *node; - bNodeSocket *sock; - - for(node= snode->edittree->nodes.first; node; node= node->next) { - if(in_out & SOCK_IN) { - for(sock= node->inputs.first; sock; sock= sock->next) - if(sock->flag & SOCK_SEL) sock->flag&= ~SOCK_SEL; - } - if(in_out & SOCK_OUT) { - for(sock= node->outputs.first; sock; sock= sock->next) - if(sock->flag & SOCK_SEL) sock->flag&= ~SOCK_SEL; - } - } -} - - static void node_remove_extra_links(SpaceNode *snode, bNodeSocket *tsock, bNodeLink *link) { bNodeLink *tlink; @@ -1745,31 +1520,10 @@ void NODE_OT_link(wmOperatorType *ot) static int node_make_link_exec(bContext *C, wmOperator *op) { SpaceNode *snode= CTX_wm_space_node(C); - bNode *fromnode, *tonode; - bNodeLink *link; - bNodeSocket *outsock= snode->edittree->selout; - bNodeSocket *insock= snode->edittree->selin; - - if (!insock || !outsock) { - BKE_report(op->reports, RPT_ERROR, "No input or output socket(s) selected"); - return OPERATOR_CANCELLED; - } - if (nodeFindLink(snode->edittree, outsock, insock)) { - BKE_report(op->reports, RPT_ERROR, "There is already a link between these sockets"); - return OPERATOR_CANCELLED; - } + int replace = RNA_boolean_get(op->ptr, "replace"); - if (nodeFindNode(snode->edittree, outsock, &fromnode, NULL) && - nodeFindNode(snode->edittree, insock, &tonode, NULL)) - { - link= nodeAddLink(snode->edittree, fromnode, outsock, tonode, insock); - NodeTagChanged(snode->edittree, tonode); - node_remove_extra_links(snode, insock, link); - } - else - return OPERATOR_CANCELLED; + snode_autoconnect(snode, 0, replace); - ntreeSolveOrder(snode->edittree); node_tree_verify_groups(snode->nodetree); snode_handle_recalc(C, snode); @@ -1789,6 +1543,8 @@ void NODE_OT_link_make(wmOperatorType *ot) /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + RNA_def_boolean(ot->srna, "replace", 0, "Replace", "Replace socket connections with the new links"); } /* ********************** Cut Link operator ***************** */ @@ -2091,18 +1847,10 @@ static int node_delete_exec(bContext *C, wmOperator *op) { SpaceNode *snode= CTX_wm_space_node(C); bNode *node, *next; - bNodeSocket *sock; for(node= snode->edittree->nodes.first; node; node= next) { next= node->next; if(node->flag & SELECT) { - /* set selin and selout NULL if the sockets belong to a node to be deleted */ - for(sock= node->inputs.first; sock; sock= sock->next) - if(snode->edittree->selin == sock) snode->edittree->selin= NULL; - - for(sock= node->outputs.first; sock; sock= sock->next) - if(snode->edittree->selout == sock) snode->edittree->selout= NULL; - /* check id user here, nodeFreeNode is called for free dbase too */ if(node->id) node->id->us--; diff --git a/source/blender/editors/space_node/node_header.c b/source/blender/editors/space_node/node_header.c index 4cedbe3f666..d8a14c6412b 100644 --- a/source/blender/editors/space_node/node_header.c +++ b/source/blender/editors/space_node/node_header.c @@ -78,8 +78,17 @@ static void do_node_add(bContext *C, void *arg, int event) node= node_add_node(snode, CTX_data_scene(C), event, snode->mx, snode->my); - /* uses test flag */ - snode_autoconnect(snode, node, NODE_TEST); + /* select previous selection before autoconnect */ + for(node= snode->edittree->nodes.first; node; node= node->next) { + if(node->flag & NODE_TEST) node->flag |= NODE_SELECT; + } + + snode_autoconnect(snode, 1, 0); + + /* deselect after autoconnection */ + for(node= snode->edittree->nodes.first; node; node= node->next) { + if(node->flag & NODE_TEST) node->flag &= ~NODE_SELECT; + } snode_handle_recalc(C, snode); } diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h index 84729dd18ec..1ff2f7d7128 100644 --- a/source/blender/editors/space_node/node_intern.h +++ b/source/blender/editors/space_node/node_intern.h @@ -81,7 +81,7 @@ void node_deselectall(SpaceNode *snode); void snode_composite_job(const struct bContext *C, ScrArea *sa); bNode *node_tree_get_editgroup(bNodeTree *ntree); void node_tree_verify_groups(bNodeTree *nodetree); -void snode_autoconnect(SpaceNode *snode, bNode *node_to, int flag); +void snode_autoconnect(SpaceNode *snode, int allow_multiple, int replace); int node_has_hidden_sockets(bNode *node); void NODE_OT_duplicate(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_node/node_ops.c b/source/blender/editors/space_node/node_ops.c index 534ca0aa99c..bc04268c6f0 100644 --- a/source/blender/editors/space_node/node_ops.c +++ b/source/blender/editors/space_node/node_ops.c @@ -109,14 +109,16 @@ void node_keymap(struct wmKeyConfig *keyconf) RNA_boolean_set(kmi->ptr, "extend", 1); kmi= WM_keymap_add_item(keymap, "NODE_OT_select", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0); RNA_boolean_set(kmi->ptr, "extend", 1); + RNA_boolean_set(WM_keymap_add_item(keymap, "NODE_OT_select_border", EVT_TWEAK_S, KM_ANY, 0, 0)->ptr, "tweak", 1); /* each of these falls through if not handled... */ WM_keymap_add_item(keymap, "NODE_OT_link", LEFTMOUSE, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "NODE_OT_resize", LEFTMOUSE, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "NODE_OT_visibility_toggle", LEFTMOUSE, KM_PRESS, 0, 0); - WM_keymap_add_item(keymap, "NODE_OT_links_cut", RIGHTMOUSE, KM_PRESS, KM_ALT, 0); + WM_keymap_add_item(keymap, "NODE_OT_links_cut", LEFTMOUSE, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "NODE_OT_link_make", FKEY, KM_PRESS, 0, 0); + RNA_boolean_set(WM_keymap_add_item(keymap, "NODE_OT_link_make", FKEY, KM_PRESS, KM_CTRL, 0)->ptr, "replace", 1); WM_keymap_add_menu(keymap, "NODE_MT_add", AKEY, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "NODE_OT_duplicate_move", DKEY, KM_PRESS, KM_SHIFT, 0); diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.c index c81cfb47f5b..518901bcbec 100644 --- a/source/blender/editors/space_node/node_select.c +++ b/source/blender/editors/space_node/node_select.c @@ -55,7 +55,21 @@ #include "UI_view2d.h" #include "node_intern.h" - + +/* ****** helpers ****** */ + +static bNode *node_under_mouse(bNodeTree *ntree, int mx, int my) +{ + bNode *node; + + for(next_node(ntree); (node=next_node(NULL));) { + /* node body (header and scale are in other operators) */ + if (BLI_in_rctf(&node->totr, mx, my)) + return node; + } + return NULL; +} + /* ****** Click Select ****** */ static bNode *node_mouse_select(SpaceNode *snode, ARegion *ar, short *mval, short extend) @@ -70,11 +84,7 @@ static bNode *node_mouse_select(SpaceNode *snode, ARegion *ar, short *mval, shor UI_view2d_region_to_view(&ar->v2d, mval[0], mval[1], &mx, &my); /* find the closest visible node */ - for(next_node(snode->edittree); (node=next_node(NULL));) { - /* node body (header and scale are in other operators) */ - if (BLI_in_rctf(&node->totr, mx, my)) - break; - } + node = node_under_mouse(snode->edittree, mx, my); if (node) { if (extend == 0) { @@ -177,9 +187,6 @@ static int node_borderselect_exec(bContext *C, wmOperator *op) rect.ymax= RNA_int_get(op->ptr, "ymax"); UI_view2d_region_to_view(&ar->v2d, rect.xmax, rect.ymax, &rectf.xmax, &rectf.ymax); - if (snode->edittree == NULL) // XXX should this be in poll()? - campbell - return OPERATOR_FINISHED; - for(node= snode->edittree->nodes.first; node; node= node->next) { if(BLI_isect_rctf(&rectf, &node->totr, NULL)) { if(gesture_mode==GESTURE_MODAL_SELECT) @@ -194,6 +201,34 @@ static int node_borderselect_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } +static int node_border_select_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + int tweak = RNA_boolean_get(op->ptr, "tweak"); + + if (tweak) { + /* prevent initiating the border select if the mouse is over a node */ + /* this allows border select on empty space, but drag-translate on nodes */ + SpaceNode *snode= CTX_wm_space_node(C); + ARegion *ar= CTX_wm_region(C); + short mval[2]; + float mx, my; + + mval[0]= event->x - ar->winrct.xmin; + mval[1]= event->y - ar->winrct.ymin; + + /* get mouse coordinates in view2d space */ + mx= (float)mval[0]; + my= (float)mval[1]; + + UI_view2d_region_to_view(&ar->v2d, mval[0], mval[1], &mx, &my); + + if (node_under_mouse(snode->edittree, mx, my)) + return OPERATOR_CANCELLED|OPERATOR_PASS_THROUGH; + } + + return WM_border_select_invoke(C, op, event); +} + void NODE_OT_select_border(wmOperatorType *ot) { /* identifiers */ @@ -201,7 +236,7 @@ void NODE_OT_select_border(wmOperatorType *ot) ot->idname= "NODE_OT_select_border"; /* api callbacks */ - ot->invoke= WM_border_select_invoke; + ot->invoke= node_border_select_invoke; ot->exec= node_borderselect_exec; ot->modal= WM_border_select_modal; @@ -212,6 +247,7 @@ void NODE_OT_select_border(wmOperatorType *ot) /* rna */ WM_operator_properties_gesture_border(ot, FALSE); + RNA_def_boolean(ot->srna, "tweak", 0, "Tweak", "Only activate when mouse is not over a node - useful for tweak gesture"); } /* ****** Select/Deselect All ****** */ diff --git a/source/blender/editors/space_outliner/outliner.c b/source/blender/editors/space_outliner/outliner.c index f3485328c52..93b32086614 100644 --- a/source/blender/editors/space_outliner/outliner.c +++ b/source/blender/editors/space_outliner/outliner.c @@ -69,6 +69,7 @@ #include "BKE_context.h" #include "BKE_deform.h" #include "BKE_depsgraph.h" +#include "BKE_fcurve.h" #include "BKE_global.h" #include "BKE_group.h" #include "BKE_library.h" @@ -913,18 +914,25 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i TreeElement *ted= outliner_add_element(soops, &te->subtree, adt, te, TSE_DRIVER_BASE, 0); ID *lastadded= NULL; FCurve *fcu; - DriverTarget *dtar; ted->name= "Drivers"; for (fcu= adt->drivers.first; fcu; fcu= fcu->next) { - if (fcu->driver && fcu->driver->targets.first) { - for (dtar= fcu->driver->targets.first; dtar; dtar= dtar->next) { - if (lastadded != dtar->id) { - // XXX this lastadded check is rather lame, and also fails quite badly... - outliner_add_element(soops, &ted->subtree, dtar->id, ted, TSE_LINKED_OB, 0); - lastadded= dtar->id; + if (fcu->driver && fcu->driver->variables.first) { + ChannelDriver *driver= fcu->driver; + DriverVar *dvar; + + for (dvar= driver->variables.first; dvar; dvar= dvar->next) { + /* loop over all targets used here */ + DRIVER_TARGETS_USED_LOOPER(dvar) + { + if (lastadded != dtar->id) { + // XXX this lastadded check is rather lame, and also fails quite badly... + outliner_add_element(soops, &ted->subtree, dtar->id, ted, TSE_LINKED_OB, 0); + lastadded= dtar->id; + } } + DRIVER_TARGETS_LOOPER_END } } } @@ -5029,7 +5037,7 @@ static uiBlock *operator_search_menu(bContext *C, ARegion *ar, void *arg_kmi) /* fake button, it holds space for search items */ uiDefBut(block, LABEL, 0, "", 10, 15, 150, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL); - but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, 256, 10, 0, 150, 19, ""); + but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, 256, 10, 0, 150, 19, 0, 0, ""); uiButSetSearchFunc(but, operator_search_cb, arg_kmi, operator_call_cb, ot); uiBoundsBlock(block, 6); diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index a2525430a10..37bb75a5efd 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -699,8 +699,14 @@ void draw_image_seq(Scene *scene, ARegion *ar, SpaceSeq *sseq) break; } - if(ibuf->rect_float && ibuf->rect==NULL) - IMB_rect_from_float(ibuf); + if(ibuf->rect_float && ibuf->rect==NULL) { + if (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) { + ibuf->profile = IB_PROFILE_LINEAR_RGB; + } else { + ibuf->profile = IB_PROFILE_NONE; + } + IMB_rect_from_float(ibuf); + } /* needed for gla draw */ glaDefine2DArea(&ar->winrct); diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index f174e96120c..bd1db4c29b6 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -382,55 +382,6 @@ Sequence *find_nearest_seq(Scene *scene, View2D *v2d, int *hand, short mval[2]) return 0; } -void update_seq_ipo_rect(Scene *scene, View2D *v2d, Sequence *seq) -{ - float start; - float end; - - if (!seq || !seq->ipo) { - return; - } - start = -5.0; - end = 105.0; - - - /* Adjust IPO window to sequence and - avoid annoying snap-back to startframe - when Lock Time is on */ - if (0) { // XXX v2d->flag & V2D_VIEWLOCK) { - if ((seq->flag & SEQ_IPO_FRAME_LOCKED) != 0) { - start = -5.0 + seq->startdisp; - end = 5.0 + seq->enddisp; - } else { - start = (float)scene->r.sfra - 0.1; - end = scene->r.efra; - } - } - - seq->ipo->cur.xmin= start; - seq->ipo->cur.xmax= end; -} - -void update_seq_icu_rects(Sequence * seq) -{ - IpoCurve *icu= NULL; - struct SeqEffectHandle sh; - - if (!seq || !seq->ipo) { - return; - } - - if(!(seq->type & SEQ_EFFECT)) { - return; - } - - sh = get_sequence_effect(seq); - - for(icu= seq->ipo->curve.first; icu; icu= icu->next) { - sh.store_icu_yrange(seq, icu->adrcode, &icu->ymin, &icu->ymax); - } -} - static int seq_is_parent(Sequence *par, Sequence *seq) { @@ -2331,11 +2282,13 @@ void SEQUENCER_OT_view_all_preview(wmOperatorType *ot) ot->flag= OPTYPE_REGISTER; } +#if 0 static EnumPropertyItem view_type_items[] = { {SEQ_VIEW_SEQUENCE, "SEQUENCER", ICON_SEQ_SEQUENCER, "Sequencer", ""}, {SEQ_VIEW_PREVIEW, "PREVIEW", ICON_SEQ_PREVIEW, "Image Preview", ""}, {SEQ_VIEW_SEQUENCE_PREVIEW, "SEQUENCER_PREVIEW", ICON_SEQ_SEQUENCER, "Sequencer and Image Preview", ""}, {0, NULL, 0, NULL, NULL}}; +#endif /* view_all operator */ static int sequencer_view_toggle_exec(bContext *C, wmOperator *op) diff --git a/source/blender/editors/space_text/space_text.c b/source/blender/editors/space_text/space_text.c index 2f0e631e927..292249bb0e8 100644 --- a/source/blender/editors/space_text/space_text.c +++ b/source/blender/editors/space_text/space_text.c @@ -209,6 +209,7 @@ static void text_operatortypes(void) static void text_keymap(struct wmKeyConfig *keyconf) { wmKeyMap *keymap; + wmKeyMapItem *kmi; keymap= WM_keymap_find(keyconf, "Text", SPACE_TEXT, 0); @@ -229,6 +230,22 @@ static void text_keymap(struct wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "TEXT_OT_select_line", AKEY, KM_PRESS, KM_SHIFT|KM_OSKEY, 0); #endif + kmi = WM_keymap_add_item(keymap, "WM_OT_context_cycle_int", WHEELUPMOUSE, KM_PRESS, KM_CTRL, 0); + RNA_string_set(kmi->ptr, "path", "space_data.font_size"); + RNA_boolean_set(kmi->ptr, "reverse", 0); + + kmi = WM_keymap_add_item(keymap, "WM_OT_context_cycle_int", WHEELDOWNMOUSE, KM_PRESS, KM_CTRL, 0); + RNA_string_set(kmi->ptr, "path", "space_data.font_size"); + RNA_boolean_set(kmi->ptr, "reverse", 1); + + kmi = WM_keymap_add_item(keymap, "WM_OT_context_cycle_int", PADPLUSKEY, KM_PRESS, KM_CTRL, 0); + RNA_string_set(kmi->ptr, "path", "space_data.font_size"); + RNA_boolean_set(kmi->ptr, "reverse", 0); + + kmi = WM_keymap_add_item(keymap, "WM_OT_context_cycle_int", PADMINUS, KM_PRESS, KM_CTRL, 0); + RNA_string_set(kmi->ptr, "path", "space_data.font_size"); + RNA_boolean_set(kmi->ptr, "reverse", 1); + WM_keymap_add_item(keymap, "TEXT_OT_new", NKEY, KM_PRESS, KM_ALT, 0); WM_keymap_add_item(keymap, "TEXT_OT_open", OKEY, KM_PRESS, KM_ALT, 0); WM_keymap_add_item(keymap, "TEXT_OT_reload", RKEY, KM_PRESS, KM_ALT, 0); diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c index 1a23b9ecc42..0504db51a72 100644 --- a/source/blender/editors/space_text/text_ops.c +++ b/source/blender/editors/space_text/text_ops.c @@ -526,6 +526,11 @@ void TEXT_OT_save_as(wmOperatorType *ot) /******************* run script operator *********************/ +static int run_script_poll(bContext *C) +{ + return (CTX_data_edit_text(C) != NULL); +} + static int run_script_exec(bContext *C, wmOperator *op) { #ifdef DISABLE_PYTHON @@ -534,12 +539,13 @@ static int run_script_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; #else Text *text= CTX_data_edit_text(C); + SpaceText *st= CTX_wm_space_text(C); if (BPY_run_python_script(C, NULL, text, op->reports)) return OPERATOR_FINISHED; /* Dont report error messages while live editing */ - if(!CTX_wm_space_text(C)->live_edit) + if(!(st && st->live_edit)) BKE_report(op->reports, RPT_ERROR, "Python script fail, look in the console for now..."); return OPERATOR_CANCELLED; @@ -554,8 +560,8 @@ void TEXT_OT_run_script(wmOperatorType *ot) ot->description= "Run active script."; /* api callbacks */ + ot->poll= run_script_poll; ot->exec= run_script_exec; -// ot->poll= text_edit_poll; // dont do this since linked texts cant run } diff --git a/source/blender/editors/space_view3d/drawanimviz.c b/source/blender/editors/space_view3d/drawanimviz.c new file mode 100644 index 00000000000..b8184a60cee --- /dev/null +++ b/source/blender/editors/space_view3d/drawanimviz.c @@ -0,0 +1,564 @@ +/** + * $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) 2009 by the Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Joshua Leung + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include <stdlib.h> +#include <string.h> +#include <math.h> + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "MEM_guardedalloc.h" + +#include "DNA_anim_types.h" +#include "DNA_action_types.h" +#include "DNA_armature_types.h" +#include "DNA_constraint_types.h" +#include "DNA_ID.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" +#include "DNA_screen_types.h" +#include "DNA_space_types.h" +#include "DNA_view3d_types.h" +#include "DNA_userdef_types.h" + +#include "BLI_blenlib.h" +#include "BLI_math.h" +#include "BLI_dlrbTree.h" + +#include "BKE_anim.h" +#include "BKE_animsys.h" +#include "BKE_action.h" +#include "BKE_armature.h" +#include "BKE_constraint.h" +#include "BKE_context.h" +#include "BKE_depsgraph.h" +#include "BKE_DerivedMesh.h" +#include "BKE_global.h" +#include "BKE_main.h" +#include "BKE_modifier.h" +#include "BKE_nla.h" +#include "BKE_object.h" +#include "BKE_utildefines.h" + +#include "BIF_gl.h" +#include "BIF_glutil.h" + +#include "ED_armature.h" +#include "ED_anim_api.h" +#include "ED_keyframes_draw.h" + +#include "WM_api.h" +#include "WM_types.h" +#include "BLF_api.h" + +#include "UI_resources.h" + +#include "view3d_intern.h" + +/* ************************************ Motion Paths ************************************* */ + +// TODO: +// - options to draw paths with lines +// - include support for editing the path verts + +/* Set up drawing environment for drawing motion paths */ +void draw_motion_paths_init(Scene *scene, View3D *v3d, ARegion *ar) +{ + RegionView3D *rv3d= ar->regiondata; + + if (v3d->zbuf) glDisable(GL_DEPTH_TEST); + + glPushMatrix(); + glLoadMatrixf(rv3d->viewmat); +} + +/* Draw the given motion path for an Object or a Bone + * - assumes that the viewport has already been initialised properly + * i.e. draw_motion_paths_init() has been called + */ +void draw_motion_path_instance(Scene *scene, View3D *v3d, ARegion *ar, + Object *ob, bPoseChannel *pchan, bAnimVizSettings *avs, bMotionPath *mpath) +{ + //RegionView3D *rv3d= ar->regiondata; + bMotionPathVert *mpv, *mpv_start; + int i, stepsize= avs->path_step; + int sfra, efra, len; + + + /* get frame ranges */ + if (avs->path_type == MOTIONPATH_TYPE_ACFRA) { + int sind; + + /* With "Around Current", we only choose frames from around + * the current frame to draw. However, this range is still + * restricted by the limits of the original path. + */ + sfra= CFRA - avs->path_bc; + efra= CFRA + avs->path_ac; + if (sfra < mpath->start_frame) sfra= mpath->start_frame; + if (efra > mpath->end_frame) efra= mpath->end_frame; + + len= efra - sfra; + + sind= sfra - mpath->start_frame; + mpv_start= (mpath->points + sind); + } + else { + sfra= mpath->start_frame; + efra = sfra + mpath->length; + len = mpath->length; + mpv_start= mpath->points; + } + + /* draw curve-line of path */ + glShadeModel(GL_SMOOTH); + + glBegin(GL_LINE_STRIP); + for (i=0, mpv=mpv_start; i < len; i++, mpv++) { + short sel= (pchan) ? (pchan->bone->flag & BONE_SELECTED) : (ob->flag & SELECT); + float intensity; /* how faint */ + + /* set color + * - more intense for active/selected bones, less intense for unselected bones + * - black for before current frame, green for current frame, blue for after current frame + * - intensity decreases as distance from current frame increases + */ + #define SET_INTENSITY(A, B, C, min, max) (((1.0f - ((C - B) / (C - A))) * (max-min)) + min) + if ((sfra+i) < CFRA) { + /* black - before cfra */ + if (sel) { + // intensity= 0.5f; + intensity = SET_INTENSITY(sfra, i, CFRA, 0.25f, 0.75f); + } + else { + //intensity= 0.8f; + intensity = SET_INTENSITY(sfra, i, CFRA, 0.68f, 0.92f); + } + UI_ThemeColorBlend(TH_WIRE, TH_BACK, intensity); + } + else if ((sfra+i) > CFRA) { + /* blue - after cfra */ + if (sel) { + //intensity = 0.5f; + intensity = SET_INTENSITY(CFRA, i, efra, 0.25f, 0.75f); + } + else { + //intensity = 0.8f; + intensity = SET_INTENSITY(CFRA, i, efra, 0.68f, 0.92f); + } + UI_ThemeColorBlend(TH_BONE_POSE, TH_BACK, intensity); + } + else { + /* green - on cfra */ + if (sel) { + intensity= 0.5f; + } + else { + intensity= 0.99f; + } + UI_ThemeColorBlendShade(TH_CFRAME, TH_BACK, intensity, 10); + } + + /* draw a vertex with this color */ + glVertex3fv(mpv->co); + } + + glEnd(); + glShadeModel(GL_FLAT); + + glPointSize(1.0); + + /* draw little black point at each frame + * NOTE: this is not really visible/noticable + */ + glBegin(GL_POINTS); + for (i=0, mpv=mpv_start; i < len; i++, mpv++) + glVertex3fv(mpv->co); + glEnd(); + + /* Draw little white dots at each framestep value */ + UI_ThemeColor(TH_TEXT_HI); + glBegin(GL_POINTS); + for (i=0, mpv=mpv_start; i < len; i+=stepsize, mpv+=stepsize) + glVertex3fv(mpv->co); + glEnd(); + + /* Draw frame numbers at each framestep value */ + if (avs->path_viewflag & MOTIONPATH_VIEW_FNUMS) { + for (i=0, mpv=mpv_start; i < len; i+=stepsize, mpv+=stepsize) { + char str[32]; + + /* only draw framenum if several consecutive highlighted points don't occur on same point */ + if (i == 0) { + sprintf(str, "%d", (i+sfra)); + view3d_cached_text_draw_add(mpv->co[0], mpv->co[1], mpv->co[2], str, 0); + } + else if ((i > stepsize) && (i < len-stepsize)) { + bMotionPathVert *mpvP = (mpv - stepsize); + bMotionPathVert *mpvN = (mpv + stepsize); + + if ((equals_v3v3(mpv->co, mpvP->co)==0) || (equals_v3v3(mpv->co, mpvN->co)==0)) { + sprintf(str, "%d", (sfra+i)); + view3d_cached_text_draw_add(mpv->co[0], mpv->co[1], mpv->co[2], str, 0); + } + } + } + } + + /* Keyframes - dots and numbers */ + if (avs->path_viewflag & MOTIONPATH_VIEW_KFNOS) { + AnimData *adt= BKE_animdata_from_id(&ob->id); + DLRBT_Tree keys; + + /* build list of all keyframes in active action for object or pchan */ + BLI_dlrbTree_init(&keys); + + if (adt) { + /* for now, it is assumed that keyframes for bones are all grouped in a single group */ + if (pchan) { + bActionGroup *agrp= action_groups_find_named(adt->action, pchan->name); + + if (agrp) { + agroup_to_keylist(adt, agrp, &keys, NULL); + BLI_dlrbTree_linkedlist_sync(&keys); + } + } + else { + action_to_keylist(adt, adt->action, &keys, NULL); + BLI_dlrbTree_linkedlist_sync(&keys); + } + } + + /* Draw slightly-larger yellow dots at each keyframe */ + UI_ThemeColor(TH_VERTEX_SELECT); + glPointSize(4.0f); // XXX perhaps a bit too big + + glBegin(GL_POINTS); + for (i=0, mpv=mpv_start; i < len; i++, mpv++) { + float mframe= (float)(sfra + i); + + if (BLI_dlrbTree_search_exact(&keys, compare_ak_cfraPtr, &mframe)) + glVertex3fv(mpv->co); + } + glEnd(); + + glPointSize(1.0f); + + /* Draw frame numbers of keyframes */ + if (avs->path_viewflag & (MOTIONPATH_VIEW_FNUMS|MOTIONPATH_VIEW_KFNOS)) { + for (i=0, mpv=mpv_start; i < len; i++, mpv++) { + float mframe= (float)(sfra + i); + + if (BLI_dlrbTree_search_exact(&keys, compare_ak_cfraPtr, &mframe)) { + char str[32]; + + sprintf(str, "%d", (sfra+i)); + view3d_cached_text_draw_add(mpv->co[0], mpv->co[1], mpv->co[2], str, 0); + } + } + } + + BLI_dlrbTree_free(&keys); + } +} + +/* Clean up drawing environment after drawing motion paths */ +void draw_motion_paths_cleanup(Scene *scene, View3D *v3d, ARegion *ar) +{ + if (v3d->zbuf) glEnable(GL_DEPTH_TEST); + glPopMatrix(); +} + +#if 0 // XXX temp file guards + +/* ***************************** Onion Skinning (Ghosts) ******************************** */ + +#if 0 // XXX only for bones +/* helper function for ghost drawing - sets/removes flags for temporarily + * hiding unselected bones while drawing ghosts + */ +static void ghost_poses_tag_unselected(Object *ob, short unset) +{ + bArmature *arm= ob->data; + bPose *pose= ob->pose; + bPoseChannel *pchan; + + /* don't do anything if no hiding any bones */ + if ((arm->flag & ARM_GHOST_ONLYSEL)==0) + return; + + /* loop over all pchans, adding/removing tags as appropriate */ + for (pchan= pose->chanbase.first; pchan; pchan= pchan->next) { + if ((pchan->bone) && (arm->layer & pchan->bone->layer)) { + if (unset) { + /* remove tags from all pchans if cleaning up */ + pchan->bone->flag &= ~BONE_HIDDEN_PG; + } + else { + /* set tags on unselected pchans only */ + if ((pchan->bone->flag & BONE_SELECTED)==0) + pchan->bone->flag |= BONE_HIDDEN_PG; + } + } + } +} +#endif // XXX only for bones + +/* draw ghosts that occur within a frame range + * note: object should be in posemode + */ +static void draw_ghost_poses_range(Scene *scene, View3D *v3d, ARegion *ar, Base *base) +{ + Object *ob= base->object; + AnimData *adt= BKE_animdata_from_id(&ob->id); + bArmature *arm= ob->data; + bPose *posen, *poseo; + float start, end, stepsize, range, colfac; + int cfrao, flago, ipoflago; + + start = (float)arm->ghostsf; + end = (float)arm->ghostef; + if (end <= start) + return; + + stepsize= (float)(arm->ghostsize); + range= (float)(end - start); + + /* store values */ + ob->mode &= ~OB_MODE_POSE; + cfrao= CFRA; + flago= arm->flag; + arm->flag &= ~(ARM_DRAWNAMES|ARM_DRAWAXES); + ipoflago= ob->ipoflag; + ob->ipoflag |= OB_DISABLE_PATH; + + /* copy the pose */ + poseo= ob->pose; + copy_pose(&posen, ob->pose, 1); + ob->pose= posen; + armature_rebuild_pose(ob, ob->data); /* child pointers for IK */ + ghost_poses_tag_unselected(ob, 0); /* hide unselected bones if need be */ + + glEnable(GL_BLEND); + if (v3d->zbuf) glDisable(GL_DEPTH_TEST); + + /* draw from first frame of range to last */ + for (CFRA= (int)start; CFRA < end; CFRA += (int)stepsize) { + colfac = (end - (float)CFRA) / range; + UI_ThemeColorShadeAlpha(TH_WIRE, 0, -128-(int)(120.0*sqrt(colfac))); + + BKE_animsys_evaluate_animdata(&ob->id, adt, (float)CFRA, ADT_RECALC_ALL); + where_is_pose(scene, ob); + draw_pose_bones(scene, v3d, ar, base, OB_WIRE); + } + glDisable(GL_BLEND); + if (v3d->zbuf) glEnable(GL_DEPTH_TEST); + + ghost_poses_tag_unselected(ob, 1); /* unhide unselected bones if need be */ + free_pose(posen); + + /* restore */ + CFRA= cfrao; + ob->pose= poseo; + arm->flag= flago; + armature_rebuild_pose(ob, ob->data); + ob->mode |= OB_MODE_POSE; + ob->ipoflag= ipoflago; +} + +/* draw ghosts on keyframes in action within range + * - object should be in posemode + */ +static void draw_ghost_poses_keys(Scene *scene, View3D *v3d, ARegion *ar, Base *base) +{ + Object *ob= base->object; + AnimData *adt= BKE_animdata_from_id(&ob->id); + bAction *act= (adt) ? adt->action : NULL; + bArmature *arm= ob->data; + bPose *posen, *poseo; + DLRBT_Tree keys; + ActKeyColumn *ak, *akn; + float start, end, range, colfac, i; + int cfrao, flago; + + start = (float)arm->ghostsf; + end = (float)arm->ghostef; + if (end <= start) + return; + + /* get keyframes - then clip to only within range */ + BLI_dlrbTree_init(&keys); + action_to_keylist(adt, act, &keys, NULL); + BLI_dlrbTree_linkedlist_sync(&keys); + + range= 0; + for (ak= keys.first; ak; ak= akn) { + akn= ak->next; + + if ((ak->cfra < start) || (ak->cfra > end)) + BLI_freelinkN((ListBase *)&keys, ak); + else + range++; + } + if (range == 0) return; + + /* store values */ + ob->mode &= ~OB_MODE_POSE; + cfrao= CFRA; + flago= arm->flag; + arm->flag &= ~(ARM_DRAWNAMES|ARM_DRAWAXES); + ob->ipoflag |= OB_DISABLE_PATH; + + /* copy the pose */ + poseo= ob->pose; + copy_pose(&posen, ob->pose, 1); + ob->pose= posen; + armature_rebuild_pose(ob, ob->data); /* child pointers for IK */ + ghost_poses_tag_unselected(ob, 0); /* hide unselected bones if need be */ + + glEnable(GL_BLEND); + if (v3d->zbuf) glDisable(GL_DEPTH_TEST); + + /* draw from first frame of range to last */ + for (ak=keys.first, i=0; ak; ak=ak->next, i++) { + colfac = i/range; + UI_ThemeColorShadeAlpha(TH_WIRE, 0, -128-(int)(120.0*sqrt(colfac))); + + CFRA= (int)ak->cfra; + + BKE_animsys_evaluate_animdata(&ob->id, adt, (float)CFRA, ADT_RECALC_ALL); + where_is_pose(scene, ob); + draw_pose_bones(scene, v3d, ar, base, OB_WIRE); + } + glDisable(GL_BLEND); + if (v3d->zbuf) glEnable(GL_DEPTH_TEST); + + ghost_poses_tag_unselected(ob, 1); /* unhide unselected bones if need be */ + BLI_dlrbTree_free(&keys); + free_pose(posen); + + /* restore */ + CFRA= cfrao; + ob->pose= poseo; + arm->flag= flago; + armature_rebuild_pose(ob, ob->data); + ob->mode |= OB_MODE_POSE; +} + +/* draw ghosts around current frame + * - object is supposed to be armature in posemode + */ +static void draw_ghost_poses(Scene *scene, View3D *v3d, ARegion *ar, Base *base) +{ + Object *ob= base->object; + AnimData *adt= BKE_animdata_from_id(&ob->id); + bArmature *arm= ob->data; + bPose *posen, *poseo; + float cur, start, end, stepsize, range, colfac, actframe, ctime; + int cfrao, flago; + + /* pre conditions, get an action with sufficient frames */ + if ELEM(NULL, adt, adt->action) + return; + + calc_action_range(adt->action, &start, &end, 0); + if (start == end) + return; + + stepsize= (float)(arm->ghostsize); + range= (float)(arm->ghostep)*stepsize + 0.5f; /* plus half to make the for loop end correct */ + + /* store values */ + ob->mode &= ~OB_MODE_POSE; + cfrao= CFRA; + actframe= BKE_nla_tweakedit_remap(adt, (float)CFRA, 0); + flago= arm->flag; + arm->flag &= ~(ARM_DRAWNAMES|ARM_DRAWAXES); + + /* copy the pose */ + poseo= ob->pose; + copy_pose(&posen, ob->pose, 1); + ob->pose= posen; + armature_rebuild_pose(ob, ob->data); /* child pointers for IK */ + ghost_poses_tag_unselected(ob, 0); /* hide unselected bones if need be */ + + glEnable(GL_BLEND); + if (v3d->zbuf) glDisable(GL_DEPTH_TEST); + + /* draw from darkest blend to lowest */ + for(cur= stepsize; cur<range; cur+=stepsize) { + ctime= cur - (float)fmod(cfrao, stepsize); /* ensures consistant stepping */ + colfac= ctime/range; + UI_ThemeColorShadeAlpha(TH_WIRE, 0, -128-(int)(120.0*sqrt(colfac))); + + /* only within action range */ + if (actframe+ctime >= start && actframe+ctime <= end) { + CFRA= (int)BKE_nla_tweakedit_remap(adt, actframe+ctime, NLATIME_CONVERT_MAP); + + if (CFRA != cfrao) { + BKE_animsys_evaluate_animdata(&ob->id, adt, (float)CFRA, ADT_RECALC_ALL); + where_is_pose(scene, ob); + draw_pose_bones(scene, v3d, ar, base, OB_WIRE); + } + } + + ctime= cur + (float)fmod((float)cfrao, stepsize) - stepsize+1.0f; /* ensures consistant stepping */ + colfac= ctime/range; + UI_ThemeColorShadeAlpha(TH_WIRE, 0, -128-(int)(120.0*sqrt(colfac))); + + /* only within action range */ + if ((actframe-ctime >= start) && (actframe-ctime <= end)) { + CFRA= (int)BKE_nla_tweakedit_remap(adt, actframe-ctime, NLATIME_CONVERT_MAP); + + if (CFRA != cfrao) { + BKE_animsys_evaluate_animdata(&ob->id, adt, (float)CFRA, ADT_RECALC_ALL); + where_is_pose(scene, ob); + draw_pose_bones(scene, v3d, ar, base, OB_WIRE); + } + } + } + glDisable(GL_BLEND); + if (v3d->zbuf) glEnable(GL_DEPTH_TEST); + + ghost_poses_tag_unselected(ob, 1); /* unhide unselected bones if need be */ + free_pose(posen); + + /* restore */ + CFRA= cfrao; + ob->pose= poseo; + arm->flag= flago; + armature_rebuild_pose(ob, ob->data); + ob->mode |= OB_MODE_POSE; +} + + + +#endif // XXX temp file guards diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c index d8c2fb9d43e..c59c5cddb3f 100644 --- a/source/blender/editors/space_view3d/drawarmature.c +++ b/source/blender/editors/space_view3d/drawarmature.c @@ -1622,8 +1622,14 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, if ( (bone) && !(bone->flag & (BONE_HIDDEN_P|BONE_HIDDEN_PG)) ) { if (bone->layer & arm->layer) { + int use_custom = (pchan->custom) && !(arm->flag & ARM_NO_CUSTOM); glPushMatrix(); - glMultMatrixf(pchan->pose_mat); + + if(use_custom && pchan->custom_tx) { + glMultMatrixf(pchan->custom_tx->pose_mat); + } else { + glMultMatrixf(pchan->pose_mat); + } /* catch exception for bone with hidden parent */ flag= bone->flag; @@ -1637,7 +1643,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, /* set color-set to use */ set_pchan_colorset(ob, pchan); - if ((pchan->custom) && !(arm->flag & ARM_NO_CUSTOM)) { + if (use_custom) { /* if drawwire, don't try to draw in solid */ if (pchan->bone->flag & BONE_DRAWWIRE) draw_wire= 1; @@ -1687,7 +1693,12 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, if (pchan->custom) { if ((dt < OB_SOLID) || (bone->flag & BONE_DRAWWIRE)) { glPushMatrix(); - glMultMatrixf(pchan->pose_mat); + + if(pchan->custom_tx) { + glMultMatrixf(pchan->custom_tx->pose_mat); + } else { + glMultMatrixf(pchan->pose_mat); + } /* prepare colors */ if (arm->flag & ARM_POSEMODE) diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index c689b4d338f..77d8ed0f24d 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -103,7 +103,6 @@ #include "GPU_draw.h" #include "GPU_material.h" #include "GPU_extensions.h" -#include "gpu_buffers.h" #include "ED_mesh.h" #include "ED_particle.h" @@ -798,25 +797,30 @@ static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob) curcol[3]= 0.6; glColor4fv(curcol); - if(ob->id.us>1) { - if (ob==OBACT || (ob->flag & SELECT)) glColor4ub(0x88, 0xFF, 0xFF, 155); - else glColor4ub(0x77, 0xCC, 0xCC, 155); - } - - /* Inner Circle */ - VECCOPY(vec, ob->obmat[3]); - glEnable(GL_BLEND); - drawcircball(GL_LINE_LOOP, vec, lampsize, imat); - glDisable(GL_BLEND); - drawcircball(GL_POLYGON, vec, lampsize, imat); - - /* restore */ - if(ob->id.us>1) - glColor4fv(curcol); + if(lampsize > 0.0f) { + + if(ob->id.us>1) { + if (ob==OBACT || (ob->flag & SELECT)) glColor4ub(0x88, 0xFF, 0xFF, 155); + else glColor4ub(0x77, 0xCC, 0xCC, 155); + } + + /* Inner Circle */ + VECCOPY(vec, ob->obmat[3]); + glEnable(GL_BLEND); + drawcircball(GL_LINE_LOOP, vec, lampsize, imat); + glDisable(GL_BLEND); + drawcircball(GL_POLYGON, vec, lampsize, imat); - /* Outer circle */ - circrad = 3.0f*lampsize; - drawcircball(GL_LINE_LOOP, vec, circrad, imat); + /* restore */ + if(ob->id.us>1) + glColor4fv(curcol); + + /* Outer circle */ + circrad = 3.0f*lampsize; + drawcircball(GL_LINE_LOOP, vec, circrad, imat); + } + else + circrad = 0.0f; setlinestyle(3); @@ -1572,82 +1576,15 @@ static void draw_dm_verts__mapFunc(void *userData, int index, float *co, float * } } -/* disabled because it crashes combined with e.g. subsurf modifier, - * the derivedmesh can't be assumed to be an EditMeshDerivedMesh, - * nor should this struct be copied around, it should be defined in - * a single place only to avoid them getting out of sync */ -#if 0 -/* originally defined in DerivedMesh.c */ -typedef struct { - DerivedMesh dm; - - EditMesh *em; - float (*vertexCos)[3]; - float (*vertexNos)[3]; - float (*faceNos)[3]; -} EditMeshDerivedMesh; -#endif - static void draw_dm_verts(DerivedMesh *dm, int sel, EditVert *eve_act) { struct { int sel; EditVert *eve_act; } data; - //GPUBuffer *buffer; - //float *varray; data.sel = sel; data.eve_act = eve_act; -#if 0 - /* first come the unselected vertices, then the selected */ - buffer = GPU_buffer_legacy(dm)?0:GPU_buffer_alloc( sizeof(float)*3*dm->getNumVerts(dm)*2, 0 ); - - if( (varray = GPU_buffer_lock_stream( buffer )) && bglPointHack() == 0 ) { - EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; - EditVert *eve; - int i; - int numverts = 0, numselected = 0; - int datatype[] = { GPU_BUFFER_INTER_V3F, GPU_BUFFER_INTER_END }; - GPU_buffer_unlock( buffer ); - GPU_interleaved_setup( buffer, datatype ); - varray = GPU_buffer_lock_stream( buffer ); - - glBegin(GL_POINTS); - for (i=0,eve= emdm->em->verts.first; eve; i++,eve=eve->next) { - if (eve->h==0 && (eve->f&SELECT)==data.sel) { - if (eve==data.eve_act) { - if (emdm->vertexCos) { - VECCOPY(&varray[3*(dm->getNumVerts(dm)+numselected)],emdm->vertexCos[i]); - } - else { - VECCOPY(&varray[3*(dm->getNumVerts(dm)+numselected)],eve->co); - } - numselected++; - } else { - if (emdm->vertexCos) { - VECCOPY(&varray[3*numverts],emdm->vertexCos[i]); - } else { - VECCOPY(&varray[3*numverts],eve->co); - } - numverts++; - } - } - } - glEnd(); - GPU_buffer_unlock( buffer ); - glDrawArrays(GL_POINTS,0,numverts); - UI_ThemeColor4(TH_EDITMESH_ACTIVE); - glDrawArrays(GL_POINTS,dm->getNumVerts(dm),numselected); - UI_ThemeColor4(data.sel?TH_VERTEX_SELECT:TH_VERTEX); - GPU_buffer_unbind(); - } - { -#endif - bglBegin(GL_POINTS); - dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data); - bglEnd(); -#if 0 - } - GPU_buffer_free( buffer, 0 ); -#endif + bglBegin(GL_POINTS); + dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data); + bglEnd(); } /* Draw edges with color set based on selection */ @@ -1719,55 +1656,8 @@ static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int i static void draw_dm_edges_sel_interp(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol) { unsigned char *cols[2] = {baseCol, selCol}; -#if 0 - int elemsize = sizeof(float)*3+sizeof(unsigned char)*4; - EditMeshDerivedMesh *emdm = (EditMeshDerivedMesh *)dm; - EditMesh *em= emdm->em; - unsigned char *varray; - int i; - GPUBuffer *buffer; - - buffer = GPU_buffer_legacy(dm)?0:GPU_buffer_alloc( elemsize*em->totedge*2, 0 ); - if( (varray = GPU_buffer_lock_stream( buffer )) ) { - EditEdge *eed; - int numedges = 0; - int datatype[] = { GPU_BUFFER_INTER_V3F, GPU_BUFFER_INTER_C4UB, GPU_BUFFER_INTER_END }; - GPU_buffer_unlock( buffer ); - GPU_interleaved_setup( buffer, datatype ); - varray = GPU_buffer_lock_stream( buffer ); - for (i=0,eed= em->edges.first; eed; i++,eed= eed->next) { - if(eed->h==0) { - unsigned char *col0 = cols[(eed->v1->f&SELECT)?1:0]; - unsigned char *col1 = cols[(eed->v2->f&SELECT)?1:0]; - - if( emdm->vertexCos ) { - VECCOPY(((float *)&varray[elemsize*numedges*2]),emdm->vertexCos[(int) eed->v1->tmp.l]); - } - else { - VECCOPY(((float *)&varray[elemsize*numedges*2]),eed->v1->co); - } - QUATCOPY(&varray[elemsize*numedges*2+sizeof(float)*3],col0); - if( emdm->vertexCos ) { - VECCOPY(((float *)&varray[elemsize*numedges*2+elemsize]),emdm->vertexCos[(int) eed->v2->tmp.l]); - } - else { - VECCOPY(((float *)&varray[elemsize*numedges*2+elemsize]),eed->v2->co); - } - QUATCOPY(&varray[elemsize*numedges*2+elemsize+sizeof(float)*3],col1); - numedges++; - } - } - GPU_buffer_unlock( buffer ); - glDrawArrays(GL_LINES,0,numedges*2); - GPU_buffer_unbind(); - } - else { -#endif - dm->drawMappedEdgesInterp(dm, draw_dm_edges_sel_interp__setDrawOptions, draw_dm_edges_sel_interp__setDrawInterpOptions, cols); -#if 0 - } - GPU_buffer_free( buffer, 0 ); -#endif + + dm->drawMappedEdgesInterp(dm, draw_dm_edges_sel_interp__setDrawOptions, draw_dm_edges_sel_interp__setDrawInterpOptions, cols); } /* Draw only seam edges */ @@ -1821,236 +1711,12 @@ static int draw_dm_faces_sel__setDrawOptions(void *userData, int index, int *dra static void draw_dm_faces_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditFace *efa_act) { struct { unsigned char *cols[3]; EditFace *efa_act; } data; - //EditMeshDerivedMesh *emdm = (EditMeshDerivedMesh *)dm; - EditFace *efa; - unsigned char *col; - GPUBuffer *buffer; - unsigned char *varray; - unsigned char black[] = { 0, 0, 0, 0 }; - int i, draw=0; - int elemsize = (sizeof(float)*6+sizeof(unsigned char)*4); data.cols[0] = baseCol; data.cols[1] = selCol; data.cols[2] = actCol; data.efa_act = efa_act; - - buffer = GPU_buffer_legacy(dm)?0:GPU_buffer_alloc( elemsize*dm->getNumFaces(dm)*3*2, 0 ); - if( dm->getVertCos == 0 && (varray = GPU_buffer_lock_stream( buffer )) ) { - int prevdraw = 0; - int numfaces = 0; - int datatype[] = { GPU_BUFFER_INTER_V3F, GPU_BUFFER_INTER_N3F, GPU_BUFFER_INTER_C4UB, GPU_BUFFER_INTER_END }; - GPU_buffer_unlock( buffer ); - GPU_interleaved_setup( buffer, datatype ); - glShadeModel(GL_SMOOTH); - varray = GPU_buffer_lock_stream( buffer ); - for (i=0,efa= efa_act; efa; i++,efa= efa->next) { - int drawSmooth = (efa->flag & ME_SMOOTH); - if (efa->h==0) { - if (efa == data.efa_act) { - draw = 2; - } else { - col = data.cols[(efa->f&SELECT)?1:0]; - if (col[3]==0) draw = 0; - else draw = 1; - } - } - else { - draw = 0; - } - if( prevdraw != draw && prevdraw != 0 && numfaces > 0) { - if( prevdraw==2 ) { - glEnable(GL_POLYGON_STIPPLE); - glPolygonStipple(stipple_quarttone); - } - GPU_buffer_unlock( buffer ); - glDrawArrays(GL_TRIANGLES,0,numfaces*3); - if( prevdraw==2 ) { - glDisable(GL_POLYGON_STIPPLE); - } - varray = GPU_buffer_lock_stream( buffer ); - numfaces = 0; - } - - if( draw != 0 ) { - if(!drawSmooth) { - /*if (emdm->vertexCos) { - VECCOPY((float *)&varray[elemsize*3*numfaces],emdm->vertexCos[(int) efa->v1->tmp.l]); - VECCOPY((float *)&varray[elemsize*3*numfaces+sizeof(float)*3],emdm->faceNos[i]); - - VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize],emdm->vertexCos[(int) efa->v2->tmp.l]); - VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize+sizeof(float)*3],emdm->faceNos[i]); - - VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2],emdm->vertexCos[(int) efa->v3->tmp.l]); - VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*3],emdm->faceNos[i]); - } - else {*/ - VECCOPY((float *)&varray[elemsize*3*numfaces],efa->v1->co); - VECCOPY((float *)&varray[elemsize*3*numfaces+sizeof(float)*3],efa->n); - - VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize],efa->v2->co); - VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize+sizeof(float)*3],efa->n); - - VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2],efa->v3->co); - VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*3],efa->n); - /*}*/ - if( draw == 2 ) { - QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],data.cols[2]); - QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],data.cols[2]); - QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],data.cols[2]); - } - else if( draw == 1 ) { - QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]); - QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]); - QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]); - } - else { - QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],black); - QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],black); - QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],black); - } - - numfaces++; - if( efa->v4 ) { - /*if (emdm->vertexCos) { - VECCOPY((float *)&varray[elemsize*3*numfaces],emdm->vertexCos[(int) efa->v3->tmp.l]); - VECCOPY((float *)&varray[elemsize*3*numfaces+sizeof(float)*3],emdm->faceNos[i]); - - VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize],emdm->vertexCos[(int) efa->v4->tmp.l]); - VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize+sizeof(float)*3],emdm->faceNos[i]); - - VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2],emdm->vertexCos[(int) efa->v1->tmp.l]); - VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*3],emdm->faceNos[i]); - } - else {*/ - VECCOPY((float *)&varray[elemsize*3*numfaces],efa->v3->co); - VECCOPY((float *)&varray[elemsize*3*numfaces+sizeof(float)*3],efa->n); - - VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize],efa->v4->co); - VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize+sizeof(float)*3],efa->n); - - VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2],efa->v1->co); - VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*3],efa->n); - /*}*/ - - if( draw == 2 ) { - QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],data.cols[2]); - QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],data.cols[2]); - QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],data.cols[2]); - } - else if( draw == 1 ) { - QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]); - QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]); - QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]); - } - else { - QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],black); - QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],black); - QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],black); - } - - numfaces++; - } - } - else { - /*if (emdm->vertexCos) { - VECCOPY((float *)&varray[elemsize*3*numfaces],emdm->vertexCos[(int) efa->v1->tmp.l]); - VECCOPY((float *)&varray[elemsize*3*numfaces+sizeof(float)*3],emdm->vertexNos[(int) efa->v1->tmp.l]); - - VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize],emdm->vertexCos[(int) efa->v2->tmp.l]); - VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize+sizeof(float)*3],emdm->vertexNos[(int) efa->v2->tmp.l]); - - VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2],emdm->vertexCos[(int) efa->v3->tmp.l]); - VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*3],emdm->vertexNos[(int) efa->v3->tmp.l]); - } - else {*/ - VECCOPY((float *)&varray[elemsize*3*numfaces],efa->v1->co); - VECCOPY((float *)&varray[elemsize*3*numfaces+sizeof(float)*3],efa->v1->no); - - VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize],efa->v2->co); - VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize+sizeof(float)*3],efa->v2->no); - - VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2],efa->v3->co); - VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*3],efa->v3->no); - /*}*/ - - if( draw == 2 ) { - QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],data.cols[2]); - QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],data.cols[2]); - QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],data.cols[2]); - } - else if( draw == 1 ) { - QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]); - QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]); - QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]); - } - else { - QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],black); - QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],black); - QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],black); - } - - numfaces++; - if( efa->v4 ) { - /*if (emdm->vertexCos) { - VECCOPY((float *)&varray[elemsize*3*numfaces],emdm->vertexCos[(int) efa->v3->tmp.l]); - VECCOPY((float *)&varray[elemsize*3*numfaces+sizeof(float)*3],emdm->vertexNos[(int) efa->v1->tmp.l]); - - VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize],emdm->vertexCos[(int) efa->v4->tmp.l]); - VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize+sizeof(float)*3],emdm->vertexNos[(int) efa->v2->tmp.l]); - - VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2],emdm->vertexCos[(int) efa->v1->tmp.l]); - VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*3],emdm->vertexNos[(int) efa->v3->tmp.l]); - } - else {*/ - VECCOPY((float *)&varray[elemsize*3*numfaces],efa->v3->co); - VECCOPY((float *)&varray[elemsize*3*numfaces+sizeof(float)*3],efa->v3->no); - - VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize],efa->v4->co); - VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize+sizeof(float)*3],efa->v4->no); - - VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2],efa->v1->co); - VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*3],efa->v1->no); - /*}*/ - - if( draw == 2 ) { - QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],data.cols[2]); - QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],data.cols[2]); - QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],data.cols[2]); - } - else if( draw == 1 ) { - QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]); - QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]); - QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]); - } - else { - QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],black); - QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],black); - QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],black); - } - - numfaces++; - } - } - } - prevdraw = draw; - } - GPU_buffer_unlock( buffer ); - if( prevdraw != 0 && numfaces > 0) { - if( prevdraw==2 ) { - glEnable(GL_POLYGON_STIPPLE); - glPolygonStipple(stipple_quarttone); - } - glDrawArrays(GL_TRIANGLES,0,numfaces*3); - if( prevdraw==2 ) { - glDisable(GL_POLYGON_STIPPLE); - } - } - GPU_buffer_unbind(); - } else { - dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, &data, 0); - } - GPU_buffer_free( buffer, 0 ); + dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, &data, 0); } static int draw_dm_creases__setDrawOptions(void *userData, int index) @@ -2464,114 +2130,12 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object } else { /* 3 floats for position, 3 for normal and times two because the faces may actually be quads instead of triangles */ - GPUBuffer *buffer = GPU_buffer_legacy(em->derivedFinal)?0:GPU_buffer_alloc( sizeof(float)*6*em->totface*3*2, 0 ); - float *varray; - EditFace *efa; - int i, curmat = 0, draw = 0; - glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED); glEnable(GL_LIGHTING); glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW); - if( finalDM->getVertCos == 0 && (varray = GPU_buffer_lock_stream( buffer )) ) { - int prevdraw = 0, prevmat = 0; - int numfaces = 0; - int datatype[] = { GPU_BUFFER_INTER_V3F, GPU_BUFFER_INTER_N3F, GPU_BUFFER_INTER_END }; - GPU_buffer_unlock( buffer ); - GPU_interleaved_setup( buffer, datatype ); - glShadeModel(GL_SMOOTH); - varray = GPU_buffer_lock_stream( buffer ); - for (i=0,efa= em->faces.first; efa; i++,efa= efa->next) { - int drawSmooth = (efa->flag & ME_SMOOTH); - if( efa->h == 0 ) { - curmat = efa->mat_nr+1; - draw = 1; - } - else { - draw = 0; - } - if( ((prevdraw != draw) || (curmat != prevmat)) && prevdraw != 0 && numfaces > 0) { - if( prevdraw==2 ) { - glEnable(GL_POLYGON_STIPPLE); - glPolygonStipple(stipple_quarttone); - } - GPU_buffer_unlock( buffer ); - GPU_enable_material(prevmat, NULL); - glDrawArrays(GL_TRIANGLES,0,numfaces*3); - if( prevdraw==2 ) { - glDisable(GL_POLYGON_STIPPLE); - } - varray = GPU_buffer_lock_stream( buffer ); - numfaces = 0; - } - if( draw != 0 ) { - if(!drawSmooth) { - VECCOPY(&varray[numfaces*18],efa->v1->co); - VECCOPY(&varray[numfaces*18+3],efa->n); - - VECCOPY(&varray[numfaces*18+6],efa->v2->co); - VECCOPY(&varray[numfaces*18+9],efa->n); - - VECCOPY(&varray[numfaces*18+12],efa->v3->co); - VECCOPY(&varray[numfaces*18+15],efa->n); - numfaces++; - if( efa->v4 ) { - VECCOPY(&varray[numfaces*18],efa->v3->co); - VECCOPY(&varray[numfaces*18+3],efa->n); - - VECCOPY(&varray[numfaces*18+6],efa->v4->co); - VECCOPY(&varray[numfaces*18+9],efa->n); - - VECCOPY(&varray[numfaces*18+12],efa->v1->co); - VECCOPY(&varray[numfaces*18+15],efa->n); - numfaces++; - } - } - else { - VECCOPY(&varray[numfaces*18],efa->v1->co); - VECCOPY(&varray[numfaces*18+3],efa->v1->no); - - VECCOPY(&varray[numfaces*18+6],efa->v2->co); - VECCOPY(&varray[numfaces*18+9],efa->v2->no); - - VECCOPY(&varray[numfaces*18+12],efa->v3->co); - VECCOPY(&varray[numfaces*18+15],efa->v3->no); - numfaces++; - if( efa->v4 ) { - VECCOPY(&varray[numfaces*18],efa->v3->co); - VECCOPY(&varray[numfaces*18+3],efa->v3->no); - - VECCOPY(&varray[numfaces*18+6],efa->v4->co); - VECCOPY(&varray[numfaces*18+9],efa->v4->no); - - VECCOPY(&varray[numfaces*18+12],efa->v1->co); - VECCOPY(&varray[numfaces*18+15],efa->v1->no); - numfaces++; - } - } - } - prevdraw = draw; - prevmat = curmat; - } - GPU_buffer_unlock( buffer ); - if( prevdraw != 0 && numfaces > 0) { - if( prevdraw==2 ) { - glEnable(GL_POLYGON_STIPPLE); - glPolygonStipple(stipple_quarttone); - } - GPU_enable_material(prevmat, NULL); - glDrawArrays(GL_TRIANGLES,0,numfaces*3); - if( prevdraw==2 ) { - glDisable(GL_POLYGON_STIPPLE); - } - } - GPU_buffer_unbind(); - } - else { - finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, 0, 0); - } - GPU_buffer_free(buffer,0); + finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, 0, 0); glFrontFace(GL_CCW); glDisable(GL_LIGHTING); @@ -6154,7 +5718,10 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag) } else if((flag & DRAW_CONSTCOLOR)==0) { /* we don't draw centers for duplicators and sets */ - drawcentercircle(v3d, rv3d, ob->obmat[3], do_draw_center, ob->id.lib || ob->id.us>1); + if(U.obcenter_dia > 0) { + /* check > 0 otherwise grease pencil can draw into the circle select which is annoying. */ + drawcentercircle(v3d, rv3d, ob->obmat[3], do_draw_center, ob->id.lib || ob->id.us>1); + } } } } @@ -6306,24 +5873,13 @@ static void bbs_mesh_solid_EM(Scene *scene, View3D *v3d, Object *ob, DerivedMesh } } -static int bbs_mesh_solid_hide__setDrawOpts(void *userData, int index, int *drawSmooth_r) -{ - Mesh *me = userData; - - if (!(me->mface[index].flag&ME_HIDE)) { - return 1; - } else { - return 0; - } -} - -static int bbs_mesh_solid__setDrawOpts_legacy(void *userData, int index, int *drawSmooth_r) +static int bbs_mesh_solid__setDrawOpts(void *userData, int index, int *drawSmooth_r) { WM_set_framebuffer_index_color(index+1); return 1; } -static int bbs_mesh_solid_hide__setDrawOpts_legacy(void *userData, int index, int *drawSmooth_r) +static int bbs_mesh_solid_hide__setDrawOpts(void *userData, int index, int *drawSmooth_r) { Mesh *me = userData; @@ -6339,43 +5895,12 @@ static void bbs_mesh_solid(Scene *scene, View3D *v3d, Object *ob) { DerivedMesh *dm = mesh_get_derived_final(scene, ob, v3d->customdata_mask); Mesh *me = (Mesh*)ob->data; - MCol *colors; - int i,j; int face_sel_mode = (me->flag & ME_EDIT_PAINT_MASK) ? 1:0; glColor3ub(0, 0, 0); - if( !GPU_buffer_legacy(dm) ) { - int *index = DM_get_face_data_layer(dm, CD_ORIGINDEX); - int ind; - colors = MEM_mallocN(dm->getNumFaces(dm)*sizeof(MCol)*4,"bbs_mesh_solid"); - for(i=0;i<dm->getNumFaces(dm);i++) { - ind= ( index )? index[i]: i; - - if (face_sel_mode==0 || !(me->mface[ind].flag&ME_HIDE)) { - unsigned int fbindex = index_to_framebuffer(ind+1); - for(j=0;j<4;j++) { - colors[i*4+j].b = ((fbindex)&0xFF); - colors[i*4+j].g = (((fbindex)>>8)&0xFF); - colors[i*4+j].r = (((fbindex)>>16)&0xFF); - } - } - else { - memset(&colors[i*4],0,sizeof(MCol)*4); - } - } - - CustomData_add_layer( &dm->faceData, CD_ID_MCOL, CD_ASSIGN, colors, dm->numFaceData ); - GPU_buffer_free(dm->drawObject->colors,0); - dm->drawObject->colors = 0; - - if(face_sel_mode) dm->drawMappedFaces(dm, bbs_mesh_solid_hide__setDrawOpts, me, 1); - else dm->drawMappedFaces(dm, NULL, me, 1); - } - else { - if(face_sel_mode) dm->drawMappedFaces(dm, bbs_mesh_solid_hide__setDrawOpts_legacy, me, 0); - else dm->drawMappedFaces(dm, bbs_mesh_solid__setDrawOpts_legacy, me, 0); - } + if(face_sel_mode) dm->drawMappedFaces(dm, bbs_mesh_solid_hide__setDrawOpts, me, 0); + else dm->drawMappedFaces(dm, bbs_mesh_solid__setDrawOpts, me, 0); dm->release(dm); } diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index f1db3ca53fc..6ee0e341849 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -488,6 +488,10 @@ static void view3d_main_area_listener(ARegion *ar, wmNotifier *wmn) /* all group ops for now */ ED_region_tag_redraw(ar); break; + case NC_BRUSH: + if(wmn->action == NA_EDITED) + ED_region_tag_redraw(ar); + break; case NC_MATERIAL: switch(wmn->data) { case ND_SHADING_DRAW: @@ -636,6 +640,10 @@ static void view3d_buttons_area_listener(ARegion *ar, wmNotifier *wmn) break; } break; + case NC_TEXTURE: + /* for brush textures */ + ED_region_tag_redraw(ar); + break; case NC_BRUSH: if(wmn->action==NA_EDITED) ED_region_tag_redraw(ar); diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 2cef7461e85..8af16641c00 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -1044,14 +1044,6 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d) UI_ThemeColor(TH_WIRE); glRectf(x1, y1, x2, y2); - /* camera name - draw in highlighted text color */ - if (ca && (ca->flag & CAM_SHOWNAME)) { - UI_ThemeColor(TH_TEXT_HI); - BLF_draw_default(x1, y1-15, 0.0f, v3d->camera->id.name+2); - UI_ThemeColor(TH_WIRE); - } - - /* border */ if(scene->r.mode & R_BORDER) { @@ -1086,6 +1078,12 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d) setlinestyle(0); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + /* camera name - draw in highlighted text color */ + if (ca && (ca->flag & CAM_SHOWNAME)) { + UI_ThemeColor(TH_TEXT_HI); + BLF_draw_default(x1, y1-15, 0.0f, v3d->camera->id.name+2); + UI_ThemeColor(TH_WIRE); + } } /* *********************** backdraw for selection *************** */ @@ -1096,16 +1094,6 @@ void backdrawview3d(Scene *scene, ARegion *ar, View3D *v3d) struct Base *base = scene->basact; rcti winrct; -/*for 2.43 release, don't use glext and just define the constant. - this to avoid possibly breaking platforms before release.*/ -#ifndef GL_MULTISAMPLE_ARB - #define GL_MULTISAMPLE_ARB 0x809D -#endif - -#ifdef GL_MULTISAMPLE_ARB - int m; -#endif - if(base && (base->object->mode & (OB_MODE_VERTEX_PAINT|OB_MODE_WEIGHT_PAINT) || paint_facesel_test(base->object))); else if((base && (base->object->mode & OB_MODE_TEXTURE_PAINT)) && @@ -1126,16 +1114,6 @@ void backdrawview3d(Scene *scene, ARegion *ar, View3D *v3d) // } // } - /* Disable FSAA for backbuffer selection. - - Only works if GL_MULTISAMPLE_ARB is defined by the header - file, which is should be for every OS that supports FSAA.*/ - -#ifdef GL_MULTISAMPLE_ARB - m = glIsEnabled(GL_MULTISAMPLE_ARB); - if (m) glDisable(GL_MULTISAMPLE_ARB); -#endif - if(v3d->drawtype > OB_WIRE) v3d->zbuf= TRUE; glDisable(GL_DITHER); @@ -1172,10 +1150,6 @@ void backdrawview3d(Scene *scene, ARegion *ar, View3D *v3d) if(rv3d->rflag & RV3D_CLIPPING) view3d_clr_clipping(); -#ifdef GL_MULTISAMPLE_ARB - if (m) glEnable(GL_MULTISAMPLE_ARB); -#endif - /* it is important to end a view in a transform compatible with buttons */ // persp(PERSP_WIN); // set ortho @@ -1643,22 +1617,46 @@ void view3d_update_depths(ARegion *ar, View3D *v3d) } } +void draw_depth_gpencil(Scene *scene, ARegion *ar, View3D *v3d) +{ + short zbuf= v3d->zbuf; + RegionView3D *rv3d= ar->regiondata; + + setwinmatrixview3d(ar, v3d, NULL); /* 0= no pick rect */ + setviewmatrixview3d(scene, v3d, rv3d); /* note: calls where_is_object for camera... */ + + mul_m4_m4m4(rv3d->persmat, rv3d->viewmat, rv3d->winmat); + invert_m4_m4(rv3d->persinv, rv3d->persmat); + invert_m4_m4(rv3d->viewinv, rv3d->viewmat); + + glClear(GL_DEPTH_BUFFER_BIT); + + wmLoadMatrix(rv3d->viewmat); + + v3d->zbuf= TRUE; + glEnable(GL_DEPTH_TEST); + + draw_gpencil_3dview_ext(scene, ar, 1); + + v3d->zbuf= zbuf; + +} + void draw_depth(Scene *scene, ARegion *ar, View3D *v3d, int (* func)(void *)) { RegionView3D *rv3d= ar->regiondata; Base *base; Scene *sce; - short zbuf, flag; - float glalphaclip; + short zbuf= v3d->zbuf; + short flag= v3d->flag; + float glalphaclip= U.glalphaclip; + int obcenter_dia= U.obcenter_dia; /* temp set drawtype to solid */ /* Setting these temporarily is not nice */ - zbuf = v3d->zbuf; - flag = v3d->flag; - glalphaclip = U.glalphaclip; - - U.glalphaclip = 0.5; /* not that nice but means we wont zoom into billboards */ v3d->flag &= ~V3D_SELECT_OUTLINE; + U.glalphaclip = 0.5; /* not that nice but means we wont zoom into billboards */ + U.obcenter_dia= 0; setwinmatrixview3d(ar, v3d, NULL); /* 0= no pick rect */ setviewmatrixview3d(scene, v3d, rv3d); /* note: calls where_is_object for camera... */ @@ -1742,6 +1740,7 @@ void draw_depth(Scene *scene, ARegion *ar, View3D *v3d, int (* func)(void *)) v3d->zbuf = zbuf; U.glalphaclip = glalphaclip; v3d->flag = flag; + U.obcenter_dia= obcenter_dia; } typedef struct View3DShadow { @@ -1928,8 +1927,16 @@ void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar, int winx, G.f |= G_RENDER_OGL; GPU_free_images(); - /* set background color */ - glClearColor(scene->world->horr, scene->world->horg, scene->world->horb, 0.0); + /* set background color, fallback on the view background color */ + if(scene->world) { + glClearColor(scene->world->horr, scene->world->horg, scene->world->horb, 0.0); + } + else { + float col[3]; + UI_GetThemeColor3fv(TH_BACK, col); + glClearColor(col[0], col[1], col[2], 0.0); + } + glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); /* setup view matrices */ @@ -2032,6 +2039,10 @@ void view3d_main_area_draw(const bContext *C, ARegion *ar) } else v3d->zbuf= FALSE; + + /* enables anti-aliasing for 3D view drawing */ + if (!(U.gameflags & USER_DISABLE_AA)) + glEnable(GL_MULTISAMPLE_ARB); // needs to be done always, gridview is adjusted in drawgrid() now rv3d->gridview= v3d->grid; @@ -2139,6 +2150,10 @@ void view3d_main_area_draw(const bContext *C, ARegion *ar) BIF_draw_manipulator(C); + /* Disable back anti-aliasing */ + if (!(U.gameflags & USER_DISABLE_AA)) + glDisable(GL_MULTISAMPLE_ARB); + if(v3d->zbuf) { v3d->zbuf= FALSE; glDisable(GL_DEPTH_TEST); diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index e8c2b48e4be..3d4cc8ef309 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -445,7 +445,9 @@ enum { #define VIEW_MODAL_CONFIRM 1 /* used for all view operations */ #define VIEWROT_MODAL_AXIS_SNAP_ENABLE 2 #define VIEWROT_MODAL_AXIS_SNAP_DISABLE 3 - +#define VIEWROT_MODAL_SWITCH_ZOOM 4 +#define VIEWROT_MODAL_SWITCH_MOVE 5 +#define VIEWROT_MODAL_SWITCH_ROTATE 6 /* called in transform_ops.c, on each regeneration of keymaps */ void viewrotate_modal_keymap(wmKeyConfig *keyconf) @@ -454,7 +456,10 @@ void viewrotate_modal_keymap(wmKeyConfig *keyconf) {VIEW_MODAL_CONFIRM, "CONFIRM", 0, "Cancel", ""}, {VIEWROT_MODAL_AXIS_SNAP_ENABLE, "AXIS_SNAP_ENABLE", 0, "Enable Axis Snap", ""}, - {VIEWROT_MODAL_AXIS_SNAP_DISABLE, "AXIS_SNAP_DISABLE", 0, "Enable Axis Snap", ""}, + {VIEWROT_MODAL_AXIS_SNAP_DISABLE, "AXIS_SNAP_DISABLE", 0, "Disable Axis Snap", ""}, + + {VIEWROT_MODAL_SWITCH_ZOOM, "SWITCH_TO_ZOOM", 0, "Switch to Zoom"}, + {VIEWROT_MODAL_SWITCH_MOVE, "SWITCH_TO_MOVE", 0, "Switch to Move"}, {0, NULL, 0, NULL, NULL}}; @@ -469,9 +474,13 @@ void viewrotate_modal_keymap(wmKeyConfig *keyconf) WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_RELEASE, KM_ANY, 0, VIEW_MODAL_CONFIRM); WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, VIEW_MODAL_CONFIRM); - WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_AXIS_SNAP_ENABLE); - WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_AXIS_SNAP_DISABLE); + WM_modalkeymap_add_item(keymap, LEFTALTKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_AXIS_SNAP_ENABLE); + WM_modalkeymap_add_item(keymap, LEFTALTKEY, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_AXIS_SNAP_DISABLE); + WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ZOOM); + WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ZOOM); + WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_MOVE); + /* assign map to operators */ WM_modalkeymap_assign(keymap, "VIEW3D_OT_rotate"); @@ -633,6 +642,14 @@ static int viewrotate_modal(bContext *C, wmOperator *op, wmEvent *event) vod->axis_snap= FALSE; event_code= VIEW_APPLY; break; + case VIEWROT_MODAL_SWITCH_ZOOM: + WM_operator_name_call(C, "VIEW3D_OT_zoom", WM_OP_INVOKE_DEFAULT, NULL); + event_code= VIEW_CONFIRM; + break; + case VIEWROT_MODAL_SWITCH_MOVE: + WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL); + event_code= VIEW_CONFIRM; + break; } } else if(event->type==vod->origkey && event->val==KM_RELEASE) { @@ -680,6 +697,20 @@ static int viewrotate_invoke(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_RUNNING_MODAL; } +static int ED_operator_view3d_rotate(bContext *C) +{ + if (!ED_operator_view3d_active(C)) { + return 0; + } else { + RegionView3D *rv3d= CTX_wm_region_view3d(C); + /* rv3d is null in menus, but it's ok when the menu is clicked on */ + /* XXX of course, this doesn't work with quadview + * Maybe having exec return PASSTHROUGH would be better than polling here + * Poll functions are full of problems anyway. + * */ + return rv3d == NULL || rv3d->viewlock == 0; + } +} void VIEW3D_OT_rotate(wmOperatorType *ot) { @@ -722,6 +753,10 @@ void viewmove_modal_keymap(wmKeyConfig *keyconf) WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_RELEASE, KM_ANY, 0, VIEW_MODAL_CONFIRM); WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, VIEW_MODAL_CONFIRM); + WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ZOOM); + WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ZOOM); + WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE); + /* assign map to operators */ WM_modalkeymap_assign(keymap, "VIEW3D_OT_move"); } @@ -770,6 +805,14 @@ static int viewmove_modal(bContext *C, wmOperator *op, wmEvent *event) case VIEW_MODAL_CONFIRM: event_code= VIEW_CONFIRM; break; + case VIEWROT_MODAL_SWITCH_ZOOM: + WM_operator_name_call(C, "VIEW3D_OT_zoom", WM_OP_INVOKE_DEFAULT, NULL); + event_code= VIEW_CONFIRM; + break; + case VIEWROT_MODAL_SWITCH_ROTATE: + WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL); + event_code= VIEW_CONFIRM; + break; } } else if(event->type==vod->origkey && event->val==KM_RELEASE) { @@ -840,6 +883,10 @@ void viewzoom_modal_keymap(wmKeyConfig *keyconf) WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_RELEASE, KM_ANY, 0, VIEW_MODAL_CONFIRM); WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, VIEW_MODAL_CONFIRM); + WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE); + WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE); + WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_MOVE); + /* assign map to operators */ WM_modalkeymap_assign(keymap, "VIEW3D_OT_zoom"); } @@ -981,6 +1028,14 @@ static int viewzoom_modal(bContext *C, wmOperator *op, wmEvent *event) case VIEW_MODAL_CONFIRM: event_code= VIEW_CONFIRM; break; + case VIEWROT_MODAL_SWITCH_MOVE: + WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL); + event_code= VIEW_CONFIRM; + break; + case VIEWROT_MODAL_SWITCH_ROTATE: + WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL); + event_code= VIEW_CONFIRM; + break; } } else if(event->type==vod->origkey && event->val==KM_RELEASE) { @@ -1460,7 +1515,7 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op) /* ZBuffer depth vars */ bglMats mats; - float depth, depth_close= MAXFLOAT; + float depth, depth_close= FLT_MAX; int had_depth = 0; double cent[2], p[3]; int xs, ys; @@ -1517,7 +1572,7 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op) double p_corner[3]; /* no depths to use, we cant do anything! */ - if (depth_close==MAXFLOAT){ + if (depth_close==FLT_MAX){ BKE_report(op->reports, RPT_ERROR, "Depth Too Large"); return OPERATOR_CANCELLED; } @@ -1545,7 +1600,7 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op) new_dist = rv3d->dist; /* convert the drawn rectangle into 3d space */ - if (depth_close!=MAXFLOAT && gluUnProject(cent[0], cent[1], depth_close, mats.modelview, mats.projection, (GLint *)mats.viewport, &p[0], &p[1], &p[2])) { + if (depth_close!=FLT_MAX && gluUnProject(cent[0], cent[1], depth_close, mats.modelview, mats.projection, (GLint *)mats.viewport, &p[0], &p[1], &p[2])) { new_ofs[0] = -p[0]; new_ofs[1] = -p[1]; new_ofs[2] = -p[2]; @@ -1822,9 +1877,8 @@ static EnumPropertyItem prop_view_orbit_items[] = { static int vieworbit_exec(bContext *C, wmOperator *op) { - ARegion *ar= CTX_wm_region(C); RegionView3D *rv3d= CTX_wm_region_view3d(C); - float phi, si, q1[4]; + float phi, si, q1[4], new_quat[4]; int orbitdir; orbitdir = RNA_enum_get(op->ptr, "type"); @@ -1840,10 +1894,10 @@ static int vieworbit_exec(bContext *C, wmOperator *op) q1[0]= (float)cos(phi); q1[1]= q1[2]= 0.0; q1[3]= si; - mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, q1); + mul_qt_qtqt(new_quat, rv3d->viewquat, q1); rv3d->view= 0; } - if(orbitdir == V3D_VIEW_STEPDOWN || orbitdir == V3D_VIEW_STEPUP) { + else if(orbitdir == V3D_VIEW_STEPDOWN || orbitdir == V3D_VIEW_STEPUP) { /* horizontal axis */ VECCOPY(q1+1, rv3d->viewinv[0]); @@ -1855,10 +1909,11 @@ static int vieworbit_exec(bContext *C, wmOperator *op) q1[1]*= si; q1[2]*= si; q1[3]*= si; - mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, q1); + mul_qt_qtqt(new_quat, rv3d->viewquat, q1); rv3d->view= 0; } - ED_region_tag_redraw(ar); + + smooth_view(C, NULL, NULL, NULL, new_quat, NULL, NULL); } } @@ -2183,22 +2238,66 @@ void VIEW3D_OT_manipulator(wmOperatorType *ot) /* ************************* below the line! *********************** */ +static float view_autodist_depth_margin(ARegion *ar, short *mval, int margin) +{ + RegionView3D *rv3d= ar->regiondata; + float depth= FLT_MAX; + + if(margin==0) { + if (mval[0] < 0) return 0; + if (mval[1] < 0) return 0; + if (mval[0] >= rv3d->depths->w) return 0; + if (mval[1] >= rv3d->depths->h) return 0; + + /* Get Z Depths, needed for perspective, nice for ortho */ + depth= rv3d->depths->depths[mval[1]*rv3d->depths->w+mval[0]]; + if(depth >= rv3d->depths->depth_range[1] || depth <= rv3d->depths->depth_range[0]) { + depth= FLT_MAX; + } + } + else { + rcti rect; + float depth_close= FLT_MAX; + int xs, ys; + + rect.xmax = mval[0] + margin; + rect.ymax = mval[1] + margin; + + rect.xmin = mval[0] - margin; + rect.ymin = mval[1] - margin; + + /* Constrain rect to depth bounds */ + if (rect.xmin < 0) rect.xmin = 0; + if (rect.ymin < 0) rect.ymin = 0; + if (rect.xmax >= rv3d->depths->w) rect.xmax = rv3d->depths->w-1; + if (rect.ymax >= rv3d->depths->h) rect.ymax = rv3d->depths->h-1; + + /* Find the closest Z pixel */ + for (xs=rect.xmin; xs < rect.xmax; xs++) { + for (ys=rect.ymin; ys < rect.ymax; ys++) { + depth= rv3d->depths->depths[ys*rv3d->depths->w+xs]; + if(depth < rv3d->depths->depth_range[1] && depth > rv3d->depths->depth_range[0]) { + if (depth_close > depth) { + depth_close = depth; + } + } + } + } + + depth= depth_close; + } + + return depth; +} + /* XXX todo Zooms in on a border drawn by the user */ int view_autodist(Scene *scene, ARegion *ar, View3D *v3d, short *mval, float mouse_worldloc[3] ) //, float *autodist ) { RegionView3D *rv3d= ar->regiondata; bglMats mats; /* ZBuffer depth vars */ - rcti rect; - float depth, depth_close= MAXFLOAT; + float depth_close= FLT_MAX; int had_depth = 0; double cent[2], p[3]; - int xs, ys; - - rect.xmax = mval[0] + 4; - rect.ymax = mval[1] + 4; - - rect.xmin = mval[0] - 4; - rect.ymin = mval[1] - 4; /* Get Z Depths, needed for perspective, nice for ortho */ bgl_get_mats(&mats); @@ -2212,25 +2311,9 @@ int view_autodist(Scene *scene, ARegion *ar, View3D *v3d, short *mval, float mou view3d_update_depths(ar, v3d); - /* Constrain rect to depth bounds */ - if (rect.xmin < 0) rect.xmin = 0; - if (rect.ymin < 0) rect.ymin = 0; - if (rect.xmax >= rv3d->depths->w) rect.xmax = rv3d->depths->w-1; - if (rect.ymax >= rv3d->depths->h) rect.ymax = rv3d->depths->h-1; + depth_close= view_autodist_depth_margin(ar, mval, 4); - /* Find the closest Z pixel */ - for (xs=rect.xmin; xs < rect.xmax; xs++) { - for (ys=rect.ymin; ys < rect.ymax; ys++) { - depth= rv3d->depths->depths[ys*rv3d->depths->w+xs]; - if(depth < rv3d->depths->depth_range[1] && depth > rv3d->depths->depth_range[0]) { - if (depth_close > depth) { - depth_close = depth; - } - } - } - } - - if (depth_close==MAXFLOAT) + if (depth_close==FLT_MAX) return 0; if (had_depth==0) { @@ -2251,12 +2334,19 @@ int view_autodist(Scene *scene, ARegion *ar, View3D *v3d, short *mval, float mou return 1; } -int view_autodist_init(Scene *scene, ARegion *ar, View3D *v3d) //, float *autodist ) +int view_autodist_init(Scene *scene, ARegion *ar, View3D *v3d, int mode) //, float *autodist ) { RegionView3D *rv3d= ar->regiondata; /* Get Z Depths, needed for perspective, nice for ortho */ - draw_depth(scene, ar, v3d, NULL); + switch(mode) { + case 0: + draw_depth(scene, ar, v3d, NULL); + break; + case 1: + draw_depth_gpencil(scene, ar, v3d); + break; + } /* force updating */ if (rv3d->depths) { @@ -2268,28 +2358,25 @@ int view_autodist_init(Scene *scene, ARegion *ar, View3D *v3d) //, float *autodi } // no 4x4 sampling, run view_autodist_init first -int view_autodist_simple(ARegion *ar, short *mval, float mouse_worldloc[3] ) //, float *autodist ) +int view_autodist_simple(ARegion *ar, short *mval, float mouse_worldloc[3], int margin, float *force_depth) //, float *autodist ) { - RegionView3D *rv3d= ar->regiondata; bglMats mats; /* ZBuffer depth vars, could cache? */ float depth; double cent[2], p[3]; - if (mval[0] < 0) return 0; - if (mval[1] < 0) return 0; - if (mval[0] >= rv3d->depths->w) return 0; - if (mval[1] >= rv3d->depths->h) return 0; - /* Get Z Depths, needed for perspective, nice for ortho */ - bgl_get_mats(&mats); - depth= rv3d->depths->depths[mval[1]*rv3d->depths->w+mval[0]]; + if(force_depth) + depth= *force_depth; + else + depth= view_autodist_depth_margin(ar, mval, margin); - if (depth==MAXFLOAT) + if (depth==FLT_MAX) return 0; cent[0] = (double)mval[0]; cent[1] = (double)mval[1]; + bgl_get_mats(&mats); if (!gluUnProject(cent[0], cent[1], depth, mats.modelview, mats.projection, (GLint *)mats.viewport, &p[0], &p[1], &p[2])) return 0; @@ -2299,6 +2386,14 @@ int view_autodist_simple(ARegion *ar, short *mval, float mouse_worldloc[3] ) //, return 1; } +int view_autodist_depth(struct ARegion *ar, short *mval, int margin, float *depth) +{ + *depth= view_autodist_depth_margin(ar, mval, margin); + + return (*depth==FLT_MAX) ? 0:1; + return 0; +} + /* ********************* NDOF ************************ */ /* note: this code is confusing and unclear... (ton) */ /* **************************************************** */ diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c index 9b6cfc6cbd0..98f0f2fec65 100644 --- a/source/blender/editors/space_view3d/view3d_header.c +++ b/source/blender/editors/space_view3d/view3d_header.c @@ -173,6 +173,7 @@ static int layers_exec(bContext *C, wmOperator *op) ScrArea *sa= CTX_wm_area(C); View3D *v3d= sa->spacedata.first; int nr= RNA_int_get(op->ptr, "nr"); + int toggle= RNA_boolean_get(op->ptr, "toggle"); if(nr < 0) return OPERATOR_CANCELLED; @@ -188,9 +189,12 @@ static int layers_exec(bContext *C, wmOperator *op) else { nr--; - if(RNA_boolean_get(op->ptr, "extend")) - v3d->lay |= (1<<nr); - else + if(RNA_boolean_get(op->ptr, "extend")) { + if(toggle && v3d->lay & (1<<nr) && (v3d->lay & ~(1<<nr))) + v3d->lay &= ~(1<<nr); + else + v3d->lay |= (1<<nr); + } else v3d->lay = (1<<nr); /* set active layer, ensure to always have one */ @@ -238,6 +242,11 @@ static int layers_invoke(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_FINISHED; } +int layers_poll(bContext *C) +{ + return (ED_operator_view3d_active(C) && CTX_wm_view3d(C)->localvd==NULL); +} + void VIEW3D_OT_layers(wmOperatorType *ot) { /* identifiers */ @@ -248,13 +257,14 @@ void VIEW3D_OT_layers(wmOperatorType *ot) /* api callbacks */ ot->invoke= layers_invoke; ot->exec= layers_exec; - ot->poll= ED_operator_view3d_active; + ot->poll= layers_poll; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; RNA_def_int(ot->srna, "nr", 1, 0, 20, "Number", "The layer number to set, zero for all layers", 0, 20); RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Add this layer to the current view layers"); + RNA_def_boolean(ot->srna, "toggle", 1, "Toggle", "Toggle the layer"); } static char *view3d_modeselect_pup(Scene *scene) diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index bf5d516c03a..a5d4c61bc01 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -43,6 +43,9 @@ struct wmWindowManager; struct EditMesh; struct ViewContext; struct ARegionType; +struct bPoseChannel; +struct bAnimVizSettings; +struct bMotionPath; #define BL_NEAR_CLIP 0.001 @@ -84,6 +87,15 @@ void VIEW3D_OT_drawtype(struct wmOperatorType *ot); void view3d_boxview_copy(ScrArea *sa, ARegion *ar); +/* drawanim.c */ +void draw_motion_paths_init(Scene *scene, View3D *v3d, struct ARegion *ar); +void draw_motion_path_instance(Scene *scene, View3D *v3d, struct ARegion *ar, + struct Object *ob, struct bPoseChannel *pchan, + struct bAnimVizSettings *avs, struct bMotionPath *mpath); +void draw_motion_paths_cleanup(Scene *scene, View3D *v3d, struct ARegion *ar); + + + /* drawobject.c */ void draw_object(Scene *scene, struct ARegion *ar, View3D *v3d, Base *base, int flag); int draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, int dt); @@ -104,6 +116,7 @@ void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *o /* view3d_draw.c */ void view3d_main_area_draw(const struct bContext *C, struct ARegion *ar); void draw_depth(Scene *scene, struct ARegion *ar, View3D *v3d, int (* func)(void *)); +void draw_depth_gpencil(Scene *scene, ARegion *ar, View3D *v3d); void view3d_clr_clipping(void); void view3d_set_clipping(RegionView3D *rv3d); void add_view3d_after(View3D *v3d, Base *base, int type, int flag); diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c index c211e55d7a0..2bcd78b3d3d 100644 --- a/source/blender/editors/space_view3d/view3d_ops.c +++ b/source/blender/editors/space_view3d/view3d_ops.c @@ -159,7 +159,17 @@ void view3d_keymap(wmKeyConfig *keyconf) RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_pan", PAD4, KM_PRESS, KM_CTRL, 0)->ptr, "type", V3D_VIEW_PANLEFT); RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_pan", PAD6, KM_PRESS, KM_CTRL, 0)->ptr, "type", V3D_VIEW_PANRIGHT); RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_pan", PAD8, KM_PRESS, KM_CTRL, 0)->ptr, "type", V3D_VIEW_PANUP); - + + RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_pan", WHEELUPMOUSE, KM_PRESS, KM_CTRL, 0)->ptr, "type", V3D_VIEW_PANRIGHT); + RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_pan", WHEELDOWNMOUSE, KM_PRESS, KM_CTRL, 0)->ptr, "type", V3D_VIEW_PANLEFT); + RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_pan", WHEELUPMOUSE, KM_PRESS, KM_SHIFT, 0)->ptr, "type", V3D_VIEW_PANUP); + RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_pan", WHEELDOWNMOUSE, KM_PRESS, KM_SHIFT, 0)->ptr, "type", V3D_VIEW_PANDOWN); + + RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_orbit", WHEELUPMOUSE, KM_PRESS, KM_CTRL|KM_ALT, 0)->ptr, "type", V3D_VIEW_STEPLEFT); + RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_orbit", WHEELDOWNMOUSE, KM_PRESS, KM_CTRL|KM_ALT, 0)->ptr, "type", V3D_VIEW_STEPRIGHT); + RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_orbit", WHEELUPMOUSE, KM_PRESS, KM_SHIFT|KM_ALT, 0)->ptr, "type", V3D_VIEW_STEPUP); + RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_orbit", WHEELDOWNMOUSE, KM_PRESS, KM_SHIFT|KM_ALT, 0)->ptr, "type", V3D_VIEW_STEPDOWN); + /* active aligned, replaces '*' key in 2.4x */ kmi= WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", PAD1, KM_PRESS, KM_SHIFT, 0); RNA_enum_set(kmi->ptr, "type", RV3D_VIEW_FRONT); diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index e7c8070b7c5..0ed7f4c0d0a 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -94,14 +94,14 @@ #include "view3d_intern.h" // own include - +// TODO: should return whether there is valid context to continue void view3d_set_viewcontext(bContext *C, ViewContext *vc) { memset(vc, 0, sizeof(ViewContext)); vc->ar= CTX_wm_region(C); vc->scene= CTX_data_scene(C); vc->v3d= CTX_wm_view3d(C); - vc->rv3d= vc->ar->regiondata; + vc->rv3d= CTX_wm_region_view3d(C); vc->obact= CTX_data_active_object(C); vc->obedit= CTX_data_edit_object(C); } @@ -1424,6 +1424,8 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op) else if(obedit==NULL && (obact && obact->mode & OB_MODE_PARTICLE_EDIT)) { return PE_border_select(C, &rect, selecting, extend); } + else if(obedit==NULL && (obact && obact->mode & OB_MODE_SCULPT)) + return OPERATOR_CANCELLED; if(obedit) { if(obedit->type==OB_MESH) { @@ -1689,6 +1691,8 @@ static int view3d_select_invoke(bContext *C, wmOperator *op, wmEvent *event) retval = mouse_mball(C, event->mval, extend); } + else if(obact && obact->mode & OB_MODE_SCULPT) + return OPERATOR_CANCELLED; else if(obact && obact->mode & OB_MODE_PARTICLE_EDIT) return PE_mouse_particles(C, event->mval, extend); else if(obact && paint_facesel_test(obact)) @@ -2012,6 +2016,9 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op) else return PE_circle_select(C, selecting, mval, (float)radius); } + else if(obact && obact->mode & OB_MODE_SCULPT) { + return OPERATOR_CANCELLED; + } else { Base *base; selecting= selecting?BA_SELECT:BA_DESELECT; diff --git a/source/blender/editors/space_view3d/view3d_toolbar.c b/source/blender/editors/space_view3d/view3d_toolbar.c index 0384a23579e..b05043cd76e 100644 --- a/source/blender/editors/space_view3d/view3d_toolbar.c +++ b/source/blender/editors/space_view3d/view3d_toolbar.c @@ -239,7 +239,7 @@ static uiBlock *tool_search_menu(bContext *C, ARegion *ar, void *arg_listbase) /* fake button, it holds space for search items */ uiDefBut(block, LABEL, 0, "", 10, 15, 150, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL); - but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, OP_MAX_TYPENAME, 10, 0, 150, 19, ""); + but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, OP_MAX_TYPENAME, 10, 0, 150, 19, 0, 0, ""); uiButSetSearchFunc(but, operator_search_cb, arg_listbase, operator_call_cb, NULL); uiBoundsBlock(block, 6); diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index 48f3c77091f..adb1e6c6f1c 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -536,6 +536,7 @@ void viewline(ARegion *ar, View3D *v3d, float mval[2], float ray_start[3], float { RegionView3D *rv3d= ar->regiondata; float vec[4]; + int a; if(rv3d->persp != RV3D_ORTHO){ vec[0]= 2.0f * mval[0] / ar->winx - 1; @@ -564,6 +565,11 @@ void viewline(ARegion *ar, View3D *v3d, float mval[2], float ray_start[3], float VECADDFAC(ray_start, vec, rv3d->viewinv[2], 1000.0f); VECADDFAC(ray_end, vec, rv3d->viewinv[2], -1000.0f); } + + /* clipping */ + if(rv3d->rflag & RV3D_CLIPPING) + for(a=0; a<4; a++) + clip_line_plane(ray_start, ray_end, rv3d->clip[a]); } /* create intersection ray in view Z direction at mouse coordinates */ @@ -1650,11 +1656,6 @@ void game_set_commmandline_options(GameData *gm) if ( (syshandle = SYS_GetSystem()) ) { /* User defined settings */ - test= (U.gameflags & USER_DISABLE_SOUND); - /* if user already disabled audio at the command-line, don't re-enable it */ - if (test) - SYS_WriteCommandLineInt(syshandle, "noaudio", test); - test= (U.gameflags & USER_DISABLE_MIPMAP); GPU_set_mipmap(!test); SYS_WriteCommandLineInt(syshandle, "nomipmap", test); @@ -2480,14 +2481,7 @@ static int flyApply(FlyInfo *fly) if (rv3d->persp==RV3D_CAMOB) { rv3d->persp= RV3D_PERSP; /*set this so setviewmatrixview3d uses the ofs and quat instead of the camera */ setviewmatrixview3d(scene, v3d, rv3d); - setcameratoview3d(v3d, rv3d, v3d->camera); - - { //XXX - some reason setcameratoview3d doesnt copy, shouldnt not be needed! - VECCOPY(v3d->camera->loc, rv3d->ofs); - negate_v3(v3d->camera->loc); - } - rv3d->persp= RV3D_CAMOB; #if 0 //XXX2.5 /* record the motion */ diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index fa435f29773..93abe0d6cfe 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -1381,6 +1381,11 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op) RNA_float_set(op->ptr, "proportional_size", t->prop_size); } + if (RNA_struct_find_property(op->ptr, "axis")) + { + RNA_float_set_array(op->ptr, "axis", t->axis); + } + if (RNA_struct_find_property(op->ptr, "mirror")) { RNA_boolean_set(op->ptr, "mirror", t->flag & T_MIRROR); @@ -1574,6 +1579,13 @@ int initTransform(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event, int t->flag |= T_AUTOVALUES; } + /* Transformation axis from operator */ + if (RNA_struct_find_property(op->ptr, "axis") && RNA_property_is_set(op->ptr, "axis")) + { + RNA_float_get_array(op->ptr, "axis", t->axis); + normalize_v3(t->axis); + } + /* Constraint init from operator */ if (RNA_struct_find_property(op->ptr, "constraint_axis") && RNA_property_is_set(op->ptr, "constraint_axis")) { @@ -2662,6 +2674,10 @@ void initRotation(TransInfo *t) if (t->flag & T_2D_EDIT) t->flag |= T_NO_CONSTRAINT; + + VECCOPY(t->axis, t->viewinv[2]); + mul_v3_fl(t->axis, -1.0f); + normalize_v3(t->axis); } static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short around) { @@ -2906,13 +2922,8 @@ int Rotation(TransInfo *t, short mval[2]) float final; - float axis[3]; float mat[3][3]; - VECCOPY(axis, t->viewinv[2]); - mul_v3_fl(axis, -1.0f); - normalize_v3(axis); - final = t->values[0]; applyNDofInput(&t->ndof, &final); @@ -2920,7 +2931,7 @@ int Rotation(TransInfo *t, short mval[2]) snapGrid(t, &final); if (t->con.applyRot) { - t->con.applyRot(t, NULL, axis, &final); + t->con.applyRot(t, NULL, t->axis, &final); } applySnapping(t, &final); @@ -2947,13 +2958,13 @@ int Rotation(TransInfo *t, short mval[2]) sprintf(str, "Rot: %.2f%s %s", 180.0*final/M_PI, t->con.text, t->proptext); } - vec_rot_to_mat3( mat,axis, final); + vec_rot_to_mat3( mat, t->axis, final); // TRANSFORM_FIX_ME // t->values[0] = final; // used in manipulator // copy_m3_m3(t->mat, mat); // used in manipulator - applyRotation(t, final, axis); + applyRotation(t, final, t->axis); recalcData(t); @@ -3085,9 +3096,11 @@ void initTranslation(TransInfo *t) if(t->spacetype == SPACE_VIEW3D) { RegionView3D *rv3d = t->ar->regiondata; - t->snap[0] = 0.0f; - t->snap[1] = rv3d->gridview * 1.0f; - t->snap[2] = t->snap[1] * 0.1f; + if (rv3d) { + t->snap[0] = 0.0f; + t->snap[1] = rv3d->gridview * 1.0f; + t->snap[2] = t->snap[1] * 0.1f; + } } else if(t->spacetype == SPACE_IMAGE) { t->snap[0] = 0.0f; diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 72d970c967a..fd4f67f4f27 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -315,6 +315,8 @@ typedef struct TransInfo { float values[4]; float auto_values[4]; + float axis[3]; + void *view; struct ScrArea *sa; struct ARegion *ar; diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 822c0e5a961..7a89765fef2 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -332,7 +332,7 @@ static void createTransTexspace(bContext *C, TransInfo *t) /* ********************* edge (for crease) ***** */ static void createTransEdge(bContext *C, TransInfo *t) { -#if 0 // TRANSFORM_FIX_ME + EditMesh *em = ((Mesh *)t->obedit->data)->edit_mesh; TransData *td = NULL; EditEdge *eed; float mtx[3][3], smtx[3][3]; @@ -390,7 +390,6 @@ static void createTransEdge(bContext *C, TransInfo *t) { td++; } } -#endif } /* ********************* pose mode ************* */ @@ -5148,11 +5147,11 @@ void createTransData(bContext *C, TransInfo *t) Scene *scene = CTX_data_scene(C); Object *ob = OBACT; - if (t->options == CTX_TEXTURE) { + if (t->options & CTX_TEXTURE) { t->flag |= T_TEXTURE; createTransTexspace(C, t); } - else if (t->options == CTX_EDGE) { + else if (t->options & CTX_EDGE) { t->ext = NULL; t->flag |= T_EDIT; createTransEdge(C, t); diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 061b2adbd79..3be863fc3f7 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -919,6 +919,11 @@ int initTransInfo (bContext *C, TransInfo *t, wmOperator *op, wmEvent *event) t->flag |= T_MODAL; } + /* Crease needs edge flag */ + if (t->mode == TFM_CREASE) { + t->options |= CTX_EDGE; + } + t->spacetype = sa->spacetype; if(t->spacetype == SPACE_VIEW3D) { diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index 4c118aa2625..f3789880ce9 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -67,6 +67,7 @@ char OP_TILT[] = "TRANSFORM_OT_tilt"; char OP_TRACKBALL[] = "TRANSFORM_OT_trackball"; char OP_MIRROR[] = "TRANSFORM_OT_mirror"; char OP_EDGE_SLIDE[] = "TRANSFORM_OT_edge_slide"; +char OP_EDGE_CREASE[] = "TRANSFORM_OT_edge_crease"; char OP_SEQ_SLIDE[] = "TRANSFORM_OT_seq_slide"; void TRANSFORM_OT_translate(struct wmOperatorType *ot); @@ -80,6 +81,7 @@ void TRANSFORM_OT_tilt(struct wmOperatorType *ot); void TRANSFORM_OT_trackball(struct wmOperatorType *ot); void TRANSFORM_OT_mirror(struct wmOperatorType *ot); void TRANSFORM_OT_edge_slide(struct wmOperatorType *ot); +void TRANSFORM_OT_edge_crease(struct wmOperatorType *ot); void TRANSFORM_OT_seq_slide(struct wmOperatorType *ot); TransformModeItem transform_modes[] = @@ -95,6 +97,7 @@ TransformModeItem transform_modes[] = {OP_TRACKBALL, TFM_TRACKBALL, TRANSFORM_OT_trackball}, {OP_MIRROR, TFM_MIRROR, TRANSFORM_OT_mirror}, {OP_EDGE_SLIDE, TFM_EDGE_SLIDE, TRANSFORM_OT_edge_slide}, + {OP_EDGE_CREASE, TFM_CREASE, TRANSFORM_OT_edge_crease}, {OP_SEQ_SLIDE, TFM_SEQ_SLIDE, TRANSFORM_OT_seq_slide}, {NULL, 0} }; @@ -385,6 +388,15 @@ void Properties_Proportional(struct wmOperatorType *ot) RNA_def_float(ot->srna, "proportional_size", 1, 0, FLT_MAX, "Proportional Size", "", 0, 100); } +void Properties_Axis(struct wmOperatorType *ot) +{ + PropertyRNA *prop; + + prop= RNA_def_property(ot->srna, "axis", PROP_FLOAT, PROP_DIRECTION); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Axis", "The axis around which the transformation occurs."); +} + void Properties_Snapping(struct wmOperatorType *ot, short fullsnap, short align) { RNA_def_boolean(ot->srna, "snap", 0, "Use Snapping Options", ""); @@ -504,6 +516,8 @@ void TRANSFORM_OT_rotate(struct wmOperatorType *ot) RNA_def_float_rotation(ot->srna, "value", 1, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI*2, M_PI*2); + Properties_Axis(ot); + Properties_Proportional(ot); RNA_def_boolean(ot->srna, "mirror", 0, "Mirror Editing", ""); @@ -686,6 +700,26 @@ void TRANSFORM_OT_edge_slide(struct wmOperatorType *ot) Properties_Snapping(ot, 0, 0); } +void TRANSFORM_OT_edge_crease(struct wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Edge Crease"; + ot->description= "Change the crease of edges."; + ot->idname = OP_EDGE_CREASE; + ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING; + + /* api callbacks */ + ot->invoke = transform_invoke; + ot->exec = transform_exec; + ot->modal = transform_modal; + ot->cancel = transform_cancel; + ot->poll = ED_operator_editmesh; + + RNA_def_float_factor(ot->srna, "value", 0, -1.0f, 1.0f, "Factor", "", -1.0f, 1.0f); + + Properties_Snapping(ot, 0, 0); +} + void TRANSFORM_OT_seq_slide(struct wmOperatorType *ot) { /* identifiers */ @@ -757,6 +791,8 @@ void TRANSFORM_OT_transform(struct wmOperatorType *ot) RNA_def_float_vector(ot->srna, "value", 4, NULL, -FLT_MAX, FLT_MAX, "Values", "", -FLT_MAX, FLT_MAX); + Properties_Axis(ot); + Properties_Proportional(ot); RNA_def_boolean(ot->srna, "mirror", 0, "Mirror Editing", ""); diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp index e16568b5cf6..2a29576a981 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp +++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp @@ -268,6 +268,6 @@ Render* BlenderStrokeRenderer::RenderScene( Render *re ) { Render* freestyle_render = RE_NewRender(freestyle_scene->id.name); - RE_BlenderFrame( freestyle_render, freestyle_scene, 1); + RE_BlenderFrame( freestyle_render, freestyle_scene, NULL, 1); return freestyle_render; } diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h index fabe1420e83..36af91f140b 100644 --- a/source/blender/gpu/GPU_draw.h +++ b/source/blender/gpu/GPU_draw.h @@ -57,6 +57,10 @@ struct SmokeModifierData; void GPU_state_init(void); +/* Debugging */ + +void GPU_state_print(void); + /* Material drawing * - first the state is initialized by a particular object and * it's materials diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index db6c7fa5ce0..74b9f362939 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -1313,5 +1313,370 @@ void GPU_state_init(void) glFrontFace(GL_CCW); glCullFace(GL_BACK); glDisable(GL_CULL_FACE); + + glDisable(GL_MULTISAMPLE_ARB); +} + +/* debugging aid */ +static void gpu_get_print(const char *name, GLenum type) +{ + float value[16]; + int a; + + memset(value, 0, sizeof(value)); + glGetFloatv(type, value); + + printf("%s: ", name); + for(a=0; a<16; a++) + printf("%.2f ", value[a]); + printf("\n"); +} + +void GPU_state_print(void) +{ + gpu_get_print("GL_ACCUM_ALPHA_BITS", GL_ACCUM_ALPHA_BITS); + gpu_get_print("GL_ACCUM_BLUE_BITS", GL_ACCUM_BLUE_BITS); + gpu_get_print("GL_ACCUM_CLEAR_VALUE", GL_ACCUM_CLEAR_VALUE); + gpu_get_print("GL_ACCUM_GREEN_BITS", GL_ACCUM_GREEN_BITS); + gpu_get_print("GL_ACCUM_RED_BITS", GL_ACCUM_RED_BITS); + gpu_get_print("GL_ACTIVE_TEXTURE", GL_ACTIVE_TEXTURE); + gpu_get_print("GL_ALIASED_POINT_SIZE_RANGE", GL_ALIASED_POINT_SIZE_RANGE); + gpu_get_print("GL_ALIASED_LINE_WIDTH_RANGE", GL_ALIASED_LINE_WIDTH_RANGE); + gpu_get_print("GL_ALPHA_BIAS", GL_ALPHA_BIAS); + gpu_get_print("GL_ALPHA_BITS", GL_ALPHA_BITS); + gpu_get_print("GL_ALPHA_SCALE", GL_ALPHA_SCALE); + gpu_get_print("GL_ALPHA_TEST", GL_ALPHA_TEST); + gpu_get_print("GL_ALPHA_TEST_FUNC", GL_ALPHA_TEST_FUNC); + gpu_get_print("GL_ALPHA_TEST_REF", GL_ALPHA_TEST_REF); + gpu_get_print("GL_ARRAY_BUFFER_BINDING", GL_ARRAY_BUFFER_BINDING); + gpu_get_print("GL_ATTRIB_STACK_DEPTH", GL_ATTRIB_STACK_DEPTH); + gpu_get_print("GL_AUTO_NORMAL", GL_AUTO_NORMAL); + gpu_get_print("GL_AUX_BUFFERS", GL_AUX_BUFFERS); + gpu_get_print("GL_BLEND", GL_BLEND); + gpu_get_print("GL_BLEND_COLOR", GL_BLEND_COLOR); + gpu_get_print("GL_BLEND_DST_ALPHA", GL_BLEND_DST_ALPHA); + gpu_get_print("GL_BLEND_DST_RGB", GL_BLEND_DST_RGB); + gpu_get_print("GL_BLEND_EQUATION_RGB", GL_BLEND_EQUATION_RGB); + gpu_get_print("GL_BLEND_EQUATION_ALPHA", GL_BLEND_EQUATION_ALPHA); + gpu_get_print("GL_BLEND_SRC_ALPHA", GL_BLEND_SRC_ALPHA); + gpu_get_print("GL_BLEND_SRC_RGB", GL_BLEND_SRC_RGB); + gpu_get_print("GL_BLUE_BIAS", GL_BLUE_BIAS); + gpu_get_print("GL_BLUE_BITS", GL_BLUE_BITS); + gpu_get_print("GL_BLUE_SCALE", GL_BLUE_SCALE); + gpu_get_print("GL_CLIENT_ACTIVE_TEXTURE", GL_CLIENT_ACTIVE_TEXTURE); + gpu_get_print("GL_CLIENT_ATTRIB_STACK_DEPTH", GL_CLIENT_ATTRIB_STACK_DEPTH); + gpu_get_print("GL_CLIP_PLANE0", GL_CLIP_PLANE0); + gpu_get_print("GL_COLOR_ARRAY", GL_COLOR_ARRAY); + gpu_get_print("GL_COLOR_ARRAY_BUFFER_BINDING", GL_COLOR_ARRAY_BUFFER_BINDING); + gpu_get_print("GL_COLOR_ARRAY_SIZE", GL_COLOR_ARRAY_SIZE); + gpu_get_print("GL_COLOR_ARRAY_STRIDE", GL_COLOR_ARRAY_STRIDE); + gpu_get_print("GL_COLOR_ARRAY_TYPE", GL_COLOR_ARRAY_TYPE); + gpu_get_print("GL_COLOR_CLEAR_VALUE", GL_COLOR_CLEAR_VALUE); + gpu_get_print("GL_COLOR_LOGIC_OP", GL_COLOR_LOGIC_OP); + gpu_get_print("GL_COLOR_MATERIAL", GL_COLOR_MATERIAL); + gpu_get_print("GL_COLOR_MATERIAL_FACE", GL_COLOR_MATERIAL_FACE); + gpu_get_print("GL_COLOR_MATERIAL_PARAMETER", GL_COLOR_MATERIAL_PARAMETER); + gpu_get_print("GL_COLOR_MATRIX", GL_COLOR_MATRIX); + gpu_get_print("GL_COLOR_MATRIX_STACK_DEPTH", GL_COLOR_MATRIX_STACK_DEPTH); + gpu_get_print("GL_COLOR_SUM", GL_COLOR_SUM); + gpu_get_print("GL_COLOR_TABLE", GL_COLOR_TABLE); + gpu_get_print("GL_COLOR_WRITEMASK", GL_COLOR_WRITEMASK); + gpu_get_print("GL_COMPRESSED_TEXTURE_FORMATS", GL_COMPRESSED_TEXTURE_FORMATS); + gpu_get_print("GL_CONVOLUTION_1D", GL_CONVOLUTION_1D); + gpu_get_print("GL_CONVOLUTION_2D", GL_CONVOLUTION_2D); + gpu_get_print("GL_CULL_FACE", GL_CULL_FACE); + gpu_get_print("GL_CULL_FACE_MODE", GL_CULL_FACE_MODE); + gpu_get_print("GL_CURRENT_COLOR", GL_CURRENT_COLOR); + gpu_get_print("GL_CURRENT_FOG_COORD", GL_CURRENT_FOG_COORD); + gpu_get_print("GL_CURRENT_INDEX", GL_CURRENT_INDEX); + gpu_get_print("GL_CURRENT_NORMAL", GL_CURRENT_NORMAL); + gpu_get_print("GL_CURRENT_PROGRAM", GL_CURRENT_PROGRAM); + gpu_get_print("GL_CURRENT_RASTER_COLOR", GL_CURRENT_RASTER_COLOR); + gpu_get_print("GL_CURRENT_RASTER_DISTANCE", GL_CURRENT_RASTER_DISTANCE); + gpu_get_print("GL_CURRENT_RASTER_INDEX", GL_CURRENT_RASTER_INDEX); + gpu_get_print("GL_CURRENT_RASTER_POSITION", GL_CURRENT_RASTER_POSITION); + gpu_get_print("GL_CURRENT_RASTER_POSITION_VALID", GL_CURRENT_RASTER_POSITION_VALID); + gpu_get_print("GL_CURRENT_RASTER_SECONDARY_COLOR", GL_CURRENT_RASTER_SECONDARY_COLOR); + gpu_get_print("GL_CURRENT_RASTER_TEXTURE_COORDS", GL_CURRENT_RASTER_TEXTURE_COORDS); + gpu_get_print("GL_CURRENT_SECONDARY_COLOR", GL_CURRENT_SECONDARY_COLOR); + gpu_get_print("GL_CURRENT_TEXTURE_COORDS", GL_CURRENT_TEXTURE_COORDS); + gpu_get_print("GL_DEPTH_BIAS", GL_DEPTH_BIAS); + gpu_get_print("GL_DEPTH_BITS", GL_DEPTH_BITS); + gpu_get_print("GL_DEPTH_CLEAR_VALUE", GL_DEPTH_CLEAR_VALUE); + gpu_get_print("GL_DEPTH_FUNC", GL_DEPTH_FUNC); + gpu_get_print("GL_DEPTH_RANGE", GL_DEPTH_RANGE); + gpu_get_print("GL_DEPTH_SCALE", GL_DEPTH_SCALE); + gpu_get_print("GL_DEPTH_TEST", GL_DEPTH_TEST); + gpu_get_print("GL_DEPTH_WRITEMASK", GL_DEPTH_WRITEMASK); + gpu_get_print("GL_DITHER", GL_DITHER); + gpu_get_print("GL_DOUBLEBUFFER", GL_DOUBLEBUFFER); + gpu_get_print("GL_DRAW_BUFFER", GL_DRAW_BUFFER); + gpu_get_print("GL_DRAW_BUFFER0", GL_DRAW_BUFFER0); + gpu_get_print("GL_EDGE_FLAG", GL_EDGE_FLAG); + gpu_get_print("GL_EDGE_FLAG_ARRAY", GL_EDGE_FLAG_ARRAY); + gpu_get_print("GL_EDGE_FLAG_ARRAY_BUFFER_BINDING", GL_EDGE_FLAG_ARRAY_BUFFER_BINDING); + gpu_get_print("GL_EDGE_FLAG_ARRAY_STRIDE", GL_EDGE_FLAG_ARRAY_STRIDE); + gpu_get_print("GL_ELEMENT_ARRAY_BUFFER_BINDING", GL_ELEMENT_ARRAY_BUFFER_BINDING); + gpu_get_print("GL_FEEDBACK_BUFFER_SIZE", GL_FEEDBACK_BUFFER_SIZE); + gpu_get_print("GL_FEEDBACK_BUFFER_TYPE", GL_FEEDBACK_BUFFER_TYPE); + gpu_get_print("GL_FOG", GL_FOG); + gpu_get_print("GL_FOG_COORD_ARRAY", GL_FOG_COORD_ARRAY); + gpu_get_print("GL_FOG_COORD_ARRAY_BUFFER_BINDING", GL_FOG_COORD_ARRAY_BUFFER_BINDING); + gpu_get_print("GL_FOG_COORD_ARRAY_STRIDE", GL_FOG_COORD_ARRAY_STRIDE); + gpu_get_print("GL_FOG_COORD_ARRAY_TYPE", GL_FOG_COORD_ARRAY_TYPE); + gpu_get_print("GL_FOG_COORD_SRC", GL_FOG_COORD_SRC); + gpu_get_print("GL_FOG_COLOR", GL_FOG_COLOR); + gpu_get_print("GL_FOG_DENSITY", GL_FOG_DENSITY); + gpu_get_print("GL_FOG_END", GL_FOG_END); + gpu_get_print("GL_FOG_HINT", GL_FOG_HINT); + gpu_get_print("GL_FOG_INDEX", GL_FOG_INDEX); + gpu_get_print("GL_FOG_MODE", GL_FOG_MODE); + gpu_get_print("GL_FOG_START", GL_FOG_START); + gpu_get_print("GL_FRAGMENT_SHADER_DERIVATIVE_HINT", GL_FRAGMENT_SHADER_DERIVATIVE_HINT); + gpu_get_print("GL_FRONT_FACE", GL_FRONT_FACE); + gpu_get_print("GL_GENERATE_MIPMAP_HINT", GL_GENERATE_MIPMAP_HINT); + gpu_get_print("GL_GREEN_BIAS", GL_GREEN_BIAS); + gpu_get_print("GL_GREEN_BITS", GL_GREEN_BITS); + gpu_get_print("GL_GREEN_SCALE", GL_GREEN_SCALE); + gpu_get_print("GL_HISTOGRAM", GL_HISTOGRAM); + gpu_get_print("GL_INDEX_ARRAY", GL_INDEX_ARRAY); + gpu_get_print("GL_INDEX_ARRAY_BUFFER_BINDING", GL_INDEX_ARRAY_BUFFER_BINDING); + gpu_get_print("GL_INDEX_ARRAY_STRIDE", GL_INDEX_ARRAY_STRIDE); + gpu_get_print("GL_INDEX_ARRAY_TYPE", GL_INDEX_ARRAY_TYPE); + gpu_get_print("GL_INDEX_BITS", GL_INDEX_BITS); + gpu_get_print("GL_INDEX_CLEAR_VALUE", GL_INDEX_CLEAR_VALUE); + gpu_get_print("GL_INDEX_LOGIC_OP", GL_INDEX_LOGIC_OP); + gpu_get_print("GL_INDEX_MODE", GL_INDEX_MODE); + gpu_get_print("GL_INDEX_OFFSET", GL_INDEX_OFFSET); + gpu_get_print("GL_INDEX_SHIFT", GL_INDEX_SHIFT); + gpu_get_print("GL_INDEX_WRITEMASK", GL_INDEX_WRITEMASK); + gpu_get_print("GL_LIGHT0", GL_LIGHT0); + gpu_get_print("GL_LIGHTING", GL_LIGHTING); + gpu_get_print("GL_LIGHT_MODEL_AMBIENT", GL_LIGHT_MODEL_AMBIENT); + gpu_get_print("GL_LIGHT_MODEL_COLOR_CONTROL", GL_LIGHT_MODEL_COLOR_CONTROL); + gpu_get_print("GL_LIGHT_MODEL_LOCAL_VIEWER", GL_LIGHT_MODEL_LOCAL_VIEWER); + gpu_get_print("GL_LIGHT_MODEL_TWO_SIDE", GL_LIGHT_MODEL_TWO_SIDE); + gpu_get_print("GL_LINE_SMOOTH", GL_LINE_SMOOTH); + gpu_get_print("GL_LINE_SMOOTH_HINT", GL_LINE_SMOOTH_HINT); + gpu_get_print("GL_LINE_STIPPLE", GL_LINE_STIPPLE); + gpu_get_print("GL_LINE_STIPPLE_PATTERN", GL_LINE_STIPPLE_PATTERN); + gpu_get_print("GL_LINE_STIPPLE_REPEAT", GL_LINE_STIPPLE_REPEAT); + gpu_get_print("GL_LINE_WIDTH", GL_LINE_WIDTH); + gpu_get_print("GL_LINE_WIDTH_GRANULARITY", GL_LINE_WIDTH_GRANULARITY); + gpu_get_print("GL_LINE_WIDTH_RANGE", GL_LINE_WIDTH_RANGE); + gpu_get_print("GL_LIST_BASE", GL_LIST_BASE); + gpu_get_print("GL_LIST_INDEX", GL_LIST_INDEX); + gpu_get_print("GL_LIST_MODE", GL_LIST_MODE); + gpu_get_print("GL_LOGIC_OP_MODE", GL_LOGIC_OP_MODE); + gpu_get_print("GL_MAP1_COLOR_4", GL_MAP1_COLOR_4); + gpu_get_print("GL_MAP1_GRID_DOMAIN", GL_MAP1_GRID_DOMAIN); + gpu_get_print("GL_MAP1_GRID_SEGMENTS", GL_MAP1_GRID_SEGMENTS); + gpu_get_print("GL_MAP1_INDEX", GL_MAP1_INDEX); + gpu_get_print("GL_MAP1_NORMAL", GL_MAP1_NORMAL); + gpu_get_print("GL_MAP1_TEXTURE_COORD_1", GL_MAP1_TEXTURE_COORD_1); + gpu_get_print("GL_MAP1_TEXTURE_COORD_2", GL_MAP1_TEXTURE_COORD_2); + gpu_get_print("GL_MAP1_TEXTURE_COORD_3", GL_MAP1_TEXTURE_COORD_3); + gpu_get_print("GL_MAP1_TEXTURE_COORD_4", GL_MAP1_TEXTURE_COORD_4); + gpu_get_print("GL_MAP1_VERTEX_3", GL_MAP1_VERTEX_3); + gpu_get_print("GL_MAP1_VERTEX_4", GL_MAP1_VERTEX_4); + gpu_get_print("GL_MAP2_COLOR_4", GL_MAP2_COLOR_4); + gpu_get_print("GL_MAP2_GRID_DOMAIN", GL_MAP2_GRID_DOMAIN); + gpu_get_print("GL_MAP2_GRID_SEGMENTS", GL_MAP2_GRID_SEGMENTS); + gpu_get_print("GL_MAP2_INDEX", GL_MAP2_INDEX); + gpu_get_print("GL_MAP2_NORMAL", GL_MAP2_NORMAL); + gpu_get_print("GL_MAP2_TEXTURE_COORD_1", GL_MAP2_TEXTURE_COORD_1); + gpu_get_print("GL_MAP2_TEXTURE_COORD_2", GL_MAP2_TEXTURE_COORD_2); + gpu_get_print("GL_MAP2_TEXTURE_COORD_3", GL_MAP2_TEXTURE_COORD_3); + gpu_get_print("GL_MAP2_TEXTURE_COORD_4", GL_MAP2_TEXTURE_COORD_4); + gpu_get_print("GL_MAP2_VERTEX_3", GL_MAP2_VERTEX_3); + gpu_get_print("GL_MAP2_VERTEX_4", GL_MAP2_VERTEX_4); + gpu_get_print("GL_MAP_COLOR", GL_MAP_COLOR); + gpu_get_print("GL_MAP_STENCIL", GL_MAP_STENCIL); + gpu_get_print("GL_MATRIX_MODE", GL_MATRIX_MODE); + gpu_get_print("GL_MAX_3D_TEXTURE_SIZE", GL_MAX_3D_TEXTURE_SIZE); + gpu_get_print("GL_MAX_CLIENT_ATTRIB_STACK_DEPTH", GL_MAX_CLIENT_ATTRIB_STACK_DEPTH); + gpu_get_print("GL_MAX_ATTRIB_STACK_DEPTH", GL_MAX_ATTRIB_STACK_DEPTH); + gpu_get_print("GL_MAX_CLIP_PLANES", GL_MAX_CLIP_PLANES); + gpu_get_print("GL_MAX_COLOR_MATRIX_STACK_DEPTH", GL_MAX_COLOR_MATRIX_STACK_DEPTH); + gpu_get_print("GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS", GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS); + gpu_get_print("GL_MAX_CUBE_MAP_TEXTURE_SIZE", GL_MAX_CUBE_MAP_TEXTURE_SIZE); + gpu_get_print("GL_MAX_DRAW_BUFFERS", GL_MAX_DRAW_BUFFERS); + gpu_get_print("GL_MAX_ELEMENTS_INDICES", GL_MAX_ELEMENTS_INDICES); + gpu_get_print("GL_MAX_ELEMENTS_VERTICES", GL_MAX_ELEMENTS_VERTICES); + gpu_get_print("GL_MAX_EVAL_ORDER", GL_MAX_EVAL_ORDER); + gpu_get_print("GL_MAX_FRAGMENT_UNIFORM_COMPONENTS", GL_MAX_FRAGMENT_UNIFORM_COMPONENTS); + gpu_get_print("GL_MAX_LIGHTS", GL_MAX_LIGHTS); + gpu_get_print("GL_MAX_LIST_NESTING", GL_MAX_LIST_NESTING); + gpu_get_print("GL_MAX_MODELVIEW_STACK_DEPTH", GL_MAX_MODELVIEW_STACK_DEPTH); + gpu_get_print("GL_MAX_NAME_STACK_DEPTH", GL_MAX_NAME_STACK_DEPTH); + gpu_get_print("GL_MAX_PIXEL_MAP_TABLE", GL_MAX_PIXEL_MAP_TABLE); + gpu_get_print("GL_MAX_PROJECTION_STACK_DEPTH", GL_MAX_PROJECTION_STACK_DEPTH); + gpu_get_print("GL_MAX_TEXTURE_COORDS", GL_MAX_TEXTURE_COORDS); + gpu_get_print("GL_MAX_TEXTURE_IMAGE_UNITS", GL_MAX_TEXTURE_IMAGE_UNITS); + gpu_get_print("GL_MAX_TEXTURE_LOD_BIAS", GL_MAX_TEXTURE_LOD_BIAS); + gpu_get_print("GL_MAX_TEXTURE_SIZE", GL_MAX_TEXTURE_SIZE); + gpu_get_print("GL_MAX_TEXTURE_STACK_DEPTH", GL_MAX_TEXTURE_STACK_DEPTH); + gpu_get_print("GL_MAX_TEXTURE_UNITS", GL_MAX_TEXTURE_UNITS); + gpu_get_print("GL_MAX_VARYING_FLOATS", GL_MAX_VARYING_FLOATS); + gpu_get_print("GL_MAX_VERTEX_ATTRIBS", GL_MAX_VERTEX_ATTRIBS); + gpu_get_print("GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS", GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS); + gpu_get_print("GL_MAX_VERTEX_UNIFORM_COMPONENTS", GL_MAX_VERTEX_UNIFORM_COMPONENTS); + gpu_get_print("GL_MAX_VIEWPORT_DIMS", GL_MAX_VIEWPORT_DIMS); + gpu_get_print("GL_MINMAX", GL_MINMAX); + gpu_get_print("GL_MODELVIEW_MATRIX", GL_MODELVIEW_MATRIX); + gpu_get_print("GL_MODELVIEW_STACK_DEPTH", GL_MODELVIEW_STACK_DEPTH); + gpu_get_print("GL_NAME_STACK_DEPTH", GL_NAME_STACK_DEPTH); + gpu_get_print("GL_NORMAL_ARRAY", GL_NORMAL_ARRAY); + gpu_get_print("GL_NORMAL_ARRAY_BUFFER_BINDING", GL_NORMAL_ARRAY_BUFFER_BINDING); + gpu_get_print("GL_NORMAL_ARRAY_STRIDE", GL_NORMAL_ARRAY_STRIDE); + gpu_get_print("GL_NORMAL_ARRAY_TYPE", GL_NORMAL_ARRAY_TYPE); + gpu_get_print("GL_NORMALIZE", GL_NORMALIZE); + gpu_get_print("GL_NUM_COMPRESSED_TEXTURE_FORMATS", GL_NUM_COMPRESSED_TEXTURE_FORMATS); + gpu_get_print("GL_PACK_ALIGNMENT", GL_PACK_ALIGNMENT); + gpu_get_print("GL_PACK_IMAGE_HEIGHT", GL_PACK_IMAGE_HEIGHT); + gpu_get_print("GL_PACK_LSB_FIRST", GL_PACK_LSB_FIRST); + gpu_get_print("GL_PACK_ROW_LENGTH", GL_PACK_ROW_LENGTH); + gpu_get_print("GL_PACK_SKIP_IMAGES", GL_PACK_SKIP_IMAGES); + gpu_get_print("GL_PACK_SKIP_PIXELS", GL_PACK_SKIP_PIXELS); + gpu_get_print("GL_PACK_SKIP_ROWS", GL_PACK_SKIP_ROWS); + gpu_get_print("GL_PACK_SWAP_BYTES", GL_PACK_SWAP_BYTES); + gpu_get_print("GL_PERSPECTIVE_CORRECTION_HINT", GL_PERSPECTIVE_CORRECTION_HINT); + gpu_get_print("GL_PIXEL_MAP_A_TO_A_SIZE", GL_PIXEL_MAP_A_TO_A_SIZE); + gpu_get_print("GL_PIXEL_MAP_B_TO_B_SIZE", GL_PIXEL_MAP_B_TO_B_SIZE); + gpu_get_print("GL_PIXEL_MAP_G_TO_G_SIZE", GL_PIXEL_MAP_G_TO_G_SIZE); + gpu_get_print("GL_PIXEL_MAP_I_TO_A_SIZE", GL_PIXEL_MAP_I_TO_A_SIZE); + gpu_get_print("GL_PIXEL_MAP_I_TO_B_SIZE", GL_PIXEL_MAP_I_TO_B_SIZE); + gpu_get_print("GL_PIXEL_MAP_I_TO_G_SIZE", GL_PIXEL_MAP_I_TO_G_SIZE); + gpu_get_print("GL_PIXEL_MAP_I_TO_I_SIZE", GL_PIXEL_MAP_I_TO_I_SIZE); + gpu_get_print("GL_PIXEL_MAP_I_TO_R_SIZE", GL_PIXEL_MAP_I_TO_R_SIZE); + gpu_get_print("GL_PIXEL_MAP_R_TO_R_SIZE", GL_PIXEL_MAP_R_TO_R_SIZE); + gpu_get_print("GL_PIXEL_MAP_S_TO_S_SIZE", GL_PIXEL_MAP_S_TO_S_SIZE); + gpu_get_print("GL_PIXEL_PACK_BUFFER_BINDING", GL_PIXEL_PACK_BUFFER_BINDING); + gpu_get_print("GL_PIXEL_UNPACK_BUFFER_BINDING", GL_PIXEL_UNPACK_BUFFER_BINDING); + gpu_get_print("GL_POINT_DISTANCE_ATTENUATION", GL_POINT_DISTANCE_ATTENUATION); + gpu_get_print("GL_POINT_FADE_THRESHOLD_SIZE", GL_POINT_FADE_THRESHOLD_SIZE); + gpu_get_print("GL_POINT_SIZE", GL_POINT_SIZE); + gpu_get_print("GL_POINT_SIZE_GRANULARITY", GL_POINT_SIZE_GRANULARITY); + gpu_get_print("GL_POINT_SIZE_MAX", GL_POINT_SIZE_MAX); + gpu_get_print("GL_POINT_SIZE_MIN", GL_POINT_SIZE_MIN); + gpu_get_print("GL_POINT_SIZE_RANGE", GL_POINT_SIZE_RANGE); + gpu_get_print("GL_POINT_SMOOTH", GL_POINT_SMOOTH); + gpu_get_print("GL_POINT_SMOOTH_HINT", GL_POINT_SMOOTH_HINT); + gpu_get_print("GL_POINT_SPRITE", GL_POINT_SPRITE); + gpu_get_print("GL_POLYGON_MODE", GL_POLYGON_MODE); + gpu_get_print("GL_POLYGON_OFFSET_FACTOR", GL_POLYGON_OFFSET_FACTOR); + gpu_get_print("GL_POLYGON_OFFSET_UNITS", GL_POLYGON_OFFSET_UNITS); + gpu_get_print("GL_POLYGON_OFFSET_FILL", GL_POLYGON_OFFSET_FILL); + gpu_get_print("GL_POLYGON_OFFSET_LINE", GL_POLYGON_OFFSET_LINE); + gpu_get_print("GL_POLYGON_OFFSET_POINT", GL_POLYGON_OFFSET_POINT); + gpu_get_print("GL_POLYGON_SMOOTH", GL_POLYGON_SMOOTH); + gpu_get_print("GL_POLYGON_SMOOTH_HINT", GL_POLYGON_SMOOTH_HINT); + gpu_get_print("GL_POLYGON_STIPPLE", GL_POLYGON_STIPPLE); + gpu_get_print("GL_POST_COLOR_MATRIX_COLOR_TABLE", GL_POST_COLOR_MATRIX_COLOR_TABLE); + gpu_get_print("GL_POST_COLOR_MATRIX_RED_BIAS", GL_POST_COLOR_MATRIX_RED_BIAS); + gpu_get_print("GL_POST_COLOR_MATRIX_GREEN_BIAS", GL_POST_COLOR_MATRIX_GREEN_BIAS); + gpu_get_print("GL_POST_COLOR_MATRIX_BLUE_BIAS", GL_POST_COLOR_MATRIX_BLUE_BIAS); + gpu_get_print("GL_POST_COLOR_MATRIX_ALPHA_BIAS", GL_POST_COLOR_MATRIX_ALPHA_BIAS); + gpu_get_print("GL_POST_COLOR_MATRIX_RED_SCALE", GL_POST_COLOR_MATRIX_RED_SCALE); + gpu_get_print("GL_POST_COLOR_MATRIX_GREEN_SCALE", GL_POST_COLOR_MATRIX_GREEN_SCALE); + gpu_get_print("GL_POST_COLOR_MATRIX_BLUE_SCALE", GL_POST_COLOR_MATRIX_BLUE_SCALE); + gpu_get_print("GL_POST_COLOR_MATRIX_ALPHA_SCALE", GL_POST_COLOR_MATRIX_ALPHA_SCALE); + gpu_get_print("GL_POST_CONVOLUTION_COLOR_TABLE", GL_POST_CONVOLUTION_COLOR_TABLE); + gpu_get_print("GL_POST_CONVOLUTION_RED_BIAS", GL_POST_CONVOLUTION_RED_BIAS); + gpu_get_print("GL_POST_CONVOLUTION_GREEN_BIAS", GL_POST_CONVOLUTION_GREEN_BIAS); + gpu_get_print("GL_POST_CONVOLUTION_BLUE_BIAS", GL_POST_CONVOLUTION_BLUE_BIAS); + gpu_get_print("GL_POST_CONVOLUTION_ALPHA_BIAS", GL_POST_CONVOLUTION_ALPHA_BIAS); + gpu_get_print("GL_POST_CONVOLUTION_RED_SCALE", GL_POST_CONVOLUTION_RED_SCALE); + gpu_get_print("GL_POST_CONVOLUTION_GREEN_SCALE", GL_POST_CONVOLUTION_GREEN_SCALE); + gpu_get_print("GL_POST_CONVOLUTION_BLUE_SCALE", GL_POST_CONVOLUTION_BLUE_SCALE); + gpu_get_print("GL_POST_CONVOLUTION_ALPHA_SCALE", GL_POST_CONVOLUTION_ALPHA_SCALE); + gpu_get_print("GL_PROJECTION_MATRIX", GL_PROJECTION_MATRIX); + gpu_get_print("GL_PROJECTION_STACK_DEPTH", GL_PROJECTION_STACK_DEPTH); + gpu_get_print("GL_READ_BUFFER", GL_READ_BUFFER); + gpu_get_print("GL_RED_BIAS", GL_RED_BIAS); + gpu_get_print("GL_RED_BITS", GL_RED_BITS); + gpu_get_print("GL_RED_SCALE", GL_RED_SCALE); + gpu_get_print("GL_RENDER_MODE", GL_RENDER_MODE); + gpu_get_print("GL_RESCALE_NORMAL", GL_RESCALE_NORMAL); + gpu_get_print("GL_RGBA_MODE", GL_RGBA_MODE); + gpu_get_print("GL_SAMPLE_BUFFERS", GL_SAMPLE_BUFFERS); + gpu_get_print("GL_SAMPLE_COVERAGE_VALUE", GL_SAMPLE_COVERAGE_VALUE); + gpu_get_print("GL_SAMPLE_COVERAGE_INVERT", GL_SAMPLE_COVERAGE_INVERT); + gpu_get_print("GL_SAMPLES", GL_SAMPLES); + gpu_get_print("GL_SCISSOR_BOX", GL_SCISSOR_BOX); + gpu_get_print("GL_SCISSOR_TEST", GL_SCISSOR_TEST); + gpu_get_print("GL_SECONDARY_COLOR_ARRAY", GL_SECONDARY_COLOR_ARRAY); + gpu_get_print("GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING", GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING); + gpu_get_print("GL_SECONDARY_COLOR_ARRAY_SIZE", GL_SECONDARY_COLOR_ARRAY_SIZE); + gpu_get_print("GL_SECONDARY_COLOR_ARRAY_STRIDE", GL_SECONDARY_COLOR_ARRAY_STRIDE); + gpu_get_print("GL_SECONDARY_COLOR_ARRAY_TYPE", GL_SECONDARY_COLOR_ARRAY_TYPE); + gpu_get_print("GL_SELECTION_BUFFER_SIZE", GL_SELECTION_BUFFER_SIZE); + gpu_get_print("GL_SEPARABLE_2D", GL_SEPARABLE_2D); + gpu_get_print("GL_SHADE_MODEL", GL_SHADE_MODEL); + gpu_get_print("GL_SMOOTH_LINE_WIDTH_RANGE", GL_SMOOTH_LINE_WIDTH_RANGE); + gpu_get_print("GL_SMOOTH_LINE_WIDTH_GRANULARITY", GL_SMOOTH_LINE_WIDTH_GRANULARITY); + gpu_get_print("GL_SMOOTH_POINT_SIZE_RANGE", GL_SMOOTH_POINT_SIZE_RANGE); + gpu_get_print("GL_SMOOTH_POINT_SIZE_GRANULARITY", GL_SMOOTH_POINT_SIZE_GRANULARITY); + gpu_get_print("GL_STENCIL_BACK_FAIL", GL_STENCIL_BACK_FAIL); + gpu_get_print("GL_STENCIL_BACK_FUNC", GL_STENCIL_BACK_FUNC); + gpu_get_print("GL_STENCIL_BACK_PASS_DEPTH_FAIL", GL_STENCIL_BACK_PASS_DEPTH_FAIL); + gpu_get_print("GL_STENCIL_BACK_PASS_DEPTH_PASS", GL_STENCIL_BACK_PASS_DEPTH_PASS); + gpu_get_print("GL_STENCIL_BACK_REF", GL_STENCIL_BACK_REF); + gpu_get_print("GL_STENCIL_BACK_VALUE_MASK", GL_STENCIL_BACK_VALUE_MASK); + gpu_get_print("GL_STENCIL_BACK_WRITEMASK", GL_STENCIL_BACK_WRITEMASK); + gpu_get_print("GL_STENCIL_BITS", GL_STENCIL_BITS); + gpu_get_print("GL_STENCIL_CLEAR_VALUE", GL_STENCIL_CLEAR_VALUE); + gpu_get_print("GL_STENCIL_FAIL", GL_STENCIL_FAIL); + gpu_get_print("GL_STENCIL_FUNC", GL_STENCIL_FUNC); + gpu_get_print("GL_STENCIL_PASS_DEPTH_FAIL", GL_STENCIL_PASS_DEPTH_FAIL); + gpu_get_print("GL_STENCIL_PASS_DEPTH_PASS", GL_STENCIL_PASS_DEPTH_PASS); + gpu_get_print("GL_STENCIL_REF", GL_STENCIL_REF); + gpu_get_print("GL_STENCIL_TEST", GL_STENCIL_TEST); + gpu_get_print("GL_STENCIL_VALUE_MASK", GL_STENCIL_VALUE_MASK); + gpu_get_print("GL_STENCIL_WRITEMASK", GL_STENCIL_WRITEMASK); + gpu_get_print("GL_STEREO", GL_STEREO); + gpu_get_print("GL_SUBPIXEL_BITS", GL_SUBPIXEL_BITS); + gpu_get_print("GL_TEXTURE_1D", GL_TEXTURE_1D); + gpu_get_print("GL_TEXTURE_BINDING_1D", GL_TEXTURE_BINDING_1D); + gpu_get_print("GL_TEXTURE_2D", GL_TEXTURE_2D); + gpu_get_print("GL_TEXTURE_BINDING_2D", GL_TEXTURE_BINDING_2D); + gpu_get_print("GL_TEXTURE_3D", GL_TEXTURE_3D); + gpu_get_print("GL_TEXTURE_BINDING_3D", GL_TEXTURE_BINDING_3D); + gpu_get_print("GL_TEXTURE_BINDING_CUBE_MAP", GL_TEXTURE_BINDING_CUBE_MAP); + gpu_get_print("GL_TEXTURE_COMPRESSION_HINT", GL_TEXTURE_COMPRESSION_HINT); + gpu_get_print("GL_TEXTURE_COORD_ARRAY", GL_TEXTURE_COORD_ARRAY); + gpu_get_print("GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING", GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING); + gpu_get_print("GL_TEXTURE_COORD_ARRAY_SIZE", GL_TEXTURE_COORD_ARRAY_SIZE); + gpu_get_print("GL_TEXTURE_COORD_ARRAY_STRIDE", GL_TEXTURE_COORD_ARRAY_STRIDE); + gpu_get_print("GL_TEXTURE_COORD_ARRAY_TYPE", GL_TEXTURE_COORD_ARRAY_TYPE); + gpu_get_print("GL_TEXTURE_CUBE_MAP", GL_TEXTURE_CUBE_MAP); + gpu_get_print("GL_TEXTURE_GEN_Q", GL_TEXTURE_GEN_Q); + gpu_get_print("GL_TEXTURE_GEN_R", GL_TEXTURE_GEN_R); + gpu_get_print("GL_TEXTURE_GEN_S", GL_TEXTURE_GEN_S); + gpu_get_print("GL_TEXTURE_GEN_T", GL_TEXTURE_GEN_T); + gpu_get_print("GL_TEXTURE_MATRIX", GL_TEXTURE_MATRIX); + gpu_get_print("GL_TEXTURE_STACK_DEPTH", GL_TEXTURE_STACK_DEPTH); + gpu_get_print("GL_TRANSPOSE_COLOR_MATRIX", GL_TRANSPOSE_COLOR_MATRIX); + gpu_get_print("GL_TRANSPOSE_MODELVIEW_MATRIX", GL_TRANSPOSE_MODELVIEW_MATRIX); + gpu_get_print("GL_TRANSPOSE_PROJECTION_MATRIX", GL_TRANSPOSE_PROJECTION_MATRIX); + gpu_get_print("GL_TRANSPOSE_TEXTURE_MATRIX", GL_TRANSPOSE_TEXTURE_MATRIX); + gpu_get_print("GL_UNPACK_ALIGNMENT", GL_UNPACK_ALIGNMENT); + gpu_get_print("GL_UNPACK_IMAGE_HEIGHT", GL_UNPACK_IMAGE_HEIGHT); + gpu_get_print("GL_UNPACK_LSB_FIRST", GL_UNPACK_LSB_FIRST); + gpu_get_print("GL_UNPACK_ROW_LENGTH", GL_UNPACK_ROW_LENGTH); + gpu_get_print("GL_UNPACK_SKIP_IMAGES", GL_UNPACK_SKIP_IMAGES); + gpu_get_print("GL_UNPACK_SKIP_PIXELS", GL_UNPACK_SKIP_PIXELS); + gpu_get_print("GL_UNPACK_SKIP_ROWS", GL_UNPACK_SKIP_ROWS); + gpu_get_print("GL_UNPACK_SWAP_BYTES", GL_UNPACK_SWAP_BYTES); + gpu_get_print("GL_VERTEX_ARRAY", GL_VERTEX_ARRAY); + gpu_get_print("GL_VERTEX_ARRAY_BUFFER_BINDING", GL_VERTEX_ARRAY_BUFFER_BINDING); + gpu_get_print("GL_VERTEX_ARRAY_SIZE", GL_VERTEX_ARRAY_SIZE); + gpu_get_print("GL_VERTEX_ARRAY_STRIDE", GL_VERTEX_ARRAY_STRIDE); + gpu_get_print("GL_VERTEX_ARRAY_TYPE", GL_VERTEX_ARRAY_TYPE); + gpu_get_print("GL_VERTEX_PROGRAM_POINT_SIZE", GL_VERTEX_PROGRAM_POINT_SIZE); + gpu_get_print("GL_VERTEX_PROGRAM_TWO_SIDE", GL_VERTEX_PROGRAM_TWO_SIDE); + gpu_get_print("GL_VIEWPORT", GL_VIEWPORT); + gpu_get_print("GL_ZOOM_X", GL_ZOOM_X); + gpu_get_print("GL_ZOOM_Y", GL_ZOOM_Y); } diff --git a/source/blender/imbuf/intern/amiga.c b/source/blender/imbuf/intern/amiga.c index f84740826ae..91638a7ea72 100644 --- a/source/blender/imbuf/intern/amiga.c +++ b/source/blender/imbuf/intern/amiga.c @@ -452,6 +452,7 @@ struct ImBuf *imb_loadamiga(int *iffmem,int flags) if (ibuf == 0) return (0); ibuf->ftype = (ftype | AMI); + ibuf->profile = IB_PROFILE_SRGB; if (cmap){ ibuf->mincol = 0; diff --git a/source/blender/imbuf/intern/bmp.c b/source/blender/imbuf/intern/bmp.c index 141b8a985cf..ada5fcebf73 100644 --- a/source/blender/imbuf/intern/bmp.c +++ b/source/blender/imbuf/intern/bmp.c @@ -175,6 +175,7 @@ struct ImBuf *imb_bmp_decode(unsigned char *mem, int size, int flags) if (ibuf) { ibuf->ftype = BMP; + ibuf->profile = IB_PROFILE_SRGB; } return(ibuf); diff --git a/source/blender/imbuf/intern/dds/dds_api.cpp b/source/blender/imbuf/intern/dds/dds_api.cpp index cf2f6c16d08..d7ff4761605 100644 --- a/source/blender/imbuf/intern/dds/dds_api.cpp +++ b/source/blender/imbuf/intern/dds/dds_api.cpp @@ -101,6 +101,7 @@ struct ImBuf *imb_load_dds(unsigned char *mem, int size, int flags) if (ibuf == 0) return(0); /* memory allocation failed */ ibuf->ftype = DDS; + ibuf->profile = IB_PROFILE_SRGB; if ((flags & IB_test) == 0) { if (!imb_addrectImBuf(ibuf)) return(ibuf); diff --git a/source/blender/imbuf/intern/divers.c b/source/blender/imbuf/intern/divers.c index 35be1f716e6..bcf913e6caf 100644 --- a/source/blender/imbuf/intern/divers.c +++ b/source/blender/imbuf/intern/divers.c @@ -175,12 +175,14 @@ void IMB_gamwarp(struct ImBuf *ibuf, double gamma) } +/* assume converting from linear float to sRGB byte */ void IMB_rect_from_float(struct ImBuf *ibuf) { /* quick method to convert floatbuf to byte */ float *tof = (float *)ibuf->rect_float; - float dither= ibuf->dither; - float srgb[3]; + int do_dither = ibuf->dither != 0.f; + float dither= ibuf->dither / 255.0; + float srgb[4]; int i, channels= ibuf->channels; short profile= ibuf->profile; unsigned char *to = (unsigned char *) ibuf->rect; @@ -195,7 +197,7 @@ void IMB_rect_from_float(struct ImBuf *ibuf) for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof++) to[1]= to[2]= to[3]= to[0] = FTOCHAR(tof[0]); } - else if (profile == IB_PROFILE_SRGB) { + else if (profile == IB_PROFILE_LINEAR_RGB) { if(channels == 3) { for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof+=3) { srgb[0]= linearrgb_to_srgb(tof[0]); @@ -209,10 +211,26 @@ void IMB_rect_from_float(struct ImBuf *ibuf) } } else if (channels == 4) { - floatbuf_to_srgb_byte(tof, to, 0, ibuf->x, 0, ibuf->y, ibuf->x); + if (dither != 0.f) { + for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof+=4) { + const float d = (BLI_frand()-0.5)*dither; + + srgb[0]= d + linearrgb_to_srgb(tof[0]); + srgb[1]= d + linearrgb_to_srgb(tof[1]); + srgb[2]= d + linearrgb_to_srgb(tof[2]); + srgb[3]= d + tof[3]; + + to[0] = FTOCHAR(srgb[0]); + to[1] = FTOCHAR(srgb[1]); + to[2] = FTOCHAR(srgb[2]); + to[3] = FTOCHAR(srgb[3]); + } + } else { + floatbuf_to_srgb_byte(tof, to, 0, ibuf->x, 0, ibuf->y, ibuf->x); + } } } - else if(ELEM(profile, IB_PROFILE_NONE, IB_PROFILE_LINEAR_RGB) && dither==0.0f) { + else if(ELEM(profile, IB_PROFILE_NONE, IB_PROFILE_SRGB)) { if(channels==3) { for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof+=3) { to[0] = FTOCHAR(tof[0]); @@ -222,32 +240,26 @@ void IMB_rect_from_float(struct ImBuf *ibuf) } } else { - for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof+=4) { - to[0] = FTOCHAR(tof[0]); - to[1] = FTOCHAR(tof[1]); - to[2] = FTOCHAR(tof[2]); - to[3] = FTOCHAR(tof[3]); + if (dither != 0.f) { + float col[3]; + for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof+=4) { + const float d = (BLI_frand()-0.5)*dither; + const float col[4] = {d+tof[0], d+tof[1], d+tof[2], d+tof[3]}; + to[0] = FTOCHAR(col[0]); + to[1] = FTOCHAR(col[1]); + to[2] = FTOCHAR(col[2]); + to[3] = FTOCHAR(col[3]); + } + } else { + for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof+=4) { + to[0] = FTOCHAR(tof[0]); + to[1] = FTOCHAR(tof[1]); + to[2] = FTOCHAR(tof[2]); + to[3] = FTOCHAR(tof[3]); + } } } } - else { - float dither_value, col; - dither= dither/255.0f; - for (i = ibuf->x * ibuf->y; i > 0; i--) { - dither_value = (BLI_frand()-0.5)*dither; - col= tof[0] + dither_value; - to[0] = FTOCHAR(col); - col= tof[1] + dither_value; - to[1] = FTOCHAR(col); - col= tof[2] + dither_value; - to[2] = FTOCHAR(col); - col= tof[3] + dither_value; - to[3] = FTOCHAR(col); - - to += 4; - tof += 4; - } - } } void IMB_float_from_rect(struct ImBuf *ibuf) @@ -263,8 +275,11 @@ void IMB_float_from_rect(struct ImBuf *ibuf) tof = ibuf->rect_float; } - if (ibuf->profile == IB_PROFILE_SRGB) { - /* convert from srgb to linear rgb */ + /* Float bufs should be stored linear */ + + if (ibuf->profile != IB_PROFILE_NONE) { + /* if the image has been given a profile then we're working + * with color management in mind, so convert it to linear space */ for (i = ibuf->x * ibuf->y; i > 0; i--) { diff --git a/source/blender/imbuf/intern/hamx.c b/source/blender/imbuf/intern/hamx.c index 258c196fcdf..222604121f9 100644 --- a/source/blender/imbuf/intern/hamx.c +++ b/source/blender/imbuf/intern/hamx.c @@ -387,6 +387,7 @@ struct ImBuf *imb_loadanim(int *iffmem, int flags) if (ibuf==0) return (0); ibuf->ftype = (Anim | adat.type); + ibuf->profile = IB_PROFILE_SRGB; ibuf->xorig = adat.xorig; ibuf->yorig = adat.yorig; ibuf->flags = flags; diff --git a/source/blender/imbuf/intern/iris.c b/source/blender/imbuf/intern/iris.c index 7b8c383ddb9..4389eea8939 100644 --- a/source/blender/imbuf/intern/iris.c +++ b/source/blender/imbuf/intern/iris.c @@ -494,6 +494,7 @@ struct ImBuf *imb_loadiris(unsigned char *mem, int flags) } ibuf->ftype = IMAGIC; + ibuf->profile = IB_PROFILE_SRGB; if (flags & IB_ttob) IMB_flipy(ibuf); test_endian_zbuf(ibuf); diff --git a/source/blender/imbuf/intern/jpeg.c b/source/blender/imbuf/intern/jpeg.c index 2df522ff4a2..2b2d17784e2 100644 --- a/source/blender/imbuf/intern/jpeg.c +++ b/source/blender/imbuf/intern/jpeg.c @@ -416,6 +416,7 @@ next_stamp_marker: jpeg_destroy((j_common_ptr) cinfo); ibuf->ftype = ibuf_ftype; + ibuf->profile = IB_PROFILE_SRGB; } return(ibuf); diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index a780727b1a2..18462121810 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -933,6 +933,9 @@ struct ImBuf *imb_load_openexr(unsigned char *mem, int size, int flags) ibuf = IMB_allocImBuf(width, height, 32, 0, 0); ibuf->ftype = OPENEXR; + + /* openEXR is linear as per EXR spec */ + ibuf->profile = IB_PROFILE_LINEAR_RGB; if (!(flags & IB_test)) { diff --git a/source/blender/imbuf/intern/png.c b/source/blender/imbuf/intern/png.c index 3d42eafe623..724f209884c 100644 --- a/source/blender/imbuf/intern/png.c +++ b/source/blender/imbuf/intern/png.c @@ -368,6 +368,7 @@ struct ImBuf *imb_loadpng(unsigned char *mem, int size, int flags) if (ibuf) { ibuf->ftype = PNG; + ibuf->profile = IB_PROFILE_SRGB; } else { printf("Couldn't allocate memory for PNG image\n"); } diff --git a/source/blender/imbuf/intern/radiance_hdr.c b/source/blender/imbuf/intern/radiance_hdr.c index 69c4970df38..5acde1232fd 100644 --- a/source/blender/imbuf/intern/radiance_hdr.c +++ b/source/blender/imbuf/intern/radiance_hdr.c @@ -204,6 +204,7 @@ struct ImBuf *imb_loadhdr(unsigned char *mem, int size, int flags) if (ibuf==NULL) return NULL; ibuf->ftype = RADHDR; + ibuf->profile = IB_PROFILE_LINEAR_RGB; ibuf->xorig = ibuf->yorig = 0; if (flags & IB_test) return ibuf; diff --git a/source/blender/imbuf/intern/readimage.c b/source/blender/imbuf/intern/readimage.c index 61254944001..ce3d6f9ce91 100644 --- a/source/blender/imbuf/intern/readimage.c +++ b/source/blender/imbuf/intern/readimage.c @@ -161,6 +161,7 @@ ImBuf *IMB_ibImageFromMemory(int *mem, int size, int flags) { ibuf = imb_cocoaLoadImage((uchar *)mem, size, flags); if(ibuf) { ibuf->ftype = TIF; + ibuf->profile = IB_PROFILE_SRGB; return ibuf; } #else diff --git a/source/blender/imbuf/intern/targa.c b/source/blender/imbuf/intern/targa.c index acc3e06448f..9e6a774e4e5 100644 --- a/source/blender/imbuf/intern/targa.c +++ b/source/blender/imbuf/intern/targa.c @@ -569,6 +569,7 @@ struct ImBuf *imb_loadtarga(unsigned char *mem, int mem_size, int flags) if (ibuf == 0) return(0); ibuf->ftype = TGA; + ibuf->profile = IB_PROFILE_SRGB; ibuf->xorig = tga.xorig; ibuf->yorig = tga.yorig; mem = mem + 18 + tga.numid; diff --git a/source/blender/imbuf/intern/tiff.c b/source/blender/imbuf/intern/tiff.c index b2465d6cc2f..0a81e903d05 100644 --- a/source/blender/imbuf/intern/tiff.c +++ b/source/blender/imbuf/intern/tiff.c @@ -347,6 +347,7 @@ struct ImBuf *imb_loadtiff(unsigned char *mem, int size, int flags) ibuf = IMB_allocImBuf(width, height, 8*bytesperpixel, 0, 0); if (ibuf) { ibuf->ftype = TIF; + ibuf->profile = IB_PROFILE_SRGB; } else { fprintf(stderr, "imb_loadtiff: could not allocate memory for TIFF " \ diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h index 0c38421a3f5..8c835dd7ca7 100644 --- a/source/blender/makesdna/DNA_ID.h +++ b/source/blender/makesdna/DNA_ID.h @@ -212,8 +212,8 @@ typedef struct PreviewImage { #define LIB_FAKEUSER 512 /* free test flag */ #define LIB_DOIT 1024 -/* */ -#define LIB_APPEND_TAG 2048 +/* tag existing data before linking so we know what is new */ +#define LIB_PRE_EXISTING 2048 #ifdef __cplusplus } diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h index 9847b3a9219..dbc715ba87f 100644 --- a/source/blender/makesdna/DNA_action_types.h +++ b/source/blender/makesdna/DNA_action_types.h @@ -46,13 +46,23 @@ struct Object; /* Motion Paths ------------------------------------ */ /* (used for Pose Channels and Objects) */ -/* Data point for motion path */ +/* Data point for motion path (mpv) */ typedef struct bMotionPathVert { float co[3]; /* coordinates of point in 3D-space */ int flag; /* quick settings */ } bMotionPathVert; -/* Motion Path data cache - for elements providing transforms (i.e. Objects or PoseChannels) */ +/* bMotionPathVert->flag */ +typedef enum eMotionPathVert_Flag { + /* vert is selected */ + MOTIONPATH_VERT_SEL = (1<<0), +} eMotionPathVert_Flag; + +/* ........ */ + +/* Motion Path data cache (mpath) + * - for elements providing transforms (i.e. Objects or PoseChannels) + */ typedef struct bMotionPath { bMotionPathVert *points; /* path samples */ int length; /* the number of cached verts */ @@ -60,33 +70,97 @@ typedef struct bMotionPath { int start_frame; /* for drawing paths, the start frame number */ int end_frame; /* for drawing paths, the end frame number */ - int flag; /* extra settings */ + int flag; /* baking settings - eMotionPath_Flag */ } bMotionPath; +/* bMotionPath->flag */ +typedef enum eMotionPath_Flag { + /* (for bones) path represents the head of the bone */ + MOTIONPATH_FLAG_BHEAD = (1<<0), + /* motion path is being edited */ + MOTIONPATH_FLAG_EDIT = (1<<1), +} eMotionPath_Flag; +/* Visualisation General --------------------------- */ +/* for Objects or Poses (but NOT PoseChannels) */ -/* Animation Visualisation Settings - for Objects or Armatures (not PoseChannels) */ +/* Animation Visualisation Settings (avs) */ typedef struct bAnimVizSettings { - int pad; - int pathflag; /* eMotionPath_Settings */ + /* Onion-Skinning Settings ----------------- */ + int ghost_sf, ghost_ef; /* start and end frames of ghost-drawing range (only used for GHOST_TYPE_RANGE) */ + int ghost_bc, ghost_ac; /* number of frames before/after current frame to show */ + + short ghost_type; /* eOnionSkin_Types */ + short ghost_step; /* number of frames between each ghost shown (not for GHOST_TYPE_KEYS) */ + + short ghost_flag; /* eOnionSkin_Flag */ + + /* General Settings ------------------------ */ + short recalc; /* eAnimViz_RecalcFlags */ + + /* Motion Path Settings ------------------- */ + short path_type; /* eMotionPath_Types */ + short path_step; /* number of frames between points indicated on the paths */ - int pathsf, pathef; /* start and end frames of path-calculation range */ - int pathbc, pathac; /* number of frames before/after current frame of path-calculation */ + short path_viewflag; /* eMotionPaths_ViewFlag */ + short path_bakeflag; /* eMotionPaths_BakeFlag */ + + int path_sf, path_ef; /* start and end frames of path-calculation range */ + int path_bc, path_ac; /* number of frames before/after current frame to show */ } bAnimVizSettings; -/* bMotionPathSettings->flag */ -typedef enum eMotionPath_Settings { + +/* bAnimVizSettings->recalc */ +typedef enum eAnimViz_RecalcFlags { + /* motionpaths need recalculating */ + ANIMVIZ_RECALC_PATHS = (1<<0), +} eAnimViz_RecalcFlags; + + +/* bAnimVizSettings->ghost_type */ +typedef enum eOnionSkin_Types { + /* no ghosts at all */ + GHOST_TYPE_NONE = 0, + /* around current frame */ + GHOST_TYPE_ACFRA, + /* show ghosts within the specified frame range */ + GHOST_TYPE_RANGE, + /* show ghosts on keyframes within the specified range only */ + GHOST_TYPE_KEYS, +} eOnionSkin_Types; + +/* bAnimVizSettings->ghost_flag */ +typedef enum eOnionSkin_Flag { + /* only show selected bones in ghosts */ + GHOST_FLAG_ONLYSEL = (1<<0), +} eOnionSkin_Flag; + + +/* bAnimVizSettings->path_type */ +typedef enum eMotionPaths_Types { + /* show the paths along their entire ranges */ + MOTIONPATH_TYPE_RANGE = 0, + /* only show the parts of the paths around the current frame */ + MOTIONPATH_TYPE_ACFRA, +} eMotionPath_Types; + +/* bAnimVizSettings->path_viewflag */ +typedef enum eMotionPaths_ViewFlag { /* show frames on path */ - MOTIONPATH_FLAG_FNUMS = (1<<0), + MOTIONPATH_VIEW_FNUMS = (1<<0), /* show keyframes on path */ - MOTIONPATH_FLAG_KFRAS = (1<<1), - /* for bones - calculate head-points for curves instead of tips */ - MOTIONPATH_FLAG_HEADS = (1<<2), - /* show path around current frame */ - MOTIONPATH_FLAG_ACFRA = (1<<3), + MOTIONPATH_VIEW_KFRAS = (1<<1), /* show keyframe/frame numbers */ - MOTIONPATH_FLAG_KFNOS = (1<<4) -} eMotionPath_Settings; + MOTIONPATH_VIEW_KFNOS = (1<<2), +} eMotionPath_ViewFlag; + +/* bAnimVizSettings->path_bakeflag */ +typedef enum eMotionPaths_BakeFlag { + /* motion paths directly associated with this block of settings needs updating */ + MOTIONPATH_BAKE_NEEDS_RECALC = (1<<0), + /* for bones - calculate head-points for curves instead of tips */ + MOTIONPATH_BAKE_HEADS = (1<<1), +} eMotionPath_BakeFlag; /* ************************************************ */ /* Poses */ @@ -113,9 +187,11 @@ typedef struct bPoseChannel { short protectflag; /* protect channels from being transformed */ short agrp_index; /* index of action-group this bone belongs to (0 = default/no group) */ +// XXX depreceated.... old animation system (armature only viz) ---- int pathlen; /* for drawing paths, the amount of frames */ int pathsf; /* for drawing paths, the start frame number */ int pathef; /* for drawing paths, the end frame number */ +// XXX end of depreceated code ------------------------------------- struct Bone *bone; /* set on read file or rebuild pose */ struct bPoseChannel *parent; /* set on read file or rebuild pose */ @@ -152,8 +228,10 @@ typedef struct bPoseChannel { float ikrotweight; /* weight of joint rotation constraint */ float iklinweight; /* weight of joint stretch constraint */ - float *path; /* totpath x 3 x float */ - struct Object *custom; /* draws custom object instead of this channel */ + float *path; /* totpath x 3 x float */ // XXX depreceated... old animation system (armature only viz) + bMotionPath *mpath; /* motion path cache for this bone */ + struct Object *custom; /* draws custom object instead of default bone shape */ + struct bPoseChannel *custom_tx; /* odd feature, display with another bones transform. needed in rare cases for advanced rigs, since the alternative is highly complicated - campbell */ } bPoseChannel; @@ -259,6 +337,8 @@ typedef struct bPose { int iksolver; /* ik solver to use, see ePose_IKSolverType */ void *ikdata; /* temporary IK data, depends on the IK solver. Not saved in file */ void *ikparam; /* IK solver parameters, structure depends on iksolver */ + + bAnimVizSettings avs; /* settings for visualisation of bone animation */ } bPose; @@ -283,7 +363,7 @@ typedef enum ePose_Flags { /* IK Solvers ------------------------------------ */ /* bPose->iksolver and bPose->ikparam->iksolver */ -typedef enum { +typedef enum ePose_IKSolverType { IKSOLVER_LEGACY = 0, IKSOLVER_ITASC, } ePose_IKSolverType; @@ -310,7 +390,7 @@ typedef struct bItasc { } bItasc; /* bItasc->flag */ -typedef enum { +typedef enum eItasc_Flags { ITASC_AUTO_STEP = (1<<0), ITASC_INITIAL_REITERATION = (1<<1), ITASC_REITERATION = (1<<2), @@ -318,7 +398,7 @@ typedef enum { } eItasc_Flags; /* bItasc->solver */ -typedef enum { +typedef enum eItasc_Solver { ITASC_SOLVER_SDLS = 0, /* selective damped least square, suitable for CopyPose constraint */ ITASC_SOLVER_DLS /* damped least square with numerical filtering of damping */ } eItasc_Solver; @@ -509,15 +589,14 @@ typedef enum eSAction_Flag { } eSAction_Flag; /* SpaceAction Mode Settings */ -// XXX should this be used by other editors too? typedef enum eAnimEdit_Context { - /* action (default) */ + /* action on the active object */ SACTCONT_ACTION = 0, - /* editing of shapekey's IPO block */ + /* list of all shapekeys on the active object, linked with their F-Curves */ SACTCONT_SHAPEKEY, /* editing of gpencil data */ SACTCONT_GPENCIL, - /* dopesheet */ + /* dopesheet (default) */ SACTCONT_DOPESHEET, } eAnimEdit_Context; diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h index dcb10d0f2cf..958add428a4 100644 --- a/source/blender/makesdna/DNA_anim_types.h +++ b/source/blender/makesdna/DNA_anim_types.h @@ -232,27 +232,93 @@ typedef enum eFMod_Noise_Modifications { /* Drivers -------------------------------------- */ -/* Driver Target +/* Driver Target (dtar) * - * A 'variable' for use as a target of the driver/expression. - * Defines a way of accessing some channel to use, that can be - * referred to in the expression as a variable, thus simplifying - * expressions and also Depsgraph building. + * Defines how to access a dependency needed for a driver variable. */ typedef struct DriverTarget { - struct DriverTarget *next, *prev; + ID *id; /* ID-block which owns the target */ - ID *id; /* ID-block which owns the target */ - char *rna_path; /* target channel to use as driver value */ - int array_index; /* if applicable, the index of the RNA-array item to use as driver */ + char *rna_path; /* RNA path defining the setting to use (for DVAR_TYPE_SINGLE_PROP) */ - int idtype; /* type of ID-block that this target can use */ - int flags; /* flags for the validity of the target */ - int pad; + char pchan_name[32]; /* name of the posebone to use (for vars where DTAR_FLAG_STRUCT_REF is used) */ + short transChan; /* transform channel index (for DVAR_TYPE_TRANSFORM_CHAN)*/ - char name[64]; /* name of the variable */ + short flag; /* flags for the validity of the target (NOTE: these get reset everytime the types change) */ + int idtype; /* type of ID-block that this target can use */ } DriverTarget; +/* Driver Target flags */ +typedef enum eDriverTarget_Flag { + /* used for targets that use the pchan_name instead of RNA path + * (i.e. rotation difference) + */ + DTAR_FLAG_STRUCT_REF = (1<<0), + /* idtype can only be 'Object' */ + DTAR_FLAG_ID_OB_ONLY = (1<<1), + /* toggles localspace (where transforms are manually obtained) */ + DTAR_FLAG_LOCALSPACE = (1<<2), +} eDriverTarget_Flag; + +/* Transform Channels for Driver Targets */ +typedef enum eDriverTarget_TransformChannels { + DTAR_TRANSCHAN_LOCX = 0, + DTAR_TRANSCHAN_LOCY, + DTAR_TRANSCHAN_LOCZ, + DTAR_TRANSCHAN_ROTX, + DTAR_TRANSCHAN_ROTY, + DTAR_TRANSCHAN_ROTZ, + DTAR_TRANSCHAN_SCALEX, + DTAR_TRANSCHAN_SCALEY, + DTAR_TRANSCHAN_SCALEZ, + + MAX_DTAR_TRANSCHAN_TYPES +} eDriverTarget_TransformChannels; + +/* --- */ + +/* maximum number of driver targets per variable */ +#define MAX_DRIVER_TARGETS 8 + + +/* Driver Variable (dvar) + * + * A 'variable' for use as an input for the driver evaluation. + * Defines a way of accessing some channel to use, that can be + * referred to in the expression as a variable, thus simplifying + * expressions and also Depsgraph building. + */ +typedef struct DriverVar { + struct DriverVar *next, *prev; + + char name[64]; /* name of the variable to use in py-expression (must be valid python identifier) */ + + DriverTarget targets[8]; /* MAX_DRIVER_TARGETS, target slots */ + int num_targets; /* number of targets actually used by this variable */ + + int type; /* type of driver target (eDriverTarget_Types) */ +} DriverVar; + +/* Driver Variable Types */ +typedef enum eDriverVar_Types { + /* single RNA property */ + DVAR_TYPE_SINGLE_PROP = 0, + /* rotation difference (between 2 bones) */ + DVAR_TYPE_ROT_DIFF, + /* distance between objects/bones */ + DVAR_TYPE_LOC_DIFF, + /* 'final' transform for object/bones */ + DVAR_TYPE_TRANSFORM_CHAN, + + /* maximum number of variable types + * NOTE: this must always be th last item in this list, + * so add new types above this line + */ + MAX_DVAR_TYPES +} eDriverVar_Types; + +/* --- */ + /* Channel Driver (i.e. Drivers / Expressions) (driver) * * Channel Drivers are part of the dependency system, and are executed in addition to @@ -265,7 +331,7 @@ typedef struct DriverTarget { * evaluated in. This order is set by the Depsgraph's sorting stuff. */ typedef struct ChannelDriver { - ListBase targets; /* targets for this driver (i.e. list of DriverTarget) */ + ListBase variables; /* targets for this driver (i.e. list of DriverVar) */ /* python expression to execute (may call functions defined in an accessory file) * which relates the target 'variables' in some way to yield a single usable value @@ -287,10 +353,12 @@ typedef enum eDriver_Types { DRIVER_TYPE_AVERAGE = 0, /* python expression/function relates targets */ DRIVER_TYPE_PYTHON, - /* rotational difference (must use rotation channels only) */ - DRIVER_TYPE_ROTDIFF, /* sum of all values */ DRIVER_TYPE_SUM, + /* smallest value */ + DRIVER_TYPE_MIN, + /* largest value */ + DRIVER_TYPE_MAX, } eDriver_Types; /* driver flags */ @@ -301,9 +369,11 @@ typedef enum eDriver_Flags { DRIVER_FLAG_RECALC = (1<<1), /* driver does replace value, but overrides (for layering of animation over driver) */ // TODO: this needs to be implemented at some stage or left out... - DRIVER_FLAG_LAYERING = (1<<2), + //DRIVER_FLAG_LAYERING = (1<<2), /* use when the expression needs to be recompiled */ - DRIVER_FLAG_RECOMPILE = (1<<3), + DRIVER_FLAG_RECOMPILE = (1<<3), + /* the names are cached so they dont need have python unicode versions created each time */ + DRIVER_FLAG_RENAMEVAR = (1<<4), } eDriver_Flags; /* F-Curves -------------------------------------- */ diff --git a/source/blender/makesdna/DNA_armature_types.h b/source/blender/makesdna/DNA_armature_types.h index ea549f9aeba..010f210d5aa 100644 --- a/source/blender/makesdna/DNA_armature_types.h +++ b/source/blender/makesdna/DNA_armature_types.h @@ -92,11 +92,14 @@ typedef struct bArmature { int pad; int layer, layer_protected; /* for buttons to work, both variables in this order together */ + +// XXX depreceated... old animaton system (armature only viz) --- short ghostep, ghostsize; /* number of frames to ghosts to show, and step between them */ short ghosttype, pathsize; /* ghost drawing options and number of frames between points of path */ int ghostsf, ghostef; /* start and end frames of ghost-drawing range */ int pathsf, pathef; /* start and end frames of path-calculation range for all bones */ int pathbc, pathac; /* number of frames before/after current frame of path-calculation for all bones */ +// XXX end of depreceated code ---------------------------------- } bArmature; /* armature->flag */ @@ -114,7 +117,7 @@ typedef enum eArmature_Flag { ARM_AUTO_IK = (1<<9), ARM_NO_CUSTOM = (1<<10), /* made option negative, for backwards compat */ ARM_COL_CUSTOM = (1<<11), /* draw custom colours */ - ARM_GHOST_ONLYSEL = (1<<12), /* when ghosting, only show selected bones (this should belong to ghostflag instead) */ + ARM_GHOST_ONLYSEL = (1<<12), /* when ghosting, only show selected bones (this should belong to ghostflag instead) */ // XXX depreceated ARM_DS_EXPAND = (1<<13) } eArmature_Flag; @@ -136,6 +139,7 @@ typedef enum eArmature_DeformFlag { } eArmature_DeformFlag; /* armature->pathflag */ +// XXX depreceated... old animation system (armature only viz) typedef enum eArmature_PathFlag { ARM_PATH_FNUMS = (1<<0), ARM_PATH_KFRAS = (1<<1), @@ -145,6 +149,7 @@ typedef enum eArmature_PathFlag { } eArmature_PathFlag; /* armature->ghosttype */ +// XXX depreceated... old animation system (armature only viz) typedef enum eArmature_GhostType { ARM_GHOST_CUR = 0, ARM_GHOST_RANGE, diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h index c8fc14ca0f0..4738b0d81e8 100644 --- a/source/blender/makesdna/DNA_brush_types.h +++ b/source/blender/makesdna/DNA_brush_types.h @@ -31,6 +31,7 @@ #define DNA_BRUSH_TYPES_H #include "DNA_ID.h" +#include "DNA_texture_types.h" #ifndef MAX_MTEX #define MAX_MTEX 18 @@ -50,9 +51,8 @@ typedef struct Brush { ID id; struct BrushClone clone; - struct CurveMapping *curve; /* falloff curve */ - struct MTex *mtex[18]; /* MAX_MTEX */ + struct MTex mtex; short flag, blend; /* general purpose flag, blend mode */ int size; /* brush diameter */ @@ -65,10 +65,8 @@ typedef struct Brush { float rgb[3]; /* color */ float alpha; /* opacity */ - short texact; /* active texture */ char sculpt_tool; /* active tool */ - - char pad[1]; + char pad2[3]; } Brush; /* Brush.flag */ diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h index 0476d69544a..163933da12a 100644 --- a/source/blender/makesdna/DNA_constraint_types.h +++ b/source/blender/makesdna/DNA_constraint_types.h @@ -200,6 +200,20 @@ typedef struct bLocateLikeConstraint { char subtarget[32]; } bLocateLikeConstraint; +/* Copy Scale Constraint */ +typedef struct bSizeLikeConstraint { + Object *tar; + int flag; + int reserved1; + char subtarget[32]; +} bSizeLikeConstraint; + +/* Copy Transform Constraint */ +typedef struct bTransLikeConstraint { + Object *tar; + char subtarget[32]; +} bTransLikeConstraint; + /* Floor Constraint */ typedef struct bMinMaxConstraint { Object *tar; @@ -211,14 +225,6 @@ typedef struct bMinMaxConstraint { char subtarget[32]; } bMinMaxConstraint; -/* Copy Scale Constraint */ -typedef struct bSizeLikeConstraint { - Object *tar; - int flag; - int reserved1; - char subtarget[32]; -} bSizeLikeConstraint; - /* Action Constraint */ typedef struct bActionConstraint { Object *tar; @@ -401,6 +407,7 @@ typedef enum eBConstraint_Types { CONSTRAINT_TYPE_SHRINKWRAP, /* shrinkwrap (loc/rot) constraint */ CONSTRAINT_TYPE_DAMPTRACK, /* New Tracking constraint that minimises twisting */ CONSTRAINT_TYPE_SPLINEIK, /* Spline-IK - Align 'n' bones to a curve */ + CONSTRAINT_TYPE_TRANSLIKE, /* Copy transform matrix */ /* NOTE: no constraints are allowed to be added after this */ NUM_CONSTRAINT_TYPES diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h index 4bae9935ea7..00afd687f79 100644 --- a/source/blender/makesdna/DNA_gpencil_types.h +++ b/source/blender/makesdna/DNA_gpencil_types.h @@ -113,6 +113,8 @@ typedef struct bGPDlayer { #define GP_LAYER_ONIONSKIN (1<<4) /* for editing in Action Editor */ #define GP_LAYER_SELECT (1<<5) + /* current frame for layer can't be changed */ +#define GP_LAYER_FRAMELOCK (1<<6) /* Grease-Pencil Annotations - 'DataBlock' */ @@ -146,5 +148,10 @@ typedef struct bGPdata { #define GP_DATA_EDITPAINT (1<<3) /* new strokes are added in viewport space */ #define GP_DATA_VIEWALIGN (1<<4) + /* Project into the screens Z values */ +#define GP_DATA_DEPTH_VIEW (1<<5) +#define GP_DATA_DEPTH_STROKE (1<<6) + +#define GP_DATA_DEPTH_STROKE_ENDPOINTS (1<<7) #endif /* DNA_GPENCIL_TYPES_H */ diff --git a/source/blender/makesdna/DNA_lamp_types.h b/source/blender/makesdna/DNA_lamp_types.h index 0a0046f8470..c321c9feea7 100644 --- a/source/blender/makesdna/DNA_lamp_types.h +++ b/source/blender/makesdna/DNA_lamp_types.h @@ -136,7 +136,7 @@ typedef struct Lamp { #define LA_SQUARE 128 #define LA_TEXTURE 256 #define LA_OSATEX 512 -#define LA_DEEP_SHADOW 1024 +/* #define LA_DEEP_SHADOW 1024 */ /* not used anywhere */ #define LA_NO_DIFF 2048 #define LA_NO_SPEC 4096 #define LA_SHAD_RAY 8192 diff --git a/source/blender/makesdna/DNA_material_types.h b/source/blender/makesdna/DNA_material_types.h index 36de890e6dc..7a19262b0cd 100644 --- a/source/blender/makesdna/DNA_material_types.h +++ b/source/blender/makesdna/DNA_material_types.h @@ -69,7 +69,7 @@ typedef struct VolumeSettings { float stepsize; float ms_diff; float ms_intensity; - int ms_steps; + float ms_spread; } VolumeSettings; typedef struct Material { diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 7ca8cea0763..9b433c5bf8c 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -95,8 +95,6 @@ typedef struct bNodeSocket { #define SOCK_IN_USE 4 /* unavailable is for dynamic sockets */ #define SOCK_UNAVAIL 8 - /* flag for selection status */ -#define SOCK_SEL 16 # # typedef struct bNodePreview { @@ -185,10 +183,8 @@ typedef struct bNodeTree { ListBase alltypes; /* type definitions */ struct bNodeType *owntype; /* for groups or dynamic trees, no read/write */ - /* selected input/output socket */ - bNodeSocket *selin; - bNodeSocket *selout; - + int pad2[2]; + /* callbacks */ void (*timecursor)(void *, int nr); void (*stats_draw)(void *, char *str); diff --git a/source/blender/makesdna/DNA_object_force.h b/source/blender/makesdna/DNA_object_force.h index 99b8f400a5e..b3cdd6135e7 100644 --- a/source/blender/makesdna/DNA_object_force.h +++ b/source/blender/makesdna/DNA_object_force.h @@ -87,8 +87,9 @@ typedef struct PartDeflect { float pdef_perm; /* Chance of particle passing through mesh */ float pdef_frict; /* Friction factor for particle deflection */ float pdef_rfrict; /* Random element of friction for deflection */ + float pdef_stickness;/* surface particle stickness */ - float absorption, pad; /* used for forces */ + float absorption; /* used for forces */ /* softbody collisions */ float pdef_sbdamp; /* Damping factor for softbody deflection */ diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index d780aec7895..ace56e78a46 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -35,12 +35,12 @@ #include "DNA_listBase.h" #include "DNA_ID.h" +#include "DNA_action_types.h" #ifdef __cplusplus extern "C" { #endif - -struct bPose; + struct Object; struct AnimData; struct Ipo; @@ -115,6 +115,9 @@ typedef struct Object { struct bGPdata *gpd; /* Grease Pencil data */ + bAnimVizSettings avs; /* settings for visualisation of object-transform animation */ + bMotionPath *mpath; /* motion path cache for this object */ + ListBase constraintChannels; // XXX depreceated... old animation system ListBase effect; ListBase disp; diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 38a9eb0356a..ae370f9a4db 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -1135,7 +1135,7 @@ typedef enum SculptFlags { #define PE_DEFLECT_EMITTER 4 #define PE_INTERPOLATE_ADDED 8 #define PE_DRAW_PART 16 -#define PE_X_MIRROR 64 +#define PE_X_MIRROR 64 /* deprecated */ #define PE_FADE_TIME 128 #define PE_AUTO_VELOCITY 256 diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h index 2bc7b1e8431..12f61cbb026 100644 --- a/source/blender/makesdna/DNA_screen_types.h +++ b/source/blender/makesdna/DNA_screen_types.h @@ -212,14 +212,16 @@ typedef struct ARegion { #define SCREEN_HANDLER_VERSE 3 /* regiontype, first two are the default set */ -#define RGN_TYPE_WINDOW 0 -#define RGN_TYPE_HEADER 1 -#define RGN_TYPE_CHANNELS 2 -#define RGN_TYPE_TEMPORARY 3 -#define RGN_TYPE_UI 4 -#define RGN_TYPE_TOOLS 5 -#define RGN_TYPE_TOOL_PROPS 6 -#define RGN_TYPE_PREVIEW 7 +enum { + RGN_TYPE_WINDOW = 0, + RGN_TYPE_HEADER, + RGN_TYPE_CHANNELS, + RGN_TYPE_TEMPORARY, + RGN_TYPE_UI, + RGN_TYPE_TOOLS, + RGN_TYPE_TOOL_PROPS, + RGN_TYPE_PREVIEW +}; /* region alignment */ #define RGN_ALIGN_NONE 0 diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index e06aa899c49..56323c54491 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -657,6 +657,7 @@ enum FileSortTypeE { #define FILE_SYNCPOSE 128 #define FILE_FILTER 256 #define FILE_BOOKMARKS 512 +#define FILE_GROUP_INSTANCE 1024 /* files in filesel list: 2=ACTIVE */ #define EDITING 1 diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index a6be7256170..bd8573fe8ce 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -266,7 +266,7 @@ typedef struct bTheme { ThemeWireColor tarm[20]; /*ThemeWireColor tobj[20];*/ - int active_theme_group, pad; + int active_theme_area, pad; } bTheme; @@ -337,6 +337,8 @@ typedef struct UserDef { short glreslimit; short ndof_pan, ndof_rotate; short curssize, ipo_new; + short color_picker_type; + short pad2[3]; char versemaster[160]; char verseuser[160]; @@ -465,9 +467,11 @@ extern UserDef U; /* from blenkernel blender.c */ /* gameflags */ #define USER_DEPRECATED_FLAG 1 -#define USER_DISABLE_SOUND 2 +// #define USER_DISABLE_SOUND 2 deprecated, don't use without checking for +// backwards compatibilty in do_versions! #define USER_DISABLE_MIPMAP 4 #define USER_DISABLE_VBO 8 +#define USER_DISABLE_AA 16 /* wm draw method */ #define USER_DRAW_TRIPLE 0 @@ -480,6 +484,12 @@ extern UserDef U; /* from blenkernel blender.c */ #define GP_PAINT_DOSMOOTH (1<<0) #define GP_PAINT_DOSIMPLIFY (1<<1) +/* color picker types */ +#define USER_CP_CIRCLE 0 +#define USER_CP_SQUARE_SV 1 +#define USER_CP_SQUARE_HS 2 +#define USER_CP_SQUARE_HV 3 + /* theme drawtypes */ #define TH_MINIMAL 0 #define TH_ROUNDSHADED 1 diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h index 48d67714f15..7df49bfb2e2 100644 --- a/source/blender/makesdna/DNA_windowmanager_types.h +++ b/source/blender/makesdna/DNA_windowmanager_types.h @@ -182,7 +182,7 @@ typedef struct wmOperatorTypeMacro { struct wmOperatorTypeMacro *next, *prev; /* operator id */ - char idname[MAX_ID_NAME]; + char idname[64]; /* rna pointer to access properties, like keymap */ struct IDProperty *properties; /* operator properties, assigned to ptr->data and can be written to a file */ struct PointerRNA *ptr; @@ -194,7 +194,7 @@ typedef struct wmKeyMapItem { struct wmKeyMapItem *next, *prev; /* operator */ - char idname[64]; /* used to retrieve operator type pointer */ + char idname[64]; /* used to retrieve operator type pointer */ IDProperty *properties; /* operator properties, assigned to ptr->data and can be written to a file */ /* modal */ @@ -267,7 +267,7 @@ typedef struct wmOperator { struct wmOperator *next, *prev; /* saved */ - char idname[64]; /* used to retrieve type pointer */ + char idname[64];/* used to retrieve type pointer */ IDProperty *properties; /* saved, user-settable properties */ /* runtime */ diff --git a/source/blender/makesdna/intern/Makefile b/source/blender/makesdna/intern/Makefile index 857e53d2573..01c4d87a4fc 100644 --- a/source/blender/makesdna/intern/Makefile +++ b/source/blender/makesdna/intern/Makefile @@ -56,6 +56,10 @@ ifeq ($(OS),windows) endif endif +ifeq ($(OS), darwin) + LDFLAGS += -arch $(MACOSX_ARCHITECTURE) #-isysroot $(MACOSX_SDK) -mmacosx-version-min=$(MACOSX_MIN_VERS) +endif + clean:: @$(RM) $(DIR)/makesdna* $(DIR)/DNA.c @$(RM) $(DIR)/debug/makesdna* $(DIR)/debug/DNA.c diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index e5ab692165f..c7cc74c2798 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -52,6 +52,9 @@ extern StructRNA RNA_ActuatorSensor; extern StructRNA RNA_AlwaysSensor; extern StructRNA RNA_AndController; extern StructRNA RNA_AnimData; +extern StructRNA RNA_AnimViz; +extern StructRNA RNA_AnimVizOnionSkinning; +extern StructRNA RNA_AnimVizMotionPaths; extern StructRNA RNA_AnyType; extern StructRNA RNA_Area; extern StructRNA RNA_AreaLamp; @@ -167,6 +170,7 @@ extern StructRNA RNA_Controller; extern StructRNA RNA_CopyLocationConstraint; extern StructRNA RNA_CopyRotationConstraint; extern StructRNA RNA_CopyScaleConstraint; +extern StructRNA RNA_CopyTransformsConstraint; extern StructRNA RNA_Curve; extern StructRNA RNA_CurveMap; extern StructRNA RNA_CurveMapping; @@ -181,6 +185,7 @@ extern StructRNA RNA_DistortedNoiseTexture; extern StructRNA RNA_DomainFluidSettings; extern StructRNA RNA_Driver; extern StructRNA RNA_DriverTarget; +extern StructRNA RNA_DriverVariable; extern StructRNA RNA_DupliObject; extern StructRNA RNA_EdgeSplitModifier; extern StructRNA RNA_EditBone; @@ -304,6 +309,8 @@ extern StructRNA RNA_MirrorModifier; extern StructRNA RNA_Modifier; extern StructRNA RNA_MouseSensor; extern StructRNA RNA_MovieSequence; +extern StructRNA RNA_MotionPath; +extern StructRNA RNA_MotionPathVert; extern StructRNA RNA_MultiresModifier; extern StructRNA RNA_MusgraveTexture; extern StructRNA RNA_NandController; @@ -320,6 +327,7 @@ extern StructRNA RNA_Object; extern StructRNA RNA_ObjectBase; extern StructRNA RNA_ObstacleFluidSettings; extern StructRNA RNA_Operator; +extern StructRNA RNA_Macro; extern StructRNA RNA_OperatorFileListElement; extern StructRNA RNA_OperatorMousePath; extern StructRNA RNA_OperatorProperties; @@ -853,7 +861,6 @@ char *RNA_pointer_as_string(PointerRNA *ptr); /* Function */ const char *RNA_function_identifier(FunctionRNA *func); -PropertyRNA *RNA_function_return(FunctionRNA *func); const char *RNA_function_ui_description(FunctionRNA *func); int RNA_function_flag(FunctionRNA *func); int RNA_function_defined(FunctionRNA *func); diff --git a/source/blender/makesrna/RNA_define.h b/source/blender/makesrna/RNA_define.h index 37abe44f128..f340834d93b 100644 --- a/source/blender/makesrna/RNA_define.h +++ b/source/blender/makesrna/RNA_define.h @@ -172,6 +172,7 @@ void RNA_def_property_srna(PropertyRNA *prop, const char *type); FunctionRNA *RNA_def_function(StructRNA *srna, const char *identifier, const char *call); FunctionRNA *RNA_def_function_runtime(StructRNA *srna, const char *identifier, CallFunc call); void RNA_def_function_return(FunctionRNA *func, PropertyRNA *ret); +void RNA_def_function_return_mark(FunctionRNA *func, PropertyRNA *ret); void RNA_def_function_flag(FunctionRNA *func, int flag); void RNA_def_function_ui_description(FunctionRNA *func, const char *description); diff --git a/source/blender/makesrna/RNA_types.h b/source/blender/makesrna/RNA_types.h index 8cc949f628e..4e60fb413db 100644 --- a/source/blender/makesrna/RNA_types.h +++ b/source/blender/makesrna/RNA_types.h @@ -210,6 +210,7 @@ typedef struct CollectionPointerLink { } CollectionPointerLink; typedef enum RawPropertyType { + PROP_RAW_UNSET=-1, PROP_RAW_INT, // XXX - abused for types that are not set, eg. MFace.verts, needs fixing. PROP_RAW_SHORT, PROP_RAW_CHAR, diff --git a/source/blender/makesrna/intern/Makefile b/source/blender/makesrna/intern/Makefile index e4e4e859ed3..5fefb2ae15b 100644 --- a/source/blender/makesrna/intern/Makefile +++ b/source/blender/makesrna/intern/Makefile @@ -104,6 +104,10 @@ ifeq ($(OS),windows) endif endif +ifeq ($(OS), darwin) + LDFLAGS += -arch $(MACOSX_ARCHITECTURE) #-isysroot $(MACOSX_SDK) -mmacosx-version-min=$(MACOSX_MIN_VERS) +endif + clean:: @$(RM) $(DIR)/makesrna* $(DIR)/rna* @$(RM) $(DIR)/debug/makesrna* $(DIR)/debug/rna* diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index 5bdfe228e89..a03903eb652 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -1236,16 +1236,21 @@ static void rna_def_function_funcs(FILE *f, StructDefRNA *dsrna, FunctionDefRNA for(; dparm; dparm= dparm->next) { if(dparm->prop->arraydimension) ptrstr= "*"; - else if(dparm->prop==func->ret) + else if(dparm->prop==func->c_ret) ptrstr= ((dparm->prop->type == PROP_POINTER) && !(dparm->prop->flag & PROP_RNAPTR))? "*": ""; - else + else if ((dparm->prop->flag & PROP_RETURN)) { + if ((dparm->prop->flag & PROP_THICK_WRAP) && (dparm->prop->type == PROP_STRING)) + ptrstr= ""; + else + ptrstr= ((dparm->prop->type == PROP_POINTER) && !(dparm->prop->flag & PROP_RNAPTR))? "**": "*"; + } else ptrstr= (dparm->prop->type == PROP_POINTER)? "*": ""; - + fprintf(f, "\t%s%s %s%s;\n", rna_type_struct(dparm->prop), rna_parameter_type_name(dparm->prop), ptrstr, dparm->prop->identifier); } fprintf(f, "\tchar *_data"); - if(func->ret) fprintf(f, ", *_retdata"); + if(func->c_ret) fprintf(f, ", *_retdata"); fprintf(f, ";\n"); fprintf(f, "\t\n"); @@ -1259,7 +1264,12 @@ static void rna_def_function_funcs(FILE *f, StructDefRNA *dsrna, FunctionDefRNA dparm= dfunc->cont.properties.first; for(; dparm; dparm= dparm->next) { - if(dparm->prop==func->ret) + if ((dparm->prop->flag & PROP_RETURN)) + ptrstr= ""; + else + ptrstr= "*"; + + if(dparm->prop==func->c_ret) fprintf(f, "\t_retdata= _data;\n"); else if(dparm->prop->arraydimension) fprintf(f, "\t%s= ((%s%s*)_data);\n", dparm->prop->identifier, rna_type_struct(dparm->prop), rna_parameter_type_name(dparm->prop)); @@ -1267,10 +1277,14 @@ static void rna_def_function_funcs(FILE *f, StructDefRNA *dsrna, FunctionDefRNA if(dparm->prop->flag & PROP_RNAPTR) fprintf(f, "\t%s= ((%s%s*)_data);\n", dparm->prop->identifier, rna_type_struct(dparm->prop), rna_parameter_type_name(dparm->prop)); else - fprintf(f, "\t%s= *((%s%s**)_data);\n", dparm->prop->identifier, rna_type_struct(dparm->prop), rna_parameter_type_name(dparm->prop)); + fprintf(f, "\t%s= %s((%s%s**)_data);\n", dparm->prop->identifier, ptrstr, rna_type_struct(dparm->prop), rna_parameter_type_name(dparm->prop)); + } + else { + if ((dparm->prop->flag & PROP_THICK_WRAP) && (dparm->prop->type == PROP_STRING)) + fprintf(f, "\t%s= %s((%s%s)_data);\n", dparm->prop->identifier, ptrstr, rna_type_struct(dparm->prop), rna_parameter_type_name(dparm->prop)); + else + fprintf(f, "\t%s= %s((%s%s*)_data);\n", dparm->prop->identifier, ptrstr, rna_type_struct(dparm->prop), rna_parameter_type_name(dparm->prop)); } - else - fprintf(f, "\t%s= *((%s%s*)_data);\n", dparm->prop->identifier, rna_type_struct(dparm->prop), rna_parameter_type_name(dparm->prop)); if(dparm->next) fprintf(f, "\t_data+= %d;\n", rna_parameter_size(dparm->prop)); @@ -1279,7 +1293,7 @@ static void rna_def_function_funcs(FILE *f, StructDefRNA *dsrna, FunctionDefRNA if(dfunc->call) { fprintf(f, "\t\n"); fprintf(f, "\t"); - if(func->ret) fprintf(f, "%s= ", func->ret->identifier); + if(func->c_ret) fprintf(f, "%s= ", func->c_ret->identifier); fprintf(f, "%s(", dfunc->call); first= 1; @@ -1303,7 +1317,7 @@ static void rna_def_function_funcs(FILE *f, StructDefRNA *dsrna, FunctionDefRNA dparm= dfunc->cont.properties.first; for(; dparm; dparm= dparm->next) { - if(dparm->prop==func->ret) + if(dparm->prop==func->c_ret) continue; if(!first) fprintf(f, ", "); @@ -1314,10 +1328,10 @@ static void rna_def_function_funcs(FILE *f, StructDefRNA *dsrna, FunctionDefRNA fprintf(f, ");\n"); - if(func->ret) { - dparm= rna_find_parameter_def(func->ret); + if(func->c_ret) { + dparm= rna_find_parameter_def(func->c_ret); ptrstr= (((dparm->prop->type == PROP_POINTER) && !(dparm->prop->flag & PROP_RNAPTR)) || (dparm->prop->arraydimension))? "*": ""; - fprintf(f, "\t*((%s%s%s*)_retdata)= %s;\n", rna_type_struct(dparm->prop), rna_parameter_type_name(dparm->prop), ptrstr, func->ret->identifier); + fprintf(f, "\t*((%s%s%s*)_retdata)= %s;\n", rna_type_struct(dparm->prop), rna_parameter_type_name(dparm->prop), ptrstr, func->c_ret->identifier); } } @@ -1552,13 +1566,14 @@ static void rna_generate_static_parameter_prototypes(BlenderRNA *brna, StructRNA PropertyDefRNA *dparm; StructDefRNA *dsrna; int first; + char *ptrstr; dsrna= rna_find_struct_def(srna); func= dfunc->func; /* return type */ for(dparm= dfunc->cont.properties.first; dparm; dparm= dparm->next) { - if(dparm->prop==func->ret) { + if(dparm->prop==func->c_ret) { if(dparm->prop->arraydimension) fprintf(f, "XXX no array return types yet"); /* XXX not supported */ else if(dparm->prop->type == PROP_POINTER && !(dparm->prop->flag & PROP_RNAPTR)) @@ -1600,18 +1615,25 @@ static void rna_generate_static_parameter_prototypes(BlenderRNA *brna, StructRNA /* defined parameters */ for(dparm= dfunc->cont.properties.first; dparm; dparm= dparm->next) { - if(dparm->prop==func->ret) + if(dparm->prop==func->c_ret) continue; if(!first) fprintf(f, ", "); first= 0; + if((dparm->prop->type == PROP_STRING && dparm->prop->flag & PROP_THICK_WRAP)) + ptrstr= ""; + else if(dparm->prop->flag & PROP_RETURN) + ptrstr= "*"; + else + ptrstr= ""; + if(dparm->prop->arraydimension) fprintf(f, "%s%s %s[%d]", rna_type_struct(dparm->prop), rna_parameter_type_name(dparm->prop), dparm->prop->identifier, dparm->prop->totarraylength); else if(dparm->prop->type == PROP_POINTER) - fprintf(f, "%s%s *%s", rna_type_struct(dparm->prop), rna_parameter_type_name(dparm->prop), dparm->prop->identifier); + fprintf(f, "%s%s *%s%s", rna_type_struct(dparm->prop), rna_parameter_type_name(dparm->prop), (dparm->prop->flag & PROP_RNAPTR) ? "" : ptrstr, dparm->prop->identifier); else - fprintf(f, "%s%s %s", rna_type_struct(dparm->prop), rna_parameter_type_name(dparm->prop), dparm->prop->identifier); + fprintf(f, "%s%s %s%s", rna_type_struct(dparm->prop), rna_parameter_type_name(dparm->prop), ptrstr, dparm->prop->identifier); } fprintf(f, ");\n"); @@ -1766,7 +1788,7 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr fprintf(f, "\t%s%s, %d, %s, %s,\n", (prop->flag & PROP_CONTEXT_UPDATE)? "(UpdateFunc)": "", rna_function_string(prop->update), prop->noteflag, rna_function_string(prop->editable), rna_function_string(prop->itemeditable)); if(prop->flag & PROP_RAW_ACCESS) rna_set_raw_offset(f, srna, prop); - else fprintf(f, "\t0, 0"); + else fprintf(f, "\t0, -1"); /* our own type - collections/arrays only */ if(prop->srna) fprintf(f, ", &RNA_%s", (char*)prop->srna); @@ -1890,8 +1912,8 @@ static void rna_generate_struct(BlenderRNA *brna, StructRNA *srna, FILE *f) dfunc= rna_find_function_def(func); if(dfunc->gencall) fprintf(f, "\t%s,\n", dfunc->gencall); else fprintf(f, "\tNULL,\n"); - - if(func->ret) fprintf(f, "\t(PropertyRNA*)&rna_%s_%s_%s\n", srna->identifier, func->identifier, func->ret->identifier); + + if(func->c_ret) fprintf(f, "\t(PropertyRNA*)&rna_%s_%s_%s\n", srna->identifier, func->identifier, func->c_ret->identifier); else fprintf(f, "\tNULL\n"); fprintf(f, "};\n"); @@ -1983,6 +2005,7 @@ RNAProcessItem PROCESS_ITEMS[]= { {"rna_texture.c", NULL, RNA_def_texture}, {"rna_action.c", "rna_action_api.c", RNA_def_action}, {"rna_animation.c", "rna_animation_api.c", RNA_def_animation}, + {"rna_animviz.c", NULL, RNA_def_animviz}, {"rna_actuator.c", NULL, RNA_def_actuator}, {"rna_armature.c", "rna_armature_api.c", RNA_def_armature}, {"rna_boid.c", NULL, RNA_def_boid}, diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c index a250f0a49b4..e931f08c3a3 100644 --- a/source/blender/makesrna/intern/rna_ID.c +++ b/source/blender/makesrna/intern/rna_ID.c @@ -380,6 +380,7 @@ static void rna_def_ID(BlenderRNA *brna) prop= RNA_def_property(srna, "tag", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", LIB_DOIT); + RNA_def_property_flag(prop, PROP_LIB_EXCEPTION); RNA_def_property_ui_text(prop, "Tag", "Tools can use this to tag data, (initial state is undefined)."); prop= RNA_def_property(srna, "library", PROP_POINTER, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index 7dcc72e4158..ce06bc8f6c4 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -249,7 +249,7 @@ static int rna_ensure_property_array_length(PointerRNA *ptr, PropertyRNA *prop) { if(prop->magic == RNA_MAGIC) { int arraylen[RNA_MAX_ARRAY_DIMENSION]; - return (prop->getlength)? prop->getlength(ptr, arraylen): prop->totarraylength; + return (prop->getlength && ptr->data)? prop->getlength(ptr, arraylen): prop->totarraylength; } else { IDProperty *idprop= (IDProperty*)prop; @@ -2021,7 +2021,7 @@ int RNA_property_collection_remove(PointerRNA *ptr, PropertyRNA *prop, int key) if(key+1 < len) { /* move element to be removed to the back */ memcpy(&tmp, &array[key], sizeof(IDProperty)); - memmove(array+key, array+key+1, sizeof(IDProperty)*(len-key+1)); + memmove(array+key, array+key+1, sizeof(IDProperty)*(len-(key+1))); memcpy(&array[len-1], &tmp, sizeof(IDProperty)); } @@ -2266,8 +2266,9 @@ static int rna_raw_access(ReportList *reports, PointerRNA *ptr, PropertyRNA *pro /* try to access as raw array */ if(RNA_property_collection_raw_array(ptr, prop, itemprop, &out)) { - if(in.len != itemlen*out.len) { - BKE_reportf(reports, RPT_ERROR, "Array length mismatch (expected %d, got %d).", out.len*itemlen, in.len); + int arraylen = (itemlen == 0) ? 1 : itemlen; + if(in.len != arraylen*out.len) { + BKE_reportf(reports, RPT_ERROR, "Array length mismatch (expected %d, got %d).", out.len*arraylen, in.len); return 0; } @@ -2277,8 +2278,7 @@ static int rna_raw_access(ReportList *reports, PointerRNA *ptr, PropertyRNA *pro void *outp= out.array; int a, size; - itemlen= (itemlen == 0)? 1: itemlen; - size= RNA_raw_type_sizeof(out.type) * itemlen; + size= RNA_raw_type_sizeof(out.type) * arraylen; for(a=0; a<out.len; a++) { if(set) memcpy(outp, inp, size); @@ -2300,6 +2300,12 @@ static int rna_raw_access(ReportList *reports, PointerRNA *ptr, PropertyRNA *pro void *tmparray= NULL; int tmplen= 0; int err= 0, j, a= 0; + int needconv = 1; + + if (((itemtype == PROP_BOOLEAN || itemtype == PROP_INT) && in.type == PROP_RAW_INT) || + (itemtype == PROP_FLOAT && in.type == PROP_RAW_FLOAT)) + /* avoid creating temporary buffer if the data type match */ + needconv = 0; /* no item property pointer, can still be id property, or * property of a type derived from the collection pointer type */ @@ -2387,7 +2393,7 @@ static int rna_raw_access(ReportList *reports, PointerRNA *ptr, PropertyRNA *pro } a++; } - else { + else if (needconv == 1) { /* allocate temporary array if needed */ if(tmparray && tmplen != itemlen) { MEM_freeN(tmparray); @@ -2448,6 +2454,50 @@ static int rna_raw_access(ReportList *reports, PointerRNA *ptr, PropertyRNA *pro } } } + else { + if(set) { + switch(itemtype) { + case PROP_BOOLEAN: { + RNA_property_boolean_set_array(&itemptr, iprop, &((int*)in.array)[a]); + a += itemlen; + break; + } + case PROP_INT: { + RNA_property_int_set_array(&itemptr, iprop, &((int*)in.array)[a]); + a += itemlen; + break; + } + case PROP_FLOAT: { + RNA_property_float_set_array(&itemptr, iprop, &((float*)in.array)[a]); + a += itemlen; + break; + } + default: + break; + } + } + else { + switch(itemtype) { + case PROP_BOOLEAN: { + RNA_property_boolean_get_array(&itemptr, iprop, &((int*)in.array)[a]); + a += itemlen; + break; + } + case PROP_INT: { + RNA_property_int_get_array(&itemptr, iprop, &((int*)in.array)[a]); + a += itemlen; + break; + } + case PROP_FLOAT: { + RNA_property_float_get_array(&itemptr, iprop, &((float*)in.array)[a]); + a += itemlen; + break; + } + default: + break; + } + } + } } } } @@ -2462,6 +2512,21 @@ static int rna_raw_access(ReportList *reports, PointerRNA *ptr, PropertyRNA *pro RawPropertyType RNA_property_raw_type(PropertyRNA *prop) { + if (prop->rawtype == PROP_RAW_UNSET) { + /* this property has no raw access, yet we try to provide a raw type to help building the array */ + switch (prop->type) { + case PROP_BOOLEAN: + return PROP_RAW_INT; + case PROP_INT: + return PROP_RAW_INT; + case PROP_FLOAT: + return PROP_RAW_FLOAT; + case PROP_ENUM: + return PROP_RAW_INT; + default: + break; + } + } return prop->rawtype; } @@ -3464,11 +3529,6 @@ const char *RNA_function_identifier(FunctionRNA *func) return func->identifier; } -PropertyRNA *RNA_function_return(FunctionRNA *func) -{ - return func->ret; -} - const char *RNA_function_ui_description(FunctionRNA *func) { return func->description; @@ -3929,7 +3989,7 @@ int RNA_function_call_direct_va(bContext *C, ReportList *reports, PointerRNA *pt tid= RNA_struct_identifier(ptr->type); fid= RNA_function_identifier(func); - pret= RNA_function_return(func); + pret= func->c_ret; flen= strlen(format); RNA_parameter_list_create(&parms, ptr, func); @@ -3937,14 +3997,17 @@ int RNA_function_call_direct_va(bContext *C, ReportList *reports, PointerRNA *pt for(i= 0, ofs= 0; iter.valid; RNA_parameter_list_next(&iter), i++) { parm= iter.parm; + flag= RNA_property_flag(parm); if(parm==pret) { retdata= iter.data; continue; } + else if (flag & PROP_RETURN) { + continue; + } pid= RNA_property_identifier(parm); - flag= RNA_property_flag(parm); if (ofs>=flen || format[ofs]=='N') { if (flag & PROP_REQUIRED) { diff --git a/source/blender/makesrna/intern/rna_action.c b/source/blender/makesrna/intern/rna_action.c index 00c5b8ce7c4..b9c5661b771 100644 --- a/source/blender/makesrna/intern/rna_action.c +++ b/source/blender/makesrna/intern/rna_action.c @@ -88,7 +88,7 @@ static void rna_def_dopesheet(BlenderRNA *brna) prop= RNA_def_property(srna, "display_summary", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "filterflag", ADS_FILTER_SUMMARY); - RNA_def_property_ui_text(prop, "Display Summary", "Display an additional 'summary' line."); + RNA_def_property_ui_text(prop, "Display Summary", "Display an additional 'summary' line. (DopeSheet Editors only)"); RNA_def_property_ui_icon(prop, ICON_BORDERMOVE, 0); RNA_def_property_update(prop, NC_ANIMATION|ND_ANIMCHAN_EDIT, NULL); @@ -172,7 +172,7 @@ static void rna_def_dopesheet(BlenderRNA *brna) prop= RNA_def_property(srna, "collapse_summary", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", ADS_FLAG_SUMMARY_COLLAPSED); - RNA_def_property_ui_text(prop, "Collapse Summary", "Collapse summary when shown, so all other channels get hidden. (DopeSheet Window Editors Only)"); + RNA_def_property_ui_text(prop, "Collapse Summary", "Collapse summary when shown, so all other channels get hidden. (DopeSheet Editors Only)"); RNA_def_property_update(prop, NC_ANIMATION|ND_ANIMCHAN_EDIT, NULL); } diff --git a/source/blender/makesrna/intern/rna_animviz.c b/source/blender/makesrna/intern/rna_animviz.c new file mode 100644 index 00000000000..261cfc83b6c --- /dev/null +++ b/source/blender/makesrna/intern/rna_animviz.c @@ -0,0 +1,350 @@ +/** + * $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. + * + * Contributor(s): Blender Foundation (2010), Joshua Leung + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include <stdlib.h> + +#include "RNA_access.h" +#include "RNA_define.h" +#include "RNA_types.h" +#include "RNA_enum_types.h" + +#include "rna_internal.h" + +#include "DNA_anim_types.h" +#include "DNA_action_types.h" +#include "DNA_scene_types.h" + +#include "MEM_guardedalloc.h" + +#include "WM_types.h" + +#ifdef RNA_RUNTIME + +static PointerRNA rna_AnimViz_onion_skinning_get(PointerRNA *ptr) +{ + return rna_pointer_inherit_refine(ptr, &RNA_AnimVizOnionSkinning, ptr->data); +} + +static PointerRNA rna_AnimViz_motion_paths_get(PointerRNA *ptr) +{ + return rna_pointer_inherit_refine(ptr, &RNA_AnimVizMotionPaths, ptr->data); +} + +static void rna_AnimViz_ghost_start_frame_set(PointerRNA *ptr, int value) +{ + bAnimVizSettings *data= (bAnimVizSettings*)ptr->data; + + CLAMP(value, 1, data->ghost_ef); + data->ghost_sf= value; +} + +static void rna_AnimViz_ghost_end_frame_set(PointerRNA *ptr, int value) +{ + bAnimVizSettings *data= (bAnimVizSettings*)ptr->data; + + CLAMP(value, data->ghost_sf, (int)(MAXFRAMEF/2)); + data->ghost_ef= value; +} + +static void rna_AnimViz_path_start_frame_set(PointerRNA *ptr, int value) +{ + bAnimVizSettings *data= (bAnimVizSettings*)ptr->data; + + CLAMP(value, 1, data->path_ef); + data->path_sf= value; +} + +static void rna_AnimViz_path_end_frame_set(PointerRNA *ptr, int value) +{ + bAnimVizSettings *data= (bAnimVizSettings*)ptr->data; + + CLAMP(value, data->path_sf, (int)(MAXFRAMEF/2)); + data->path_ef= value; +} + +#else + +void rna_def_motionpath_common(StructRNA *srna) +{ + PropertyRNA *prop; + + prop= RNA_def_property(srna, "motion_path", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "mpath"); + RNA_def_property_ui_text(prop, "Motion Path", "Motion Path for this element."); +} + +static void rna_def_animviz_motionpath_vert(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna= RNA_def_struct(brna, "MotionPathVert", NULL); + RNA_def_struct_sdna(srna, "bMotionPathVert"); + RNA_def_struct_ui_text(srna, "Motion Path Cache Point", "Cached location on path."); + + prop= RNA_def_property(srna, "co", PROP_FLOAT, PROP_XYZ); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Coordinates", ""); + + prop= RNA_def_property(srna, "selected", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", MOTIONPATH_VERT_SEL); + RNA_def_property_ui_text(prop, "Selected", "Path point is selected for editing."); +} + +static void rna_def_animviz_motion_path(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna= RNA_def_struct(brna, "MotionPath", NULL); + RNA_def_struct_sdna(srna, "bMotionPath"); + RNA_def_struct_ui_text(srna, "Motion Path", "Cache of the worldspace positions of an element over a frame range."); + + /* Collections */ + prop= RNA_def_property(srna, "points", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "points", "length"); + RNA_def_property_struct_type(prop, "MotionPathVert"); + RNA_def_property_ui_text(prop, "Motion Path Points", "Cached positions per frame"); + + /* Playback Ranges */ + prop= RNA_def_property(srna, "start_frame", PROP_INT, PROP_TIME); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Start Frame", "Starting frame of the stored range."); + + prop= RNA_def_property(srna, "end_frame", PROP_INT, PROP_TIME); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "End Frame", "End frame of the stored range."); + + prop= RNA_def_property(srna, "length", PROP_INT, PROP_TIME); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Length", "Number of frames cached."); + + /* Settings */ + prop= RNA_def_property(srna, "use_bone_head", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", MOTIONPATH_FLAG_BHEAD); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); // xxx + RNA_def_property_ui_text(prop, "Use Bone Heads", "For PoseBone paths, use the bone head location when calculating this path."); + + prop= RNA_def_property(srna, "editing", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", MOTIONPATH_FLAG_EDIT); + RNA_def_property_ui_text(prop, "Edit Path", "Path is being edited."); +} + +/* --- */ + +static void rna_def_animviz_ghosts(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + static const EnumPropertyItem prop_type_items[] = { + {GHOST_TYPE_NONE, "NONE", 0, "No Ghosts", "Don not show any ghosts"}, + {GHOST_TYPE_ACFRA, "CURRENT_FRAME", 0, "Around Current Frame", "Show ghosts from around the current frame"}, + {GHOST_TYPE_RANGE, "RANGE", 0, "In Range", "Show ghosts for the specified frame range"}, + {GHOST_TYPE_KEYS, "KEYS", 0, "On Keyframes", "Show ghosts on keyframes"}, + {0, NULL, 0, NULL, NULL}}; + + + srna= RNA_def_struct(brna, "AnimVizOnionSkinning", NULL); + RNA_def_struct_sdna(srna, "bAnimVizSettings"); + RNA_def_struct_nested(brna, srna, "AnimViz"); + RNA_def_struct_ui_text(srna, "Onion Skinning Settings", "Onion Skinning settings for animation visualisation."); + + /* Enums */ + prop= RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "ghost_type"); + RNA_def_property_enum_items(prop, prop_type_items); + RNA_def_property_ui_text(prop, "Type", "Method used for determining what ghosts get drawn."); + RNA_def_property_update(prop, NC_SPACE|ND_SPACE_VIEW3D, NULL); /* XXX since this is only for 3d-view drawing */ + + /* Settings */ + prop= RNA_def_property(srna, "only_selected", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "ghost_flag", GHOST_FLAG_ONLYSEL); + RNA_def_property_ui_text(prop, "On Selected Bones Only", "For Pose-Mode drawing, only draw ghosts for selected bones."); + RNA_def_property_update(prop, NC_SPACE|ND_SPACE_VIEW3D, NULL); /* XXX since this is only for 3d-view drawing */ + + prop= RNA_def_property(srna, "frame_step", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "ghost_step"); + RNA_def_property_range(prop, 1, 20); + RNA_def_property_ui_text(prop, "Frame Step", "Number of frames between ghosts shown (not for 'On Keyframes' Onion-skining method)."); + RNA_def_property_update(prop, NC_SPACE|ND_SPACE_VIEW3D, NULL); /* XXX since this is only for 3d-view drawing */ + + /* Playback Ranges */ + prop= RNA_def_property(srna, "start_frame", PROP_INT, PROP_TIME); + RNA_def_property_int_sdna(prop, NULL, "ghost_sf"); + RNA_def_property_int_funcs(prop, NULL, "rna_AnimViz_ghost_start_frame_set", NULL); + RNA_def_property_ui_text(prop, "Start Frame", "Starting frame of range of Ghosts to display (not for 'Around Current Frame' Onion-skinning method)."); + RNA_def_property_update(prop, NC_SPACE|ND_SPACE_VIEW3D, NULL); /* XXX since this is only for 3d-view drawing */ + + prop= RNA_def_property(srna, "end_frame", PROP_INT, PROP_TIME); + RNA_def_property_int_sdna(prop, NULL, "ghost_ef"); + RNA_def_property_int_funcs(prop, NULL, "rna_AnimViz_ghost_end_frame_set", NULL); + RNA_def_property_ui_text(prop, "End Frame", "End frame of range of Ghosts to display (not for 'Around Current Frame' Onion-skinning method)."); + RNA_def_property_update(prop, NC_SPACE|ND_SPACE_VIEW3D, NULL); /* XXX since this is only for 3d-view drawing */ + + /* Around Current Ranges */ + prop= RNA_def_property(srna, "before_current", PROP_INT, PROP_TIME); + RNA_def_property_int_sdna(prop, NULL, "ghost_bc"); + RNA_def_property_range(prop, 0, 30); + RNA_def_property_ui_text(prop, "Before Current", "Number of frames to show before the current frame (only for 'Around Current Frame' Onion-skinning method)."); + RNA_def_property_update(prop, NC_SPACE|ND_SPACE_VIEW3D, NULL); /* XXX since this is only for 3d-view drawing */ + + prop= RNA_def_property(srna, "after_current", PROP_INT, PROP_TIME); + RNA_def_property_int_sdna(prop, NULL, "ghost_ac"); + RNA_def_property_range(prop, 0, 30); + RNA_def_property_ui_text(prop, "After Current", "Number of frames to show after the current frame (only for 'Around Current Frame' Onion-skinning method)."); + RNA_def_property_update(prop, NC_SPACE|ND_SPACE_VIEW3D, NULL); /* XXX since this is only for 3d-view drawing */ +} + +static void rna_def_animviz_paths(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + static const EnumPropertyItem prop_type_items[]= { + {MOTIONPATH_TYPE_RANGE, "RANGE", 0, "In Range", "Display Paths of poses within specified range."}, + {MOTIONPATH_TYPE_ACFRA, "CURRENT_FRAME", 0, "Around Frame", "Display Paths of poses within a fixed number of frames around the current frame."}, + {0, NULL, 0, NULL, NULL}}; + static const EnumPropertyItem prop_location_items[]= { + {MOTIONPATH_BAKE_HEADS, "HEADS", 0, "Heads", "Calculate bone paths from heads"}, + {0, "TAILS", 0, "Tails", "Calculate bone paths from tails"}, + {0, NULL, 0, NULL, NULL}}; + + srna= RNA_def_struct(brna, "AnimVizMotionPaths", NULL); + RNA_def_struct_sdna(srna, "bAnimVizSettings"); + RNA_def_struct_nested(brna, srna, "AnimViz"); + RNA_def_struct_ui_text(srna, "Motion Path Settings", "Motion Path settings for animation visualisation."); + + /* Enums */ + prop= RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "path_type"); + RNA_def_property_enum_items(prop, prop_type_items); + RNA_def_property_ui_text(prop, "Paths Type", "Type of range to show for Motion Paths"); + RNA_def_property_update(prop, NC_SPACE|ND_SPACE_VIEW3D, NULL); /* XXX since this is only for 3d-view drawing */ + + prop= RNA_def_property(srna, "bake_location", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_bitflag_sdna(prop, NULL, "path_bakeflag"); + RNA_def_property_enum_items(prop, prop_location_items); + RNA_def_property_ui_text(prop, "Bake Location", "When calculating Bone Paths, use Head or Tips"); + RNA_def_property_update(prop, NC_SPACE|ND_SPACE_VIEW3D, NULL); /* XXX since this is only for 3d-view drawing */ + + /* Settings */ + prop= RNA_def_property(srna, "show_frame_numbers", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "path_viewflag", MOTIONPATH_VIEW_FNUMS); + RNA_def_property_ui_text(prop, "Show Frame Numbers", "Show frame numbers on Motion Paths"); + RNA_def_property_update(prop, NC_SPACE|ND_SPACE_VIEW3D, NULL); /* XXX since this is only for 3d-view drawing */ + + prop= RNA_def_property(srna, "highlight_keyframes", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "path_viewflag", MOTIONPATH_VIEW_KFRAS); + RNA_def_property_ui_text(prop, "Highlight Keyframes", "Emphasize position of keyframes on Motion Paths"); + RNA_def_property_update(prop, NC_SPACE|ND_SPACE_VIEW3D, NULL); /* XXX since this is only for 3d-view drawing */ + + prop= RNA_def_property(srna, "show_keyframe_numbers", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "path_viewflag", MOTIONPATH_VIEW_KFNOS); + RNA_def_property_ui_text(prop, "Show Keyframe Numbers", "Show frame numbers of Keyframes on Motion Paths"); + RNA_def_property_update(prop, NC_SPACE|ND_SPACE_VIEW3D, NULL); /* XXX since this is only for 3d-view drawing */ + + prop= RNA_def_property(srna, "frame_step", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "path_step"); + RNA_def_property_range(prop, 1, 100); + RNA_def_property_ui_text(prop, "Frame Step", "Number of frames between paths shown (not for 'On Keyframes' Onion-skining method)."); + RNA_def_property_update(prop, NC_SPACE|ND_SPACE_VIEW3D, NULL); /* XXX since this is only for 3d-view drawing */ + + + /* Playback Ranges */ + prop= RNA_def_property(srna, "start_frame", PROP_INT, PROP_TIME); + RNA_def_property_int_sdna(prop, NULL, "path_sf"); + RNA_def_property_int_funcs(prop, NULL, "rna_AnimViz_path_start_frame_set", NULL); + RNA_def_property_ui_text(prop, "Start Frame", "Starting frame of range of paths to display/calculate (not for 'Around Current Frame' Onion-skinning method)."); + RNA_def_property_update(prop, NC_SPACE|ND_SPACE_VIEW3D, NULL); /* XXX since this is only for 3d-view drawing */ + + prop= RNA_def_property(srna, "end_frame", PROP_INT, PROP_TIME); + RNA_def_property_int_sdna(prop, NULL, "path_ef"); + RNA_def_property_int_funcs(prop, NULL, "rna_AnimViz_path_end_frame_set", NULL); + RNA_def_property_ui_text(prop, "End Frame", "End frame of range of paths to display/calculate (not for 'Around Current Frame' Onion-skinning method)."); + RNA_def_property_update(prop, NC_SPACE|ND_SPACE_VIEW3D, NULL); /* XXX since this is only for 3d-view drawing */ + + /* Around Current Ranges */ + prop= RNA_def_property(srna, "before_current", PROP_INT, PROP_TIME); + RNA_def_property_int_sdna(prop, NULL, "path_bc"); + RNA_def_property_range(prop, 1, MAXFRAMEF/2); + RNA_def_property_ui_text(prop, "Before Current", "Number of frames to show before the current frame (only for 'Around Current Frame' Onion-skinning method)."); + RNA_def_property_update(prop, NC_SPACE|ND_SPACE_VIEW3D, NULL); /* XXX since this is only for 3d-view drawing */ + + prop= RNA_def_property(srna, "after_current", PROP_INT, PROP_TIME); + RNA_def_property_int_sdna(prop, NULL, "path_ac"); + RNA_def_property_range(prop, 1, MAXFRAMEF/2); + RNA_def_property_ui_text(prop, "After Current", "Number of frames to show after the current frame (only for 'Around Current Frame' Onion-skinning method)."); + RNA_def_property_update(prop, NC_SPACE|ND_SPACE_VIEW3D, NULL); /* XXX since this is only for 3d-view drawing */ +} + +/* --- */ + +void rna_def_animviz_common(StructRNA *srna) +{ + PropertyRNA *prop; + + prop= RNA_def_property(srna, "animation_visualisation", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); + RNA_def_property_pointer_sdna(prop, NULL, "avs"); + RNA_def_property_ui_text(prop, "Animation Visualisation", "Animation data for this datablock."); +} + +static void rna_def_animviz(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna= RNA_def_struct(brna, "AnimViz", NULL); + RNA_def_struct_sdna(srna, "bAnimVizSettings"); + RNA_def_struct_ui_text(srna, "Animation Visualisation", "Settings for the visualisation of motion."); + + /* onion-skinning settings (nested struct) */ + prop= RNA_def_property(srna, "onion_skinning", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); + RNA_def_property_struct_type(prop, "AnimVizOnionSkinning"); + RNA_def_property_pointer_funcs(prop, "rna_AnimViz_onion_skinning_get", NULL, NULL); + RNA_def_property_ui_text(prop, "Onion Skinning", "Onion Skinning (ghosting) settings for visualisation."); + + /* motion path settings (nested struct) */ + prop= RNA_def_property(srna, "motion_paths", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); + RNA_def_property_struct_type(prop, "AnimVizMotionPaths"); + RNA_def_property_pointer_funcs(prop, "rna_AnimViz_motion_paths_get", NULL, NULL); + RNA_def_property_ui_text(prop, "Motion Paths", "Motion Path settings for visualisation."); +} + +/* --- */ + +void RNA_def_animviz(BlenderRNA *brna) +{ + rna_def_animviz(brna); + rna_def_animviz_ghosts(brna); + rna_def_animviz_paths(brna); + + rna_def_animviz_motion_path(brna); + rna_def_animviz_motionpath_vert(brna); +} + +#endif diff --git a/source/blender/makesrna/intern/rna_armature_api.c b/source/blender/makesrna/intern/rna_armature_api.c index 22bd7313166..f3983a43b4f 100644 --- a/source/blender/makesrna/intern/rna_armature_api.c +++ b/source/blender/makesrna/intern/rna_armature_api.c @@ -58,7 +58,7 @@ void RNA_api_armature_edit_bone(StructRNA *srna) PropertyRNA *parm; func= RNA_def_function(srna, "align_roll", "rna_EditBone_align_roll"); - RNA_def_function_ui_description(func, "Align the bone to a localspace vector."); + RNA_def_function_ui_description(func, "Align the bone to a localspace roll so the Z axis points in the direction of the vector given."); parm= RNA_def_float_vector(func, "vector", 3, NULL, -FLT_MAX, FLT_MAX, "Vector", "", -FLT_MAX, FLT_MAX); RNA_def_property_flag(parm, PROP_REQUIRED); } diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c index 7f7126c659a..8f8dd4681ab 100644 --- a/source/blender/makesrna/intern/rna_brush.c +++ b/source/blender/makesrna/intern/rna_brush.c @@ -33,6 +33,7 @@ #include "DNA_texture_types.h" #include "IMB_imbuf.h" +#include "WM_types.h" EnumPropertyItem brush_sculpt_tool_items[] = { {SCULPT_TOOL_DRAW, "DRAW", 0, "Draw", ""}, @@ -52,29 +53,6 @@ EnumPropertyItem brush_sculpt_tool_items[] = { #include "BKE_texture.h" #include "WM_api.h" -#include "WM_types.h" - -static void rna_Brush_mtex_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) -{ - Brush *brush= (Brush*)ptr->data; - rna_iterator_array_begin(iter, (void*)brush->mtex, sizeof(MTex*), MAX_MTEX, 0, NULL); -} - -static PointerRNA rna_Brush_active_texture_get(PointerRNA *ptr) -{ - Brush *br= (Brush*)ptr->data; - Tex *tex; - - tex= give_current_brush_texture(br); - return rna_pointer_inherit_refine(ptr, &RNA_Texture, tex); -} - -static void rna_Brush_active_texture_set(PointerRNA *ptr, PointerRNA value) -{ - Brush *br= (Brush*)ptr->data; - - set_current_brush_texture(br, value.data); -} static void rna_Brush_update(Main *bmain, Scene *scene, PointerRNA *ptr) { @@ -291,8 +269,17 @@ static void rna_def_brush(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_Brush_update"); /* texture */ - rna_def_mtex_common(srna, "rna_Brush_mtex_begin", "rna_Brush_active_texture_get", - "rna_Brush_active_texture_set", "BrushTextureSlot", "rna_Brush_update"); + prop= RNA_def_property(srna, "texture_slot", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "BrushTextureSlot"); + RNA_def_property_pointer_sdna(prop, NULL, "mtex"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Texture Slot", ""); + + prop= RNA_def_property(srna, "texture", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "mtex.tex"); + RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Texture", ""); + RNA_def_property_update(prop, NC_TEXTURE, "rna_Brush_update"); /* clone tool */ prop= RNA_def_property(srna, "clone_image", PROP_POINTER, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c index f9405dec531..5ec8d438c42 100644 --- a/source/blender/makesrna/intern/rna_constraint.c +++ b/source/blender/makesrna/intern/rna_constraint.c @@ -43,6 +43,7 @@ EnumPropertyItem constraint_type_items[] ={ {CONSTRAINT_TYPE_LOCLIKE, "COPY_LOCATION", ICON_CONSTRAINT_DATA, "Copy Location", ""}, {CONSTRAINT_TYPE_ROTLIKE, "COPY_ROTATION", ICON_CONSTRAINT_DATA, "Copy Rotation", ""}, {CONSTRAINT_TYPE_SIZELIKE, "COPY_SCALE", ICON_CONSTRAINT_DATA, "Copy Scale", ""}, + {CONSTRAINT_TYPE_TRANSLIKE, "COPY_TRANSFORMS", ICON_CONSTRAINT_DATA, "Copy Transforms", ""}, {CONSTRAINT_TYPE_DISTLIMIT, "LIMIT_DISTANCE", ICON_CONSTRAINT_DATA, "Limit Distance", ""}, {CONSTRAINT_TYPE_LOCLIMIT, "LIMIT_LOCATION", ICON_CONSTRAINT_DATA, "Limit Location", ""}, {CONSTRAINT_TYPE_ROTLIMIT, "LIMIT_ROTATION", ICON_CONSTRAINT_DATA, "Limit Rotation", ""}, @@ -151,6 +152,8 @@ static StructRNA *rna_ConstraintType_refine(struct PointerRNA *ptr) return &RNA_DampedTrackConstraint; case CONSTRAINT_TYPE_SPLINEIK: return &RNA_SplineIKConstraint; + case CONSTRAINT_TYPE_TRANSLIKE: + return &RNA_CopyTransformsConstraint; default: return &RNA_UnknownType; } @@ -647,6 +650,69 @@ static void rna_def_constraint_track_to(BlenderRNA *brna) RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update"); } +static void rna_def_constraint_locate_like(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna= RNA_def_struct(brna, "CopyLocationConstraint", "Constraint"); + RNA_def_struct_ui_text(srna, "Copy Location Constraint", "Copies the location of the target."); + + prop= RNA_def_property(srna, "head_tail", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, "bConstraint", "headtail"); + RNA_def_property_ui_text(prop, "Head/Tail", "Target along length of bone: Head=0, Tail=1."); + RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update"); + + RNA_def_struct_sdna_from(srna, "bLocateLikeConstraint", "data"); + + prop= RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "tar"); + RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Target", "Target Object"); + RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_dependency_update"); + + prop= RNA_def_property(srna, "subtarget", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "subtarget"); + RNA_def_property_ui_text(prop, "Sub-Target", ""); + RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_dependency_update"); + + prop= RNA_def_property(srna, "use_x", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", LOCLIKE_X); + RNA_def_property_ui_text(prop, "Copy X", "Copy the target's X location."); + RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update"); + + prop= RNA_def_property(srna, "use_y", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", LOCLIKE_Y); + RNA_def_property_ui_text(prop, "Copy Y", "Copy the target's Y location."); + RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update"); + + prop= RNA_def_property(srna, "use_z", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", LOCLIKE_Z); + RNA_def_property_ui_text(prop, "Copy Z", "Copy the target's Z location."); + RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update"); + + prop= RNA_def_property(srna, "invert_x", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", LOCLIKE_X_INVERT); + RNA_def_property_ui_text(prop, "Invert X", "Invert the X location."); + RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update"); + + prop= RNA_def_property(srna, "invert_y", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", LOCLIKE_Y_INVERT); + RNA_def_property_ui_text(prop, "Invert Y", "Invert the Y location."); + RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update"); + + prop= RNA_def_property(srna, "invert_z", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", LOCLIKE_Z_INVERT); + RNA_def_property_ui_text(prop, "Invert Z", "Invert the Z location."); + RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update"); + + prop= RNA_def_property(srna, "use_offset", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", LOCLIKE_OFFSET); + RNA_def_property_ui_text(prop, "Offset", "Add original location into copied location."); + RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update"); +} + static void rna_def_constraint_rotate_like(BlenderRNA *brna) { StructRNA *srna; @@ -703,20 +769,14 @@ static void rna_def_constraint_rotate_like(BlenderRNA *brna) RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update"); } -static void rna_def_constraint_locate_like(BlenderRNA *brna) +static void rna_def_constraint_size_like(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - srna= RNA_def_struct(brna, "CopyLocationConstraint", "Constraint"); - RNA_def_struct_ui_text(srna, "Copy Location Constraint", "Copies the location of the target."); - - prop= RNA_def_property(srna, "head_tail", PROP_FLOAT, PROP_FACTOR); - RNA_def_property_float_sdna(prop, "bConstraint", "headtail"); - RNA_def_property_ui_text(prop, "Head/Tail", "Target along length of bone: Head=0, Tail=1."); - RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update"); - - RNA_def_struct_sdna_from(srna, "bLocateLikeConstraint", "data"); + srna= RNA_def_struct(brna, "CopyScaleConstraint", "Constraint"); + RNA_def_struct_ui_text(srna, "Copy Scale Constraint", "Copies the scale of the target."); + RNA_def_struct_sdna_from(srna, "bSizeLikeConstraint", "data"); prop= RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "tar"); @@ -731,39 +791,50 @@ static void rna_def_constraint_locate_like(BlenderRNA *brna) RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_dependency_update"); prop= RNA_def_property(srna, "use_x", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", LOCLIKE_X); - RNA_def_property_ui_text(prop, "Copy X", "Copy the target's X location."); + RNA_def_property_boolean_sdna(prop, NULL, "flag", SIZELIKE_X); + RNA_def_property_ui_text(prop, "Copy X", "Copy the target's X scale."); RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update"); prop= RNA_def_property(srna, "use_y", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", LOCLIKE_Y); - RNA_def_property_ui_text(prop, "Copy Y", "Copy the target's Y location."); + RNA_def_property_boolean_sdna(prop, NULL, "flag", SIZELIKE_Y); + RNA_def_property_ui_text(prop, "Copy Y", "Copy the target's Y scale."); RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update"); prop= RNA_def_property(srna, "use_z", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", LOCLIKE_Z); - RNA_def_property_ui_text(prop, "Copy Z", "Copy the target's Z location."); + RNA_def_property_boolean_sdna(prop, NULL, "flag", SIZELIKE_Z); + RNA_def_property_ui_text(prop, "Copy Z", "Copy the target's Z scale."); RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update"); - prop= RNA_def_property(srna, "invert_x", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", LOCLIKE_X_INVERT); - RNA_def_property_ui_text(prop, "Invert X", "Invert the X location."); + prop= RNA_def_property(srna, "use_offset", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", SIZELIKE_OFFSET); + RNA_def_property_ui_text(prop, "Offset", "Add original scale into copied scale."); RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update"); +} - prop= RNA_def_property(srna, "invert_y", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", LOCLIKE_Y_INVERT); - RNA_def_property_ui_text(prop, "Invert Y", "Invert the Y location."); - RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update"); +static void rna_def_constraint_transform_like(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; - prop= RNA_def_property(srna, "invert_z", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", LOCLIKE_Z_INVERT); - RNA_def_property_ui_text(prop, "Invert Z", "Invert the Z location."); + srna= RNA_def_struct(brna, "CopyTransformsConstraint", "Constraint"); + RNA_def_struct_ui_text(srna, "Copy Transforms Constraint", "Copies all the transforms of the target."); + RNA_def_struct_sdna_from(srna, "bTransLikeConstraint", "data"); + + prop= RNA_def_property(srna, "head_tail", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, "bConstraint", "headtail"); + RNA_def_property_ui_text(prop, "Head/Tail", "Target along length of bone: Head=0, Tail=1."); RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update"); - prop= RNA_def_property(srna, "use_offset", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", LOCLIKE_OFFSET); - RNA_def_property_ui_text(prop, "Offset", "Add original location into copied location."); - RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update"); + prop= RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "tar"); + RNA_def_property_ui_text(prop, "Target", "Target Object"); + RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_dependency_update"); + + prop= RNA_def_property(srna, "subtarget", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "subtarget"); + RNA_def_property_ui_text(prop, "Sub-Target", ""); + RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_dependency_update"); } static void rna_def_constraint_minmax(BlenderRNA *brna) @@ -817,48 +888,6 @@ static void rna_def_constraint_minmax(BlenderRNA *brna) RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update"); } -static void rna_def_constraint_size_like(BlenderRNA *brna) -{ - StructRNA *srna; - PropertyRNA *prop; - - srna= RNA_def_struct(brna, "CopyScaleConstraint", "Constraint"); - RNA_def_struct_ui_text(srna, "Copy Scale Constraint", "Copies the scale of the target."); - RNA_def_struct_sdna_from(srna, "bSizeLikeConstraint", "data"); - - prop= RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE); - RNA_def_property_pointer_sdna(prop, NULL, "tar"); - RNA_def_property_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "Target", "Target Object"); - RNA_def_property_flag(prop, PROP_EDITABLE); - RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_dependency_update"); - - prop= RNA_def_property(srna, "subtarget", PROP_STRING, PROP_NONE); - RNA_def_property_string_sdna(prop, NULL, "subtarget"); - RNA_def_property_ui_text(prop, "Sub-Target", ""); - RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_dependency_update"); - - prop= RNA_def_property(srna, "use_x", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", SIZELIKE_X); - RNA_def_property_ui_text(prop, "Copy X", "Copy the target's X scale."); - RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update"); - - prop= RNA_def_property(srna, "use_y", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", SIZELIKE_Y); - RNA_def_property_ui_text(prop, "Copy Y", "Copy the target's Y scale."); - RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update"); - - prop= RNA_def_property(srna, "use_z", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", SIZELIKE_Z); - RNA_def_property_ui_text(prop, "Copy Z", "Copy the target's Z scale."); - RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update"); - - prop= RNA_def_property(srna, "use_offset", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", SIZELIKE_OFFSET); - RNA_def_property_ui_text(prop, "Offset", "Add original scale into copied scale."); - RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update"); -} - static void rna_def_constraint_action(BlenderRNA *brna) { StructRNA *srna; @@ -1869,6 +1898,7 @@ void RNA_def_constraint(BlenderRNA *brna) rna_def_constraint_size_like(brna); rna_def_constraint_locate_like(brna); rna_def_constraint_rotate_like(brna); + rna_def_constraint_transform_like(brna); rna_def_constraint_minmax(brna); rna_def_constraint_track_to(brna); rna_def_constraint_kinematic(brna); diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c index 9bf5afdac48..ed10c0819fd 100644 --- a/source/blender/makesrna/intern/rna_define.c +++ b/source/blender/makesrna/intern/rna_define.c @@ -931,6 +931,8 @@ PropertyRNA *RNA_def_property(StructOrFunctionRNA *cont_, const char *identifier prop->subtype= subtype; prop->name= identifier; prop->description= ""; + /* a priori not raw editable */ + prop->rawtype = -1; if(type != PROP_COLLECTION && type != PROP_POINTER) { prop->flag= PROP_EDITABLE; @@ -2417,9 +2419,16 @@ FunctionRNA *RNA_def_function_runtime(StructRNA *srna, const char *identifier, C return func; } +/* C return value only!, multiple rna returns can be done with RNA_def_function_return_mark */ void RNA_def_function_return(FunctionRNA *func, PropertyRNA *ret) { - func->ret= ret; + func->c_ret= ret; + + RNA_def_function_return_mark(func, ret); +} + +void RNA_def_function_return_mark(FunctionRNA *func, PropertyRNA *ret) +{ ret->flag|=PROP_RETURN; } @@ -2461,7 +2470,12 @@ int rna_parameter_size(PropertyRNA *parm) case PROP_FLOAT: return sizeof(float); case PROP_STRING: - return sizeof(char *); + /* return valyes dont store a pointer to the original */ + if(parm->flag & PROP_THICK_WRAP) { + StringPropertyRNA *sparm= (StringPropertyRNA*)parm; + return sizeof(char) * sparm->maxlength; + } else + return sizeof(char *); case PROP_POINTER: { #ifdef RNA_RUNTIME if(parm->flag & PROP_RNAPTR) diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c index 62ee19df352..b6b05eb4896 100644 --- a/source/blender/makesrna/intern/rna_fcurve.c +++ b/source/blender/makesrna/intern/rna_fcurve.c @@ -116,10 +116,12 @@ static void rna_DriverTarget_update_data(Main *bmain, Scene *scene, PointerRNA * AnimData *adt= BKE_animdata_from_id(ptr->id.data); /* find the driver this belongs to and update it */ - for(fcu=adt->drivers.first; fcu; fcu=fcu->next) { + for (fcu=adt->drivers.first; fcu; fcu=fcu->next) { driver= fcu->driver; - - if(driver && BLI_findindex(&driver->targets, ptr->data) != -1) { + + if (driver) { + // FIXME: need to be able to search targets for required one... + //BLI_findindex(&driver->targets, ptr->data) != -1) RNA_pointer_create(ptr->id.data, &RNA_Driver, driver, &driverptr); rna_ChannelDriver_update_data(bmain, scene, &driverptr); return; @@ -127,6 +129,15 @@ static void rna_DriverTarget_update_data(Main *bmain, Scene *scene, PointerRNA * } } +static void rna_DriverTarget_update_name(Main *bmain, Scene *scene, PointerRNA *ptr) +{ + ChannelDriver *driver= ptr->data; + rna_DriverTarget_update_data(bmain, scene, ptr); + + driver->flag |= DRIVER_FLAG_RENAMEVAR; + +} + /* ----------- */ static StructRNA *rna_DriverTarget_id_typef(PointerRNA *ptr) @@ -185,6 +196,14 @@ static void rna_DriverTarget_RnaPath_set(PointerRNA *ptr, const char *value) dtar->rna_path= NULL; } +static void rna_DriverVariable_type_set(PointerRNA *ptr, int value) +{ + DriverVar *dvar= (DriverVar *)ptr->data; + + /* call the API function for this */ + driver_change_variable_type(dvar, value); +} + /* ****************************** */ static void rna_FCurve_RnaPath_get(PointerRNA *ptr, char *value) @@ -220,15 +239,16 @@ static void rna_FCurve_RnaPath_set(PointerRNA *ptr, const char *value) fcu->rna_path= NULL; } -DriverTarget *rna_Driver_new_target(ChannelDriver *driver) +DriverVar *rna_Driver_new_variable(ChannelDriver *driver) { - return driver_add_new_target(driver); + /* call the API function for this */ + return driver_add_new_variable(driver); } -void rna_Driver_remove_target(ChannelDriver *driver, DriverTarget *dtar) +void rna_Driver_remove_variable(ChannelDriver *driver, DriverVar *dvar) { /* call the API function for this */ - driver_free_target(driver, dtar); + driver_free_variable(driver, dvar); } @@ -676,14 +696,20 @@ static void rna_def_drivertarget(BlenderRNA *brna) StructRNA *srna; PropertyRNA *prop; - srna= RNA_def_struct(brna, "DriverTarget", NULL); - RNA_def_struct_ui_text(srna, "Driver Target", "Variable from some source/target for driver relationship."); + static EnumPropertyItem prop_trans_chan_items[] = { + {DTAR_TRANSCHAN_LOCX, "LOC_X", 0, "X Location", ""}, + {DTAR_TRANSCHAN_LOCY, "LOC_Y", 0, "Y Location", ""}, + {DTAR_TRANSCHAN_LOCZ, "LOC_Z", 0, "Z Location", ""}, + {DTAR_TRANSCHAN_ROTX, "ROT_X", 0, "X Rotation", ""}, + {DTAR_TRANSCHAN_ROTY, "ROT_Y", 0, "Y Rotation", ""}, + {DTAR_TRANSCHAN_ROTZ, "ROT_Z", 0, "Z Rotation", ""}, + {DTAR_TRANSCHAN_SCALEX, "SCALE_X", 0, "X Scale", ""}, + {DTAR_TRANSCHAN_SCALEY, "SCALE_Y", 0, "Y Scale", ""}, + {DTAR_TRANSCHAN_SCALEZ, "SCALE_Z", 0, "Z Scale", ""}, + {0, NULL, 0, NULL, NULL}}; - /* Variable Name */ - prop= RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); - RNA_def_struct_name_property(srna, prop); - RNA_def_property_ui_text(prop, "Name", "Name to use in scripted expressions/functions. (No spaces or dots are allowed. Also, must not start with a symbol or digit)"); - RNA_def_property_update(prop, 0, "rna_DriverTarget_update_data"); + srna= RNA_def_struct(brna, "DriverTarget", NULL); + RNA_def_struct_ui_text(srna, "Driver Target", "Source of input values for driver variables."); /* Target Properties - ID-block to Drive */ prop= RNA_def_property(srna, "id", PROP_POINTER, PROP_NONE); @@ -698,6 +724,7 @@ static void rna_def_drivertarget(BlenderRNA *brna) RNA_def_property_enum_sdna(prop, NULL, "idtype"); RNA_def_property_enum_items(prop, id_type_items); RNA_def_property_enum_default(prop, ID_OB); + // XXX need to add an 'editable func' for this, in the case where certain flags are set already... RNA_def_property_enum_funcs(prop, NULL, "rna_DriverTarget_id_type_set", NULL); RNA_def_property_ui_text(prop, "ID Type", "Type of ID-block that can be used."); RNA_def_property_update(prop, 0, "rna_DriverTarget_update_data"); @@ -705,44 +732,93 @@ static void rna_def_drivertarget(BlenderRNA *brna) /* Target Properties - Property to Drive */ prop= RNA_def_property(srna, "data_path", PROP_STRING, PROP_NONE); RNA_def_property_string_funcs(prop, "rna_DriverTarget_RnaPath_get", "rna_DriverTarget_RnaPath_length", "rna_DriverTarget_RnaPath_set"); - RNA_def_property_ui_text(prop, "Data Path", "RNA Path (from Object) to property used"); + RNA_def_property_ui_text(prop, "Data Path", "RNA Path (from ID-block) to property used."); RNA_def_property_update(prop, 0, "rna_DriverTarget_update_data"); - prop= RNA_def_property(srna, "array_index", PROP_INT, PROP_NONE); - RNA_def_property_ui_text(prop, "RNA Array Index", "Index to the specific property used (if applicable)"); + prop= RNA_def_property(srna, "bone_target", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "pchan_name"); + RNA_def_property_ui_text(prop, "Bone Name", "Name of PoseBone to use as target."); RNA_def_property_update(prop, 0, "rna_DriverTarget_update_data"); + + prop= RNA_def_property(srna, "transform_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "transChan"); + RNA_def_property_enum_items(prop, prop_trans_chan_items); + RNA_def_property_ui_text(prop, "Type", "Driver variable type."); + RNA_def_property_update(prop, 0, "rna_DriverTarget_update_data"); + + prop= RNA_def_property(srna, "use_local_space_transforms", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", DTAR_FLAG_LOCALSPACE); + RNA_def_property_ui_text(prop, "Local Space", "Use transforms in Local Space (as opposed to the worldspace default)."); + RNA_def_property_update(prop, 0, "rna_DriverTarget_update_data"); +} + +static void rna_def_drivervar(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + static EnumPropertyItem prop_type_items[] = { + {DVAR_TYPE_SINGLE_PROP, "SINGLE_PROP", 0, "Single Property", "Use the value from some RNA property (Default)"}, + {DVAR_TYPE_TRANSFORM_CHAN, "TRANSFORMS", 0, "Transform Channel", "Final transformation value of object or bone"}, + {DVAR_TYPE_ROT_DIFF, "ROTATION_DIFF", 0, "Rotational Difference", "Use the angle between two bones"}, + {DVAR_TYPE_LOC_DIFF, "LOC_DIFF", 0, "Distance", "Distance between two bones or objects"}, + {0, NULL, 0, NULL, NULL}}; + + + srna= RNA_def_struct(brna, "DriverVariable", NULL); + RNA_def_struct_sdna(srna, "DriverVar"); + RNA_def_struct_ui_text(srna, "Driver Variable", "Variable from some source/target for driver relationship."); + + /* Variable Name */ + prop= RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); + RNA_def_struct_name_property(srna, prop); + RNA_def_property_ui_text(prop, "Name", "Name to use in scripted expressions/functions. (No spaces or dots are allowed. Also, must not start with a symbol or digit)"); + RNA_def_property_update(prop, 0, "rna_DriverTarget_update_name"); // XXX + + /* Enums */ + prop= RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, prop_type_items); + RNA_def_property_enum_funcs(prop, NULL, "rna_DriverVariable_type_set", NULL); + RNA_def_property_ui_text(prop, "Type", "Driver variable type."); + RNA_def_property_update(prop, 0, "rna_ChannelDriver_update_data"); // XXX + + /* Targets */ + // TODO: for nicer api, only expose the relevant props via subclassing, instead of exposing the collection of targets + prop= RNA_def_property(srna, "targets", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "targets", "num_targets"); + RNA_def_property_struct_type(prop, "DriverTarget"); + RNA_def_property_ui_text(prop, "Targets", "Sources of input data for evaluating this variable."); } -/* channeldriver.targets.* */ -static void rna_def_channeldriver_targets(BlenderRNA *brna, PropertyRNA *cprop) +/* channeldriver.variables.* */ +static void rna_def_channeldriver_variables(BlenderRNA *brna, PropertyRNA *cprop) { StructRNA *srna; // PropertyRNA *prop; - + FunctionRNA *func; PropertyRNA *parm; - - RNA_def_property_srna(cprop, "ChannelDriverTargets"); - srna= RNA_def_struct(brna, "ChannelDriverTargets", NULL); + + RNA_def_property_srna(cprop, "ChannelDriverVariables"); + srna= RNA_def_struct(brna, "ChannelDriverVariables", NULL); RNA_def_struct_sdna(srna, "ChannelDriver"); - RNA_def_struct_ui_text(srna, "ChannelDriver Targets", "Collection of channel driver Targets."); - - - /* add target */ - func= RNA_def_function(srna, "new", "rna_Driver_new_target"); - RNA_def_function_ui_description(func, "Add a new target for the driver."); + RNA_def_struct_ui_text(srna, "ChannelDriver Variables", "Collection of channel driver Variables."); + + + /* add variable */ + func= RNA_def_function(srna, "new", "rna_Driver_new_variable"); + RNA_def_function_ui_description(func, "Add a new variable for the driver."); /* return type */ - parm= RNA_def_pointer(func, "target", "DriverTarget", "", "Newly created Driver Target."); + parm= RNA_def_pointer(func, "var", "DriverVariable", "", "Newly created Driver Variable."); RNA_def_function_return(func, parm); - /* remove target */ - func= RNA_def_function(srna, "remove", "rna_Driver_remove_target"); - RNA_def_function_ui_description(func, "Remove an existing target from the driver."); - /* target to remove*/ - parm= RNA_def_pointer(func, "target", "DriverTarget", "", "Target to remove from the driver."); + /* remove variable */ + func= RNA_def_function(srna, "remove", "rna_Driver_remove_variable"); + RNA_def_function_ui_description(func, "Remove an existing variable from the driver."); + /* target to remove */ + parm= RNA_def_pointer(func, "var", "DriverVariable", "", "Variable to remove from the driver."); RNA_def_property_flag(parm, PROP_REQUIRED); - } static void rna_def_channeldriver(BlenderRNA *brna) @@ -754,7 +830,8 @@ static void rna_def_channeldriver(BlenderRNA *brna) {DRIVER_TYPE_AVERAGE, "AVERAGE", 0, "Averaged Value", ""}, {DRIVER_TYPE_SUM, "SUM", 0, "Sum Values", ""}, {DRIVER_TYPE_PYTHON, "SCRIPTED", 0, "Scripted Expression", ""}, - {DRIVER_TYPE_ROTDIFF, "ROTDIFF", 0, "Rotational Difference", ""}, + {DRIVER_TYPE_MIN, "MIN", 0, "Minimum Value", ""}, + {DRIVER_TYPE_MAX, "MAX", 0, "Maximum Value", ""}, {0, NULL, 0, NULL, NULL}}; srna= RNA_def_struct(brna, "Driver", NULL); @@ -764,7 +841,7 @@ static void rna_def_channeldriver(BlenderRNA *brna) /* Enums */ prop= RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, prop_type_items); - RNA_def_property_ui_text(prop, "Type", "Driver types."); + RNA_def_property_ui_text(prop, "Type", "Driver type."); RNA_def_property_update(prop, 0, "rna_ChannelDriver_update_data"); /* String values */ @@ -773,11 +850,11 @@ static void rna_def_channeldriver(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_ChannelDriver_update_expr"); /* Collections */ - prop= RNA_def_property(srna, "targets", PROP_COLLECTION, PROP_NONE); - RNA_def_property_collection_sdna(prop, NULL, "targets", NULL); - RNA_def_property_struct_type(prop, "DriverTarget"); - RNA_def_property_ui_text(prop, "Target Variables", "Properties acting as targets for this driver."); - rna_def_channeldriver_targets(brna, prop); + prop= RNA_def_property(srna, "variables", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "variables", NULL); + RNA_def_property_struct_type(prop, "DriverVariable"); + RNA_def_property_ui_text(prop, "Variables", "Properties acting as inputs for this driver."); + rna_def_channeldriver_variables(brna, prop); /* Functions */ RNA_api_drivers(srna); @@ -933,6 +1010,7 @@ void RNA_def_fcurve(BlenderRNA *brna) rna_def_fpoint(brna); rna_def_drivertarget(brna); + rna_def_drivervar(brna); rna_def_channeldriver(brna); rna_def_fmodifier(brna); diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c index 129fad4e98c..30591efc481 100644 --- a/source/blender/makesrna/intern/rna_gpencil.c +++ b/source/blender/makesrna/intern/rna_gpencil.c @@ -199,6 +199,10 @@ static void rna_def_gpencil_layer(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_LOCKED); RNA_def_property_ui_text(prop, "Locked", "Layer is protected from further editing and/or frame changes."); + prop= RNA_def_property(srna, "frame_lock", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_FRAMELOCK); + RNA_def_property_ui_text(prop, "Frame Locked", "Current frame displayed by layer cannot be changed."); + prop= RNA_def_property(srna, "active", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_ACTIVE); RNA_def_property_boolean_funcs(prop, NULL, "rna_GPencilLayer_active_set"); @@ -220,6 +224,13 @@ static void rna_def_gpencil_data(BlenderRNA *brna) StructRNA *srna; PropertyRNA *prop; + static EnumPropertyItem draw_mode_items[] = { + {GP_DATA_VIEWALIGN, "CURSOR", 0, "Cursor", ""}, + {0, "VIEW", 0, "View", ""}, /* weired, GP_DATA_VIEWALIGN is inverted */ + {GP_DATA_VIEWALIGN|GP_DATA_DEPTH_VIEW, "SURFACE", 0, "Surface", ""}, + {GP_DATA_VIEWALIGN|GP_DATA_DEPTH_STROKE, "STROKE", 0, "Stroke", ""}, + {0, NULL, 0, NULL, NULL}}; + srna= RNA_def_struct(brna, "GreasePencil", "ID"); RNA_def_struct_sdna(srna, "bGPdata"); RNA_def_struct_ui_text(srna, "Grease Pencil", "Freehand annotation sketchbook."); @@ -232,9 +243,16 @@ static void rna_def_gpencil_data(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Layers", "Similar to layers in Photoshop."); /* Flags */ - prop= RNA_def_property(srna, "view_space_draw", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", GP_DATA_VIEWALIGN); - RNA_def_property_ui_text(prop, "Stick to View", "Newly drawn strokes get added in view space (i.e. sketches stick to data when view is manipulated)."); + prop= RNA_def_property(srna, "draw_mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag"); + RNA_def_property_enum_items(prop, draw_mode_items); + RNA_def_property_ui_text(prop, "Draw Mode", ""); + + prop= RNA_def_property(srna, "use_stroke_endpoints", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_DATA_DEPTH_STROKE_ENDPOINTS); + RNA_def_property_ui_text(prop, "Only Endpoints", "When snapping the stroke to existing lines, only use the first and last parts of the line."); + + } /* --- */ diff --git a/source/blender/makesrna/intern/rna_image.c b/source/blender/makesrna/intern/rna_image.c index e0d8a6950de..c4d7e772c58 100644 --- a/source/blender/makesrna/intern/rna_image.c +++ b/source/blender/makesrna/intern/rna_image.c @@ -153,6 +153,26 @@ static int rna_Image_has_data_get(PointerRNA *ptr) return 0; } +static void rna_Image_size_get(PointerRNA *ptr,int *values) +{ + Image *im= (Image*)ptr->data; + ImBuf *ibuf; + void *lock; + + ibuf = BKE_image_acquire_ibuf(im, NULL , &lock); + if (ibuf) { + values[0]= ibuf->x; + values[1]= ibuf->y; + } + else { + values[0]= 0; + values[1]= 0; + } + + BKE_image_release_ibuf(im, lock); +} + + static int rna_Image_depth_get(PointerRNA *ptr) { Image *im= (Image*)ptr->data; @@ -401,6 +421,10 @@ static void rna_def_image(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Depth", "Image bit depth."); RNA_def_property_clear_flag(prop, PROP_EDITABLE); + prop= RNA_def_int_vector(srna, "size" , 2 , NULL , 0, 0, "Size" , "Width and height in pixels, zero when image data cant be loaded." , 0 , 0); + RNA_def_property_int_funcs(prop, "rna_Image_size_get" , NULL, NULL); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_api_image(srna); } diff --git a/source/blender/makesrna/intern/rna_image_api.c b/source/blender/makesrna/intern/rna_image_api.c index 2bb7905fc03..34e2fc06ad7 100644 --- a/source/blender/makesrna/intern/rna_image_api.c +++ b/source/blender/makesrna/intern/rna_image_api.c @@ -63,6 +63,35 @@ static char *rna_Image_get_export_path(Image *image, char *dest_dir, int rel) return path; } +static void rna_Image_save(Image *image, bContext *C, ReportList *reports, char *path, Scene *scene) +{ + ImBuf *ibuf; + + if (scene == NULL) { + scene = CTX_data_scene(C); + } + + if (scene) { + ImageUser iuser; + void *lock; + + iuser.scene = scene; + iuser.ok = 1; + + ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock); + + if (ibuf == NULL) { + BKE_reportf(reports, RPT_ERROR, "Couldn't acquire buffer from image"); + } + + if (!BKE_write_ibuf(NULL, ibuf, path, scene->r.imtype, scene->r.subimtype, scene->r.quality)) { + BKE_reportf(reports, RPT_ERROR, "Couldn't write image: %s", path); + } + } else { + BKE_reportf(reports, RPT_ERROR, "Scene not in context, couldn't get save parameters"); + } +} + char *rna_Image_get_abs_filename(Image *image, bContext *C) { char *filename= MEM_callocN(FILE_MAX, "Image.get_abs_filename()"); @@ -95,6 +124,13 @@ void RNA_api_image(StructRNA *srna) RNA_def_function_flag(func, FUNC_USE_CONTEXT); parm= RNA_def_string_file_path(func, "abs_filename", NULL, 0, "", "Image/movie absolute filename."); RNA_def_function_return(func, parm); + + func= RNA_def_function(srna, "save", "rna_Image_save"); + RNA_def_function_ui_description(func, "Save image to a specific path."); + RNA_def_function_flag(func, FUNC_USE_CONTEXT|FUNC_USE_REPORTS); + parm= RNA_def_string(func, "path", "", 0, "", "Save path."); + RNA_def_property_flag(parm, PROP_REQUIRED); + parm= RNA_def_pointer(func, "scene", "Scene", "", "Scene to take image parameters from."); } #endif diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h index 5bb3c82395d..3d18804036a 100644 --- a/source/blender/makesrna/intern/rna_internal.h +++ b/source/blender/makesrna/intern/rna_internal.h @@ -118,6 +118,7 @@ extern BlenderRNA BLENDER_RNA; void RNA_def_ID(struct BlenderRNA *brna); void RNA_def_action(struct BlenderRNA *brna); void RNA_def_animation(struct BlenderRNA *brna); +void RNA_def_animviz(struct BlenderRNA *brna); void RNA_def_armature(struct BlenderRNA *brna); void RNA_def_actuator(struct BlenderRNA *brna); void RNA_def_boid(struct BlenderRNA *brna); @@ -175,6 +176,9 @@ void RNA_def_world(struct BlenderRNA *brna); void rna_def_animdata_common(struct StructRNA *srna); +void rna_def_animviz_common(struct StructRNA *srna); +void rna_def_motionpath_common(struct StructRNA *srna); + void rna_def_texmat_common(struct StructRNA *srna, const char *texspace_editable); void rna_def_mtex_common(struct StructRNA *srna, const char *begin, const char *activeget, const char *activeset, const char *structname, const char *update); void rna_def_render_layer_common(struct StructRNA *srna, int scene); @@ -211,6 +215,7 @@ void RNA_api_armature_edit_bone(StructRNA *srna); void RNA_api_drivers(StructRNA *srna); void RNA_api_image(struct StructRNA *srna); void RNA_api_operator(struct StructRNA *srna); +void RNA_api_macro(struct StructRNA *srna); void RNA_api_keyconfig(struct StructRNA *srna); void RNA_api_keyingset(struct StructRNA *srna); void RNA_api_keymap(struct StructRNA *srna); @@ -220,11 +225,39 @@ void RNA_api_material(StructRNA *srna); void RNA_api_mesh(struct StructRNA *srna); void RNA_api_object(struct StructRNA *srna); void RNA_api_pose_channel(struct StructRNA *srna); -void RNA_api_scene(struct StructRNA *srna); +void RNA_api_scene(struct StructRNA *srna); +void RNA_api_scene_render(struct StructRNA *srna); void RNA_api_text(struct StructRNA *srna); void RNA_api_ui_layout(struct StructRNA *srna); void RNA_api_wm(struct StructRNA *srna); +/* main collection functions */ +void RNA_def_main_cameras(BlenderRNA *brna, PropertyRNA *cprop); +void RNA_def_main_scenes(BlenderRNA *brna, PropertyRNA *cprop); +void RNA_def_main_objects(BlenderRNA *brna, PropertyRNA *cprop); +void RNA_def_main_materials(BlenderRNA *brna, PropertyRNA *cprop); +void RNA_def_main_node_groups(BlenderRNA *brna, PropertyRNA *cprop); +void RNA_def_main_meshes(BlenderRNA *brna, PropertyRNA *cprop); +void RNA_def_main_lamps(BlenderRNA *brna, PropertyRNA *cprop); +void RNA_def_main_libraries(BlenderRNA *brna, PropertyRNA *cprop); +void RNA_def_main_screens(BlenderRNA *brna, PropertyRNA *cprop); +void RNA_def_main_window_managers(BlenderRNA *brna, PropertyRNA *cprop); +void RNA_def_main_images(BlenderRNA *brna, PropertyRNA *cprop); +void RNA_def_main_lattices(BlenderRNA *brna, PropertyRNA *cprop); +void RNA_def_main_curves(BlenderRNA *brna, PropertyRNA *cprop); +void RNA_def_main_metaballs(BlenderRNA *brna, PropertyRNA *cprop); +void RNA_def_main_vfonts(BlenderRNA *brna, PropertyRNA *cprop); +void RNA_def_main_textures(BlenderRNA *brna, PropertyRNA *cprop); +void RNA_def_main_brushes(BlenderRNA *brna, PropertyRNA *cprop); +void RNA_def_main_worlds(BlenderRNA *brna, PropertyRNA *cprop); +void RNA_def_main_groups(BlenderRNA *brna, PropertyRNA *cprop); +void RNA_def_main_texts(BlenderRNA *brna, PropertyRNA *cprop); +void RNA_def_main_sounds(BlenderRNA *brna, PropertyRNA *cprop); +void RNA_def_main_armatures(BlenderRNA *brna, PropertyRNA *cprop); +void RNA_def_main_actions(BlenderRNA *brna, PropertyRNA *cprop); +void RNA_def_main_particles(BlenderRNA *brna, PropertyRNA *cprop); +void RNA_def_main_gpencil(BlenderRNA *brna, PropertyRNA *cprop); + /* ID Properties */ extern StringPropertyRNA rna_IDProperty_string; diff --git a/source/blender/makesrna/intern/rna_internal_types.h b/source/blender/makesrna/intern/rna_internal_types.h index 4f05e6132f7..bef568bfa7d 100644 --- a/source/blender/makesrna/intern/rna_internal_types.h +++ b/source/blender/makesrna/intern/rna_internal_types.h @@ -118,8 +118,9 @@ struct FunctionRNA { /* callback to execute the function */ CallFunc call; - /* parameter for the return value */ - PropertyRNA *ret; + /* parameter for the return value + * note: this is only the C return value, rna functions can have multiple return values */ + PropertyRNA *c_ret; }; struct PropertyRNA { diff --git a/source/blender/makesrna/intern/rna_key.c b/source/blender/makesrna/intern/rna_key.c index 9e560a50af0..6ff961070b9 100644 --- a/source/blender/makesrna/intern/rna_key.c +++ b/source/blender/makesrna/intern/rna_key.c @@ -283,7 +283,13 @@ static PointerRNA rna_ShapeKey_data_get(CollectionPropertyIterator *iter) static char *rna_ShapeKey_path(PointerRNA *ptr) { - return BLI_sprintfN("keys[\"%s\"]", ((KeyBlock*)ptr->data)->name); + KeyBlock *kb= (KeyBlock *)ptr->data; + ID *id= ptr->id.data; + + if ((id) && (GS(id->name) != ID_KE)) + return BLI_sprintfN("shape_keys.keys[\"%s\"]", kb->name); + else + return BLI_sprintfN("keys[\"%s\"]", kb->name); } static void rna_Key_update_data(Main *bmain, Scene *scene, PointerRNA *ptr) diff --git a/source/blender/makesrna/intern/rna_main.c b/source/blender/makesrna/intern/rna_main.c index 82988a06af9..4b5a404b268 100644 --- a/source/blender/makesrna/intern/rna_main.c +++ b/source/blender/makesrna/intern/rna_main.c @@ -235,40 +235,44 @@ static PointerRNA rna_Test_test_get(PointerRNA *ptr) #else +typedef void (*CollectionDefFunc)(struct BlenderRNA *brna, struct PropertyRNA *cprop); + void RNA_def_main(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; + CollectionDefFunc func; + + const char *lists[][6]= { + {"cameras", "Camera", "rna_Main_camera_begin", "Cameras", "Camera datablocks.", (char *)RNA_def_main_cameras}, + {"scenes", "Scene", "rna_Main_scene_begin", "Scenes", "Scene datablocks.", (char *)RNA_def_main_scenes}, + {"objects", "Object", "rna_Main_object_begin", "Objects", "Object datablocks.", (char *)RNA_def_main_objects}, + {"materials", "Material", "rna_Main_mat_begin", "Materials", "Material datablocks.", (char *)RNA_def_main_materials}, + {"node_groups", "NodeTree", "rna_Main_nodetree_begin", "Node Groups", "Node group datablocks.", (char *)RNA_def_main_node_groups}, + {"meshes", "Mesh", "rna_Main_mesh_begin", "Meshes", "Mesh datablocks.", (char *)RNA_def_main_meshes}, + {"lamps", "Lamp", "rna_Main_lamp_begin", "Lamps", "Lamp datablocks.", (char *)RNA_def_main_lamps}, + {"libraries", "Library", "rna_Main_library_begin", "Libraries", "Library datablocks.", (char *)RNA_def_main_libraries}, + {"screens", "Screen", "rna_Main_screen_begin", "Screens", "Screen datablocks.", (char *)RNA_def_main_screens}, + {"window_managers", "WindowManager", "rna_Main_wm_begin", "Window Managers", "Window manager datablocks.", (char *)RNA_def_main_window_managers}, + {"images", "Image", "rna_Main_image_begin", "Images", "Image datablocks.", (char *)RNA_def_main_images}, + {"lattices", "Lattice", "rna_Main_latt_begin", "Lattices", "Lattice datablocks.", (char *)RNA_def_main_lattices}, + {"curves", "Curve", "rna_Main_curve_begin", "Curves", "Curve datablocks.", (char *)RNA_def_main_curves} , + {"metaballs", "MetaBall", "rna_Main_mball_begin", "Metaballs", "Metaball datablocks.", (char *)RNA_def_main_metaballs}, + {"vfonts", "VectorFont", "rna_Main_vfont_begin", "Vector Fonts", "Vector font datablocks.", (char *)RNA_def_main_vfonts}, + {"textures", "Texture", "rna_Main_tex_begin", "Textures", "Texture datablocks.", (char *)RNA_def_main_textures}, + {"brushes", "Brush", "rna_Main_brush_begin", "Brushes", "Brush datablocks.", (char *)RNA_def_main_brushes}, + {"worlds", "World", "rna_Main_world_begin", "Worlds", "World datablocks.", (char *)RNA_def_main_worlds}, + {"groups", "Group", "rna_Main_group_begin", "Groups", "Group datablocks.", (char *)RNA_def_main_groups}, +/* {"keys", "Key", "rna_Main_key_begin", "Keys", "Key datablocks.", NULL}, */ + {"scripts", "ID", "rna_Main_script_begin", "Scripts", "Script datablocks (DEPRECATED).", (char *)NULL}, + {"texts", "Text", "rna_Main_text_begin", "Texts", "Text datablocks.", (char *)RNA_def_main_texts}, + {"sounds", "Sound", "rna_Main_sound_begin", "Sounds", "Sound datablocks.", (char *)RNA_def_main_sounds}, + {"armatures", "Armature", "rna_Main_armature_begin", "Armatures", "Armature datablocks.", (char *)RNA_def_main_armatures}, + {"actions", "Action", "rna_Main_action_begin", "Actions", "Action datablocks.", (char *)RNA_def_main_actions}, + {"particles", "ParticleSettings", "rna_Main_particle_begin", "Particles", "Particle datablocks.", (char *)RNA_def_main_particles}, + {"gpencil", "GreasePencil", "rna_Main_gpencil_begin", "Grease Pencil", "Grease Pencil datablocks.", (char *)RNA_def_main_gpencil}, + {NULL, NULL, NULL, NULL, NULL, NULL}}; - const char *lists[][5]= { - {"cameras", "Camera", "rna_Main_camera_begin", "Cameras", "Camera datablocks."}, - {"scenes", "Scene", "rna_Main_scene_begin", "Scenes", "Scene datablocks."}, - {"objects", "Object", "rna_Main_object_begin", "Objects", "Object datablocks."}, - {"materials", "Material", "rna_Main_mat_begin", "Materials", "Material datablocks."}, - {"nodegroups", "NodeTree", "rna_Main_nodetree_begin", "Node Groups", "Node group datablocks."}, - {"meshes", "Mesh", "rna_Main_mesh_begin", "Meshes", "Mesh datablocks."}, // "add_mesh", "remove_mesh" - {"lamps", "Lamp", "rna_Main_lamp_begin", "Lamps", "Lamp datablocks."}, - {"libraries", "Library", "rna_Main_library_begin", "Libraries", "Library datablocks."}, - {"screens", "Screen", "rna_Main_screen_begin", "Screens", "Screen datablocks."}, - {"windowmanagers", "WindowManager", "rna_Main_wm_begin", "Window Managers", "Window manager datablocks."}, - {"images", "Image", "rna_Main_image_begin", "Images", "Image datablocks."}, - {"lattices", "Lattice", "rna_Main_latt_begin", "Lattices", "Lattice datablocks."}, - {"curves", "Curve", "rna_Main_curve_begin", "Curves", "Curve datablocks."} , - {"metaballs", "MetaBall", "rna_Main_mball_begin", "Metaballs", "Metaball datablocks."}, - {"vfonts", "VectorFont", "rna_Main_vfont_begin", "Vector Fonts", "Vector font datablocks."}, - {"textures", "Texture", "rna_Main_tex_begin", "Textures", "Texture datablocks."}, - {"brushes", "Brush", "rna_Main_brush_begin", "Brushes", "Brush datablocks."}, - {"worlds", "World", "rna_Main_world_begin", "Worlds", "World datablocks."}, - {"groups", "Group", "rna_Main_group_begin", "Groups", "Group datablocks."}, -/* {"keys", "Key", "rna_Main_key_begin", "Keys", "Key datablocks."}, */ - {"scripts", "ID", "rna_Main_script_begin", "Scripts", "Script datablocks (DEPRECATED)."}, - {"texts", "Text", "rna_Main_text_begin", "Texts", "Text datablocks."}, - {"sounds", "Sound", "rna_Main_sound_begin", "Sounds", "Sound datablocks."}, - {"armatures", "Armature", "rna_Main_armature_begin", "Armatures", "Armature datablocks."}, - {"actions", "Action", "rna_Main_action_begin", "Actions", "Action datablocks."}, - {"particles", "ParticleSettings", "rna_Main_particle_begin", "Particles", "Particle datablocks."}, - {"gpencil", "GreasePencil", "rna_Main_gpencil_begin", "Grease Pencil", "Grease Pencil datablocks."}, - {NULL, NULL, NULL, NULL, NULL}}; int i; srna= RNA_def_struct(brna, "Main", NULL); @@ -287,6 +291,11 @@ void RNA_def_main(BlenderRNA *brna) RNA_def_property_struct_type(prop, lists[i][1]); RNA_def_property_collection_funcs(prop, lists[i][2], "rna_iterator_listbase_next", "rna_iterator_listbase_end", "rna_iterator_listbase_get", 0, 0, 0); RNA_def_property_ui_text(prop, lists[i][3], lists[i][4]); + + /* collection functions */ + func= (CollectionDefFunc *)lists[i][5]; + if(func) + func(brna, prop); } RNA_api_main(srna); diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c index 5069bbd6ae6..ecaf6f813da 100644 --- a/source/blender/makesrna/intern/rna_main_api.c +++ b/source/blender/makesrna/intern/rna_main_api.c @@ -43,108 +43,143 @@ #include "BKE_material.h" #include "BKE_image.h" #include "BKE_texture.h" +#include "BKE_scene.h" #include "DNA_armature_types.h" +#include "DNA_camera_types.h" #include "DNA_lamp_types.h" #include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_object_types.h" -static Mesh *rna_Main_add_mesh(Main *bmain, char *name) +static Tex *rna_Main_add_texture(Main *bmain, char *name) { - Mesh *me= add_mesh(name); - me->id.us--; - return me; + return add_texture(name); } -static void rna_Main_remove_mesh(Main *bmain, ReportList *reports, Mesh *me) +/* TODO: remove texture? */ + +static Image *rna_Main_add_image(Main *bmain, char *filename) { - if(me->id.us == 0) - free_libblock(&bmain->mesh, me); - else - BKE_report(reports, RPT_ERROR, "Mesh must have zero users to be removed."); - - /* XXX python now has invalid pointer? */ + return BKE_add_image_file(filename, 0); } -static void rna_Main_remove_armature(Main *bmain, ReportList *reports, bArmature *arm) +static Camera *rna_Main_cameras_new(bContext *C, char* name) { - if(arm->id.us == 0) - free_libblock(&bmain->armature, arm); + return add_camera(name); +} +static void rna_Main_cameras_remove(bContext *C, ReportList *reports, struct Camera *camera) +{ + Main *bmain= CTX_data_main(C); + if(camera->id.us == 0) + free_libblock(&bmain->camera, camera); else - BKE_report(reports, RPT_ERROR, "Armature must have zero users to be removed."); + BKE_reportf(reports, RPT_ERROR, "Camera \"%s\" must have zero users to be removed, found %d.", camera->id.name+2, camera->id.us); /* XXX python now has invalid pointer? */ } -static bArmature *rna_Main_add_armature(Main *bmain, char *name) +static Scene *rna_Main_scenes_new(bContext *C, char* name) { - bArmature *arm= add_armature(name); - arm->id.us--; - return arm; -} - -static Lamp *rna_Main_add_lamp(Main *bmain, char *name) -{ - Lamp *la= add_lamp(name); - la->id.us--; - return la; + return add_scene(name); } - -/* -static void rna_Main_remove_lamp(Main *bmain, ReportList *reports, Lamp *la) +static void rna_Main_scenes_remove(bContext *C, ReportList *reports, struct Scene *scene) { - if(la->id.us == 0) - free_libblock(&main->lamp, la); - else - BKE_report(reports, RPT_ERROR, "Lamp must have zero users to be removed."); + Main *bmain= CTX_data_main(C); + free_libblock(&bmain->scene, scene); } -*/ -static Object* rna_Main_add_object(Main *bmain, int type, char *name) +static Object *rna_Main_objects_new(bContext *C, char* name, int type) { Object *ob= add_only_object(type, name); ob->id.us--; return ob; } +static void rna_Main_objects_remove(bContext *C, ReportList *reports, struct Object *object) +{ + /* + NOTE: the following example shows when this function should _not_ be called -/* - NOTE: the following example shows when this function should _not_ be called + ob = bpy.data.add_object() + scene.add_object(ob) - ob = bpy.data.add_object() - scene.add_object(ob) + # ob is freed here + scene.remove_object(ob) - # ob is freed here - scene.remove_object(ob) + # don't do this since ob is already freed! + bpy.data.remove_object(ob) + */ + Main *bmain= CTX_data_main(C); + if(object->id.us == 0) + free_libblock(&bmain->object, object); + else + BKE_reportf(reports, RPT_ERROR, "Object \"%s\" must have zero users to be removed, found %d.", object->id.name+2, object->id.us); +} - # don't do this since ob is already freed! - bpy.data.remove_object(ob) -*/ -static void rna_Main_remove_object(Main *bmain, ReportList *reports, Object *ob) +static Material *rna_Main_materials_new(bContext *C, char* name) { - if(ob->id.us == 0) - free_libblock(&bmain->object, ob); + return add_material(name); +} +static void rna_Main_materials_remove(bContext *C, ReportList *reports, struct Material *material) +{ + Main *bmain= CTX_data_main(C); + if(material->id.us == 0) + free_libblock(&bmain->mat, material); else - BKE_report(reports, RPT_ERROR, "Object must have zero users to be removed."); + BKE_reportf(reports, RPT_ERROR, "Material \"%s\" must have zero users to be removed, found %d.", material->id.name+2, material->id.us); + + /* XXX python now has invalid pointer? */ } -static Material *rna_Main_add_material(Main *bmain, char *name) +static Mesh *rna_Main_meshes_new(bContext *C, char* name) { - return add_material(name); + Mesh *me= add_mesh(name); + me->id.us--; + return me; } +static void rna_Main_meshes_remove(bContext *C, ReportList *reports, Mesh *mesh) +{ + Main *bmain= CTX_data_main(C); + if(mesh->id.us == 0) + free_libblock(&bmain->mesh, mesh); + else + BKE_reportf(reports, RPT_ERROR, "Mesh \"%s\" must have zero users to be removed, found %d.", mesh->id.name+2, mesh->id.us); -/* TODO: remove material? */ + /* XXX python now has invalid pointer? */ +} -struct Tex *rna_Main_add_texture(Main *bmain, char *name) +static Lamp *rna_Main_lamps_new(bContext *C, char* name) { - return add_texture(name); + Lamp *lamp= add_lamp(name); + lamp->id.us--; + return lamp; } +static void rna_Main_lamps_remove(bContext *C, ReportList *reports, Lamp *lamp) +{ + Main *bmain= CTX_data_main(C); + if(lamp->id.us == 0) + free_libblock(&bmain->lamp, lamp); + else + BKE_reportf(reports, RPT_ERROR, "Lamp \"%s\" must have zero users to be removed, found %d.", lamp->id.name+2, lamp->id.us); -/* TODO: remove texture? */ + /* XXX python now has invalid pointer? */ +} -struct Image *rna_Main_add_image(Main *bmain, char *filename) +static bArmature *rna_Main_armatures_new(bContext *C, char* name) { - return BKE_add_image_file(filename, 0); + bArmature *arm= add_armature(name); + arm->id.us--; + return arm; +} +static void rna_Main_armatures_remove(bContext *C, ReportList *reports, bArmature *arm) +{ + Main *bmain= CTX_data_main(C); + if(arm->id.us == 0) + free_libblock(&bmain->armature, arm); + else + BKE_reportf(reports, RPT_ERROR, "Armature \"%s\" must have zero users to be removed, found %d.", arm->id.name+2, arm->id.us); + + /* XXX python now has invalid pointer? */ } #else @@ -154,73 +189,281 @@ void RNA_api_main(StructRNA *srna) FunctionRNA *func; PropertyRNA *parm; - func= RNA_def_function(srna, "add_object", "rna_Main_add_object"); - RNA_def_function_ui_description(func, "Add a new object."); - parm= RNA_def_enum(func, "type", object_type_items, 0, "", "Type of Object."); + func= RNA_def_function(srna, "add_texture", "rna_Main_add_texture"); + RNA_def_function_ui_description(func, "Add a new texture."); + parm= RNA_def_string(func, "name", "Tex", 0, "", "New name for the datablock."); /* optional */ + parm= RNA_def_pointer(func, "texture", "Texture", "", "New texture."); + RNA_def_function_return(func, parm); + + func= RNA_def_function(srna, "add_image", "rna_Main_add_image"); + RNA_def_function_ui_description(func, "Add a new image."); + parm= RNA_def_string(func, "filename", "", 0, "", "Filename to load image from."); + RNA_def_property_flag(parm, PROP_REQUIRED); + parm= RNA_def_pointer(func, "image", "Image", "", "New image."); + RNA_def_function_return(func, parm); + +} + +void RNA_def_main_cameras(BlenderRNA *brna, PropertyRNA *cprop) +{ + StructRNA *srna; + FunctionRNA *func; + PropertyRNA *parm; + + RNA_def_property_srna(cprop, "MainCameras"); + srna= RNA_def_struct(brna, "MainCameras", NULL); + RNA_def_struct_sdna(srna, "Camera"); + RNA_def_struct_ui_text(srna, "Main Cameras", "Collection of cameras."); + + func= RNA_def_function(srna, "new", "rna_Main_cameras_new"); + RNA_def_function_flag(func, FUNC_NO_SELF|FUNC_USE_CONTEXT); + RNA_def_function_ui_description(func, "Add a new camera to the main database"); + parm= RNA_def_string(func, "name", "Camera", 0, "", "New name for the datablock."); + RNA_def_property_flag(parm, PROP_REQUIRED); + /* return type */ + parm= RNA_def_pointer(func, "camera", "Camera", "", "New camera datablock."); + RNA_def_function_return(func, parm); + + func= RNA_def_function(srna, "remove", "rna_Main_cameras_remove"); + RNA_def_function_flag(func, FUNC_NO_SELF|FUNC_USE_CONTEXT|FUNC_USE_REPORTS); + RNA_def_function_ui_description(func, "Remove a camera from the current blendfile."); + parm= RNA_def_pointer(func, "camera", "Camera", "", "Camera to remove."); + RNA_def_property_flag(parm, PROP_REQUIRED); +} + +void RNA_def_main_scenes(BlenderRNA *brna, PropertyRNA *cprop) +{ + StructRNA *srna; + FunctionRNA *func; + PropertyRNA *parm; + + RNA_def_property_srna(cprop, "MainScenes"); + srna= RNA_def_struct(brna, "MainScenes", NULL); + RNA_def_struct_sdna(srna, "Scene"); + RNA_def_struct_ui_text(srna, "Main Scenes", "Collection of scenes."); + + func= RNA_def_function(srna, "new", "rna_Main_scenes_new"); + RNA_def_function_flag(func, FUNC_NO_SELF|FUNC_USE_CONTEXT); + RNA_def_function_ui_description(func, "Add a new scene to the main database"); + parm= RNA_def_string(func, "name", "Scene", 0, "", "New name for the datablock."); + RNA_def_property_flag(parm, PROP_REQUIRED); + /* return type */ + parm= RNA_def_pointer(func, "scene", "Scene", "", "New scene datablock."); + RNA_def_function_return(func, parm); + + func= RNA_def_function(srna, "remove", "rna_Main_scenes_remove"); + RNA_def_function_flag(func, FUNC_NO_SELF|FUNC_USE_CONTEXT|FUNC_USE_REPORTS); + parm= RNA_def_pointer(func, "scene", "Scene", "", "Scene to remove."); + RNA_def_property_flag(parm, PROP_REQUIRED); + RNA_def_function_ui_description(func, "Remove a scene from the current blendfile."); RNA_def_property_flag(parm, PROP_REQUIRED); +} + +void RNA_def_main_objects(BlenderRNA *brna, PropertyRNA *cprop) +{ + StructRNA *srna; + FunctionRNA *func; + PropertyRNA *parm; + + RNA_def_property_srna(cprop, "MainObjects"); + srna= RNA_def_struct(brna, "MainObjects", NULL); + RNA_def_struct_sdna(srna, "Object"); + RNA_def_struct_ui_text(srna, "Main Objects", "Collection of objects."); + + func= RNA_def_function(srna, "new", "rna_Main_objects_new"); + RNA_def_function_flag(func, FUNC_NO_SELF|FUNC_USE_CONTEXT); + RNA_def_function_ui_description(func, "Add a new object to the main database"); parm= RNA_def_string(func, "name", "Object", 0, "", "New name for the datablock."); RNA_def_property_flag(parm, PROP_REQUIRED); - parm= RNA_def_pointer(func, "object", "Object", "", "New object."); + parm= RNA_def_enum(func, "type", object_type_items, 0, "", "Type of Object."); + RNA_def_property_flag(parm, PROP_REQUIRED); + + /* return type */ + parm= RNA_def_pointer(func, "object", "Object", "", "New object datablock."); RNA_def_function_return(func, parm); - func= RNA_def_function(srna, "remove_object", "rna_Main_remove_object"); - RNA_def_function_flag(func, FUNC_USE_REPORTS); - RNA_def_function_ui_description(func, "Remove an object if it has zero users."); + func= RNA_def_function(srna, "remove", "rna_Main_objects_remove"); + RNA_def_function_flag(func, FUNC_NO_SELF|FUNC_USE_CONTEXT|FUNC_USE_REPORTS); parm= RNA_def_pointer(func, "object", "Object", "", "Object to remove."); RNA_def_property_flag(parm, PROP_REQUIRED); + RNA_def_function_ui_description(func, "Remove a object from the current blendfile."); +} - func= RNA_def_function(srna, "add_mesh", "rna_Main_add_mesh"); - RNA_def_function_ui_description(func, "Add a new mesh."); - parm= RNA_def_string(func, "name", "Mesh", 0, "", "New name for the datablock."); +void RNA_def_main_materials(BlenderRNA *brna, PropertyRNA *cprop) +{ + StructRNA *srna; + FunctionRNA *func; + PropertyRNA *parm; + + RNA_def_property_srna(cprop, "MainMaterials"); + srna= RNA_def_struct(brna, "MainMaterials", NULL); + RNA_def_struct_sdna(srna, "Material"); + RNA_def_struct_ui_text(srna, "Main Material", "Collection of materials."); + + func= RNA_def_function(srna, "new", "rna_Main_materials_new"); + RNA_def_function_flag(func, FUNC_NO_SELF|FUNC_USE_CONTEXT); + RNA_def_function_ui_description(func, "Add a new material to the main database"); + parm= RNA_def_string(func, "name", "Material", 0, "", "New name for the datablock."); RNA_def_property_flag(parm, PROP_REQUIRED); - parm= RNA_def_pointer(func, "mesh", "Mesh", "", "New mesh."); + /* return type */ + parm= RNA_def_pointer(func, "material", "Material", "", "New material datablock."); RNA_def_function_return(func, parm); - func= RNA_def_function(srna, "remove_mesh", "rna_Main_remove_mesh"); - RNA_def_function_flag(func, FUNC_USE_REPORTS); - RNA_def_function_ui_description(func, "Remove a mesh if it has zero users."); - parm= RNA_def_pointer(func, "mesh", "Mesh", "", "Mesh to remove."); + func= RNA_def_function(srna, "remove", "rna_Main_materials_remove"); + RNA_def_function_flag(func, FUNC_NO_SELF|FUNC_USE_CONTEXT|FUNC_USE_REPORTS); + RNA_def_function_ui_description(func, "Remove a material from the current blendfile."); + parm= RNA_def_pointer(func, "material", "Material", "", "Material to remove."); RNA_def_property_flag(parm, PROP_REQUIRED); +} +void RNA_def_main_node_groups(BlenderRNA *brna, PropertyRNA *cprop) +{ - func= RNA_def_function(srna, "add_armature", "rna_Main_add_armature"); - RNA_def_function_ui_description(func, "Add a new armature."); - parm= RNA_def_string(func, "name", "Armature", 0, "", "New name for the datablock."); +} +void RNA_def_main_meshes(BlenderRNA *brna, PropertyRNA *cprop) +{ + StructRNA *srna; + FunctionRNA *func; + PropertyRNA *parm; + + RNA_def_property_srna(cprop, "MainMeshes"); + srna= RNA_def_struct(brna, "MainMeshes", NULL); + RNA_def_struct_sdna(srna, "Mesh"); + RNA_def_struct_ui_text(srna, "Main Meshes", "Collection of meshes."); + + func= RNA_def_function(srna, "new", "rna_Main_meshes_new"); + RNA_def_function_flag(func, FUNC_NO_SELF|FUNC_USE_CONTEXT); + RNA_def_function_ui_description(func, "Add a new mesh to the main database"); + parm= RNA_def_string(func, "name", "Mesh", 0, "", "New name for the datablock."); RNA_def_property_flag(parm, PROP_REQUIRED); - parm= RNA_def_pointer(func, "armature", "Armature", "", "New armature."); + /* return type */ + parm= RNA_def_pointer(func, "mesh", "Mesh", "", "New mesh datablock."); RNA_def_function_return(func, parm); - func= RNA_def_function(srna, "remove_armature", "rna_Main_remove_armature"); - RNA_def_function_flag(func, FUNC_USE_REPORTS); - RNA_def_function_ui_description(func, "Remove an armature if it has zero users."); - parm= RNA_def_pointer(func, "armature", "Armature", "", "Armature to remove."); + func= RNA_def_function(srna, "remove", "rna_Main_meshes_remove"); + RNA_def_function_flag(func, FUNC_NO_SELF|FUNC_USE_CONTEXT|FUNC_USE_REPORTS); + RNA_def_function_ui_description(func, "Remove a mesh from the current blendfile."); + parm= RNA_def_pointer(func, "mesh", "Mesh", "", "Mesh to remove."); RNA_def_property_flag(parm, PROP_REQUIRED); +} +void RNA_def_main_lamps(BlenderRNA *brna, PropertyRNA *cprop) +{ + StructRNA *srna; + FunctionRNA *func; + PropertyRNA *parm; + + RNA_def_property_srna(cprop, "MainLamps"); + srna= RNA_def_struct(brna, "MainLamps", NULL); + RNA_def_struct_sdna(srna, "Lamp"); + RNA_def_struct_ui_text(srna, "Main Lamps", "Collection of lamps."); - func= RNA_def_function(srna, "add_lamp", "rna_Main_add_lamp"); - RNA_def_function_ui_description(func, "Add a new lamp."); + func= RNA_def_function(srna, "new", "rna_Main_lamps_new"); + RNA_def_function_flag(func, FUNC_NO_SELF|FUNC_USE_CONTEXT); + RNA_def_function_ui_description(func, "Add a new lamp to the main database"); parm= RNA_def_string(func, "name", "Lamp", 0, "", "New name for the datablock."); RNA_def_property_flag(parm, PROP_REQUIRED); - parm= RNA_def_pointer(func, "mesh", "Lamp", "", "New lamp."); + /* return type */ + parm= RNA_def_pointer(func, "lamp", "Lamp", "", "New lamp datablock."); RNA_def_function_return(func, parm); - func= RNA_def_function(srna, "add_material", "rna_Main_add_material"); - RNA_def_function_ui_description(func, "Add a new material."); - parm= RNA_def_string(func, "name", "Material", 0, "", "New name for the datablock."); /* optional */ - parm= RNA_def_pointer(func, "material", "Material", "", "New material."); - RNA_def_function_return(func, parm); + func= RNA_def_function(srna, "remove", "rna_Main_lamps_remove"); + RNA_def_function_flag(func, FUNC_NO_SELF|FUNC_USE_CONTEXT|FUNC_USE_REPORTS); + RNA_def_function_ui_description(func, "Remove a lamp from the current blendfile."); + parm= RNA_def_pointer(func, "lamp", "Lamp", "", "Lamp to remove."); + RNA_def_property_flag(parm, PROP_REQUIRED); +} +void RNA_def_main_libraries(BlenderRNA *brna, PropertyRNA *cprop) +{ - func= RNA_def_function(srna, "add_texture", "rna_Main_add_texture"); - RNA_def_function_ui_description(func, "Add a new texture."); - parm= RNA_def_string(func, "name", "Tex", 0, "", "New name for the datablock."); /* optional */ - parm= RNA_def_pointer(func, "texture", "Texture", "", "New texture."); - RNA_def_function_return(func, parm); +} +void RNA_def_main_screens(BlenderRNA *brna, PropertyRNA *cprop) +{ - func= RNA_def_function(srna, "add_image", "rna_Main_add_image"); - RNA_def_function_ui_description(func, "Add a new image."); - parm= RNA_def_string(func, "filename", "", 0, "", "Filename to load image from."); +} +void RNA_def_main_window_managers(BlenderRNA *brna, PropertyRNA *cprop) +{ + +} +void RNA_def_main_images(BlenderRNA *brna, PropertyRNA *cprop) +{ + +} +void RNA_def_main_lattices(BlenderRNA *brna, PropertyRNA *cprop) +{ + +} +void RNA_def_main_curves(BlenderRNA *brna, PropertyRNA *cprop) +{ + +} +void RNA_def_main_metaballs(BlenderRNA *brna, PropertyRNA *cprop) +{ + +} +void RNA_def_main_vfonts(BlenderRNA *brna, PropertyRNA *cprop) +{ + +} +void RNA_def_main_textures(BlenderRNA *brna, PropertyRNA *cprop) +{ + +} +void RNA_def_main_brushes(BlenderRNA *brna, PropertyRNA *cprop) +{ + +} +void RNA_def_main_worlds(BlenderRNA *brna, PropertyRNA *cprop) +{ + +} +void RNA_def_main_groups(BlenderRNA *brna, PropertyRNA *cprop) +{ + +} +void RNA_def_main_texts(BlenderRNA *brna, PropertyRNA *cprop) +{ + +} +void RNA_def_main_sounds(BlenderRNA *brna, PropertyRNA *cprop) +{ + +} +void RNA_def_main_armatures(BlenderRNA *brna, PropertyRNA *cprop) +{ + StructRNA *srna; + FunctionRNA *func; + PropertyRNA *parm; + + RNA_def_property_srna(cprop, "MainArmatures"); + srna= RNA_def_struct(brna, "MainArmatures", NULL); + RNA_def_struct_sdna(srna, "Armature"); + RNA_def_struct_ui_text(srna, "Main Armatures", "Collection of armatures."); + + func= RNA_def_function(srna, "new", "rna_Main_armatures_new"); + RNA_def_function_flag(func, FUNC_NO_SELF|FUNC_USE_CONTEXT); + RNA_def_function_ui_description(func, "Add a new armature to the main database"); + parm= RNA_def_string(func, "name", "Armature", 0, "", "New name for the datablock."); RNA_def_property_flag(parm, PROP_REQUIRED); - parm= RNA_def_pointer(func, "image", "Image", "", "New image."); + /* return type */ + parm= RNA_def_pointer(func, "armature", "Armature", "", "New armature datablock."); RNA_def_function_return(func, parm); + func= RNA_def_function(srna, "remove", "rna_Main_armatures_remove"); + RNA_def_function_flag(func, FUNC_NO_SELF|FUNC_USE_CONTEXT|FUNC_USE_REPORTS); + RNA_def_function_ui_description(func, "Remove a armature from the current blendfile."); + parm= RNA_def_pointer(func, "armature", "Armature", "", "Armature to remove."); + RNA_def_property_flag(parm, PROP_REQUIRED); +} +void RNA_def_main_actions(BlenderRNA *brna, PropertyRNA *cprop) +{ + +} +void RNA_def_main_particles(BlenderRNA *brna, PropertyRNA *cprop) +{ + +} +void RNA_def_main_gpencil(BlenderRNA *brna, PropertyRNA *cprop) +{ + } #endif diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c index a5c1d8d5f57..b69e5130c0f 100644 --- a/source/blender/makesrna/intern/rna_material.c +++ b/source/blender/makesrna/intern/rna_material.c @@ -1023,10 +1023,11 @@ static void rna_def_material_volume(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Diffusion", "Diffusion factor, the strength of the blurring effect"); RNA_def_property_update(prop, 0, "rna_Material_update"); - prop= RNA_def_property(srna, "ms_spread", PROP_INT, PROP_NONE); - RNA_def_property_int_sdna(prop, NULL, "ms_steps"); - RNA_def_property_range(prop, 0, 1024); - RNA_def_property_ui_text(prop, "Spread", "Simulation steps, the effective distance over which the light is diffused"); + prop= RNA_def_property(srna, "ms_spread", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "ms_spread"); + RNA_def_property_range(prop, 0, FLT_MAX); + RNA_def_property_ui_range(prop, 0.0f, 1.0f, 1, 3); + RNA_def_property_ui_text(prop, "Spread", "Proportional distance over which the light is diffused"); RNA_def_property_update(prop, 0, "rna_Material_update"); prop= RNA_def_property(srna, "ms_intensity", PROP_FLOAT, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c index 528544d09dd..9f317ec6be1 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -75,10 +75,17 @@ void rna_Mesh_update_draw(Main *bmain, Scene *scene, PointerRNA *ptr) static void rna_MeshVertex_normal_get(PointerRNA *ptr, float *value) { MVert *mvert= (MVert*)ptr->data; + normal_short_to_float_v3(value, mvert->no); +} + +static void rna_MeshVertex_normal_set(PointerRNA *ptr, const float *value) +{ + MVert *mvert= (MVert*)ptr->data; + float no[3]; - value[0]= mvert->no[0]/32767.0f; - value[1]= mvert->no[1]/32767.0f; - value[2]= mvert->no[2]/32767.0f; + copy_v3_v3(no, value); + normalize_v3(no); + normal_float_to_short_v3(mvert->no, no); } static float rna_MeshVertex_bevel_weight_get(PointerRNA *ptr) @@ -1027,9 +1034,8 @@ static void rna_def_mvert(BlenderRNA *brna) prop= RNA_def_property(srna, "normal", PROP_FLOAT, PROP_DIRECTION); RNA_def_property_float_sdna(prop, NULL, "no"); - RNA_def_property_float_funcs(prop, "rna_MeshVertex_normal_get", NULL, NULL); + RNA_def_property_float_funcs(prop, "rna_MeshVertex_normal_get", "rna_MeshVertex_normal_set", NULL); RNA_def_property_ui_text(prop, "Normal", "Vertex Normal"); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); prop= RNA_def_property(srna, "selected", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SELECT); @@ -1352,6 +1358,12 @@ static void rna_def_mtface(BlenderRNA *brna) RNA_def_property_float_funcs(prop, "rna_MeshTextureFace_uv_get", "rna_MeshTextureFace_uv_set", NULL); RNA_def_property_ui_text(prop, "UV", ""); RNA_def_property_update(prop, 0, "rna_Mesh_update_data"); + + prop= RNA_def_property(srna, "uv_raw", PROP_FLOAT, PROP_NONE); + RNA_def_property_multi_array(prop, 2, uv_dim); + RNA_def_property_float_sdna(prop, NULL, "uv"); + RNA_def_property_ui_text(prop, "UV", "Fixed size UV coordinates array"); + } static void rna_def_msticky(BlenderRNA *brna) diff --git a/source/blender/makesrna/intern/rna_mesh_api.c b/source/blender/makesrna/intern/rna_mesh_api.c index 52ff98f66f0..4fba65b4db8 100644 --- a/source/blender/makesrna/intern/rna_mesh_api.c +++ b/source/blender/makesrna/intern/rna_mesh_api.c @@ -43,6 +43,11 @@ static void rna_Mesh_uv_texture_add(struct Mesh *me, struct bContext *C) ED_mesh_uv_texture_add(C, NULL, NULL, me); } +static void rna_Mesh_vertex_color_add(struct Mesh *me, struct bContext *C) +{ + ED_mesh_color_add(C, NULL, NULL, me); +} + #else void RNA_api_mesh(StructRNA *srna) @@ -68,6 +73,10 @@ void RNA_api_mesh(StructRNA *srna) RNA_def_function_flag(func, FUNC_USE_CONTEXT); RNA_def_function_ui_description(func, "Add a UV texture layer to Mesh."); + func= RNA_def_function(srna, "add_vertex_color", "rna_Mesh_vertex_color_add"); + RNA_def_function_flag(func, FUNC_USE_CONTEXT); + RNA_def_function_ui_description(func, "Add a vertex color layer to Mesh."); + func= RNA_def_function(srna, "calc_normals", "ED_mesh_calc_normals"); RNA_def_function_ui_description(func, "Calculate vertex normals."); @@ -79,6 +88,8 @@ void RNA_api_mesh(StructRNA *srna) RNA_def_function_ui_description(func, "Add a new material to Mesh."); parm= RNA_def_pointer(func, "material", "Material", "", "Material to add."); RNA_def_property_flag(parm, PROP_REQUIRED); + + } #endif diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index d1e73d6add3..9922f099cd5 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -1077,12 +1077,6 @@ static void def_cmp_render_layers(StructRNA *srna) RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_Node_scene_layer_itemf"); RNA_def_property_ui_text(prop, "Layer", ""); RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_update"); - - /* TODO: comments indicate this might be a hack */ - prop = RNA_def_property(srna, "re_render", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "custom2", 1); - RNA_def_property_ui_text(prop, "Re-render", ""); - RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_update"); } static void def_cmp_output_file(StructRNA *srna) diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index a670fb244f6..a1109e01d50 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -930,7 +930,7 @@ static PointerRNA rna_Object_active_shape_key_get(PointerRNA *ptr) return PointerRNA_NULL; kb= BLI_findlink(&key->block, ob->shapenr-1); - RNA_pointer_create(&key->id, &RNA_ShapeKey, kb, &keyptr); + RNA_pointer_create((ID *)ob->data, &RNA_ShapeKey, kb, &keyptr); return keyptr; } @@ -1559,7 +1559,7 @@ static void rna_def_object(BlenderRNA *brna) * having a single one is better for Keyframing and other property-management situations... */ prop= RNA_def_property(srna, "rotation_axis_angle", PROP_FLOAT, PROP_AXISANGLE); - RNA_def_property_array(prop, 4); // TODO: maybe we'll need to define the 'default value' getter too... + RNA_def_property_array(prop, 4); RNA_def_property_float_funcs(prop, "rna_Object_rotation_axis_angle_get", "rna_Object_rotation_axis_angle_set", NULL); RNA_def_property_editable_array_func(prop, "rna_Object_rotation_4d_editable"); RNA_def_property_float_array_default(prop, default_axisAngle); @@ -1771,6 +1771,9 @@ static void rna_def_object(BlenderRNA *brna) /* anim */ rna_def_animdata_common(srna); + rna_def_animviz_common(srna); + rna_def_motionpath_common(srna); + /* duplicates */ prop= RNA_def_property(srna, "track_override_parent", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "transflag", OB_POWERTRACK); @@ -1788,18 +1791,18 @@ static void rna_def_object(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Dupli Type", "If not None, object duplication method to use."); RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, "rna_Object_dependency_update"); - prop= RNA_def_property(srna, "dupli_frames_no_speed", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "transflag", OB_DUPLINOSPEED); - RNA_def_property_ui_text(prop, "Dupli Frames No Speed", "Set dupliframes to still, regardless of frame."); + prop= RNA_def_property(srna, "use_dupli_frames_speed", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "transflag", OB_DUPLINOSPEED); + RNA_def_property_ui_text(prop, "Dupli Frames Speed", "Set dupliframes to use the frame."); // TODO, better descriptio! RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, "rna_Object_update"); - prop= RNA_def_property(srna, "dupli_verts_rotation", PROP_BOOLEAN, PROP_NONE); + prop= RNA_def_property(srna, "use_dupli_verts_rotation", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "transflag", OB_DUPLIROT); RNA_def_property_ui_text(prop, "Dupli Verts Rotation", "Rotate dupli according to vertex normal."); RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, NULL); - prop= RNA_def_property(srna, "dupli_faces_inherit_scale", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "transflag", OB_DUPLIROT); + prop= RNA_def_property(srna, "use_dupli_faces_scale", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "transflag", OB_DUPLIFACES_SCALE); RNA_def_property_ui_text(prop, "Dupli Faces Inherit Scale", "Scale dupli based on face size."); RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, "rna_Object_update"); diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c index 481e92d1ac9..8379ae7995d 100644 --- a/source/blender/makesrna/intern/rna_object_api.c +++ b/source/blender/makesrna/intern/rna_object_api.c @@ -49,6 +49,7 @@ #include "BKE_object.h" #include "BKE_mesh.h" #include "BKE_DerivedMesh.h" +#include "BKE_bvhutils.h" #include "BKE_customdata.h" #include "BKE_anim.h" @@ -309,19 +310,23 @@ static Object *rna_Object_find_armature(Object *ob) return ob_arm; } -static KeyBlock *rna_Object_add_shape_key(Object *ob, bContext *C, ReportList *reports, char *name, int from_mix) +static PointerRNA rna_Object_add_shape_key(Object *ob, bContext *C, ReportList *reports, char *name, int from_mix) { Scene *scene= CTX_data_scene(C); KeyBlock *kb= NULL; if((kb=object_insert_shape_key(scene, ob, name, from_mix))) { + PointerRNA keyptr; + + RNA_pointer_create((ID *)ob->data, &RNA_ShapeKey, kb, &keyptr); WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); + + return keyptr; } else { BKE_reportf(reports, RPT_ERROR, "Object \"%s\"does not support shapes.", ob->id.name+2); + return PointerRNA_NULL; } - - return kb; } int rna_Object_is_visible(Object *ob, bContext *C) @@ -365,6 +370,45 @@ static void rna_Mesh_assign_verts_to_group(Object *ob, bDeformGroup *group, int } */ +void rna_Object_ray_cast(Object *ob, ReportList *reports, float ray_start[3], float ray_end[3], float r_location[3], float r_normal[3], int *index) +{ + BVHTreeFromMesh treeData; + + if(ob->derivedFinal==NULL) { + BKE_reportf(reports, RPT_ERROR, "object \"%s\" has no mesh data to be used for ray casting.", ob->id.name+2); + return; + } + + /* no need to managing allocation or freeing of the BVH data. this is generated and freed as needed */ + bvhtree_from_mesh_faces(&treeData, ob->derivedFinal, 0.0f, 4, 6); + + if(treeData.tree==NULL) { + BKE_reportf(reports, RPT_ERROR, "object \"%s\" could not create internal data for ray casting.", ob->id.name+2); + return; + } + else { + BVHTreeRayHit hit; + float ray_nor[3], dist; + sub_v3_v3v3(ray_nor, ray_end, ray_start); + + dist= hit.dist = normalize_v3(ray_nor); + hit.index = -1; + + if(BLI_bvhtree_ray_cast(treeData.tree, ray_start, ray_nor, 0.0f, &hit, treeData.raycast_callback, &treeData) != -1) { + if(hit.dist<=dist) { + copy_v3_v3(r_location, hit.co); + copy_v3_v3(r_normal, hit.no); + *index= hit.index; + return; + } + } + } + + zero_v3(r_location); + zero_v3(r_normal); + *index= -1; +} + #else void RNA_api_object(StructRNA *srna) @@ -436,8 +480,32 @@ void RNA_api_object(StructRNA *srna) parm= RNA_def_string(func, "name", "Key", 0, "", "Unique name for the new keylock."); /* optional */ parm= RNA_def_boolean(func, "from_mix", 1, "", "Create new shape from existing mix of shapes."); parm= RNA_def_pointer(func, "key", "ShapeKey", "", "New shape keyblock."); + RNA_def_property_flag(parm, PROP_RNAPTR); RNA_def_function_return(func, parm); + /* Ray Cast */ + func= RNA_def_function(srna, "ray_cast", "rna_Object_ray_cast"); + RNA_def_function_ui_description(func, "Cast a ray onto in object space."); + RNA_def_function_flag(func, FUNC_USE_REPORTS); + + /* ray start and end */ + parm= RNA_def_float_vector(func, "start", 3, NULL, -FLT_MAX, FLT_MAX, "", "", -1e4, 1e4); + RNA_def_property_flag(parm, PROP_REQUIRED); + parm= RNA_def_float_vector(func, "end", 3, NULL, -FLT_MAX, FLT_MAX, "", "", -1e4, 1e4); + RNA_def_property_flag(parm, PROP_REQUIRED); + + /* return location and normal */ + parm= RNA_def_float_vector(func, "location", 3, NULL, -FLT_MAX, FLT_MAX, "Location", "The hit location of this ray cast", -1e4, 1e4); + RNA_def_property_flag(parm, PROP_THICK_WRAP); + RNA_def_function_return_mark(func, parm); + parm= RNA_def_float_vector(func, "normal", 3, NULL, -FLT_MAX, FLT_MAX, "Normal", "The face normal at the ray cast hit location", -1e4, 1e4); + RNA_def_property_flag(parm, PROP_THICK_WRAP); + RNA_def_function_return_mark(func, parm); + + parm= RNA_def_int(func, "index", 0, 0, 0, "", "The face index, -1 when no intersection is found.", 0, 0); + RNA_def_function_return_mark(func, parm); + + /* DAG */ func= RNA_def_function(srna, "make_display_list", "rna_Object_make_display_list"); RNA_def_function_ui_description(func, "Update object's display data."); /* XXX describe better */ diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c index f4ff066f2b4..0eb4f9b9da0 100644 --- a/source/blender/makesrna/intern/rna_object_force.c +++ b/source/blender/makesrna/intern/rna_object_force.c @@ -810,6 +810,12 @@ static void rna_def_collision(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", PDEFLE_KILL_PART); RNA_def_property_ui_text(prop, "Kill Particles", "Kill collided particles"); RNA_def_property_update(prop, 0, "rna_CollisionSettings_update"); + + prop= RNA_def_property(srna, "stickness", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "pdef_stickness"); + RNA_def_property_range(prop, 0.0f, 10.0f); + RNA_def_property_ui_text(prop, "Stickness", "Amount of stickness to surface collision"); + RNA_def_property_update(prop, 0, "rna_CollisionSettings_update"); /* Soft Body and Cloth Interaction */ diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c index 07c4445872e..b37442fab6a 100644 --- a/source/blender/makesrna/intern/rna_pose.c +++ b/source/blender/makesrna/intern/rna_pose.c @@ -693,6 +693,8 @@ static void rna_def_pose_channel(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Bone Paths Calculation End Frame", "End frame of range of frames to use for Bone Path calculations."); RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_update"); + rna_def_motionpath_common(srna); + /* Relationships to other bones */ prop= RNA_def_property(srna, "bone", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); @@ -912,6 +914,13 @@ static void rna_def_pose_channel(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Custom Object", "Object that defines custom draw type for this bone."); RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_update"); + prop= RNA_def_property(srna, "custom_shape_transform", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "custom_tx"); + RNA_def_property_struct_type(prop, "PoseBone"); + RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Custom Shape Transform", "Bone that defines the display transform of this custom shape."); + RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_update"); + /* bone groups */ prop= RNA_def_property(srna, "bone_group_index", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "agrp_index"); @@ -1108,7 +1117,8 @@ static void rna_def_pose(BlenderRNA *brna) RNA_def_property_int_funcs(prop, "rna_Pose_active_bone_group_index_get", "rna_Pose_active_bone_group_index_set", "rna_Pose_active_bone_group_index_range"); RNA_def_property_ui_text(prop, "Active Bone Group Index", "Active index in bone groups array."); RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_update"); - + + /* ik solvers */ prop= RNA_def_property(srna, "ik_solver", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "iksolver"); RNA_def_property_enum_funcs(prop, NULL, "rna_Pose_ik_solver_set", NULL); @@ -1121,7 +1131,10 @@ static void rna_def_pose(BlenderRNA *brna) RNA_def_property_pointer_funcs(prop, "rna_Pose_ikparam_get", NULL, "rna_Pose_ikparam_typef"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "IK Param", "Parameters for IK solver."); - + + /* animviz */ + rna_def_animviz_common(srna); + /* RNA_api_pose(srna); */ } diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index d5de2fdc464..e35f8437995 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -96,11 +96,13 @@ EnumPropertyItem snap_element_items[] = { #include "BKE_context.h" #include "BKE_global.h" +#include "BKE_image.h" #include "BKE_main.h" #include "BKE_node.h" #include "BKE_pointcache.h" #include "BKE_scene.h" #include "BKE_depsgraph.h" +#include "BKE_image.h" #include "BKE_mesh.h" #include "BLI_threads.h" @@ -124,21 +126,28 @@ static PointerRNA rna_Scene_objects_get(CollectionPropertyIterator *iter) return rna_pointer_inherit_refine(&iter->parent, &RNA_Object, ((Base*)internal->link)->object); } -static void rna_Scene_link_object(Scene *sce, ReportList *reports, Object *ob) +static void rna_Scene_link_object(Scene *scene, ReportList *reports, Object *ob) { - Base *base= object_in_scene(ob, sce); - if (base) { - BKE_report(reports, RPT_ERROR, "Object is already in this scene."); + Base *base; + + if (ob->type != OB_EMPTY && ob->data==NULL) { + BKE_reportf(reports, RPT_ERROR, "Object \"%s\" is not an Empty type and has no Object Data set."); + return; + } + + if (object_in_scene(ob, scene)) { + BKE_reportf(reports, RPT_ERROR, "Object \"%s\" is already in scene \"%s\".", ob->id.name+2, scene->id.name+2); return; } - base= scene_add_base(sce, ob); + + base= scene_add_base(scene, ob); ob->id.us++; /* this is similar to what object_add_type and add_object do */ - ob->lay= base->lay= sce->lay; + ob->lay= base->lay= scene->lay; ob->recalc |= OB_RECALC; - DAG_scene_sort(sce); + DAG_scene_sort(scene); } static void rna_Scene_unlink_object(Scene *sce, ReportList *reports, Object *ob) @@ -359,6 +368,21 @@ static void rna_SceneRenderData_file_format_set(PointerRNA *ptr, int value) #endif } +static int rna_SceneRender_file_ext_length(PointerRNA *ptr) +{ + RenderData *rd= (RenderData*)ptr->data; + char ext[8]; + + BKE_add_image_extension(ext, rd->imtype); + return strlen(ext); +} + +static void rna_SceneRender_file_ext_get(PointerRNA *ptr, char *str) +{ + RenderData *rd= (RenderData*)ptr->data; + BKE_add_image_extension(str, rd->imtype); +} + void rna_SceneRenderData_jpeg2k_preset_update(RenderData *rd) { rd->subimtype &= ~(R_JPEG2K_12BIT|R_JPEG2K_16BIT | R_JPEG2K_CINE_PRESET|R_JPEG2K_CINE_48FPS); @@ -501,6 +525,12 @@ static int rna_SceneRenderData_engine_get(PointerRNA *ptr) return 0; } +static void rna_SceneRenderData_color_management_update(Main *bmain, Scene *unused, PointerRNA *ptr) +{ + /* reset all generated image block buffers to prevent out-of-date conversions */ + BKE_image_free_image_ibufs(); +} + static void rna_SceneRenderLayer_name_set(PointerRNA *ptr, const char *value) { Scene *scene= (Scene*)ptr->id.data; @@ -1280,7 +1310,7 @@ static void rna_def_scene_game_data(BlenderRNA *brna) prop= RNA_def_property(srna, "eye_separation", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "eyeseparation"); RNA_def_property_range(prop, 0.01, 5.0); - RNA_def_property_ui_text(prop, "Eye Separation", "Set the distance between the eyes"); + RNA_def_property_ui_text(prop, "Eye Separation", "Set the distance between the eyes - the camera focal length/30 should be fine"); RNA_def_property_update(prop, NC_SCENE, NULL); /* Dome */ @@ -1526,7 +1556,13 @@ static void rna_def_scene_render_data(BlenderRNA *brna) {R_BAKE_SPACE_OBJECT, "OBJECT", 0, "Object", ""}, {R_BAKE_SPACE_TANGENT, "TANGENT", 0, "Tangent", ""}, {0, NULL, 0, NULL, NULL}}; - + + static EnumPropertyItem bake_qyad_split_items[] ={ + {0, "AUTO", 0, "Automatic", "Split quads to give the least distortion while baking"}, + {1, "FIXED", 0, "Fixed", "Split quads pradictably (0,1,2) (0,2,3)"}, + {2, "FIXED_ALT", 0, "Fixed Alternate", "Split quads pradictably (1,2,3) (1,3,0)"}, + {0, NULL, 0, NULL, NULL}}; + static EnumPropertyItem bake_aa_items[] ={ {5, "AA_5", 0, "5", ""}, {8, "AA_8", 0, "8", ""}, @@ -2170,9 +2206,9 @@ static void rna_def_scene_render_data(BlenderRNA *brna) prop= RNA_def_property(srna, "color_management", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "color_mgt_flag", R_COLOR_MANAGEMENT); RNA_def_property_ui_text(prop, "Color Management", "Use color profiles and gamma corrected imaging pipeline"); - RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS|NC_MATERIAL|ND_SHADING, NULL); + RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS|NC_MATERIAL|ND_SHADING, "rna_SceneRenderData_color_management_update"); - prop= RNA_def_property(srna, "file_extensions", PROP_BOOLEAN, PROP_NONE); + prop= RNA_def_property(srna, "use_file_extension", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "scemode", R_EXTENSION); RNA_def_property_ui_text(prop, "File Extensions", "Add the file format extensions to the rendered file name (eg: filename + .jpg)"); RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); @@ -2183,7 +2219,13 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_enum_funcs(prop, NULL, "rna_SceneRenderData_file_format_set", NULL); RNA_def_property_ui_text(prop, "File Format", "File format to save the rendered images as."); RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); - + + prop= RNA_def_property(srna, "file_extension", PROP_STRING, PROP_NONE); + RNA_def_property_string_funcs(prop, "rna_SceneRender_file_ext_get", "rna_SceneRender_file_ext_length", NULL); + RNA_def_property_ui_text(prop, "Extension", "The file extension used for saving renders."); + RNA_def_struct_name_property(srna, prop); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + prop= RNA_def_property(srna, "free_image_textures", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "scemode", R_FREE_IMAGE); RNA_def_property_ui_text(prop, "Free Image Textures", "Free all image texture from memory after render, to save memory before compositing."); @@ -2226,13 +2268,17 @@ static void rna_def_scene_render_data(BlenderRNA *brna) prop= RNA_def_property(srna, "bake_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_bitflag_sdna(prop, NULL, "bake_mode"); RNA_def_property_enum_items(prop, bake_mode_items); - RNA_def_property_ui_text(prop, "Bake Mode", ""); + RNA_def_property_ui_text(prop, "Bake Mode", "Choose shading information to bake into the image"); prop= RNA_def_property(srna, "bake_normal_space", PROP_ENUM, PROP_NONE); RNA_def_property_enum_bitflag_sdna(prop, NULL, "bake_normal_space"); RNA_def_property_enum_items(prop, bake_normal_space_items); RNA_def_property_ui_text(prop, "Normal Space", "Choose normal space for baking"); + prop= RNA_def_property(srna, "bake_quad_split", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, bake_qyad_split_items); + RNA_def_property_ui_text(prop, "Quad Split", "Choose the method used to split a quad into 2 triangles for baking"); + prop= RNA_def_property(srna, "bake_aa_mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_bitflag_sdna(prop, NULL, "bake_osa"); RNA_def_property_enum_items(prop, bake_aa_items); @@ -2244,10 +2290,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna) prop= RNA_def_property(srna, "bake_normalized", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "bake_flag", R_BAKE_NORMALIZE); - RNA_def_property_ui_text(prop, "Normalized", ""); - //"Bake ambient occlusion normalized, without taking into acount material settings" - //"Normalized displacement value to fit the 'Dist' range" - // XXX: Need 1 tooltip here... + RNA_def_property_ui_text(prop, "Normalized", "With displacement normalize to the distance, with ambient occlusion normalize without using material settings."); prop= RNA_def_property(srna, "bake_clear", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "bake_flag", R_BAKE_CLEAR); @@ -2276,7 +2319,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna) prop= RNA_def_property(srna, "stamp_time", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "stamp", R_STAMP_TIME); - RNA_def_property_ui_text(prop, "Stamp Time", "Include the current time in image metadata"); + RNA_def_property_ui_text(prop, "Stamp Time", "Include the render frame as HH:MM:SS.FF in image metadata"); RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); prop= RNA_def_property(srna, "stamp_date", PROP_BOOLEAN, PROP_NONE); @@ -2388,6 +2431,9 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_boolean_funcs(prop, "rna_SceneRenderData_use_game_engine_get", NULL); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Use Game Engine", "Current rendering engine is a game engine."); + + /* Scene API */ + RNA_api_scene_render(srna); } diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c index 4efbed167a6..84dc3e6971e 100644 --- a/source/blender/makesrna/intern/rna_scene_api.c +++ b/source/blender/makesrna/intern/rna_scene_api.c @@ -36,12 +36,15 @@ #include "DNA_anim_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" +#include "BKE_utildefines.h" #ifdef RNA_RUNTIME #include "BKE_animsys.h" #include "BKE_scene.h" +#include "BKE_image.h" #include "BKE_depsgraph.h" +#include "BKE_writeavi.h" #include "ED_object.h" #include "ED_anim_api.h" @@ -84,6 +87,14 @@ static KeyingSet *rna_Scene_add_keying_set(Scene *sce, ReportList *reports, } } +static void rna_SceneRender_get_frame_path(RenderData *rd, int frame, char *name) +{ + if(BKE_imtype_is_movie(rd->imtype)) + BKE_makeanimstring(name, rd); + else + BKE_makepicstring(name, rd->pic, (frame==INT_MIN) ? rd->cfra : frame, rd->imtype, rd->scemode & R_EXTENSION); +} + #else void RNA_api_scene(StructRNA *srna) @@ -113,5 +124,18 @@ void RNA_api_scene(StructRNA *srna) RNA_def_boolean(func, "insertkey_visual", 0, "Insert Keyframes - Visual", "Insert keyframes based on 'visual transforms'."); } +void RNA_api_scene_render(StructRNA *srna) +{ + FunctionRNA *func; + PropertyRNA *parm; + + func= RNA_def_function(srna, "frame_path", "rna_SceneRender_get_frame_path"); + RNA_def_function_ui_description(func, "Set scene frame updating all objects immediately."); + parm= RNA_def_int(func, "frame", INT_MIN, INT_MIN, INT_MAX, "", "Frame number to use, if unset the current frame will be used.", MINAFRAME, MAXFRAME); + parm= RNA_def_string(func, "name", "", FILE_MAX, "File Name", "the resulting filename from the scenes render settings."); + RNA_def_property_flag(parm, PROP_THICK_WRAP); /* needed for string return value */ + RNA_def_function_return_mark(func, parm); +} + #endif diff --git a/source/blender/makesrna/intern/rna_screen.c b/source/blender/makesrna/intern/rna_screen.c index 883c77b3faa..5a29eee5cf2 100644 --- a/source/blender/makesrna/intern/rna_screen.c +++ b/source/blender/makesrna/intern/rna_screen.c @@ -23,6 +23,7 @@ */ #include <stdlib.h> +#include <stddef.h> #include "RNA_define.h" #include "RNA_types.h" @@ -37,9 +38,10 @@ EnumPropertyItem region_type_items[] = { {RGN_TYPE_WINDOW, "WINDOW", 0, "Window", ""}, {RGN_TYPE_HEADER, "HEADER", 0, "Header", ""}, {RGN_TYPE_CHANNELS, "CHANNELS", 0, "Channels", ""}, - {RGN_TYPE_TOOLS, "TOOLS", 0, "Tools", ""}, {RGN_TYPE_TEMPORARY, "TEMPORARY", 0, "Temporary", ""}, {RGN_TYPE_UI, "UI", 0, "UI", ""}, + {RGN_TYPE_TOOLS, "TOOLS", 0, "Tools", ""}, + {RGN_TYPE_TOOL_PROPS, "TOOL_PROPS", 0, "Tool Properties", ""}, {RGN_TYPE_PREVIEW, "PREVIEW", 0, "Preview", ""}, {0, NULL, 0, NULL, NULL}}; @@ -154,8 +156,9 @@ static void rna_def_region(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Region ID", "Unique ID for this region."); - prop= RNA_def_property(srna, "type", PROP_INT, PROP_NONE); - RNA_def_property_int_sdna(prop, NULL, "regiontype"); + prop= RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "regiontype"); + RNA_def_property_enum_items(prop, region_type_items); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Region Type", "Type of this region."); diff --git a/source/blender/makesrna/intern/rna_sculpt_paint.c b/source/blender/makesrna/intern/rna_sculpt_paint.c index 4d17da668b2..99bee9413cd 100644 --- a/source/blender/makesrna/intern/rna_sculpt_paint.c +++ b/source/blender/makesrna/intern/rna_sculpt_paint.c @@ -454,10 +454,6 @@ static void rna_def_particle_edit(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Draw Particles", "Draw actual particles."); RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, NULL); - prop= RNA_def_property(srna, "mirror_x", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", PE_X_MIRROR); - RNA_def_property_ui_text(prop, "X-Axis Mirror", "Mirror operations over the X axis while editing."); - prop= RNA_def_property(srna, "add_interpolate", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", PE_INTERPOLATE_ADDED); RNA_def_property_ui_text(prop, "Interpolate", "Interpolate new particles from the existing ones."); diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 7ab01d5ef99..35c8c7ac345 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -1351,7 +1351,7 @@ static void rna_def_space_graph(BlenderRNA *brna) RNA_def_property_enum_sdna(prop, NULL, "mode"); RNA_def_property_enum_items(prop, mode_items); RNA_def_property_ui_text(prop, "Mode", "Editing context being displayed."); - RNA_def_property_update(prop, NC_SPACE|ND_SPACE_GRAPH, NULL); + RNA_def_property_update(prop, NC_SPACE|ND_SPACE_GRAPH, NULL); // XXX need to be able to flush channel types /* display */ prop= RNA_def_property(srna, "show_seconds", PROP_BOOLEAN, PROP_NONE); @@ -1481,37 +1481,37 @@ static void rna_def_space_time(BlenderRNA *brna) /* Define Anim Playback Areas */ prop= RNA_def_property(srna, "play_top_left", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "redraws", TIME_REGION); - RNA_def_property_ui_text(prop, "Top-Left 3D Window", ""); + RNA_def_property_ui_text(prop, "Top-Left 3D Editor", ""); RNA_def_property_update(prop, NC_SPACE|ND_SPACE_TIME, "rna_SpaceTime_redraw_update"); prop= RNA_def_property(srna, "play_all_3d", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "redraws", TIME_ALL_3D_WIN); - RNA_def_property_ui_text(prop, "All 3D Windows", ""); + RNA_def_property_ui_text(prop, "All 3D View Editors", ""); RNA_def_property_update(prop, NC_SPACE|ND_SPACE_TIME, "rna_SpaceTime_redraw_update"); prop= RNA_def_property(srna, "play_anim", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "redraws", TIME_ALL_ANIM_WIN); - RNA_def_property_ui_text(prop, "Animation Windows", ""); + RNA_def_property_ui_text(prop, "Animation Editors", ""); RNA_def_property_update(prop, NC_SPACE|ND_SPACE_TIME, "rna_SpaceTime_redraw_update"); prop= RNA_def_property(srna, "play_buttons", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "redraws", TIME_ALL_BUTS_WIN); - RNA_def_property_ui_text(prop, "Properties Windows", ""); + RNA_def_property_ui_text(prop, "Property Editors", ""); RNA_def_property_update(prop, NC_SPACE|ND_SPACE_TIME, "rna_SpaceTime_redraw_update"); prop= RNA_def_property(srna, "play_image", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "redraws", TIME_ALL_IMAGE_WIN); - RNA_def_property_ui_text(prop, "Image Windows", ""); + RNA_def_property_ui_text(prop, "Image Editors", ""); RNA_def_property_update(prop, NC_SPACE|ND_SPACE_TIME, "rna_SpaceTime_redraw_update"); prop= RNA_def_property(srna, "play_sequencer", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "redraws", TIME_SEQ); - RNA_def_property_ui_text(prop, "Sequencer Windows", ""); + RNA_def_property_ui_text(prop, "Sequencer Editors", ""); RNA_def_property_update(prop, NC_SPACE|ND_SPACE_TIME, "rna_SpaceTime_redraw_update"); prop= RNA_def_property(srna, "play_nodes", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "redraws", TIME_NODES); - RNA_def_property_ui_text(prop, "Node Windows", ""); + RNA_def_property_ui_text(prop, "Node Editors", ""); RNA_def_property_update(prop, NC_SPACE|ND_SPACE_TIME, "rna_SpaceTime_redraw_update"); /* Other options */ diff --git a/source/blender/makesrna/intern/rna_texture.c b/source/blender/makesrna/intern/rna_texture.c index 19d33465ceb..79a75c89a08 100644 --- a/source/blender/makesrna/intern/rna_texture.c +++ b/source/blender/makesrna/intern/rna_texture.c @@ -1598,7 +1598,7 @@ static void rna_def_texture_pointdensity(BlenderRNA *brna) prop= RNA_def_property(srna, "radius", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "radius"); - RNA_def_property_range(prop, 0.01, FLT_MAX); + RNA_def_property_range(prop, 0.001, FLT_MAX); RNA_def_property_ui_text(prop, "Radius", "Radius from the shaded sample to look for points within"); RNA_def_property_update(prop, 0, "rna_Texture_update"); diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c index 9c4cc64fbb7..011235c862f 100644 --- a/source/blender/makesrna/intern/rna_ui_api.c +++ b/source/blender/makesrna/intern/rna_ui_api.c @@ -269,6 +269,15 @@ void RNA_api_ui_layout(StructRNA *srna) RNA_def_string(func, "open", "", 0, "", "Operator identifier to open a file for creating a new ID block."); RNA_def_string(func, "unlink", "", 0, "", "Operator identifier to unlink the ID block."); + func= RNA_def_function(srna, "template_ID_preview", "uiTemplateIDPreview"); + RNA_def_function_flag(func, FUNC_USE_CONTEXT); + api_ui_item_rna_common(func); + RNA_def_string(func, "new", "", 0, "", "Operator identifier to create a new ID block."); + RNA_def_string(func, "open", "", 0, "", "Operator identifier to open a file for creating a new ID block."); + RNA_def_string(func, "unlink", "", 0, "", "Operator identifier to unlink the ID block."); + RNA_def_int(func, "rows", 0, 0, INT_MAX, "Number of thumbnail preview rows to display", "", 0, INT_MAX); + RNA_def_int(func, "cols", 0, 0, INT_MAX, "Number of thumbnail preview columns to display", "", 0, INT_MAX); + func= RNA_def_function(srna, "template_any_ID", "uiTemplateAnyID"); RNA_def_function_flag(func, FUNC_USE_CONTEXT); parm= RNA_def_pointer(func, "data", "AnyType", "", "Data from which to take property."); @@ -311,6 +320,7 @@ void RNA_api_ui_layout(StructRNA *srna) api_ui_item_rna_common(func); RNA_def_enum(func, "type", curve_type_items, 0, "Type", "Type of curves to display."); RNA_def_boolean(func, "levels", 0, "", "Show black/white levels."); + RNA_def_boolean(func, "brush", 0, "", "Show brush options."); func= RNA_def_function(srna, "template_color_ramp", "uiTemplateColorRamp"); api_ui_item_rna_common(func); @@ -325,6 +335,10 @@ void RNA_api_ui_layout(StructRNA *srna) parm= RNA_def_int(func, "active_layer", 0, 0, INT_MAX, "Active Layer", "", 0, INT_MAX); RNA_def_property_flag(parm, PROP_REQUIRED); + func= RNA_def_function(srna, "template_color_wheel", "uiTemplateColorWheel"); + api_ui_item_rna_common(func); + RNA_def_boolean(func, "value_slider", 0, "", "Display the value slider to the right of the color wheel"); + func= RNA_def_function(srna, "template_triColorSet", "uiTemplateTriColorSet"); api_ui_item_rna_common(func); diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 9b314afeb08..bc0e11bf780 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -1434,7 +1434,7 @@ static void rna_def_userdef_themes(BlenderRNA *brna) StructRNA *srna; PropertyRNA *prop; - static EnumPropertyItem active_theme_group[] = { + static EnumPropertyItem active_theme_area[] = { {0, "USER_INTERFACE", ICON_UI, "User Interface", ""}, {1, "VIEW_3D", ICON_VIEW3D, "3D View", ""}, {2, "TIMELINE", ICON_TIME, "Timeline", ""}, @@ -1462,10 +1462,10 @@ static void rna_def_userdef_themes(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Name", "Name of the theme."); RNA_def_struct_name_property(srna, prop); - prop= RNA_def_property(srna, "active_theme", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, NULL, "active_theme_group"); - RNA_def_property_enum_items(prop, active_theme_group); - RNA_def_property_ui_text(prop, "Active Theme", ""); + prop= RNA_def_property(srna, "theme_area", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "active_theme_area"); + RNA_def_property_enum_items(prop, active_theme_area); + RNA_def_property_ui_text(prop, "Active Theme Area", ""); prop= RNA_def_property(srna, "user_interface", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); @@ -1811,8 +1811,6 @@ static void rna_def_userdef_view(BlenderRNA *brna) RNA_def_property_range(prop, 4, 10); RNA_def_property_ui_text(prop, "Object Origin Size", "Diameter in Pixels for Object/Lamp origin display."); RNA_def_property_update(prop, 0, "rna_userdef_update"); - - } static void rna_def_userdef_edit(BlenderRNA *brna) @@ -1841,7 +1839,6 @@ static void rna_def_userdef_edit(BlenderRNA *brna) {USER_ADD_VIEWALIGNED, "VIEW", 0, "View", "Align newly added objects to the world coordinates"}, {0, NULL, 0, NULL, NULL}}; - srna= RNA_def_struct(brna, "UserPreferencesEdit", NULL); RNA_def_struct_sdna(srna, "UserDef"); RNA_def_struct_nested(brna, srna, "UserPreferences"); @@ -1927,7 +1924,7 @@ static void rna_def_userdef_edit(BlenderRNA *brna) RNA_def_property_enum_items(prop, new_interpolation_types); RNA_def_property_enum_sdna(prop, NULL, "ipo_new"); RNA_def_property_ui_text(prop, "New Interpolation Type", ""); - + prop= RNA_def_property(srna, "grease_pencil_manhattan_distance", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "gp_manhattendist"); RNA_def_property_range(prop, 0, 100); @@ -2075,7 +2072,14 @@ static void rna_def_userdef_system(BlenderRNA *brna) {USER_DRAW_OVERLAP, "OVERLAP", 0, "Overlap", "Redraw all overlapping regions, minimal memory usage but more redraws."}, {USER_DRAW_FULL, "FULL", 0, "Full", "Do a full redraw each time, slow, only use for reference or when all else fails."}, {0, NULL, 0, NULL, NULL}}; - + + static EnumPropertyItem color_picker_types[] = { + {USER_CP_CIRCLE, "CIRCLE", 0, "Circle", "A circular Hue/Saturation color wheel, with Value slider"}, + {USER_CP_SQUARE_SV, "SQUARE_SV", 0, "Square (SV + H)", "A square showing Saturation/Value, with Hue slider"}, + {USER_CP_SQUARE_HS, "SQUARE_HS", 0, "Square (HS + V)", "A square showing Hue/Saturation, with Value slider"}, + {USER_CP_SQUARE_HV, "SQUARE_HV", 0, "Square (HV + S)", "A square showing Hue/Value, with Saturation slider"}, + {0, NULL, 0, NULL, NULL}}; + /* hardcoded here, could become dynamic somehow */ static EnumPropertyItem language_items[] = { {0, "ENGLISH", 0, "English", ""}, @@ -2172,6 +2176,11 @@ static void rna_def_userdef_system(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Weight Color Range", "Color range used for weight visualization in weight painting mode."); RNA_def_property_update(prop, 0, "rna_UserDef_weight_color_update"); + prop= RNA_def_property(srna, "color_picker_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, color_picker_types); + RNA_def_property_enum_sdna(prop, NULL, "color_picker_type"); + RNA_def_property_ui_text(prop, "Color Picker Type", "Different styles of displaying the color picker widget"); + prop= RNA_def_property(srna, "enable_all_codecs", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_ALLWINCODECS); RNA_def_property_ui_text(prop, "Enable All Codecs", "Enables automatic saving of preview images in the .blend file (Windows only)."); @@ -2195,10 +2204,6 @@ static void rna_def_userdef_system(BlenderRNA *brna) RNA_def_property_range(prop, 0, 32727); RNA_def_property_ui_text(prop, "Frame Server Port", "Frameserver Port for Framserver-Rendering."); - prop= RNA_def_property(srna, "game_sound", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_negative_sdna(prop, NULL, "gameflags", USER_DISABLE_SOUND); - RNA_def_property_ui_text(prop, "Game Sound", "Enables sounds to be played in games."); - prop= RNA_def_property(srna, "clip_alpha", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "glalphaclip"); RNA_def_property_range(prop, 0.0f, 1.0f); @@ -2212,6 +2217,10 @@ static void rna_def_userdef_system(BlenderRNA *brna) RNA_def_property_boolean_negative_sdna(prop, NULL, "gameflags", USER_DISABLE_VBO); RNA_def_property_ui_text(prop, "VBOs", "Use Vertex Buffer Objects (or Vertex Arrays, if unsupported) for viewport rendering."); + prop= RNA_def_property(srna, "use_antialiasing", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "gameflags", USER_DISABLE_AA); + RNA_def_property_ui_text(prop, "Anti-aliasing", "Use anti-aliasing for the 3D view (may impact redraw performance)"); + prop= RNA_def_property(srna, "gl_texture_limit", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "glreslimit"); RNA_def_property_enum_items(prop, gl_texture_clamp_items); diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index 7abba3c004a..513f2f8f0ec 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -64,6 +64,7 @@ EnumPropertyItem event_value_items[] = { {KM_PRESS, "PRESS", 0, "Press", ""}, {KM_RELEASE, "RELEASE", 0, "Release", ""}, {KM_CLICK, "CLICK", 0, "Click", ""}, + {KM_DBL_CLICK, "DOUBLECLICK", 0, "Double Click", ""}, {0, NULL, 0, NULL, NULL}}; EnumPropertyItem event_tweak_type_items[]= { @@ -692,6 +693,7 @@ static void operator_draw(bContext *C, wmOperator *op) } void operator_wrapper(wmOperatorType *ot, void *userdata); +void macro_wrapper(wmOperatorType *ot, void *userdata); static char _operator_idname[OP_MAX_TYPENAME]; static char _operator_name[OP_MAX_TYPENAME]; @@ -763,12 +765,84 @@ static StructRNA *rna_Operator_register(const bContext *C, ReportList *reports, return dummyot.ext.srna; } + +static StructRNA *rna_MacroOperator_register(const bContext *C, ReportList *reports, void *data, const char *identifier, StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free) +{ + wmOperatorType dummyot = {0}; + wmOperator dummyop= {0}; + PointerRNA dummyotr; + int have_function[4]; + + /* setup dummy operator & operator type to store static properties in */ + dummyop.type= &dummyot; + dummyot.idname= _operator_idname; /* only assigne the pointer, string is NULL'd */ + dummyot.name= _operator_name; /* only assigne the pointer, string is NULL'd */ + dummyot.description= _operator_descr; /* only assigne the pointer, string is NULL'd */ + RNA_pointer_create(NULL, &RNA_Macro, &dummyop, &dummyotr); + + /* validate the python class */ + if(validate(&dummyotr, data, have_function) != 0) + return NULL; + + { /* convert foo.bar to FOO_OT_bar + * allocate the description and the idname in 1 go */ + int idlen = strlen(_operator_idname) + 4; + int namelen = strlen(_operator_name) + 1; + int desclen = strlen(_operator_descr) + 1; + char *ch, *ch_arr; + ch_arr= ch= MEM_callocN(sizeof(char) * (idlen + namelen + desclen), "_operator_idname"); /* 2 terminators and 3 to convert a.b -> A_OT_b */ + WM_operator_bl_idname(ch, _operator_idname); /* convert the idname from python */ + dummyot.idname= ch; + ch += idlen; + strcpy(ch, _operator_name); + dummyot.name = ch; + ch += namelen; + strcpy(ch, _operator_descr); + dummyot.description = ch; + } + + if(strlen(identifier) >= sizeof(dummyop.idname)) { + BKE_reportf(reports, RPT_ERROR, "registering operator class: '%s' is too long, maximum length is %d.", identifier, sizeof(dummyop.idname)); + return NULL; + } + + /* check if we have registered this operator type before, and remove it */ + { + wmOperatorType *ot= WM_operatortype_exists(dummyot.idname); + if(ot && ot->ext.srna) + rna_Operator_unregister(C, ot->ext.srna); + } + + /* create a new menu type */ + dummyot.ext.srna= RNA_def_struct(&BLENDER_RNA, dummyot.idname, "Operator"); + dummyot.ext.data= data; + dummyot.ext.call= call; + dummyot.ext.free= free; + + dummyot.pyop_poll= (have_function[0])? operator_poll: NULL; + dummyot.ui= (have_function[3])? operator_draw: NULL; + + WM_operatortype_append_macro_ptr(macro_wrapper, (void *)&dummyot); + + /* update while blender is running */ + if(C) + WM_main_add_notifier(NC_SCREEN|NA_EDITED, NULL); + + return dummyot.ext.srna; +} + static StructRNA* rna_Operator_refine(PointerRNA *opr) { wmOperator *op= (wmOperator*)opr->data; return (op->type && op->type->ext.srna)? op->type->ext.srna: &RNA_Operator; } +static StructRNA* rna_MacroOperator_refine(PointerRNA *opr) +{ + wmOperator *op= (wmOperator*)opr->data; + return (op->type && op->type->ext.srna)? op->type->ext.srna: &RNA_Macro; +} + #else static void rna_def_operator(BlenderRNA *brna) @@ -808,6 +882,11 @@ static void rna_def_operator(BlenderRNA *brna) RNA_def_property_string_maxlength(prop, 1024); /* else it uses the pointer size! */ RNA_def_property_flag(prop, PROP_REGISTER); + prop= RNA_def_property(srna, "bl_description", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "type->description"); + RNA_def_property_string_maxlength(prop, 1024); /* else it uses the pointer size! */ + RNA_def_property_flag(prop, PROP_REGISTER); + prop= RNA_def_property(srna, "bl_register", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "type->flag", OPTYPE_REGISTER); RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL); @@ -832,6 +911,8 @@ static void rna_def_macro_operator(BlenderRNA *brna) srna= RNA_def_struct(brna, "Macro", NULL); RNA_def_struct_ui_text(srna, "Macro Operator", "Storage of a macro operator being executed, or registered after execution."); RNA_def_struct_sdna(srna, "wmOperator"); + RNA_def_struct_refine_func(srna, "rna_MacroOperator_refine"); + RNA_def_struct_register_funcs(srna, "rna_MacroOperator_register", "rna_Operator_unregister"); prop= RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_EDITABLE); @@ -844,6 +925,32 @@ static void rna_def_macro_operator(BlenderRNA *brna) RNA_def_property_struct_type(prop, "OperatorProperties"); RNA_def_property_ui_text(prop, "Properties", ""); RNA_def_property_pointer_funcs(prop, "rna_Operator_properties_get", NULL, NULL); + + /* Registration */ + prop= RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "type->idname"); + RNA_def_property_string_maxlength(prop, OP_MAX_TYPENAME); /* else it uses the pointer size! */ + RNA_def_property_flag(prop, PROP_REGISTER); + + prop= RNA_def_property(srna, "bl_label", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "type->name"); + RNA_def_property_string_maxlength(prop, 1024); /* else it uses the pointer size! */ + RNA_def_property_flag(prop, PROP_REGISTER); + + prop= RNA_def_property(srna, "bl_description", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "type->description"); + RNA_def_property_string_maxlength(prop, 1024); /* else it uses the pointer size! */ + RNA_def_property_flag(prop, PROP_REGISTER); + + prop= RNA_def_property(srna, "bl_register", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "type->flag", OPTYPE_REGISTER); + RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL); + + prop= RNA_def_property(srna, "bl_undo", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "type->flag", OPTYPE_UNDO); + RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL); + + RNA_api_macro(srna); } static void rna_def_operator_type_macro(BlenderRNA *brna) diff --git a/source/blender/makesrna/intern/rna_wm_api.c b/source/blender/makesrna/intern/rna_wm_api.c index 1afedf1c6a6..9ed6046ecd0 100644 --- a/source/blender/makesrna/intern/rna_wm_api.c +++ b/source/blender/makesrna/intern/rna_wm_api.c @@ -237,6 +237,35 @@ void RNA_api_operator(StructRNA *srna) RNA_def_pointer(func, "context", "Context", "", ""); } +void RNA_api_macro(StructRNA *srna) +{ + FunctionRNA *func; + PropertyRNA *parm; + + /* utility, not for registering */ + func= RNA_def_function(srna, "report", "rna_Operator_report"); + parm= RNA_def_enum(func, "type", wm_report_items, 0, "Type", ""); + RNA_def_property_flag(parm, PROP_REQUIRED|PROP_ENUM_FLAG); + parm= RNA_def_string(func, "message", "", 0, "Report Message", ""); + RNA_def_property_flag(parm, PROP_REQUIRED); + + + /* Registration */ + + /* poll */ + func= RNA_def_function(srna, "poll", NULL); + RNA_def_function_ui_description(func, "Test if the operator can be called or not."); + RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL); + RNA_def_function_return(func, RNA_def_boolean(func, "visible", 1, "", "")); + RNA_def_pointer(func, "context", "Context", "", ""); + + /* draw */ + func= RNA_def_function(srna, "draw", NULL); + RNA_def_function_ui_description(func, "Draw function for the operator."); + RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL); + RNA_def_pointer(func, "context", "Context", "", ""); +} + void RNA_api_keyconfig(StructRNA *srna) { FunctionRNA *func; diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_image.c b/source/blender/nodes/intern/CMP_nodes/CMP_image.c index 89a3072ac8d..a204f8df4b2 100644 --- a/source/blender/nodes/intern/CMP_nodes/CMP_image.c +++ b/source/blender/nodes/intern/CMP_nodes/CMP_image.c @@ -64,27 +64,19 @@ static CompBuf *node_composit_get_image(RenderData *rd, Image *ima, ImageUser *i ibuf= BKE_image_get_ibuf(ima, iuser); if(ibuf==NULL) return NULL; - - if (rd->color_mgt_flag & R_COLOR_MANAGEMENT) { - if (ibuf->profile == IB_PROFILE_NONE) { - /* if float buffer already exists = already linear */ - /* else ... */ - if (ibuf->rect_float == NULL) { - imb_freerectfloatImBuf(ibuf); - ibuf->profile = IB_PROFILE_SRGB; - IMB_float_from_rect(ibuf); - } else { - ibuf->profile = IB_PROFILE_LINEAR_RGB; - } - } - } else { - if (ibuf->profile == IB_PROFILE_SRGB) { - if (ibuf->rect_float != NULL) { - imb_freerectfloatImBuf(ibuf); - } - ibuf->profile = IB_PROFILE_NONE; - IMB_float_from_rect(ibuf); + + if (!(rd->color_mgt_flag & R_COLOR_MANAGEMENT)) { + int profile = IB_PROFILE_NONE; + + /* temporarily set profile to none to not disturb actual */ + SWAP(int, ibuf->profile, profile); + + if (ibuf->rect_float != NULL) { + imb_freerectfloatImBuf(ibuf); } + IMB_float_from_rect(ibuf); + + SWAP(int, ibuf->profile, profile); } if (ibuf->rect_float == NULL) { diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_outputFile.c b/source/blender/nodes/intern/CMP_nodes/CMP_outputFile.c index e63e5802507..ebb7c1e8478 100644 --- a/source/blender/nodes/intern/CMP_nodes/CMP_outputFile.c +++ b/source/blender/nodes/intern/CMP_nodes/CMP_outputFile.c @@ -62,7 +62,7 @@ static void node_composit_exec_output_file(void *data, bNode *node, bNodeStack * } } - BKE_makepicstring((Scene *)node->id, string, nif->name, rd->cfra, nif->imtype); + BKE_makepicstring(string, nif->name, rd->cfra, nif->imtype, ((Scene *)node->id)->r.scemode & R_EXTENSION); if(0 == BKE_write_ibuf((Scene *)node->id, ibuf, string, nif->imtype, nif->subimtype, nif->imtype==R_OPENEXR?nif->codec:nif->quality)) printf("Cannot save Node File Output to %s\n", string); diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_rgb.c b/source/blender/nodes/intern/CMP_nodes/CMP_rgb.c index ae2678dc5f0..496e432bebf 100644 --- a/source/blender/nodes/intern/CMP_nodes/CMP_rgb.c +++ b/source/blender/nodes/intern/CMP_nodes/CMP_rgb.c @@ -47,7 +47,7 @@ bNodeType cmp_node_rgb= { /* *next,*prev */ NULL, NULL, /* type code */ CMP_NODE_RGB, /* name */ "RGB", - /* width+range */ 100, 60, 140, + /* width+range */ 140, 80, 140, /* class+opts */ NODE_CLASS_INPUT, NODE_OPTIONS, /* input sock */ NULL, /* output sock */ cmp_node_rgb_out, diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_rgb.c b/source/blender/nodes/intern/SHD_nodes/SHD_rgb.c index 1aa1a2ffc33..1c18e006a74 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_rgb.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_rgb.c @@ -54,7 +54,7 @@ bNodeType sh_node_rgb= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_RGB, /* name */ "RGB", - /* width+range */ 100, 60, 140, + /* width+range */ 140, 80, 140, /* class+opts */ NODE_CLASS_INPUT, NODE_OPTIONS, /* input sock */ NULL, /* output sock */ sh_node_rgb_out, diff --git a/source/blender/python/generic/euler.c b/source/blender/python/generic/euler.c index f6f2e337211..ae7a6783358 100644 --- a/source/blender/python/generic/euler.c +++ b/source/blender/python/generic/euler.c @@ -541,7 +541,7 @@ static PyGetSetDef Euler_getseters[] = { {"z", (getter)Euler_getAxis, (setter)Euler_setAxis, "Euler Z axis", (void *)2}, {"wrapped", (getter)BaseMathObject_getWrapped, (setter)NULL, "True when this wraps blenders internal data", NULL}, - {"__owner__", (getter)BaseMathObject_getOwner, (setter)NULL, "Read only owner for vectors that depend on another object", NULL}, + {"_owner", (getter)BaseMathObject_getOwner, (setter)NULL, "Read only owner for vectors that depend on another object", NULL}, {NULL,NULL,NULL,NULL,NULL} /* Sentinel */ }; diff --git a/source/blender/python/generic/matrix.c b/source/blender/python/generic/matrix.c index dcd1057f881..074a397b6d9 100644 --- a/source/blender/python/generic/matrix.c +++ b/source/blender/python/generic/matrix.c @@ -1129,12 +1129,33 @@ static PyObject *Matrix_getColSize( MatrixObject * self, void *type ) return PyLong_FromLong((long) self->colSize); } +static PyObject *Matrix_getMedianScale( MatrixObject * self, void *type ) +{ + float mat[3][3]; + + if(!BaseMath_ReadCallback(self)) + return NULL; + + /*must be 3-4 cols, 3-4 rows, square matrix*/ + if(self->colSize == 4 && self->rowSize == 4) + copy_m3_m4(mat, (float (*)[4])*self->matrix); + else if(self->colSize == 3 && self->rowSize == 3) + copy_m3_m3(mat, (float (*)[3])*self->matrix); + else { + PyErr_SetString(PyExc_AttributeError, "Matrix.median_scale: inappropriate matrix size - expects 3x3 or 4x4 matrix\n"); + return NULL; + } + + return PyFloat_FromDouble(mat3_to_scale(mat)); +} + /*****************************************************************************/ /* Python attributes get/set structure: */ /*****************************************************************************/ static PyGetSetDef Matrix_getseters[] = { - {"rowSize", (getter)Matrix_getRowSize, (setter)NULL, "", NULL}, - {"colSize", (getter)Matrix_getColSize, (setter)NULL, "", NULL}, + {"row_size", (getter)Matrix_getRowSize, (setter)NULL, "", NULL}, + {"col_size", (getter)Matrix_getColSize, (setter)NULL, "", NULL}, + {"median_scale", (getter)Matrix_getMedianScale, (setter)NULL, "", NULL}, {"wrapped", (getter)BaseMathObject_getWrapped, (setter)NULL, "", NULL}, {"_owner",(getter)BaseMathObject_getOwner, (setter)NULL, "", NULL}, diff --git a/source/blender/python/generic/quat.c b/source/blender/python/generic/quat.c index 2ee78235224..e739e1a5036 100644 --- a/source/blender/python/generic/quat.c +++ b/source/blender/python/generic/quat.c @@ -739,7 +739,7 @@ static PyGetSetDef Quaternion_getseters[] = { (getter)BaseMathObject_getWrapped, (setter)NULL, "True when this wraps blenders internal data", NULL}, - {"__owner__", + {"_owner", (getter)BaseMathObject_getOwner, (setter)NULL, "Read only owner for vectors that depend on another object", NULL}, diff --git a/source/blender/python/generic/vector.c b/source/blender/python/generic/vector.c index ae2c96fa86a..0713d60c6c2 100644 --- a/source/blender/python/generic/vector.c +++ b/source/blender/python/generic/vector.c @@ -1421,7 +1421,7 @@ static PyGetSetDef Vector_getseters[] = { (getter)BaseMathObject_getWrapped, (setter)NULL, "True when this wraps blenders internal data", NULL}, - {"__owner__", + {"_owner", (getter)BaseMathObject_getOwner, (setter)NULL, "Read only owner for vectors that depend on another object", NULL}, diff --git a/source/blender/python/intern/bpy_driver.c b/source/blender/python/intern/bpy_driver.c index 76df28494ac..f80d79d9a2a 100644 --- a/source/blender/python/intern/bpy_driver.c +++ b/source/blender/python/intern/bpy_driver.c @@ -26,6 +26,8 @@ #include "DNA_anim_types.h" +#include "BLI_listbase.h" + #include "BPY_extern.h" #include "BKE_fcurve.h" @@ -145,12 +147,15 @@ float BPY_pydriver_eval (ChannelDriver *driver) { PyObject *driver_vars=NULL; PyObject *retval= NULL; + PyObject *expr_vars; /* speed up by pre-hashing string & avoids re-converting unicode strings for every execution */ + PyObject *expr_code; PyGILState_STATE gilstate; - DriverTarget *dtar; + DriverVar *dvar; float result = 0.0f; /* default return */ char *expr = NULL; short targets_ok= 1; + int i; /* sanity checks - should driver be executed? */ if ((driver == NULL) /*|| (G.f & G_DOSCRIPTLINKS)==0*/) @@ -172,43 +177,75 @@ float BPY_pydriver_eval (ChannelDriver *driver) } } + if(driver->expr_comp==NULL) + driver->flag |= DRIVER_FLAG_RECOMPILE; + + /* compile the expression first if it hasn't been compiled or needs to be rebuilt */ + if(driver->flag & DRIVER_FLAG_RECOMPILE) { + Py_XDECREF(driver->expr_comp); + driver->expr_comp= PyTuple_New(2); + + expr_code= Py_CompileString(expr, "<bpy driver>", Py_eval_input); + PyTuple_SET_ITEM(((PyObject *)driver->expr_comp), 0, expr_code); + + driver->flag &= ~DRIVER_FLAG_RECOMPILE; + driver->flag |= DRIVER_FLAG_RENAMEVAR; /* maybe this can be removed but for now best keep until were sure */ + } + else { + expr_code= PyTuple_GET_ITEM(((PyObject *)driver->expr_comp), 0); + } + + if(driver->flag & DRIVER_FLAG_RENAMEVAR) { + /* may not be set */ + expr_vars= PyTuple_GET_ITEM(((PyObject *)driver->expr_comp), 1); + Py_XDECREF(expr_vars); + + /* intern the arg names so creating the namespace for every run is faster */ + expr_vars= PyTuple_New(BLI_countlist(&driver->variables)); + PyTuple_SET_ITEM(((PyObject *)driver->expr_comp), 1, expr_vars); + + for (dvar= driver->variables.first, i=0; dvar; dvar= dvar->next) { + PyTuple_SET_ITEM(expr_vars, i++, PyUnicode_InternFromString(dvar->name)); + } + } + else { + expr_vars= PyTuple_GET_ITEM(((PyObject *)driver->expr_comp), 1); + } + /* add target values to a dict that will be used as '__locals__' dict */ driver_vars = PyDict_New(); // XXX do we need to decref this? - for (dtar= driver->targets.first; dtar; dtar= dtar->next) { + for (dvar= driver->variables.first, i=0; dvar; dvar= dvar->next) { PyObject *driver_arg = NULL; float tval = 0.0f; - + /* try to get variable value */ - tval= driver_get_target_value(driver, dtar); + tval= driver_get_variable_value(driver, dvar); driver_arg= PyFloat_FromDouble((double)tval); - + /* try to add to dictionary */ - if (PyDict_SetItemString(driver_vars, dtar->name, driver_arg)) { + /* if (PyDict_SetItemString(driver_vars, dvar->name, driver_arg)) { */ + if (PyDict_SetItem(driver_vars, PyTuple_GET_ITEM(expr_vars, i++), driver_arg)) { /* use string interning for faster namespace creation */ /* this target failed - bad name */ if (targets_ok) { /* first one - print some extra info for easier identification */ fprintf(stderr, "\nBPY_pydriver_eval() - Error while evaluating PyDriver:\n"); targets_ok= 0; } - - fprintf(stderr, "\tBPY_pydriver_eval() - couldn't add variable '%s' to namespace \n", dtar->name); + + fprintf(stderr, "\tBPY_pydriver_eval() - couldn't add variable '%s' to namespace \n", dvar->name); // BPy_errors_to_report(NULL); // TODO - reports PyErr_Print(); PyErr_Clear(); } } -#if 0 // slow +#if 0 // slow, with this can avoid all Py_CompileString above. /* execute expression to get a value */ retval = PyRun_String(expr, Py_eval_input, bpy_pydriver_Dict, driver_vars); #else - if(driver->flag & DRIVER_FLAG_RECOMPILE || driver->expr_comp==NULL) { - Py_XDECREF(driver->expr_comp); - driver->expr_comp= Py_CompileString(expr, "<bpy driver>", Py_eval_input); - driver->flag &= ~DRIVER_FLAG_RECOMPILE; - } - if(driver->expr_comp) - retval= PyEval_EvalCode(driver->expr_comp, bpy_pydriver_Dict, driver_vars); + /* evaluate the compiled expression */ + if (expr_code) + retval= PyEval_EvalCode((PyCodeObject *)expr_code, bpy_pydriver_Dict, driver_vars); #endif /* decref the driver vars first... */ diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c index 82d1c0f262a..c0f296b5233 100644 --- a/source/blender/python/intern/bpy_interface.c +++ b/source/blender/python/intern/bpy_interface.c @@ -226,12 +226,15 @@ static void bpy_init_modules( void ) /* blender info that wont change at runtime, add into _bpy */ { + extern char bprogname[]; /* argv[0] from creator.c */ + PyObject *mod_dict= PyModule_GetDict(mod); char tmpstr[256]; PyModule_AddStringConstant(mod, "_HOME", BLI_gethome()); PyDict_SetItemString(mod_dict, "_VERSION", Py_BuildValue("(iii)", BLENDER_VERSION/100, BLENDER_VERSION%100, BLENDER_SUBVERSION)); sprintf(tmpstr, "%d.%02d (sub %d)", BLENDER_VERSION/100, BLENDER_VERSION%100, BLENDER_SUBVERSION); PyModule_AddStringConstant(mod, "_VERSION_STR", tmpstr); + PyModule_AddStringConstant(mod, "_BINPATH", bprogname); } /* add our own modules dir, this is a python package */ diff --git a/source/blender/python/intern/bpy_operator.c b/source/blender/python/intern/bpy_operator.c index 101f3619da4..d5f4b2f6d08 100644 --- a/source/blender/python/intern/bpy_operator.c +++ b/source/blender/python/intern/bpy_operator.c @@ -244,10 +244,7 @@ PyObject *BPY_operator_module( void ) static PyMethodDef pyop_as_string_meth ={"as_string", (PyCFunction) pyop_as_string, METH_VARARGS, NULL}; static PyMethodDef pyop_dir_meth = {"dir", (PyCFunction) pyop_dir, METH_NOARGS, NULL}; static PyMethodDef pyop_getrna_meth = {"get_rna", (PyCFunction) pyop_getrna, METH_O, NULL}; -// static PyMethodDef pyop_add_meth = {"add", (PyCFunction) PYOP_wrap_add, METH_O, NULL}; - static PyMethodDef pyop_add_macro_meth ={"add_macro", (PyCFunction) PYOP_wrap_add_macro, METH_O, NULL}; static PyMethodDef pyop_macro_def_meth ={"macro_define", (PyCFunction) PYOP_wrap_macro_define, METH_VARARGS, NULL}; - static PyMethodDef pyop_remove_meth = {"remove", (PyCFunction) PYOP_wrap_remove, METH_O, NULL}; PyObject *submodule = PyModule_New("_bpy.ops"); PyDict_SetItemString(PySys_GetObject("modules"), "_bpy.ops", submodule); @@ -256,10 +253,7 @@ PyObject *BPY_operator_module( void ) PyModule_AddObject( submodule, "as_string",PyCFunction_New(&pyop_as_string_meth,NULL) ); PyModule_AddObject( submodule, "dir", PyCFunction_New(&pyop_dir_meth, NULL) ); PyModule_AddObject( submodule, "get_rna", PyCFunction_New(&pyop_getrna_meth, NULL) ); -// PyModule_AddObject( submodule, "add", PyCFunction_New(&pyop_add_meth, NULL) ); - PyModule_AddObject( submodule, "add_macro", PyCFunction_New(&pyop_add_macro_meth, NULL) ); PyModule_AddObject( submodule, "macro_define",PyCFunction_New(&pyop_macro_def_meth, NULL) ); - PyModule_AddObject( submodule, "remove", PyCFunction_New(&pyop_remove_meth, NULL) ); return submodule; } diff --git a/source/blender/python/intern/bpy_operator_wrap.c b/source/blender/python/intern/bpy_operator_wrap.c index 3bd18d98563..11f36d5f8ec 100644 --- a/source/blender/python/intern/bpy_operator_wrap.c +++ b/source/blender/python/intern/bpy_operator_wrap.c @@ -42,226 +42,6 @@ #include "../generic/bpy_internal_import.h" // our own imports -#define PYOP_ATTR_UINAME "bl_label" -#define PYOP_ATTR_IDNAME "bl_idname" /* the name given by python */ -#define PYOP_ATTR_IDNAME_BL "_bl_idname" /* our own name converted into blender syntax, users wont see this */ -#define PYOP_ATTR_DESCRIPTION "__doc__" /* use pythons docstring */ -#define PYOP_ATTR_REGISTER "bl_register" /* True/False. if this python operator should be registered */ -#define PYOP_ATTR_UNDO "bl_undo" /* True/False. if this python operator should be undone */ - -static struct BPY_flag_def pyop_ret_flags[] = { - {"RUNNING_MODAL", OPERATOR_RUNNING_MODAL}, - {"CANCELLED", OPERATOR_CANCELLED}, - {"FINISHED", OPERATOR_FINISHED}, - {"PASS_THROUGH", OPERATOR_PASS_THROUGH}, - {NULL, 0} -}; - -/* This invoke function can take events and - * - * It is up to the pyot->py_invoke() python func to run pyot->py_exec() - * the invoke function gets the keyword props as a dict, but can parse them - * to py_exec like this... - * - * def op_exec(x=-1, y=-1, text=""): - * ... - * - * def op_invoke(event, prop_defs): - * prop_defs['x'] = event['x'] - * ... - * op_exec(**prop_defs) - * - * when there is no invoke function, C calls exec and sets the props. - * python class instance is stored in op->customdata so exec() can access - */ - - -#define PYOP_EXEC 1 -#define PYOP_INVOKE 2 -#define PYOP_POLL 3 -#define PYOP_DRAW 4 - -extern void BPY_update_modules( void ); //XXX temp solution - -static int PYTHON_OT_generic(int mode, bContext *C, wmOperatorType *ot, wmOperator *op, wmEvent *event, uiLayout *layout) -{ - PyObject *py_class = ot->pyop_data; - PyObject *args; - PyObject *ret= NULL, *py_class_instance, *item= NULL; - int ret_flag= (mode==PYOP_POLL ? 0:OPERATOR_CANCELLED); - PointerRNA ptr_context; - PointerRNA ptr_operator; - - PyGILState_STATE gilstate; - - bpy_context_set(C, &gilstate); - - args = PyTuple_New(1); - - /* poll has no 'op', should be ok still */ - /* use an rna instance as the first arg */ - RNA_pointer_create(NULL, &RNA_Operator, op, &ptr_operator); - PyTuple_SET_ITEM(args, 0, pyrna_struct_CreatePyObject(&ptr_operator)); - - py_class_instance = PyObject_Call(py_class, args, NULL); - Py_DECREF(args); - - if (py_class_instance==NULL) { /* Initializing the class worked, now run its invoke function */ - PyErr_Print(); - PyErr_Clear(); - } - else { - RNA_pointer_create(NULL, &RNA_Context, C, &ptr_context); - - if (mode==PYOP_INVOKE) { - PointerRNA ptr_event; - item= PyObject_GetAttrString(py_class, "invoke"); - args = PyTuple_New(3); - - RNA_pointer_create(NULL, &RNA_Event, event, &ptr_event); - - // PyTuple_SET_ITEM "steals" object reference, it is - // an object passed shouldn't be DECREF'ed - PyTuple_SET_ITEM(args, 1, pyrna_struct_CreatePyObject(&ptr_context)); - PyTuple_SET_ITEM(args, 2, pyrna_struct_CreatePyObject(&ptr_event)); - } - else if (mode==PYOP_EXEC) { - item= PyObject_GetAttrString(py_class, "execute"); - args = PyTuple_New(2); - - PyTuple_SET_ITEM(args, 1, pyrna_struct_CreatePyObject(&ptr_context)); - } - else if (mode==PYOP_POLL) { - item= PyObject_GetAttrString(py_class, "poll"); - args = PyTuple_New(2); - PyTuple_SET_ITEM(args, 1, pyrna_struct_CreatePyObject(&ptr_context)); - } - else if (mode==PYOP_DRAW) { - PointerRNA ptr_layout; - item= PyObject_GetAttrString(py_class, "draw"); - args = PyTuple_New(2); - - RNA_pointer_create(NULL, &RNA_UILayout, layout, &ptr_layout); - - // PyTuple_SET_ITEM "steals" object reference, it is - // an object passed shouldn't be DECREF'ed - PyTuple_SET_ITEM(args, 1, pyrna_struct_CreatePyObject(&ptr_context)); -#if 0 - PyTuple_SET_ITEM(args, 2, pyrna_struct_CreatePyObject(&ptr_layout)); -#else - { - /* mimic panels */ - PyObject *py_layout= pyrna_struct_CreatePyObject(&ptr_layout); - PyObject *pyname= PyUnicode_FromString("layout"); - - if(PyObject_GenericSetAttr(py_class_instance, pyname, py_layout)) { - PyErr_Print(); - PyErr_Clear(); - } - else { - Py_DECREF(py_layout); - } - - Py_DECREF(pyname); - } -#endif - } - PyTuple_SET_ITEM(args, 0, py_class_instance); - - ret = PyObject_Call(item, args, NULL); - - Py_DECREF(args); - Py_DECREF(item); - } - - if (ret == NULL) { /* covers py_class_instance failing too */ - if(op) - BPy_errors_to_report(op->reports); - } - else { - if (mode==PYOP_POLL) { - if (PyBool_Check(ret) == 0) { - PyErr_Format(PyExc_ValueError, "Python operator '%s.poll', did not return a bool value", ot->idname); - BPy_errors_to_report(op ? op->reports:NULL); /* prints and clears if NULL given */ - } - else { - ret_flag= ret==Py_True ? 1:0; - } - } else if(mode==PYOP_DRAW) { - /* pass */ - } else if (BPY_flag_from_seq(pyop_ret_flags, ret, &ret_flag) == -1) { - /* the returned value could not be converted into a flag */ - PyErr_Format(PyExc_ValueError, "Python operator, error using return value from \"%s\"\n", ot->idname); - BPy_errors_to_report(op ? op->reports:NULL); - ret_flag = OPERATOR_CANCELLED; - } - /* there is no need to copy the py keyword dict modified by - * pyot->py_invoke(), back to the operator props since they are just - * thrown away anyway - * - * If we ever want to do this and use the props again, - * it can be done with - pyrna_pydict_to_props(op->ptr, kw, "") - */ - - Py_DECREF(ret); - } - -#if 0 /* only for testing */ - - /* print operator return value */ - if (mode != PYOP_POLL) { - char flag_str[100]; - char class_name[100]; - BPY_flag_def *flag_def = pyop_ret_flags; - - strcpy(flag_str, ""); - - while(flag_def->name) { - if (ret_flag & flag_def->flag) { - if(flag_str[1]) - sprintf(flag_str, "%s | %s", flag_str, flag_def->name); - else - strcpy(flag_str, flag_def->name); - } - flag_def++; - } - - /* get class name */ - item= PyObject_GetAttrString(py_class, PYOP_ATTR_IDNAME); - strcpy(class_name, _PyUnicode_AsString(item)); - Py_DECREF(item); - - fprintf(stderr, "%s's %s returned %s\n", class_name, mode == PYOP_EXEC ? "execute" : "invoke", flag_str); - } -#endif - - bpy_context_clear(C, &gilstate); - - return ret_flag; -} - -static int PYTHON_OT_invoke(bContext *C, wmOperator *op, wmEvent *event) -{ - return PYTHON_OT_generic(PYOP_INVOKE, C, op->type, op, event, NULL); -} - -static int PYTHON_OT_execute(bContext *C, wmOperator *op) -{ - return PYTHON_OT_generic(PYOP_EXEC, C, op->type, op, NULL, NULL); -} - -static int PYTHON_OT_poll(bContext *C, wmOperatorType *ot) -{ - return PYTHON_OT_generic(PYOP_POLL, C, ot, NULL, NULL, NULL); -} - -static void PYTHON_OT_draw(bContext *C, wmOperator *op, uiLayout *layout) -{ - PYTHON_OT_generic(PYOP_DRAW, C, op->type, op, NULL, layout); -} - - - void operator_wrapper(wmOperatorType *ot, void *userdata) { /* take care not to overwrite anything set in @@ -299,288 +79,46 @@ void operator_wrapper(wmOperatorType *ot, void *userdata) } } - - - - -void PYTHON_OT_wrapper(wmOperatorType *ot, void *userdata) +void macro_wrapper(wmOperatorType *ot, void *userdata) { - PyObject *py_class = (PyObject *)userdata; - PyObject *item; + wmOperatorType *data = (wmOperatorType *)userdata; - /* identifiers */ - item= PyObject_GetAttrString(py_class, PYOP_ATTR_IDNAME_BL); - ot->idname= _PyUnicode_AsString(item); - Py_DECREF(item); - - item= PyObject_GetAttrString(py_class, PYOP_ATTR_UINAME); - if (item) { - ot->name= _PyUnicode_AsString(item); - Py_DECREF(item); - } - else { - ot->name= ot->idname; - PyErr_Clear(); - } - - item= PyObject_GetAttrString(py_class, PYOP_ATTR_DESCRIPTION); - ot->description= (item && PyUnicode_Check(item)) ? _PyUnicode_AsString(item):"undocumented python operator"; - Py_XDECREF(item); - - /* api callbacks, detailed checks dont on adding */ - if (PyObject_HasAttrString(py_class, "invoke")) - ot->invoke= PYTHON_OT_invoke; - //else - // ot->invoke= WM_operator_props_popup; /* could have an option for standard invokes */ + /* only copy a couple of things, the rest is set by the macro registration */ + ot->name = data->name; + ot->idname = data->idname; + ot->description = data->description; + ot->flag |= data->flag; /* append flags to the one set by registration */ + ot->pyop_poll = data->pyop_poll; + ot->ui = data->ui; + ot->ext = data->ext; - if (PyObject_HasAttrString(py_class, "execute")) - ot->exec= PYTHON_OT_execute; - if (PyObject_HasAttrString(py_class, "poll")) - ot->pyop_poll= PYTHON_OT_poll; - if (PyObject_HasAttrString(py_class, "draw")) - ot->ui= PYTHON_OT_draw; - - ot->pyop_data= userdata; + RNA_struct_blender_type_set(ot->ext.srna, ot); - /* flags */ - ot->flag= 0; - - item= PyObject_GetAttrString(py_class, PYOP_ATTR_REGISTER); - if (item) { - ot->flag |= PyObject_IsTrue(item)!=0 ? OPTYPE_REGISTER:0; - Py_DECREF(item); - } - else { - PyErr_Clear(); - } - item= PyObject_GetAttrString(py_class, PYOP_ATTR_UNDO); - if (item) { - ot->flag |= PyObject_IsTrue(item)!=0 ? OPTYPE_UNDO:0; - Py_DECREF(item); - } - else { - PyErr_Clear(); - } /* Can't use this because it returns a dict proxy * * item= PyObject_GetAttrString(py_class, "__dict__"); */ - item= ((PyTypeObject*)py_class)->tp_dict; - if(item) { - /* only call this so pyrna_deferred_register_props gives a useful error - * WM_operatortype_append_ptr will call RNA_def_struct_identifier - * later */ - RNA_def_struct_identifier(ot->srna, ot->idname); + { + PyObject *py_class = ot->ext.data; + PyObject *item= ((PyTypeObject*)py_class)->tp_dict; + if(item) { + /* only call this so pyrna_deferred_register_props gives a useful error + * WM_operatortype_append_ptr will call RNA_def_struct_identifier + * later */ + RNA_def_struct_identifier(ot->srna, ot->idname); - if(pyrna_deferred_register_props(ot->srna, item)!=0) { - /* failed to register operator props */ - PyErr_Print(); - PyErr_Clear(); + if(pyrna_deferred_register_props(ot->srna, item)!=0) { + /* failed to register operator props */ + PyErr_Print(); + PyErr_Clear(); + } } - } - else { - PyErr_Clear(); - } -} - -void PYTHON_OT_MACRO_wrapper(wmOperatorType *ot, void *userdata) -{ - PyObject *py_class = (PyObject *)userdata; - PyObject *item; - - /* identifiers */ - item= PyObject_GetAttrString(py_class, PYOP_ATTR_IDNAME_BL); - ot->idname= _PyUnicode_AsString(item); - Py_DECREF(item); - - item= PyObject_GetAttrString(py_class, PYOP_ATTR_UINAME); - if (item) { - ot->name= _PyUnicode_AsString(item); - Py_DECREF(item); - } - else { - ot->name= ot->idname; - PyErr_Clear(); - } - - item= PyObject_GetAttrString(py_class, PYOP_ATTR_DESCRIPTION); - ot->description= (item && PyUnicode_Check(item)) ? _PyUnicode_AsString(item):"undocumented python operator"; - Py_XDECREF(item); - - if (PyObject_HasAttrString(py_class, "poll")) - ot->pyop_poll= PYTHON_OT_poll; - if (PyObject_HasAttrString(py_class, "draw")) - ot->ui= PYTHON_OT_draw; - - ot->pyop_data= userdata; - - /* flags */ - ot->flag= OPTYPE_MACRO; /* macro at least */ - - item= PyObject_GetAttrString(py_class, PYOP_ATTR_REGISTER); - if (item) { - ot->flag |= PyObject_IsTrue(item)!=0 ? OPTYPE_REGISTER:0; - Py_DECREF(item); - } - else { - PyErr_Clear(); - } - item= PyObject_GetAttrString(py_class, PYOP_ATTR_UNDO); - if (item) { - ot->flag |= PyObject_IsTrue(item)!=0 ? OPTYPE_UNDO:0; - Py_DECREF(item); - } - else { - PyErr_Clear(); - } - - /* Can't use this because it returns a dict proxy - * - * item= PyObject_GetAttrString(py_class, "__dict__"); - */ - item= ((PyTypeObject*)py_class)->tp_dict; - if(item) { - /* only call this so pyrna_deferred_register_props gives a useful error - * WM_operatortype_append_macro_ptr will call RNA_def_struct_identifier - * later */ - RNA_def_struct_identifier(ot->srna, ot->idname); - - if(pyrna_deferred_register_props(ot->srna, item)!=0) { - /* failed to register operator props */ - PyErr_Print(); + else { PyErr_Clear(); - } } - else { - PyErr_Clear(); - } -} - - -/* pyOperators - Operators defined IN Python */ -PyObject *PYOP_wrap_add(PyObject *self, PyObject *py_class) -{ - PyObject *base_class, *item; - wmOperatorType *ot; - - - char *idname= NULL; - char idname_bl[OP_MAX_TYPENAME]; /* converted to blender syntax */ - - static struct BPY_class_attr_check pyop_class_attr_values[]= { - {PYOP_ATTR_IDNAME, 's', -1, OP_MAX_TYPENAME-3, 0}, /* -3 because a.b -> A_OT_b */ - {PYOP_ATTR_UINAME, 's', -1,-1, BPY_CLASS_ATTR_OPTIONAL}, - {PYOP_ATTR_DESCRIPTION, 's', -1,-1, BPY_CLASS_ATTR_NONE_OK}, - {"execute", 'f', 2, -1, BPY_CLASS_ATTR_OPTIONAL}, - {"invoke", 'f', 3, -1, BPY_CLASS_ATTR_OPTIONAL}, - {"poll", 'f', 2, -1, BPY_CLASS_ATTR_OPTIONAL}, - {"draw", 'f', 2, -1, BPY_CLASS_ATTR_OPTIONAL}, - {NULL, 0, 0, 0} - }; - - // in python would be... - //PyObject *optype = PyObject_GetAttrString(PyObject_GetAttrString(PyDict_GetItemString(PyEval_GetGlobals(), "bpy"), "types"), "Operator"); - - //PyObject bpy_mod= PyDict_GetItemString(PyEval_GetGlobals(), "bpy"); - PyObject *bpy_mod= PyImport_ImportModuleLevel("bpy", NULL, NULL, NULL, 0); - base_class = PyObject_GetAttrStringArgs(bpy_mod, 2, "types", "Operator"); - Py_DECREF(bpy_mod); - - if(BPY_class_validate("Operator", py_class, base_class, pyop_class_attr_values, NULL) < 0) { - return NULL; /* BPY_class_validate sets the error */ - } - Py_DECREF(base_class); - - /* class name is used for operator ID - this can be changed later if we want */ - item= PyObject_GetAttrString(py_class, PYOP_ATTR_IDNAME); - idname = _PyUnicode_AsString(item); - - - /* annoying conversion! */ - WM_operator_bl_idname(idname_bl, idname); - Py_DECREF(item); - - item= PyUnicode_FromString(idname_bl); - PyObject_SetAttrString(py_class, PYOP_ATTR_IDNAME_BL, item); - idname = _PyUnicode_AsString(item); - Py_DECREF(item); - /* end annoying conversion! */ - - - /* remove if it already exists */ - if ((ot=WM_operatortype_exists(idname))) { - if(ot->pyop_data) { - Py_XDECREF((PyObject*)ot->pyop_data); - } - WM_operatortype_remove(idname); - } - - Py_INCREF(py_class); - WM_operatortype_append_ptr(PYTHON_OT_wrapper, py_class); - - Py_RETURN_NONE; -} - -/* pyOperators - Macro Operators defined IN Python */ -PyObject *PYOP_wrap_add_macro(PyObject *self, PyObject *py_class) -{ - PyObject *base_class, *item; - wmOperatorType *ot; - - - char *idname= NULL; - char idname_bl[OP_MAX_TYPENAME]; /* converted to blender syntax */ - - static struct BPY_class_attr_check pyop_class_attr_values[]= { - {PYOP_ATTR_IDNAME, 's', -1, OP_MAX_TYPENAME-3, 0}, /* -3 because a.b -> A_OT_b */ - {PYOP_ATTR_UINAME, 's', -1,-1, BPY_CLASS_ATTR_OPTIONAL}, - {PYOP_ATTR_DESCRIPTION, 's', -1,-1, BPY_CLASS_ATTR_NONE_OK}, - {"poll", 'f', 2, -1, BPY_CLASS_ATTR_OPTIONAL}, - {"draw", 'f', 2, -1, BPY_CLASS_ATTR_OPTIONAL}, - {NULL, 0, 0, 0} - }; - - //PyObject bpy_mod= PyDict_GetItemString(PyEval_GetGlobals(), "bpy"); - PyObject *bpy_mod= PyImport_ImportModuleLevel("bpy", NULL, NULL, NULL, 0); - base_class = PyObject_GetAttrStringArgs(bpy_mod, 2, "types", "Macro"); - Py_DECREF(bpy_mod); - - if(BPY_class_validate("Macro", py_class, base_class, pyop_class_attr_values, NULL) < 0) { - return NULL; /* BPY_class_validate sets the error */ - } - Py_DECREF(base_class); - - /* class name is used for operator ID - this can be changed later if we want */ - item= PyObject_GetAttrString(py_class, PYOP_ATTR_IDNAME); - idname = _PyUnicode_AsString(item); - - - /* annoying conversion! */ - WM_operator_bl_idname(idname_bl, idname); - Py_DECREF(item); - - item= PyUnicode_FromString(idname_bl); - PyObject_SetAttrString(py_class, PYOP_ATTR_IDNAME_BL, item); - idname = _PyUnicode_AsString(item); - Py_DECREF(item); - /* end annoying conversion! */ - - - /* remove if it already exists */ - if ((ot=WM_operatortype_exists(idname))) { - if(ot->pyop_data) { - Py_XDECREF((PyObject*)ot->pyop_data); - } - WM_operatortype_remove(idname); - } - - Py_INCREF(py_class); - WM_operatortype_append_macro_ptr(PYTHON_OT_MACRO_wrapper, py_class); - - Py_RETURN_NONE; } PyObject *PYOP_wrap_macro_define(PyObject *self, PyObject *args) @@ -588,11 +126,11 @@ PyObject *PYOP_wrap_macro_define(PyObject *self, PyObject *args) wmOperatorType *ot; wmOperatorTypeMacro *otmacro; PyObject *macro; - PyObject *item; PointerRNA ptr_otmacro; + StructRNA *srna; char *opname; - char *macroname; + const char *macroname; if (!PyArg_ParseTuple(args, "Os:_bpy.ops.macro_define", ¯o, &opname)) return NULL; @@ -603,21 +141,8 @@ PyObject *PYOP_wrap_macro_define(PyObject *self, PyObject *args) } /* identifiers */ - item= PyObject_GetAttrString(macro, PYOP_ATTR_IDNAME_BL); - - if (!item) { - item= PyObject_GetAttrString(macro, PYOP_ATTR_IDNAME); - - if (!item) { - PyErr_Format(PyExc_ValueError, "Macro Define: not a valid Macro class"); - } else { - macroname= _PyUnicode_AsString(item); - PyErr_Format(PyExc_ValueError, "Macro Define: '%s' hasn't been registered yet", macroname); - } - return NULL; - } - - macroname= _PyUnicode_AsString(item); + srna= srna_from_self(macro); + macroname = RNA_struct_identifier(srna); ot = WM_operatortype_exists(macroname); @@ -633,40 +158,3 @@ PyObject *PYOP_wrap_macro_define(PyObject *self, PyObject *args) return pyrna_struct_CreatePyObject(&ptr_otmacro); } - -PyObject *PYOP_wrap_remove(PyObject *self, PyObject *value) -{ - PyObject *py_class; - char *idname= NULL; - wmOperatorType *ot; - - - if (PyUnicode_Check(value)) - idname = _PyUnicode_AsString(value); - else if (PyCFunction_Check(value)) { - PyObject *cfunc_self = PyCFunction_GetSelf(value); - if (cfunc_self) - idname = _PyUnicode_AsString(cfunc_self); - } - - if (idname==NULL) { - PyErr_SetString( PyExc_ValueError, "Expected the operator name as a string or the operator function"); - return NULL; - } - - if (!(ot= WM_operatortype_exists(idname))) { - PyErr_Format( PyExc_AttributeError, "Operator \"%s\" does not exists, cant remove", idname); - return NULL; - } - - if (!(py_class= (PyObject *)ot->pyop_data)) { - PyErr_Format( PyExc_AttributeError, "Operator \"%s\" was not created by python", idname); - return NULL; - } - - Py_XDECREF(py_class); - - WM_operatortype_remove(idname); - - Py_RETURN_NONE; -} diff --git a/source/blender/python/intern/bpy_operator_wrap.h b/source/blender/python/intern/bpy_operator_wrap.h index 939fedd1f2b..b55dd674dbf 100644 --- a/source/blender/python/intern/bpy_operator_wrap.h +++ b/source/blender/python/intern/bpy_operator_wrap.h @@ -28,9 +28,5 @@ #include <Python.h> /* these are used for operator methods, used by bpy_operator.c */ -PyObject *PYOP_wrap_add(PyObject *self, PyObject *args); -PyObject *PYOP_wrap_add_macro(PyObject *self, PyObject *args); PyObject *PYOP_wrap_macro_define(PyObject *self, PyObject *args); -PyObject *PYOP_wrap_remove(PyObject *self, PyObject *args); - #endif diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index 7c4e49e93e3..ace638914dc 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -1,3 +1,4 @@ + /** * $Id$ * @@ -53,6 +54,8 @@ #include "../generic/Mathutils.h" /* so we can have mathutils callbacks */ #include "../generic/IDProp.h" /* for IDprop lookups */ +static PyObject *prop_subscript_array_slice(PointerRNA *ptr, PropertyRNA *prop, int start, int stop, int length); + /* bpyrna vector/euler/quat callbacks */ static int mathutils_rna_array_cb_index= -1; /* index for our callbacks */ @@ -138,6 +141,8 @@ Mathutils_Callback mathutils_rna_matrix_cb = { (BaseMathSetIndexFunc) NULL }; +#define PROP_ALL_VECTOR_SUBTYPES PROP_TRANSLATION: case PROP_DIRECTION: case PROP_VELOCITY: case PROP_ACCELERATION: case PROP_XYZ: case PROP_XYZ|PROP_UNIT_LENGTH + PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop) { PyObject *ret= NULL; @@ -146,28 +151,24 @@ PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop) int subtype, totdim; int len; int is_thick; + int flag= RNA_property_flag(prop); /* disallow dynamic sized arrays to be wrapped since the size could change * to a size mathutils does not support */ - if ((RNA_property_type(prop) != PROP_FLOAT) || (RNA_property_flag(prop) & PROP_DYNAMIC)) + if ((RNA_property_type(prop) != PROP_FLOAT) || (flag & PROP_DYNAMIC)) return NULL; len= RNA_property_array_length(ptr, prop); subtype= RNA_property_subtype(prop); totdim= RNA_property_array_dimension(ptr, prop, NULL); - is_thick = (RNA_property_flag(prop) & PROP_THICK_WRAP); + is_thick = (flag & PROP_THICK_WRAP); if (totdim == 1 || (totdim == 2 && subtype == PROP_MATRIX)) { if(!is_thick) ret = pyrna_prop_CreatePyObject(ptr, prop); /* owned by the Mathutils PyObject */ switch(RNA_property_subtype(prop)) { - case PROP_TRANSLATION: - case PROP_DIRECTION: - case PROP_VELOCITY: - case PROP_ACCELERATION: - case PROP_XYZ: - case PROP_XYZ|PROP_UNIT_LENGTH: + case PROP_ALL_VECTOR_SUBTYPES: if(len>=2 && len <= 4) { if(is_thick) { ret= newVectorObject(NULL, len, Py_NEW, NULL); @@ -234,8 +235,15 @@ PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop) } } - if(ret==NULL) - ret = pyrna_prop_CreatePyObject(ptr, prop); /* TODO, convert to a python list */ + if(ret==NULL) { + if(is_thick) { + /* this is an array we cant reference (since its not thin wrappable) + * and cannot be coerced into a mathutils type, so return as a list */ + ret = prop_subscript_array_slice(ptr, prop, 0, len, len); + } else { + ret = pyrna_prop_CreatePyObject(ptr, prop); /* owned by the Mathutils PyObject */ + } + } #endif @@ -244,8 +252,6 @@ PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop) #endif -static StructRNA *pyrna_struct_as_srna(PyObject *self); - static int pyrna_struct_compare( BPy_StructRNA * a, BPy_StructRNA * b ) { return (a->ptr.data==b->ptr.data) ? 0 : -1; @@ -1001,7 +1007,7 @@ static PyObject *prop_subscript_collection_str(BPy_PropertyRNA *self, char *keyn } /* static PyObject *prop_subscript_array_str(BPy_PropertyRNA *self, char *keyname) */ -static PyObject *prop_subscript_collection_slice(BPy_PropertyRNA *self, int start, int stop) +static PyObject *prop_subscript_collection_slice(PointerRNA *ptr, PropertyRNA *prop, int start, int stop, int length) { PointerRNA newptr; PyObject *list = PyList_New(stop - start); @@ -1010,8 +1016,8 @@ static PyObject *prop_subscript_collection_slice(BPy_PropertyRNA *self, int star start = MIN2(start,stop); /* values are clamped from */ for(count = start; count < stop; count++) { - if(RNA_property_collection_lookup_int(&self->ptr, self->prop, count - start, &newptr)) { - PyList_SetItem(list, count - start, pyrna_struct_CreatePyObject(&newptr)); + if(RNA_property_collection_lookup_int(ptr, prop, count - start, &newptr)) { + PyList_SET_ITEM(list, count - start, pyrna_struct_CreatePyObject(&newptr)); } else { Py_DECREF(list); @@ -1023,16 +1029,72 @@ static PyObject *prop_subscript_collection_slice(BPy_PropertyRNA *self, int star return list; } -static PyObject *prop_subscript_array_slice(BPy_PropertyRNA *self, int start, int stop) + +/* TODO - dimensions + * note: could also use pyrna_prop_to_py_index(self, count) in a loop but its a lot slower + * since at the moment it reads (and even allocates) the entire array for each index. + */ +#define PYRNA_STACK_ARRAY 32 +static PyObject *prop_subscript_array_slice(PointerRNA *ptr, PropertyRNA *prop, int start, int stop, int length) { PyObject *list = PyList_New(stop - start); int count; - start = MIN2(start,stop); /* values are clamped from PySlice_GetIndicesEx */ + switch (RNA_property_type(prop)) { + case PROP_FLOAT: + { + float values_stack[PYRNA_STACK_ARRAY]; + float *values; + if(length > PYRNA_STACK_ARRAY) { values= PyMem_MALLOC(sizeof(float) * length); } + else { values= values_stack; } + RNA_property_float_get_array(ptr, prop, values); + + for(count=start; count<stop; count++) + PyList_SET_ITEM(list, count-start, PyFloat_FromDouble(values[count])); - for(count = start; count < stop; count++) - PyList_SetItem(list, count - start, pyrna_prop_to_py_index(self, count)); + if(values != values_stack) { + PyMem_FREE(values); + } + break; + } + case PROP_BOOLEAN: + { + int values_stack[PYRNA_STACK_ARRAY]; + int *values; + if(length > PYRNA_STACK_ARRAY) { values= PyMem_MALLOC(sizeof(int) * length); } + else { values= values_stack; } + RNA_property_boolean_get_array(ptr, prop, values); + for(count=start; count<stop; count++) + PyList_SET_ITEM(list, count-start, PyBool_FromLong(values[count])); + + if(values != values_stack) { + PyMem_FREE(values); + } + break; + } + case PROP_INT: + { + int values_stack[PYRNA_STACK_ARRAY]; + int *values; + if(length > PYRNA_STACK_ARRAY) { values= PyMem_MALLOC(sizeof(int) * length); } + else { values= values_stack; } + + RNA_property_int_get_array(ptr, prop, values); + for(count=start; count<stop; count++) + PyList_SET_ITEM(list, count-start, PyLong_FromSsize_t(values[count])); + + if(values != values_stack) { + PyMem_FREE(values); + } + break; + } + default: + /* probably will never happen */ + PyErr_SetString(PyExc_TypeError, "not an array type"); + Py_DECREF(list); + list= NULL; + } return list; } @@ -1059,7 +1121,7 @@ static PyObject *prop_subscript_collection(BPy_PropertyRNA *self, PyObject *key) return PyList_New(0); } else if (step == 1) { - return prop_subscript_collection_slice(self, start, stop); + return prop_subscript_collection_slice(&self->ptr, self->prop, start, stop, len); } else { PyErr_SetString(PyExc_TypeError, "slice steps not supported with rna"); @@ -1094,7 +1156,7 @@ static PyObject *prop_subscript_array(BPy_PropertyRNA *self, PyObject *key) return PyList_New(0); } else if (step == 1) { - return prop_subscript_array_slice(self, start, stop); + return prop_subscript_array_slice(&self->ptr, self->prop, start, stop, len); } else { PyErr_SetString(PyExc_TypeError, "slice steps not supported with rna"); @@ -1119,21 +1181,93 @@ static PyObject *pyrna_prop_subscript( BPy_PropertyRNA *self, PyObject *key ) return NULL; } -static int prop_subscript_ass_array_slice(BPy_PropertyRNA *self, int begin, int end, PyObject *value) +/* could call (pyrna_py_to_prop_index(self, i, value) in a loop but it is slow */ +static int prop_subscript_ass_array_slice(PointerRNA *ptr, PropertyRNA *prop, int start, int stop, int length, PyObject *value_orig) { + PyObject *value; int count; + void *values_alloc= NULL; + int ret= 0; - /* values are clamped from */ - begin = MIN2(begin,end); + if(value_orig == NULL) { + PyErr_SetString(PyExc_TypeError, "invalid slice assignment, deleting with list types is not supported by StructRNA."); + return -1; + } - for(count = begin; count < end; count++) { - if(pyrna_py_to_prop_index(self, count - begin, value) == -1) { - /* TODO - this is wrong since some values have been assigned... will need to fix that */ - return -1; /* pyrna_struct_CreatePyObject should set the error */ + if(!(value=PySequence_Fast(value_orig, "invalid slice assignment, type is not a sequence"))) { + return -1; + } + + if(PySequence_Fast_GET_SIZE(value) != stop-start) { + Py_DECREF(value); + PyErr_SetString(PyExc_TypeError, "invalid slice assignment, resizing StructRNA arrays isn't supported."); + return -1; + } + + switch (RNA_property_type(prop)) { + case PROP_FLOAT: + { + float values_stack[PYRNA_STACK_ARRAY]; + float *values; + if(length > PYRNA_STACK_ARRAY) { values= values_alloc= PyMem_MALLOC(sizeof(float) * length); } + else { values= values_stack; } + if(start != 0 || stop != length) /* partial assignment? - need to get the array */ + RNA_property_float_get_array(ptr, prop, values); + + for(count=start; count<stop; count++) + values[count] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, count-start)); + + if(PyErr_Occurred()) ret= -1; + else RNA_property_float_set_array(ptr, prop, values); + break; + } + case PROP_BOOLEAN: + { + int values_stack[PYRNA_STACK_ARRAY]; + int *values; + if(length > PYRNA_STACK_ARRAY) { values= values_alloc= PyMem_MALLOC(sizeof(int) * length); } + else { values= values_stack; } + + if(start != 0 || stop != length) /* partial assignment? - need to get the array */ + RNA_property_boolean_get_array(ptr, prop, values); + + for(count=start; count<stop; count++) + values[count] = PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, count-start)); + + if(PyErr_Occurred()) ret= -1; + else RNA_property_boolean_set_array(ptr, prop, values); + break; } + case PROP_INT: + { + int values_stack[PYRNA_STACK_ARRAY]; + int *values; + if(length > PYRNA_STACK_ARRAY) { values= values_alloc= PyMem_MALLOC(sizeof(int) * length); } + else { values= values_stack; } + + if(start != 0 || stop != length) /* partial assignment? - need to get the array */ + RNA_property_int_get_array(ptr, prop, values); + + for(count=start; count<stop; count++) + values[count] = PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, count-start)); + + if(PyErr_Occurred()) ret= -1; + else RNA_property_int_set_array(ptr, prop, values); + break; + } + default: + PyErr_SetString(PyExc_TypeError, "not an array type"); + ret= -1; } - return 0; + Py_DECREF(value); + + if(values_alloc) { + PyMem_FREE(values_alloc); + } + + return ret; + } static int prop_subscript_ass_array_int(BPy_PropertyRNA *self, int keynum, PyObject *value) @@ -1182,7 +1316,7 @@ static int pyrna_prop_ass_subscript( BPy_PropertyRNA *self, PyObject *key, PyObj return 0; } else if (step == 1) { - return prop_subscript_ass_array_slice(self, start, stop, value); + return prop_subscript_ass_array_slice(&self->ptr, self->prop, start, stop, len, value); } else { PyErr_SetString(PyExc_TypeError, "slice steps not supported with rna"); @@ -1872,6 +2006,16 @@ static PyObject *pyrna_prop_getattro( BPy_PropertyRNA *self, PyObject *pyname ) } } } + else { + /* annoying exception, maybe we need to have different types for this... */ + if((strcmp(name, "__getitem__")==0 || strcmp(name, "__setitem__")==0) && + (RNA_property_type(self->prop) != PROP_COLLECTION) && + RNA_property_array_check(&self->ptr, self->prop)==0 + ) { + PyErr_SetString(PyExc_AttributeError, "PropertyRNA - no __getitem__ support for this type"); + return NULL; + } + } /* The error raised here will be displayed */ return PyObject_GenericGetAttr((PyObject *)self, pyname); @@ -2104,10 +2248,11 @@ static void foreach_attr_type( BPy_PropertyRNA *self, char *attr, RawPropertyType *raw_type, int *attr_tot, int *attr_signed ) { PropertyRNA *prop; - *raw_type= -1; + *raw_type= PROP_RAW_UNSET; *attr_tot= 0; *attr_signed= FALSE; + /* note: this is fail with zero length lists, so dont let this get caled in that case */ RNA_PROP_BEGIN(&self->ptr, itemptr, self->prop) { prop = RNA_struct_find_property(&itemptr, attr); *raw_type= RNA_property_raw_type(prop); @@ -2130,7 +2275,8 @@ static int foreach_parse_args( int target_tot; #endif - *size= *raw_type= *attr_tot= *attr_signed= FALSE; + *size= *attr_tot= *attr_signed= FALSE; + *raw_type= PROP_RAW_UNSET; if(!PyArg_ParseTuple(args, "sO", attr, seq) || (!PySequence_Check(*seq) && PyObject_CheckBuffer(*seq))) { PyErr_SetString( PyExc_TypeError, "foreach_get(attr, sequence) expects a string and a sequence" ); @@ -2163,6 +2309,12 @@ static int foreach_parse_args( #endif } + /* check 'attr_tot' otherwise we dont know if any values were set + * this isnt ideal because it means running on an empty list may fail silently when its not compatible. */ + if (*size == 0 && *attr_tot != 0) { + PyErr_SetString( PyExc_AttributeError, "attribute does not support foreach method" ); + return -1; + } return 0; } @@ -2184,6 +2336,8 @@ static int foreach_compat_buffer(RawPropertyType raw_type, int attr_signed, cons return (f=='f') ? 1:0; case PROP_RAW_DOUBLE: return (f=='d') ? 1:0; + case PROP_RAW_UNSET: + return 0; } return 0; @@ -2248,6 +2402,9 @@ static PyObject *foreach_getset(BPy_PropertyRNA *self, PyObject *args, int set) case PROP_RAW_DOUBLE: ((double *)array)[i]= (double)PyFloat_AsDouble(item); break; + case PROP_RAW_UNSET: + /* should never happen */ + break; } Py_DECREF(item); @@ -2299,6 +2456,9 @@ static PyObject *foreach_getset(BPy_PropertyRNA *self, PyObject *args, int set) case PROP_RAW_DOUBLE: item= PyFloat_FromDouble( (double) ((double *)array)[i] ); break; + case PROP_RAW_UNSET: + /* should never happen */ + break; } PySequence_SetItem(seq, i, item); @@ -2343,14 +2503,8 @@ PyObject *pyrna_prop_iter(BPy_PropertyRNA *self) PyObject *iter; if(RNA_property_array_check(&self->ptr, self->prop)) { - int len = pyrna_prop_array_length(self); - int i; - PyErr_Clear(); - ret = PyList_New(len); - - for (i=0; i < len; i++) { - PyList_SET_ITEM(ret, i, pyrna_prop_to_py_index(self, i)); - } + int len= pyrna_prop_array_length(self); + ret = prop_subscript_array_slice(&self->ptr, self->prop, 0, len, len); } else if ((ret = pyrna_prop_values(self))) { /* do nothing */ @@ -2449,29 +2603,48 @@ PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *data) { PyObject *ret; int type = RNA_property_type(prop); - + int flag = RNA_property_flag(prop); int a; if(RNA_property_array_check(ptr, prop)) { int len = RNA_property_array_length(ptr, prop); /* resolve the array from a new pytype */ - ret = PyTuple_New(len); /* kazanbas: TODO make multidim sequences here */ switch (type) { case PROP_BOOLEAN: + ret = PyTuple_New(len); for(a=0; a<len; a++) PyTuple_SET_ITEM(ret, a, PyBool_FromLong( ((int*)data)[a] )); break; case PROP_INT: + ret = PyTuple_New(len); for(a=0; a<len; a++) PyTuple_SET_ITEM(ret, a, PyLong_FromSsize_t( (Py_ssize_t)((int*)data)[a] )); break; case PROP_FLOAT: - for(a=0; a<len; a++) - PyTuple_SET_ITEM(ret, a, PyFloat_FromDouble( ((float*)data)[a] )); + switch(RNA_property_subtype(prop)) { + case PROP_ALL_VECTOR_SUBTYPES: + ret= newVectorObject(data, len, Py_NEW, NULL); + break; + case PROP_MATRIX: + if(len==16) { + ret= newMatrixObject(data, 4, 4, Py_NEW, NULL); + break; + } + else if (len==9) { + ret= newMatrixObject(data, 3, 3, Py_NEW, NULL); + break; + } + /* pass through */ + default: + ret = PyTuple_New(len); + for(a=0; a<len; a++) + PyTuple_SET_ITEM(ret, a, PyFloat_FromDouble( ((float*)data)[a] )); + + } break; default: PyErr_Format(PyExc_TypeError, "RNA Error: unknown array type \"%d\" (pyrna_param_to_py)", type); @@ -2493,7 +2666,10 @@ PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *data) break; case PROP_STRING: { - ret = PyUnicode_FromString( *(char**)data ); + if(flag & PROP_THICK_WRAP) + ret = PyUnicode_FromString( (char*)data ); + else + ret = PyUnicode_FromString( *(char**)data ); break; } case PROP_ENUM: @@ -2505,7 +2681,6 @@ PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *data) { PointerRNA newptr; StructRNA *type= RNA_property_pointer_type(ptr, prop); - int flag = RNA_property_flag(prop); if(flag & PROP_RNAPTR) { /* in this case we get the full ptr */ @@ -2566,11 +2741,13 @@ static PyObject * pyrna_func_call(PyObject *self, PyObject *args, PyObject *kw) PointerRNA funcptr; ParameterList parms; ParameterIterator iter; - PropertyRNA *pret, *parm; + PropertyRNA *parm; PyObject *ret, *item; - int i, args_len, parms_len, flag, err= 0, kw_tot= 0, kw_arg; + int i, args_len, parms_len, ret_len, flag, err= 0, kw_tot= 0, kw_arg; const char *parm_id; - void *retdata= NULL; + + PropertyRNA *pret_single= NULL; + void *retdata_single= NULL; /* Should never happen but it does in rare cases */ if(self_ptr==NULL) { @@ -2588,14 +2765,15 @@ static PyObject * pyrna_func_call(PyObject *self, PyObject *args, PyObject *kw) * the same ID as the functions. */ RNA_pointer_create(self_ptr->id.data, &RNA_Function, self_func, &funcptr); - pret= RNA_function_return(self_func); args_len= PyTuple_GET_SIZE(args); RNA_parameter_list_create(&parms, self_ptr, self_func); RNA_parameter_list_begin(&parms, &iter); - parms_len = RNA_parameter_list_size(&parms); + parms_len= RNA_parameter_list_size(&parms); + ret_len= 0; if(args_len + (kw ? PyDict_Size(kw):0) > parms_len) { + RNA_parameter_list_end(&iter); PyErr_Format(PyExc_TypeError, "%.200s.%.200s(): takes at most %d arguments, got %d", RNA_struct_identifier(self_ptr->type), RNA_function_identifier(self_func), parms_len, args_len); err= -1; } @@ -2603,14 +2781,20 @@ static PyObject * pyrna_func_call(PyObject *self, PyObject *args, PyObject *kw) /* parse function parameters */ for (i= 0; iter.valid && err==0; RNA_parameter_list_next(&iter)) { parm= iter.parm; + flag= RNA_property_flag(parm); + + /* only useful for single argument returns, we'll need another list loop for multiple */ + if (flag & PROP_RETURN) { + ret_len++; + if (pret_single==NULL) { + pret_single= parm; + retdata_single= iter.data; + } - if (parm==pret) { - retdata= iter.data; continue; } parm_id= RNA_property_identifier(parm); - flag= RNA_property_flag(parm); item= NULL; if ((i < args_len) && (flag & PROP_REQUIRED)) { @@ -2655,6 +2839,8 @@ static PyObject * pyrna_func_call(PyObject *self, PyObject *args, PyObject *kw) break; } } + + RNA_parameter_list_end(&iter); /* Check if we gave args that dont exist in the function @@ -2742,8 +2928,25 @@ static PyObject * pyrna_func_call(PyObject *self, PyObject *args, PyObject *kw) /* return value */ if(err==0) { - if(pret) { - ret= pyrna_param_to_py(&funcptr, pret, retdata); + if (ret_len > 0) { + if (ret_len > 1) { + ret= PyTuple_New(ret_len); + i= 0; /* arg index */ + + RNA_parameter_list_begin(&parms, &iter); + + for(; iter.valid; RNA_parameter_list_next(&iter)) { + parm= iter.parm; + flag= RNA_property_flag(parm); + + if (flag & PROP_RETURN) + PyTuple_SET_ITEM(ret, i++, pyrna_param_to_py(&funcptr, parm, iter.data)); + } + + RNA_parameter_list_end(&iter); + } + else + ret= pyrna_param_to_py(&funcptr, pret_single, retdata_single); /* possible there is an error in conversion */ if(ret==NULL) @@ -3354,7 +3557,7 @@ PyObject *BPY_rna_props( void ) return submodule; } -static StructRNA *pyrna_struct_as_srna(PyObject *self) +StructRNA *pyrna_struct_as_srna(PyObject *self) { BPy_StructRNA *py_srna = NULL; StructRNA *srna; @@ -3395,7 +3598,7 @@ static StructRNA *pyrna_struct_as_srna(PyObject *self) /* Orphan functions, not sure where they should go */ /* get the srna for methods attached to types */ /* */ -static StructRNA *srna_from_self(PyObject *self) +StructRNA *srna_from_self(PyObject *self) { /* a bit sloppy but would cause a very confusing bug if * an error happened to be set here */ @@ -3937,31 +4140,26 @@ static int bpy_class_validate(PointerRNA *dummyptr, void *py_data, int *have_fun item = PyObject_GetAttrString(py_class, identifier); if (item==NULL) { - /* Sneaky workaround to use the class name as the bl_idname */ - if(strcmp(identifier, "bl_idname") == 0) { - item= PyObject_GetAttrString(py_class, "__name__"); - if(item) { - Py_DECREF(item); /* no need to keep a ref, the class owns it */ +#define BPY_REPLACEMENT_STRING(rna_attr, py_attr) \ + if(strcmp(identifier, rna_attr) == 0) { \ + item= PyObject_GetAttrString(py_class, py_attr); \ + if(item && item != Py_None) { \ + if(pyrna_py_to_prop(dummyptr, prop, NULL, item, "validating class error:") != 0) { \ + Py_DECREF(item); \ + return -1; \ + } \ + } \ + Py_XDECREF(item); \ + } \ - if(pyrna_py_to_prop(dummyptr, prop, NULL, item, "validating class error:") != 0) - return -1; - } - } -#if 0 - if(strcmp(identifier, "bl_label") == 0) { - item= PyObject_GetAttrString(py_class, "__doc__"); + BPY_REPLACEMENT_STRING("bl_idname", "__name__"); + BPY_REPLACEMENT_STRING("bl_description", "__doc__"); - if(item) { - Py_DECREF(item); /* no need to keep a ref, the class owns it */ +#undef BPY_REPLACEMENT_STRING - if(pyrna_py_to_prop(dummyptr, prop, NULL, item, "validating class error:") != 0) - return -1; - } - } -#endif if (item == NULL && (((flag & PROP_REGISTER_OPTIONAL) != PROP_REGISTER_OPTIONAL))) { PyErr_Format( PyExc_AttributeError, "expected %.200s, %.200s class to have an \"%.200s\" attribute", class_type, py_class_name, identifier); return -1; @@ -3982,15 +4180,18 @@ static int bpy_class_validate(PointerRNA *dummyptr, void *py_data, int *have_fun extern void BPY_update_modules( void ); //XXX temp solution +/* TODO - multiple return values like with rna functions */ static int bpy_class_call(PointerRNA *ptr, FunctionRNA *func, ParameterList *parms) { PyObject *args; PyObject *ret= NULL, *py_class, *py_class_instance, *item, *parmitem; - PropertyRNA *pret= NULL, *parm; + PropertyRNA *parm; ParameterIterator iter; PointerRNA funcptr; - void *retdata= NULL; - int err= 0, i, flag; + int err= 0, i, flag, ret_len=0; + + PropertyRNA *pret_single= NULL; + void *retdata_single= NULL; PyGILState_STATE gilstate; @@ -4016,10 +4217,9 @@ static int bpy_class_call(PointerRNA *ptr, FunctionRNA *func, ParameterList *par if (py_class_instance) { /* Initializing the class worked, now run its invoke function */ item= PyObject_GetAttrString(py_class, RNA_function_identifier(func)); - flag= RNA_function_flag(func); +// flag= RNA_function_flag(func); if(item) { - pret= RNA_function_return(func); RNA_pointer_create(NULL, &RNA_Function, func, &funcptr); args = PyTuple_New(rna_function_arg_count(func)); /* first arg is included in 'item' */ @@ -4030,9 +4230,16 @@ static int bpy_class_call(PointerRNA *ptr, FunctionRNA *func, ParameterList *par /* parse function parameters */ for (i= 1; iter.valid; RNA_parameter_list_next(&iter)) { parm= iter.parm; + flag= RNA_property_flag(parm); + + /* only useful for single argument returns, we'll need another list loop for multiple */ + if (flag & PROP_RETURN) { + ret_len++; + if (pret_single==NULL) { + pret_single= parm; + retdata_single= iter.data; + } - if (parm==pret) { - retdata= iter.data; continue; } @@ -4043,6 +4250,7 @@ static int bpy_class_call(PointerRNA *ptr, FunctionRNA *func, ParameterList *par ret = PyObject_Call(item, args, NULL); + RNA_parameter_list_end(&iter); Py_DECREF(item); Py_DECREF(args); } @@ -4062,8 +4270,39 @@ static int bpy_class_call(PointerRNA *ptr, FunctionRNA *func, ParameterList *par err= -1; } else { - if(retdata) - err= pyrna_py_to_prop(&funcptr, pret, retdata, ret, "calling class function:"); + if(ret_len==1) { + err= pyrna_py_to_prop(&funcptr, pret_single, retdata_single, ret, "calling class function:"); + } + else if (ret_len > 1) { + + if(PyTuple_Check(ret)==0) { + PyErr_Format(PyExc_RuntimeError, "expected class %.200s, function %.200s to return a tuple of size %d.", RNA_struct_identifier(ptr->type), RNA_function_identifier(func), ret_len); + err= -1; + } + else if (PyTuple_GET_SIZE(ret) != ret_len) { + PyErr_Format(PyExc_RuntimeError, "class %.200s, function %.200s to returned %d items, expected %d.", RNA_struct_identifier(ptr->type), RNA_function_identifier(func), PyTuple_GET_SIZE(ret), ret_len); + err= -1; + } + else { + + RNA_parameter_list_begin(parms, &iter); + + /* parse function parameters */ + for (i= 0; iter.valid; RNA_parameter_list_next(&iter)) { + parm= iter.parm; + flag= RNA_property_flag(parm); + + /* only useful for single argument returns, we'll need another list loop for multiple */ + if (flag & PROP_RETURN) { + err= pyrna_py_to_prop(&funcptr, parm, iter.data, PyTuple_GET_ITEM(ret, i++), "calling class function:"); + if(err) + break; + } + } + + RNA_parameter_list_end(&iter); + } + } Py_DECREF(ret); } diff --git a/source/blender/python/intern/bpy_rna.h b/source/blender/python/intern/bpy_rna.h index 37f6af36726..74a16b43dc1 100644 --- a/source/blender/python/intern/bpy_rna.h +++ b/source/blender/python/intern/bpy_rna.h @@ -62,6 +62,9 @@ typedef struct { /* cheap trick */ #define BPy_BaseTypeRNA BPy_PropertyRNA +StructRNA *srna_from_self(PyObject *self); +StructRNA *pyrna_struct_as_srna(PyObject *self); + void BPY_rna_init( void ); PyObject *BPY_rna_module( void ); void BPY_update_rna_module( void ); diff --git a/source/blender/python/intern/bpy_util.c b/source/blender/python/intern/bpy_util.c index db3798146d3..2cd1337fba7 100644 --- a/source/blender/python/intern/bpy_util.c +++ b/source/blender/python/intern/bpy_util.c @@ -35,95 +35,6 @@ bContext* __py_context = NULL; bContext* BPy_GetContext(void) { return __py_context; }; void BPy_SetContext(bContext *C) { __py_context= C; }; - -PyObject *BPY_flag_to_list(struct BPY_flag_def *flagdef, int flag) -{ - PyObject *list = PyList_New(0); - - PyObject *item; - BPY_flag_def *fd; - - fd= flagdef; - while(fd->name) { - if (fd->flag & flag) { - item = PyUnicode_FromString(fd->name); - PyList_Append(list, item); - Py_DECREF(item); - } - fd++; - } - - return list; - -} - -static char *bpy_flag_error_str(BPY_flag_def *flagdef) -{ - BPY_flag_def *fd= flagdef; - DynStr *dynstr= BLI_dynstr_new(); - char *cstring; - - BLI_dynstr_append(dynstr, "Error converting a sequence of strings into a flag.\n\tExpected only these strings...\n\t"); - - while(fd->name) { - BLI_dynstr_appendf(dynstr, fd!=flagdef?", '%s'":"'%s'", fd->name); - fd++; - } - - cstring = BLI_dynstr_get_cstring(dynstr); - BLI_dynstr_free(dynstr); - return cstring; -} - -int BPY_flag_from_seq(BPY_flag_def *flagdef, PyObject *seq, int *flag) -{ - int i, error_val= 0; - char *cstring; - PyObject *item; - BPY_flag_def *fd; - *flag = 0; - - if (PySequence_Check(seq)) { - i= PySequence_Length(seq); - - while(i--) { - item = PySequence_ITEM(seq, i); - cstring= _PyUnicode_AsString(item); - if(cstring) { - fd= flagdef; - while(fd->name) { - if (strcmp(cstring, fd->name) == 0) { - (*flag) |= fd->flag; - break; - } - fd++; - } - if (fd->name==NULL) { /* could not find a match */ - error_val= 1; - } - } else { - error_val= 1; - } - Py_DECREF(item); - } - } - else { - error_val= 1; - } - - if (*flag == 0) - error_val = 1; - - if (error_val) { - char *buf = bpy_flag_error_str(flagdef); - PyErr_SetString(PyExc_AttributeError, buf); - MEM_freeN(buf); - return -1; /* error value */ - } - - return 0; /* ok */ -} - /* for debugging */ void PyObSpit(char *name, PyObject *var) { fprintf(stderr, "<%s> : ", name); diff --git a/source/blender/python/intern/bpy_util.h b/source/blender/python/intern/bpy_util.h index 83fa7a5b7c4..dcf957969e8 100644 --- a/source/blender/python/intern/bpy_util.h +++ b/source/blender/python/intern/bpy_util.h @@ -36,16 +36,6 @@ struct EnumPropertyItem; struct ReportList; -/* for internal use only, so python can interchange a sequence of strings with flags */ -typedef struct BPY_flag_def { - const char *name; - int flag; -} BPY_flag_def; - - -PyObject *BPY_flag_to_list(BPY_flag_def *flagdef, int flag); -int BPY_flag_from_seq(BPY_flag_def *flagdef, PyObject *seq, int *flag); - void PyObSpit(char *name, PyObject *var); void PyLineSpit(void); void BPY_getFileAndNum(char **filename, int *lineno); diff --git a/source/blender/python/sphinx_doc_gen.py b/source/blender/python/sphinx_doc_gen.py index c8e283ac447..afa117ea60f 100644 --- a/source/blender/python/sphinx_doc_gen.py +++ b/source/blender/python/sphinx_doc_gen.py @@ -23,10 +23,10 @@ Usage, run this script from blenders root path once you have compiled blender ./blender.bin -b -P /b/source/blender/python/sphinx_doc_gen.py -This will generate python files in "./source/blender/python/doc/bpy/sphinx-in" +This will generate python files in "./source/blender/python/doc/sphinx-in" Generate html docs by running... - sphinx-build source/blender/python/doc/bpy/sphinx-in source/blender/python/doc/bpy/sphinx-out + sphinx-build source/blender/python/doc/sphinx-in source/blender/python/doc/sphinx-out ''' # if you dont have graphvis installed ommit the --graph arg. @@ -115,7 +115,7 @@ def rna2sphinx(BASEPATH): #if not struct.identifier.startswith("Sc") and not struct.identifier.startswith("I"): # return - #if not struct.identifier.startswith("Bone"): + #if not struct.identifier == "Object": # return filepath = os.path.join(BASEPATH, "bpy.types.%s.rst" % struct.identifier) @@ -182,8 +182,17 @@ def rna2sphinx(BASEPATH): for prop in func.args: write_param(" ", fw, prop) - if func.return_value: - write_param(" ", fw, func.return_value, is_return=True) + if len(func.return_values) == 1: + write_param(" ", fw, func.return_values[0], is_return=True) + else: # multiple return values + fw(" :return (%s):\n" % ", ".join([prop.identifier for prop in func.return_values])) + for prop in func.return_values: + type_descr = prop.get_type_description(as_arg=True, class_fmt=":class:`%s`") + descr = prop.description + if not descr: + descr = prop.name + fw(" `%s`, %s, %s\n\n" % (prop.identifier, descr, type_descr)) + fw("\n") @@ -265,9 +274,9 @@ if __name__ == '__main__': print("\nError, this script must run from inside blender2.5") print(script_help_msg) else: - # os.system("rm source/blender/python/doc/bpy/sphinx-in/*.rst") - # os.system("rm -rf source/blender/python/doc/bpy/sphinx-out/*") - rna2sphinx('source/blender/python/doc/bpy/sphinx-in') + # os.system("rm source/blender/python/doc/sphinx-in/*.rst") + # os.system("rm -rf source/blender/python/doc/sphinx-out/*") + rna2sphinx('source/blender/python/doc/sphinx-in') import sys sys.exit() diff --git a/source/blender/quicktime/apple/Makefile b/source/blender/quicktime/apple/Makefile index 19f87ed31e3..70f3f05c5f0 100644 --- a/source/blender/quicktime/apple/Makefile +++ b/source/blender/quicktime/apple/Makefile @@ -31,6 +31,12 @@ LIBNAME = blenderqt DIR = $(OCGDIR)/blender/$(LIBNAME) +ifeq ($(OS), $(findstring $(OS), "darwin")) + ifeq ($(USE_QTKIT),true) + OCSRCS += $(wildcard *.m) + endif +endif + include nan_compile.mk CFLAGS += $(LEVEL1_C_WARNINGS) diff --git a/source/blender/quicktime/apple/qtkit_export.m b/source/blender/quicktime/apple/qtkit_export.m index 1466d3a3a09..8a537617348 100644 --- a/source/blender/quicktime/apple/qtkit_export.m +++ b/source/blender/quicktime/apple/qtkit_export.m @@ -153,6 +153,23 @@ void makeqtstring (RenderData *rd, char *string) { } } +void filepath_qt(char *string, RenderData *rd) { + char txt[64]; + + if (string==0) return; + + strcpy(string, rd->pic); + BLI_convertstringcode(string, G.sce); + + BLI_make_existing_file(string); + + if (BLI_strcasecmp(string + strlen(string) - 4, ".mov")) { + sprintf(txt, "%04d_%04d.mov", (rd->sfra) , (rd->efra) ); + strcat(string, txt); + } +} + + #pragma mark export functions int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, ReportList *reports) diff --git a/source/blender/quicktime/apple/quicktime_export.c b/source/blender/quicktime/apple/quicktime_export.c index abce6c08395..bd1705db13a 100644 --- a/source/blender/quicktime/apple/quicktime_export.c +++ b/source/blender/quicktime/apple/quicktime_export.c @@ -30,6 +30,7 @@ #ifdef WITH_QUICKTIME #if defined(_WIN32) || defined(__APPLE__) +#ifndef USE_QTKIT #include "DNA_scene_types.h" #include "DNA_windowmanager_types.h" @@ -487,7 +488,7 @@ static void QT_EndAddVideoSamplesToMedia (void) } -void makeqtstring (RenderData *rd, char *string) { +void filepath_qt(char *string, RenderData *rd) { char txt[64]; if (string==0) return; @@ -538,7 +539,7 @@ int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, R sframe = (rd->sfra); - makeqtstring(rd, name); + filepath_qt(name, rd); #ifdef __APPLE__ EnterMoviesOnThread(0); @@ -886,6 +887,7 @@ void SCENE_OT_render_data_set_quicktime_codec(wmOperatorType *ot) ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; } +#endif /* USE_QTKIT */ #endif /* _WIN32 || __APPLE__ */ #endif /* WITH_QUICKTIME */ diff --git a/source/blender/quicktime/apple/quicktime_import.c b/source/blender/quicktime/apple/quicktime_import.c index 571da92a292..6fd72131b00 100644 --- a/source/blender/quicktime/apple/quicktime_import.c +++ b/source/blender/quicktime/apple/quicktime_import.c @@ -30,6 +30,7 @@ #ifdef WITH_QUICKTIME #if defined(_WIN32) || defined(__APPLE__) +#ifndef USE_QTKIT #include "IMB_anim.h" #include "BLO_sys_types.h" @@ -771,6 +772,7 @@ bail: return ibuf; } +#endif /* USE_QTKIT */ #endif /* _WIN32 || __APPLE__ */ #endif /* WITH_QUICKTIME */ diff --git a/source/blender/quicktime/quicktime_export.h b/source/blender/quicktime/quicktime_export.h index 2ccda8eb526..33c9a85910f 100644 --- a/source/blender/quicktime/quicktime_export.h +++ b/source/blender/quicktime/quicktime_export.h @@ -50,6 +50,7 @@ struct ReportList; int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, struct ReportList *reports); //for movie handle (BKE writeavi.c now) int append_qt(struct RenderData *rd, int frame, int *pixels, int rectx, int recty, struct ReportList *reports); void end_qt(void); +void filepath_qt(char *string, struct RenderData *rd); /*RNA helper functions */ void quicktime_verify_image_type(struct RenderData *rd); //used by RNA for defaults values init, if needed diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h index 76e3e002513..a90220b9c1b 100644 --- a/source/blender/render/extern/include/RE_pipeline.h +++ b/source/blender/render/extern/include/RE_pipeline.h @@ -46,6 +46,7 @@ struct RenderEngineType; struct RenderResult; struct ReportList; struct Scene; +struct SceneRenderLayer; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* this include is what is exposed of render to outside world */ @@ -169,7 +170,7 @@ struct RenderLayer *RE_GetRenderLayer(struct RenderResult *rr, const char *name) float *RE_RenderLayerGetPass(struct RenderLayer *rl, int passtype); /* obligatory initialize call, disprect is optional */ -void RE_InitState (struct Render *re, struct Render *source, struct RenderData *rd, int winx, int winy, rcti *disprect); +void RE_InitState (struct Render *re, struct Render *source, struct RenderData *rd, struct SceneRenderLayer *srl, int winx, int winy, rcti *disprect); /* use this to change disprect of active render */ void RE_SetDispRect (struct Render *re, rcti *disprect); @@ -200,7 +201,7 @@ void RE_init_threadcount(Render *re); void RE_TileProcessor(struct Render *re, int firsttile, int threaded); /* only RE_NewRender() needed, main Blender render calls */ -void RE_BlenderFrame(struct Render *re, struct Scene *scene, int frame); +void RE_BlenderFrame(struct Render *re, struct Scene *scene, struct SceneRenderLayer *srl, int frame); void RE_BlenderAnim(struct Render *re, struct Scene *scene, int sfra, int efra, int tfra, struct ReportList *reports); void RE_ReadRenderResult(struct Scene *scene, struct Scene *scenode); diff --git a/source/blender/render/extern/include/RE_shader_ext.h b/source/blender/render/extern/include/RE_shader_ext.h index 2615be1440a..28d88e1f8b4 100644 --- a/source/blender/render/extern/include/RE_shader_ext.h +++ b/source/blender/render/extern/include/RE_shader_ext.h @@ -197,7 +197,7 @@ struct Image; struct Object; void RE_shade_external(struct Render *re, struct ShadeInput *shi, struct ShadeResult *shr); -int RE_bake_shade_all_selected(struct Render *re, int type, struct Object *actob); +int RE_bake_shade_all_selected(struct Render *re, int type, struct Object *actob, short *do_update); struct Image *RE_bake_shade_get_image(void); #endif /* RE_SHADER_EXT_H */ diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index 05153113a55..63782223c33 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -2284,6 +2284,14 @@ static void displace_render_face(Render *re, ObjectRen *obr, VlakRen *vlr, float shi.mat= vlr->mat; /* current input material */ shi.thread= 0; + /* TODO, assign these, displacement with new bumpmap is skipped without - campbell */ +#if 0 + /* order is not known ? */ + shi.v1= vlr->v1; + shi.v2= vlr->v2; + shi.v3= vlr->v3; +#endif + /* Displace the verts, flag is set when done */ if (!vlr->v1->flag) displace_render_vert(re, obr, &shi, vlr->v1,0, scale, mat, imat); @@ -3622,7 +3630,7 @@ static GroupObject *add_render_lamp(Render *re, Object *ob) } /* set flag for spothalo en initvars */ - if(la->type==LA_SPOT && (la->mode & LA_HALO)) { + if(la->type==LA_SPOT && (la->mode & LA_HALO) && (la->buftype != LA_SHADBUF_DEEP)) { if(la->haint>0.0) { re->flag |= R_LAMPHALO; @@ -5597,7 +5605,7 @@ void RE_make_sticky(Scene *scene, View3D *v3d) } re= RE_NewRender("_make sticky_"); - RE_InitState(re, NULL, &scene->r, scene->r.xsch, scene->r.ysch, NULL); + RE_InitState(re, NULL, &scene->r, NULL, scene->r.xsch, scene->r.ysch, NULL); /* use renderdata and camera to set viewplane */ RE_SetCamera(re, scene->camera); diff --git a/source/blender/render/intern/source/envmap.c b/source/blender/render/intern/source/envmap.c index 323eb6a9500..7ba860955b3 100644 --- a/source/blender/render/intern/source/envmap.c +++ b/source/blender/render/intern/source/envmap.c @@ -127,7 +127,7 @@ static Render *envmap_render_copy(Render *re, EnvMap *env) envre->r.size= 100; envre->r.yasp= envre->r.xasp= 1; - RE_InitState(envre, NULL, &envre->r, cuberes, cuberes, NULL); + RE_InitState(envre, NULL, &envre->r, NULL, cuberes, cuberes, NULL); envre->scene= re->scene; /* unsure about this... */ /* view stuff in env render */ diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 1d8ef12cd4d..30282c5ad2b 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -133,8 +133,8 @@ static void result_nothing(void *unused, RenderResult *rr) {} static void result_rcti_nothing(void *unused, RenderResult *rr, volatile struct rcti *rect) {} static void stats_nothing(void *unused, RenderStats *rs) {} static void int_nothing(void *unused, int val) {} -static int void_nothing(void *unused) {return 0;} static void print_error(void *unused, char *str) {printf("ERROR: %s\n", str);} +static int default_break(void *unused) {return G.afbreek == 1;} int RE_RenderInProgress(Render *re) { @@ -1118,19 +1118,12 @@ Render *RE_NewRender(const char *name) BLI_rw_mutex_init(&re->resultmutex); } - /* prevent UI to draw old results */ - BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); - RE_FreeRenderResult(re->result); - re->result= NULL; - re->result_ok= 0; - BLI_rw_mutex_unlock(&re->resultmutex); - /* set default empty callbacks */ re->display_init= result_nothing; re->display_clear= result_nothing; re->display_draw= result_rcti_nothing; re->timecursor= int_nothing; - re->test_break= void_nothing; + re->test_break= default_break; re->error= print_error; if(G.background) re->stats_draw= stats_background; @@ -1173,7 +1166,7 @@ void RE_FreeAllRender(void) /* what doesn't change during entire render sequence */ /* disprect is optional, if NULL it assumes full window render */ -void RE_InitState(Render *re, Render *source, RenderData *rd, int winx, int winy, rcti *disprect) +void RE_InitState(Render *re, Render *source, RenderData *rd, SceneRenderLayer *srl, int winx, int winy, rcti *disprect) { re->ok= TRUE; /* maybe flag */ @@ -1199,62 +1192,70 @@ void RE_InitState(Render *re, Render *source, RenderData *rd, int winx, int winy (re->rectx < 16 || re->recty < 16) )) { re->error(re->erh, "Image too small"); re->ok= 0; + return; } - else { + #ifdef WITH_OPENEXR - if(re->r.scemode & R_FULL_SAMPLE) - re->r.scemode |= R_EXR_TILE_FILE; /* enable automatic */ + if(re->r.scemode & R_FULL_SAMPLE) + re->r.scemode |= R_EXR_TILE_FILE; /* enable automatic */ #else - /* can't do this without openexr support */ - re->r.scemode &= ~(R_EXR_TILE_FILE|R_FULL_SAMPLE); + /* can't do this without openexr support */ + re->r.scemode &= ~(R_EXR_TILE_FILE|R_FULL_SAMPLE); #endif - - /* fullsample wants uniform osa levels */ - if(source && (re->r.scemode & R_FULL_SAMPLE)) { - /* but, if source has no full sample we disable it */ - if((source->r.scemode & R_FULL_SAMPLE)==0) - re->r.scemode &= ~R_FULL_SAMPLE; - else - re->r.osa= re->osa= source->osa; + + /* fullsample wants uniform osa levels */ + if(source && (re->r.scemode & R_FULL_SAMPLE)) { + /* but, if source has no full sample we disable it */ + if((source->r.scemode & R_FULL_SAMPLE)==0) + re->r.scemode &= ~R_FULL_SAMPLE; + else + re->r.osa= re->osa= source->osa; + } + else { + /* check state variables, osa? */ + if(re->r.mode & (R_OSA)) { + re->osa= re->r.osa; + if(re->osa>16) re->osa= 16; } - else { - /* check state variables, osa? */ - if(re->r.mode & (R_OSA)) { - re->osa= re->r.osa; - if(re->osa>16) re->osa= 16; - } - else re->osa= 0; + else re->osa= 0; + } + + if (srl) { + int index = BLI_findindex(&re->r.layers, srl); + if (index != -1) { + re->r.actlay = index; + re->r.scemode |= (R_SINGLE_LAYER|R_COMP_RERENDER); } - - /* always call, checks for gamma, gamma tables and jitter too */ - make_sample_tables(re); + } - /* if preview render, we try to keep old result */ - BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); + /* always call, checks for gamma, gamma tables and jitter too */ + make_sample_tables(re); + + /* if preview render, we try to keep old result */ + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); - if(re->r.scemode & R_PREVIEWBUTS) { - if(re->result && re->result->rectx==re->rectx && re->result->recty==re->recty); - else { - RE_FreeRenderResult(re->result); - re->result= NULL; - } - } + if(re->r.scemode & R_PREVIEWBUTS) { + if(re->result && re->result->rectx==re->rectx && re->result->recty==re->recty); else { - - /* make empty render result, so display callbacks can initialize */ RE_FreeRenderResult(re->result); - re->result= MEM_callocN(sizeof(RenderResult), "new render result"); - re->result->rectx= re->rectx; - re->result->recty= re->recty; + re->result= NULL; } - - BLI_rw_mutex_unlock(&re->resultmutex); - - /* we clip faces with a minimum of 2 pixel boundary outside of image border. see zbuf.c */ - re->clipcrop= 1.0f + 2.0f/(float)(re->winx>re->winy?re->winy:re->winx); + } + else { - RE_init_threadcount(re); + /* make empty render result, so display callbacks can initialize */ + RE_FreeRenderResult(re->result); + re->result= MEM_callocN(sizeof(RenderResult), "new render result"); + re->result->rectx= re->rectx; + re->result->recty= re->recty; } + + BLI_rw_mutex_unlock(&re->resultmutex); + + /* we clip faces with a minimum of 2 pixel boundary outside of image border. see zbuf.c */ + re->clipcrop= 1.0f + 2.0f/(float)(re->winx>re->winy?re->winy:re->winx); + + RE_init_threadcount(re); } /* part of external api, not called for regular render pipeline */ @@ -2164,7 +2165,7 @@ static void render_scene(Render *re, Scene *sce, int cfra) } /* initial setup */ - RE_InitState(resc, re, &sce->r, winx, winy, &re->disprect); + RE_InitState(resc, re, &sce->r, NULL, winx, winy, &re->disprect); /* still unsure entity this... */ resc->scene= sce; @@ -2676,7 +2677,7 @@ static void update_physics_cache(Render *re, Scene *scene, int anim_init) BKE_ptcache_make_cache(&baker); } /* evaluating scene options for general Blender render */ -static int render_initialize_from_scene(Render *re, Scene *scene, int anim, int anim_init) +static int render_initialize_from_scene(Render *re, Scene *scene, SceneRenderLayer *srl, int anim, int anim_init) { int winx, winy; rcti disprect; @@ -2723,10 +2724,10 @@ static int render_initialize_from_scene(Render *re, Scene *scene, int anim, int update_physics_cache(re, scene, anim_init); } - if(scene->r.scemode & R_SINGLE_LAYER) + if(srl || scene->r.scemode & R_SINGLE_LAYER) push_render_result(re); - RE_InitState(re, NULL, &scene->r, winx, winy, &disprect); + RE_InitState(re, NULL, &scene->r, srl, winx, winy, &disprect); if(!re->ok) /* if an error was printed, abort */ return 0; @@ -2743,7 +2744,7 @@ static int render_initialize_from_scene(Render *re, Scene *scene, int anim, int } /* general Blender frame render call */ -void RE_BlenderFrame(Render *re, Scene *scene, int frame) +void RE_BlenderFrame(Render *re, Scene *scene, SceneRenderLayer *srl, int frame) { /* ugly global still... is to prevent preview events and signal subsurfs etc to make full resol */ G.rendering= 1; @@ -2751,7 +2752,7 @@ void RE_BlenderFrame(Render *re, Scene *scene, int frame) scene->r.cfra= frame; - if(render_initialize_from_scene(re, scene, 0, 0)) { + if(render_initialize_from_scene(re, scene, srl, 0, 0)) { do_render_all_options(re); } @@ -2784,7 +2785,7 @@ static int do_write_image_or_movie(Render *re, Scene *scene, bMovieHandle *mh, R printf("Append frame %d", scene->r.cfra); } else { - BKE_makepicstring(scene, name, scene->r.pic, scene->r.cfra, scene->r.imtype); + BKE_makepicstring(name, scene->r.pic, scene->r.cfra, scene->r.imtype, scene->r.scemode & R_EXTENSION); if(re->r.imtype==R_MULTILAYER) { if(re->result) { @@ -2817,7 +2818,7 @@ static int do_write_image_or_movie(Render *re, Scene *scene, bMovieHandle *mh, R if(ok && scene->r.imtype==R_OPENEXR && (scene->r.subimtype & R_PREVIEW_JPG)) { if(BLI_testextensie(name, ".exr")) name[strlen(name)-4]= 0; - BKE_add_image_extension(scene, name, R_JPEG90); + BKE_add_image_extension(name, R_JPEG90); ibuf->depth= 24; BKE_write_ibuf(scene, ibuf, name, R_JPEG90, scene->r.subimtype, scene->r.quality); printf("\nSaved: %s", name); @@ -2846,7 +2847,7 @@ void RE_BlenderAnim(Render *re, Scene *scene, int sfra, int efra, int tfra, Repo int nfra; /* do not fully call for each frame, it initializes & pops output window */ - if(!render_initialize_from_scene(re, scene, 0, 1)) + if(!render_initialize_from_scene(re, scene, NULL, 0, 1)) return; /* ugly global still... is to prevent renderwin events and signal subsurfs etc to make full resol */ @@ -2880,7 +2881,7 @@ void RE_BlenderAnim(Render *re, Scene *scene, int sfra, int efra, int tfra, Repo char name[FILE_MAX]; /* only border now, todo: camera lens. (ton) */ - render_initialize_from_scene(re, scene, 1, 0); + render_initialize_from_scene(re, scene, NULL, 1, 0); if(nfra!=scene->r.cfra) { /* @@ -2902,7 +2903,7 @@ void RE_BlenderAnim(Render *re, Scene *scene, int sfra, int efra, int tfra, Repo /* Touch/NoOverwrite options are only valid for image's */ if(BKE_imtype_is_movie(scene->r.imtype) == 0) { if(scene->r.mode & (R_NO_OVERWRITE | R_TOUCH)) - BKE_makepicstring(scene, name, scene->r.pic, scene->r.cfra, scene->r.imtype); + BKE_makepicstring(name, scene->r.pic, scene->r.cfra, scene->r.imtype, scene->r.scemode & R_EXTENSION); if(scene->r.mode & R_NO_OVERWRITE && BLI_exist(name)) { printf("skipping existing frame \"%s\"\n", name); @@ -2984,7 +2985,7 @@ void RE_ReadRenderResult(Scene *scene, Scene *scenode) re= RE_GetRender(scene->id.name); if(re==NULL) re= RE_NewRender(scene->id.name); - RE_InitState(re, NULL, &scene->r, winx, winy, &disprect); + RE_InitState(re, NULL, &scene->r, NULL, winx, winy, &disprect); re->scene= scene; read_render_result(re, 0); diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 85442480a9c..9fa23c73ec6 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -192,9 +192,10 @@ void freeraytree(Render *re) static int is_raytraceable_vlr(Render *re, VlakRen *vlr) { - if((re->flag & R_BAKE_TRACE) || (vlr->mat->mode & MA_TRACEBLE)) - if(vlr->mat->material_type != MA_TYPE_WIRE) - return 1; + /* note: volumetric must be tracable, wire must not */ + if((re->flag & R_BAKE_TRACE) || (vlr->mat->mode & MA_TRACEBLE) || (vlr->mat->material_type == MA_TYPE_VOLUME)) + if(vlr->mat->material_type != MA_TYPE_WIRE) + return 1; return 0; } diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index cae6c640f8b..23875b536c9 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -1988,6 +1988,8 @@ typedef struct BakeShade { char *rect_mask; /* bake pixel mask */ float dxco[3], dyco[3]; + + short *do_update; } BakeShade; /* bake uses a char mask to know what has been baked */ @@ -2252,9 +2254,7 @@ static int bake_check_intersect(Isect *is, int ob, RayFace *face) static int bake_intersect_tree(RayObject* raytree, Isect* isect, float *start, float *dir, float sign, float *hitco, float *dist) { - //TODO - assert( 0 ); -#if 0 + //TODO, validate against blender 2.4x, results may have changed. float maxdist; int hit; @@ -2264,15 +2264,20 @@ static int bake_intersect_tree(RayObject* raytree, Isect* isect, float *start, f else maxdist= FLT_MAX + R.r.bake_biasdist; - //TODO normalized direction? - VECADDFAC(isect->start, start, dir, -R.r.bake_biasdist); - isect->dir[0] = dir[0]*sign; - isect->dir[1] = dir[1]*sign; - isect->dir[2] = dir[2]*sign; + /* 'dir' is always normalized */ + VECADDFAC(isect->start, start, dir, -R.r.bake_biasdist); + + isect->vec[0] = dir[0]*maxdist*sign; + isect->vec[1] = dir[1]*maxdist*sign; + isect->vec[2] = dir[2]*maxdist*sign; + isect->labda = maxdist; + /* TODO, 2.4x had this... + hit = RE_ray_tree_intersect_check(R.raytree, isect, bake_check_intersect); + ...the active object may NOT be ignored in some cases. + */ hit = RE_rayobject_raycast(raytree, isect); - //TODO bake_check_intersect if(hit) { hitco[0] = isect->start[0] + isect->labda*isect->vec[0]; hitco[1] = isect->start[1] + isect->labda*isect->vec[1]; @@ -2282,8 +2287,6 @@ static int bake_intersect_tree(RayObject* raytree, Isect* isect, float *start, f } return hit; -#endif - return 0; } static void bake_set_vlr_dxyco(BakeShade *bs, float *uv1, float *uv2, float *uv3) @@ -2587,6 +2590,11 @@ static void *do_bake_thread(void *bs_v) /* fast threadsafe break test */ if(R.test_break(R.tbh)) break; + + /* access is not threadsafe but since its just true/false probably ok + * only used for interactive baking */ + if(bs->do_update) + *bs->do_update= TRUE; } bs->ready= 1; @@ -2596,7 +2604,7 @@ static void *do_bake_thread(void *bs_v) /* using object selection tags, the faces with UV maps get baked */ /* render should have been setup */ /* returns 0 if nothing was handled */ -int RE_bake_shade_all_selected(Render *re, int type, Object *actob) +int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_update) { BakeShade handles[BLENDER_MAX_THREADS]; ListBase threads; @@ -2645,6 +2653,8 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob) handles[a].zspan= MEM_callocN(sizeof(ZSpan), "zspan for bake"); handles[a].usemask = usemask; + + handles[a].do_update = do_update; /* use to tell the view to update */ BLI_insert_thread(&threads, &handles[a]); } diff --git a/source/blender/render/intern/source/shadeoutput.c b/source/blender/render/intern/source/shadeoutput.c index 958a2e34215..e9386bb0d94 100644 --- a/source/blender/render/intern/source/shadeoutput.c +++ b/source/blender/render/intern/source/shadeoutput.c @@ -354,7 +354,7 @@ void renderspothalo(ShadeInput *shi, float *col, float alpha) lar= go->lampren; if(lar==NULL) continue; - if(lar->type==LA_SPOT && (lar->mode & LA_HALO) && lar->haint>0) { + if(lar->type==LA_SPOT && (lar->mode & LA_HALO) && (lar->buftype != LA_SHADBUF_DEEP) && lar->haint>0) { if(lar->mode & LA_LAYER) if(shi->vlr && (lar->lay & shi->obi->lay)==0) diff --git a/source/blender/render/intern/source/texture.c b/source/blender/render/intern/source/texture.c index 9d03889a747..7bf349705cb 100644 --- a/source/blender/render/intern/source/texture.c +++ b/source/blender/render/intern/source/texture.c @@ -1737,7 +1737,8 @@ void do_material_tex(ShadeInput *shi) // (should not be here, dudnu, dudnv, dvdnu & dvdnv should probably be part of ShadeInputUV struct, // nu/nv in ShadeInput and this calculation should then move to shadeinput.c, shade_input_set_shade_texco() func.) // NOTE: test for shi->obr->ob here, since vlr/obr/obi can be 'fake' when called from fastshade(), another reason to move it.. - if ((mtex->texflag & MTEX_NEW_BUMP) && shi->obr && shi->obr->ob) { + // NOTE: shi->v1 is NULL when called from displace_render_vert, assigning verts in this case is not trivial because the shi quad face side is not know. + if ((mtex->texflag & MTEX_NEW_BUMP) && shi->obr && shi->obr->ob && shi->v1) { if(mtex->mapto & (MAP_NORM|MAP_DISPLACE|MAP_WARP)) { MTFace* tf = RE_vlakren_get_tface(shi->obr, shi->vlr, i, NULL, 0); int j1 = shi->i1, j2 = shi->i2, j3 = shi->i3; diff --git a/source/blender/render/intern/source/volume_precache.c b/source/blender/render/intern/source/volume_precache.c index e9162b7367f..80a6dd9d6a0 100644 --- a/source/blender/render/intern/source/volume_precache.c +++ b/source/blender/render/intern/source/volume_precache.c @@ -21,7 +21,7 @@ * * The Original Code is: all of this file. * - * Contributor(s): Matt Ebb. + * Contributor(s): Matt Ebb, RaË™l Fern·ndez Hern·ndez (Farsthary). * * ***** END GPL LICENSE BLOCK ***** */ @@ -134,9 +134,10 @@ static float get_avg_surrounds(float *cache, int *res, int xx, int yy, int zz) for (x=-1; x <= 1; x++) { x_ = xx+x; if (x_ >= 0 && x_ <= res[0]-1) { - - if (cache[ V_I(x_, y_, z_, res) ] > 0.0f) { - tot += cache[ V_I(x_, y_, z_, res) ]; + const int i= V_I(x_, y_, z_, res); + + if (cache[i] > 0.0f) { + tot += cache[i]; added++; } @@ -164,12 +165,14 @@ static void lightcache_filter(VolumePrecache *vp) for (y=0; y < vp->res[1]; y++) { for (x=0; x < vp->res[0]; x++) { /* trigger for outside mesh */ - if (vp->data_r[ V_I(x, y, z, vp->res) ] < -0.f) - vp->data_r[ V_I(x, y, z, vp->res) ] = get_avg_surrounds(vp->data_r, vp->res, x, y, z); - if (vp->data_g[ V_I(x, y, z, vp->res) ] < -0.f) - vp->data_g[ V_I(x, y, z, vp->res) ] = get_avg_surrounds(vp->data_g, vp->res, x, y, z); - if (vp->data_b[ V_I(x, y, z, vp->res) ] < -0.f) - vp->data_b[ V_I(x, y, z, vp->res) ] = get_avg_surrounds(vp->data_b, vp->res, x, y, z); + const int i= V_I(x, y, z, vp->res); + + if (vp->data_r[i] < -0.f) + vp->data_r[i] = get_avg_surrounds(vp->data_r, vp->res, x, y, z); + if (vp->data_g[i] < -0.f) + vp->data_g[i] = get_avg_surrounds(vp->data_g, vp->res, x, y, z); + if (vp->data_b[i] < -0.f) + vp->data_b[i] = get_avg_surrounds(vp->data_b, vp->res, x, y, z); } } } @@ -194,12 +197,13 @@ static void lightcache_filter2(VolumePrecache *vp) for (y=0; y < vp->res[1]; y++) { for (x=0; x < vp->res[0]; x++) { /* trigger for outside mesh */ - if (vp->data_r[ V_I(x, y, z, vp->res) ] < -0.f) - new_r[ V_I(x, y, z, vp->res) ] = get_avg_surrounds(vp->data_r, vp->res, x, y, z); - if (vp->data_g[ V_I(x, y, z, vp->res) ] < -0.f) - new_g[ V_I(x, y, z, vp->res) ] = get_avg_surrounds(vp->data_g, vp->res, x, y, z); - if (vp->data_b[ V_I(x, y, z, vp->res) ] < -0.f) - new_b[ V_I(x, y, z, vp->res) ] = get_avg_surrounds(vp->data_b, vp->res, x, y, z); + const int i= V_I(x, y, z, vp->res); + if (vp->data_r[i] < -0.f) + new_r[i] = get_avg_surrounds(vp->data_r, vp->res, x, y, z); + if (vp->data_g[i] < -0.f) + new_g[i] = get_avg_surrounds(vp->data_g, vp->res, x, y, z); + if (vp->data_b[i] < -0.f) + new_b[i] = get_avg_surrounds(vp->data_b, vp->res, x, y, z); } } } @@ -216,9 +220,21 @@ static void lightcache_filter2(VolumePrecache *vp) static inline int ms_I(int x, int y, int z, int *n) //has a pad of 1 voxel surrounding the core for boundary simulation { - return z*(n[1]+2)*(n[0]+2) + y*(n[0]+2) + x; + /* different ordering to light cache */ + return x*(n[1]+2)*(n[2]+2) + y*(n[2]+2) + z; +} + +static inline int v_I_pad(int x, int y, int z, int *n) //has a pad of 1 voxel surrounding the core for boundary simulation +{ + /* same ordering to light cache, with padding */ + return z*(n[1]+2)*(n[0]+2) + y*(n[0]+2) + x; } +static inline int lc_to_ms_I(int x, int y, int z, int *n) +{ + /* converting light cache index to multiple scattering index */ + return (x-1)*(n[1]*n[2]) + (y-1)*(n[2]) + z-1; +} /* *** multiple scattering approximation *** */ @@ -232,9 +248,11 @@ static float total_ss_energy(VolumePrecache *vp) for (z=0; z < res[2]; z++) { for (y=0; y < res[1]; y++) { for (x=0; x < res[0]; x++) { - if (vp->data_r[ V_I(x, y, z, res) ] > 0.f) energy += vp->data_r[ V_I(x, y, z, res) ]; - if (vp->data_g[ V_I(x, y, z, res) ] > 0.f) energy += vp->data_g[ V_I(x, y, z, res) ]; - if (vp->data_b[ V_I(x, y, z, res) ] > 0.f) energy += vp->data_b[ V_I(x, y, z, res) ]; + const int i=V_I(x, y, z, res); + + if (vp->data_r[i] > 0.f) energy += vp->data_r[i]; + if (vp->data_g[i] > 0.f) energy += vp->data_g[i]; + if (vp->data_b[i] > 0.f) energy += vp->data_b[i]; } } } @@ -244,14 +262,14 @@ static float total_ss_energy(VolumePrecache *vp) static float total_ms_energy(float *sr, float *sg, float *sb, int *res) { - int x, y, z, i; + int x, y, z; float energy=0.f; for (z=1;z<=res[2];z++) { for (y=1;y<=res[1];y++) { for (x=1;x<=res[0];x++) { - - i = ms_I(x,y,z,res); + const int i = ms_I(x,y,z,res); + if (sr[i] > 0.f) energy += sr[i]; if (sg[i] > 0.f) energy += sg[i]; if (sb[i] > 0.f) energy += sb[i]; @@ -262,7 +280,7 @@ static float total_ms_energy(float *sr, float *sg, float *sb, int *res) return energy; } -static void ms_diffuse(int b, float* x0, float* x, float diff, int *n) +static void ms_diffuse(float *x0, float *x, float diff, int *n) //n is the unpadded resolution { int i, j, k, l; const float dt = VOL_MS_TIMESTEP; @@ -276,10 +294,9 @@ static void ms_diffuse(int b, float* x0, float* x, float diff, int *n) { for (i=1; i<=n[0]; i++) { - x[ms_I(i,j,k,n)] = (x0[ms_I(i,j,k,n)] + a*( - x[ms_I(i-1,j,k,n)]+x[ms_I(i+1,j,k,n)]+ - x[ms_I(i,j-1,k,n)]+x[ms_I(i,j+1,k,n)]+ - x[ms_I(i,j,k-1,n)]+x[ms_I(i,j,k+1,n)]))/(1+6*a); + x[v_I_pad(i,j,k,n)] = (x0[v_I_pad(i,j,k,n)]) + a*( x0[v_I_pad(i-1,j,k,n)]+ x0[v_I_pad(i+1,j,k,n)]+ x0[v_I_pad(i,j-1,k,n)]+ + x0[v_I_pad(i,j+1,k,n)]+ x0[v_I_pad(i,j,k-1,n)]+x0[v_I_pad(i,j,k+1,n)] + ) / (1+6*a); } } } @@ -289,7 +306,7 @@ static void ms_diffuse(int b, float* x0, float* x, float diff, int *n) void multiple_scattering_diffusion(Render *re, VolumePrecache *vp, Material *ma) { const float diff = ma->vol.ms_diff * 0.001f; /* compensate for scaling for a nicer UI range */ - const float simframes = ma->vol.ms_steps; + const int simframes = (int)(ma->vol.ms_spread * (float)MAX3(vp->res[0], vp->res[1], vp->res[2])); const int shade_type = ma->vol.shade_type; float fac = ma->vol.ms_intensity; @@ -299,7 +316,6 @@ void multiple_scattering_diffusion(Render *re, VolumePrecache *vp, Material *ma) double time, lasttime= PIL_check_seconds_timer(); float total; float c=1.0f; - int i; float origf; /* factor for blending in original light cache */ float energy_ss, energy_ms; @@ -324,22 +340,22 @@ void multiple_scattering_diffusion(Render *re, VolumePrecache *vp, Material *ma) { for (x=1; x<=n[0]; x++) { - i = V_I((x-1), (y-1), (z-1), n); + const int i = lc_to_ms_I(x, y ,z, n); //lc index + const int j = ms_I(x, y, z, n); //ms index + time= PIL_check_seconds_timer(); - c++; - - if (vp->data_r[i] > 0.f) - sr[ms_I(x,y,z,n)] += vp->data_r[i]; - if (vp->data_g[i] > 0.f) - sg[ms_I(x,y,z,n)] += vp->data_g[i]; - if (vp->data_b[i] > 0.f) - sb[ms_I(x,y,z,n)] += vp->data_b[i]; + c++; + if (vp->data_r[i] > 0.0f) + sr[j] += vp->data_r[i]; + if (vp->data_g[i] > 0.0f) + sg[j] += vp->data_g[i]; + if (vp->data_b[i] > 0.0f) + sb[j] += vp->data_b[i]; /* Displays progress every second */ if(time-lasttime>1.0f) { char str[64]; - sprintf(str, "Simulating multiple scattering: %d%%", (int) - (100.0f * (c / total))); + sprintf(str, "Simulating multiple scattering: %d%%", (int)(100.0f * (c / total))); re->i.infostr= str; re->stats_draw(re->sdh, &re->i); re->i.infostr= NULL; @@ -348,14 +364,14 @@ void multiple_scattering_diffusion(Render *re, VolumePrecache *vp, Material *ma) } } } - SWAP(float *, sr, sr0); - SWAP(float *, sg, sg0); - SWAP(float *, sb, sb0); - + SWAP(float *,sr,sr0); + SWAP(float *,sg,sg0); + SWAP(float *,sb,sb0); + /* main diffusion simulation */ - ms_diffuse(0, sr0, sr, diff, n); - ms_diffuse(0, sg0, sg, diff, n); - ms_diffuse(0, sb0, sb, diff, n); + ms_diffuse(sr0, sr, diff, n); + ms_diffuse(sg0, sg, diff, n); + ms_diffuse(sb0, sb, diff, n); if (re->test_break(re->tbh)) break; } @@ -379,10 +395,12 @@ void multiple_scattering_diffusion(Render *re, VolumePrecache *vp, Material *ma) { for (x=1;x<=n[0];x++) { - int index=(x-1)*n[1]*n[2] + (y-1)*n[2] + z-1; - vp->data_r[index] = origf * vp->data_r[index] + fac * sr[ms_I(x,y,z,n)]; - vp->data_g[index] = origf * vp->data_g[index] + fac * sg[ms_I(x,y,z,n)]; - vp->data_b[index] = origf * vp->data_b[index] + fac * sb[ms_I(x,y,z,n)]; + const int i = lc_to_ms_I(x, y ,z, n); //lc index + const int j = ms_I(x, y, z, n); //ms index + + vp->data_r[i] = origf * vp->data_r[i] + fac * sr[j]; + vp->data_g[i] = origf * vp->data_g[i] + fac * sg[j]; + vp->data_b[i] = origf * vp->data_b[i] + fac * sb[j]; } } } @@ -426,7 +444,7 @@ static void *vol_precache_part(void *data) ShadeInput *shi = pa->shi; float scatter_col[3] = {0.f, 0.f, 0.f}; float co[3]; - int x, y, z; + int x, y, z, i; const int res[3]= {pa->res[0], pa->res[1], pa->res[2]}; for (z= pa->minz; z < pa->maxz; z++) { @@ -437,12 +455,14 @@ static void *vol_precache_part(void *data) for (x=pa->minx; x < pa->maxx; x++) { co[0] = pa->bbmin[0] + (pa->voxel[0] * (x + 0.5f)); + + i= V_I(x, y, z, res); // don't bother if the point is not inside the volume mesh if (!point_inside_obi(tree, obi, co)) { - obi->volume_precache->data_r[ V_I(x, y, z, res) ] = -1.0f; - obi->volume_precache->data_g[ V_I(x, y, z, res) ] = -1.0f; - obi->volume_precache->data_b[ V_I(x, y, z, res) ] = -1.0f; + obi->volume_precache->data_r[i] = -1.0f; + obi->volume_precache->data_g[i] = -1.0f; + obi->volume_precache->data_b[i] = -1.0f; continue; } @@ -450,9 +470,9 @@ static void *vol_precache_part(void *data) normalize_v3(shi->view); vol_get_scattering(shi, scatter_col, co); - obi->volume_precache->data_r[ V_I(x, y, z, res) ] = scatter_col[0]; - obi->volume_precache->data_g[ V_I(x, y, z, res) ] = scatter_col[1]; - obi->volume_precache->data_b[ V_I(x, y, z, res) ] = scatter_col[2]; + obi->volume_precache->data_r[i] = scatter_col[0]; + obi->volume_precache->data_g[i] = scatter_col[1]; + obi->volume_precache->data_b[i] = scatter_col[2]; } } } @@ -684,12 +704,13 @@ void vol_precache_objectinstance_threads(Render *re, ObjectInstanceRen *obi, Mat //tree= NULL; } - lightcache_filter(obi->volume_precache); - if (ELEM(ma->vol.shade_type, MA_VOL_SHADE_MULTIPLE, MA_VOL_SHADE_SHADEDPLUSMULTIPLE)) { - multiple_scattering_diffusion(re, vp, ma); + /* this should be before the filtering */ + multiple_scattering_diffusion(re, obi->volume_precache, ma); } + + lightcache_filter(obi->volume_precache); } static int using_lightcache(Material *ma) @@ -741,7 +762,7 @@ int point_inside_volume_objectinstance(Render *re, ObjectInstanceRen *obi, float RayObject *tree; int inside=0; - tree = makeraytree_object(re, obi); //create_raytree_obi(obi, obi->obr->boundbox[0], obi->obr->boundbox[1]); + tree = makeraytree_object(re, obi); if (!tree) return 0; inside = point_inside_obi(tree, obi, co); diff --git a/source/blender/render/intern/source/volumetric.c b/source/blender/render/intern/source/volumetric.c index 32ab2980316..e44064de606 100644 --- a/source/blender/render/intern/source/volumetric.c +++ b/source/blender/render/intern/source/volumetric.c @@ -493,7 +493,7 @@ void vol_shade_one_lamp(struct ShadeInput *shi, float *co, LampRen *lar, float * if (shi->mat->vol.shade_type == MA_VOL_SHADE_SHADOWED) { mul_v3_fl(lacol, vol_get_shadow(shi, lar, co)); } - else if (shi->mat->vol.shade_type == MA_VOL_SHADE_SHADED) + else if (ELEM3(shi->mat->vol.shade_type, MA_VOL_SHADE_SHADED, MA_VOL_SHADE_MULTIPLE, MA_VOL_SHADE_SHADEDPLUSMULTIPLE)) { Isect is; diff --git a/source/blender/windowmanager/CMakeLists.txt b/source/blender/windowmanager/CMakeLists.txt index e93b9906dac..9f57fd5efec 100644 --- a/source/blender/windowmanager/CMakeLists.txt +++ b/source/blender/windowmanager/CMakeLists.txt @@ -81,9 +81,8 @@ IF(WITH_COCOA) LIST(REMOVE_ITEM SRC "${CMAKE_CURRENT_SOURCE_DIR}/intern/wm_apple.c") ENDIF(WITH_COCOA) -# TODO buildinfo -IF(BF_BUILDINFO) +IF(WITH_BUILDINFO) ADD_DEFINITIONS(-DNAN_BUILDINFO) -ENDIF(BF_BUILDINFO) +ENDIF(WITH_BUILDINFO) BLENDERLIB_NOLIST(bf_windowmanager "${SRC}" "${INC}") diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index 78125954816..9f52cde27e1 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -213,11 +213,12 @@ typedef struct wmNotifier { #define ND_NLA_SELECT (75<<16) #define ND_NLA_EDIT (76<<16) #define ND_NLA_ACTCHANGE (77<<16) +#define ND_FCURVES_ORDER (78<<16) /* NC_GEOM Geometry */ /* Mesh, Curve, MetaBall, Armature, .. */ -#define ND_SELECT (80<<16) -#define ND_DATA (81<<16) +#define ND_SELECT (90<<16) +#define ND_DATA (91<<16) /* NC_NODE Nodes */ #define ND_NODE_SELECT (1<<16) diff --git a/source/blender/windowmanager/intern/Makefile b/source/blender/windowmanager/intern/Makefile index f4d65975d43..e472c87fe54 100644 --- a/source/blender/windowmanager/intern/Makefile +++ b/source/blender/windowmanager/intern/Makefile @@ -74,6 +74,10 @@ ifeq ($(WITH_QUICKTIME),true) CPPFLAGS += -DWITH_QUICKTIME endif +ifeq ($(WITH_OPENCOLLADA), true) + CPPFLAGS += -DWITH_COLLADA +endif + ifeq ($(OS),linux) ifeq ($(CPU),alpha) CPPFLAGS += -I$(NAN_MESA)/include diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 825d8cbcf8c..aff843dc1cb 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -391,6 +391,8 @@ static wmOperator *wm_operator_create(wmWindowManager *wm, wmOperatorType *ot, P wmOperatorType *otm= WM_operatortype_find(otmacro->idname, 0); wmOperator *opm= wm_operator_create(wm, otm, otmacro->ptr, NULL); + IDP_ReplaceGroupInGroup(opm->properties, motherop->properties); + BLI_addtail(&motherop->macro, opm); opm->opm= motherop; /* pointer to mom, for modal() */ } diff --git a/source/blender/windowmanager/intern/wm_gesture.c b/source/blender/windowmanager/intern/wm_gesture.c index b95d171c1b0..a57421560a6 100644 --- a/source/blender/windowmanager/intern/wm_gesture.c +++ b/source/blender/windowmanager/intern/wm_gesture.c @@ -37,6 +37,8 @@ #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" +#include "BLI_editVert.h" /* lasso tessellation */ +#include "BLI_scanfill.h" /* lasso tessellation */ #include "BKE_context.h" #include "BKE_utildefines.h" @@ -149,8 +151,18 @@ static void wm_gesture_draw_rect(wmWindow *win, wmGesture *gt) { rcti *rect= (rcti *)gt->customdata; + glEnable(GL_BLEND); + glColor4f(1.0, 1.0, 1.0, 0.05); + glBegin(GL_QUADS); + glVertex2s(rect->xmax, rect->ymin); + glVertex2s(rect->xmax, rect->ymax); + glVertex2s(rect->xmin, rect->ymax); + glVertex2s(rect->xmin, rect->ymin); + glEnd(); + glDisable(GL_BLEND); + glEnable(GL_LINE_STIPPLE); - glColor3ub(0, 0, 0); + glColor3ub(96, 96, 96); glLineStipple(1, 0xCCCC); sdrawbox(rect->xmin, rect->ymin, rect->xmax, rect->ymax); glColor3ub(255, 255, 255); @@ -164,7 +176,7 @@ static void wm_gesture_draw_line(wmWindow *win, wmGesture *gt) rcti *rect= (rcti *)gt->customdata; glEnable(GL_LINE_STIPPLE); - glColor3ub(0, 0, 0); + glColor3ub(96, 96, 96); glLineStipple(1, 0xAAAA); sdrawline(rect->xmin, rect->ymin, rect->xmax, rect->ymax); glColor3ub(255, 255, 255); @@ -181,8 +193,13 @@ static void wm_gesture_draw_circle(wmWindow *win, wmGesture *gt) glTranslatef((float)rect->xmin, (float)rect->ymin, 0.0f); + glEnable(GL_BLEND); + glColor4f(1.0, 1.0, 1.0, 0.05); + glutil_draw_filled_arc(0.0, M_PI*2.0, rect->xmax, 40); + glDisable(GL_BLEND); + glEnable(GL_LINE_STIPPLE); - glColor3ub(0, 0, 0); + glColor3ub(96, 96, 96); glLineStipple(1, 0xAAAA); glutil_draw_lined_arc(0.0, M_PI*2.0, rect->xmax, 40); glColor3ub(255, 255, 255); @@ -194,15 +211,53 @@ static void wm_gesture_draw_circle(wmWindow *win, wmGesture *gt) } +static void draw_filled_lasso(wmGesture *gt) +{ + EditVert *v, *lastv=NULL, *firstv=NULL; + EditEdge *e; + EditFace *efa; + short *lasso= (short *)gt->customdata; + int i; + + for (i=0; i<gt->points; i++, lasso+=2) { + float co[3] = {(float)lasso[0], (float)lasso[1], 0.f}; + + v = BLI_addfillvert(co); + if (lastv) + e = BLI_addfilledge(lastv, v); + lastv = v; + if (firstv==NULL) firstv = v; + } + + BLI_addfilledge(firstv, v); + BLI_edgefill(0, 0); + + glEnable(GL_BLEND); + glColor4f(1.0, 1.0, 1.0, 0.05); + glBegin(GL_TRIANGLES); + for (efa = fillfacebase.first; efa; efa=efa->next) { + glVertex2f(efa->v1->co[0], efa->v1->co[1]); + glVertex2f(efa->v2->co[0], efa->v2->co[1]); + glVertex2f(efa->v3->co[0], efa->v3->co[1]); + } + glEnd(); + glDisable(GL_BLEND); + + BLI_end_edgefill(); +} + static void wm_gesture_draw_lasso(wmWindow *win, wmGesture *gt) { short *lasso= (short *)gt->customdata; int i; + + draw_filled_lasso(gt); glEnable(GL_LINE_STIPPLE); - glColor3ub(0, 0, 0); + glColor3ub(96, 96, 96); glLineStipple(1, 0xAAAA); glBegin(GL_LINE_STRIP); + lasso= (short *)gt->customdata; for(i=0; i<gt->points; i++, lasso+=2) glVertex2sv(lasso); if(gt->type==WM_GESTURE_LASSO) @@ -228,7 +283,7 @@ static void wm_gesture_draw_cross(wmWindow *win, wmGesture *gt) rcti *rect= (rcti *)gt->customdata; glEnable(GL_LINE_STIPPLE); - glColor3ub(0, 0, 0); + glColor3ub(96, 96, 96); glLineStipple(1, 0xCCCC); sdrawline(rect->xmin - win->sizex, rect->ymin, rect->xmin + win->sizex, rect->ymin); sdrawline(rect->xmin, rect->ymin - win->sizey, rect->xmin, rect->ymin + win->sizey); diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index f7054af9443..1d4e4eb2d39 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -42,6 +42,8 @@ #include "MEM_guardedalloc.h" +#include "BLF_api.h" + #include "PIL_time.h" #include "BLI_blenlib.h" @@ -193,6 +195,7 @@ static int wm_macro_end(wmOperator *op, int retval) if (retval & (OPERATOR_FINISHED|OPERATOR_CANCELLED)) { if (op->customdata) { MEM_freeN(op->customdata); + op->customdata = NULL; } } @@ -360,6 +363,7 @@ void WM_operatortype_append_macro_ptr(void (*opfunc)(wmOperatorType*, void*), vo ot= MEM_callocN(sizeof(wmOperatorType), "operatortype"); ot->srna= RNA_def_struct(&BLENDER_RNA, "", "OperatorProperties"); + ot->flag= OPTYPE_MACRO; ot->exec= wm_macro_exec; ot->invoke= wm_macro_invoke; ot->modal= wm_macro_modal; @@ -930,14 +934,48 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *arg_unuse uiLayout *layout, *split, *col; uiStyle *style= U.uistyles.first; struct RecentFile *recent; - int i; + int i, ver_width, rev_width; + char *version_str = NULL; + char *revision_str = NULL; + +#ifdef NAN_BUILDINFO + char version_buf[128]; + char revision_buf[128]; + extern char * build_rev; + char *cp; + + version_str = &version_buf[0]; + revision_str = &revision_buf[0]; + sprintf(version_str, "%d.%02d.%d", BLENDER_VERSION/100, BLENDER_VERSION%100, BLENDER_SUBVERSION); + sprintf(revision_str, "r%s", build_rev); + + /* here on my system I get ugly double quotes around the revision number. + * if so, clip it off: */ + cp = strchr(revision_str, '"'); + if (cp) { + memmove(cp, cp+1, strlen(cp+1)); + cp = strchr(revision_str, '"'); + if (cp) + *cp = 0; + } + + ver_width = BLF_width(version_str); + rev_width = BLF_width(revision_str); +#endif NAN_BUILDINFO + block= uiBeginBlock(C, ar, "_popup", UI_EMBOSS); uiBlockSetFlag(block, UI_BLOCK_KEEP_OPEN|UI_BLOCK_RET_1); but= uiDefBut(block, BUT_IMAGE, 0, "", 0, 10, 501, 282, NULL, 0.0, 0.0, 0, 0, ""); uiButSetFunc(but, wm_block_splash_close, block, NULL); +#ifdef NAN_BUILDINFO + uiDefBut(block, LABEL, 0, version_str, 500-ver_width, 282-24, ver_width, 20, NULL, 0, 0, 0, 0, NULL); + uiDefBut(block, LABEL, 0, revision_str, 500-rev_width, 282-36, rev_width, 20, NULL, 0, 0, 0, 0, NULL); +#endif NAN_BUILDINFO + + uiBlockSetEmboss(block, UI_EMBOSSP); layout= uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_MENU, 10, 10, 480, 110, style); @@ -956,8 +994,12 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *arg_unuse col = uiLayoutColumn(split, 0); uiItemL(col, "Recent", 0); - for(recent = G.recent_files.first, i=0; (i<6) && (recent); recent = recent->next, i++) - uiItemStringO(col, BLI_last_slash(recent->filename)+1, ICON_FILE_BLEND, "WM_OT_open_mainfile", "path", recent->filename); + for(recent = G.recent_files.first, i=0; (i<6) && (recent); recent = recent->next, i++) { + char *display_name= BLI_last_slash(recent->filename); + if(display_name) display_name++; /* skip the slash */ + else display_name= recent->filename; + uiItemStringO(col, display_name, ICON_FILE_BLEND, "WM_OT_open_mainfile", "path", recent->filename); + } uiItemS(col); @@ -1032,7 +1074,7 @@ static uiBlock *wm_block_search_menu(bContext *C, ARegion *ar, void *arg_op) block= uiBeginBlock(C, ar, "_popup", UI_EMBOSS); uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_RET_1|UI_BLOCK_MOVEMOUSE_QUIT); - but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, 256, 10, 10, 180, 19, ""); + but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, 256, 10, 10, 180, 19, 0, 0, ""); uiButSetSearchFunc(but, operator_search_cb, NULL, operator_call_cb, NULL); /* fake button, it holds space for search items */ @@ -1218,7 +1260,7 @@ static short wm_link_append_flag(wmOperator *op) if(RNA_boolean_get(op->ptr, "active_layer")) flag |= FILE_ACTIVELAY; if(RNA_boolean_get(op->ptr, "relative_paths")) flag |= FILE_STRINGCODE; if(RNA_boolean_get(op->ptr, "link")) flag |= FILE_LINK; - + if(RNA_boolean_get(op->ptr, "instance_groups")) flag |= FILE_GROUP_INSTANCE; return flag; } @@ -1234,9 +1276,6 @@ static void wm_link_make_library_local(Main *main, const char *libname) /* make local */ if(lib) { all_local(lib, 1); - /* important we unset, otherwise these object wont - * link into other scenes from this blend file */ - flag_all_listbases_ids(LIB_APPEND_TAG, 0); } } @@ -1294,9 +1333,11 @@ static int wm_link_append_exec(bContext *C, wmOperator *op) flag = wm_link_append_flag(op); - /* tag everything, all untagged data can be made local */ - if((flag & FILE_LINK)==0) - flag_all_listbases_ids(LIB_APPEND_TAG, 1); + /* tag everything, all untagged data can be made local + * its also generally useful to know what is new + * + * take extra care flag_all_listbases_ids(LIB_LINK_TAG, 0) is called after! */ + flag_all_listbases_ids(LIB_PRE_EXISTING, 1); /* here appending/linking starts */ mainl = BLO_library_append_begin(C, &bh, libname); @@ -1319,6 +1360,10 @@ static int wm_link_append_exec(bContext *C, wmOperator *op) if((flag & FILE_LINK)==0) wm_link_make_library_local(bmain, libname); + /* important we unset, otherwise these object wont + * link into other scenes from this blend file */ + flag_all_listbases_ids(LIB_PRE_EXISTING, 0); + /* recreate dependency graph to include new objects */ DAG_scene_sort(scene); DAG_ids_flush_update(0); @@ -1350,6 +1395,7 @@ static void WM_OT_link_append(wmOperatorType *ot) RNA_def_boolean(ot->srna, "link", 1, "Link", "Link the objects or datablocks rather than appending."); RNA_def_boolean(ot->srna, "autoselect", 1, "Select", "Select the linked objects."); RNA_def_boolean(ot->srna, "active_layer", 1, "Active Layer", "Put the linked objects on the active layer."); + RNA_def_boolean(ot->srna, "instance_groups", 1, "Instance Groups", "Create instances for each group as a DupliGroup."); RNA_def_boolean(ot->srna, "relative_paths", 1, "Relative Paths", "Store the library path as a relative path to current .blend file."); RNA_def_collection_runtime(ot->srna, "files", &RNA_OperatorFileListElement, "Files", ""); @@ -1489,10 +1535,10 @@ static int wm_save_as_mainfile_exec(bContext *C, wmOperator *op) fileflags= G.fileflags; /* set compression flag */ - if(RNA_boolean_get(op->ptr, "compress")) - fileflags |= G_FILE_COMPRESS; - else - fileflags &= ~G_FILE_COMPRESS; + if(RNA_boolean_get(op->ptr, "compress")) fileflags |= G_FILE_COMPRESS; + else fileflags &= ~G_FILE_COMPRESS; + if(RNA_boolean_get(op->ptr, "relative_remap")) fileflags |= G_FILE_RELATIVE_REMAP; + else fileflags &= ~G_FILE_RELATIVE_REMAP; WM_write_file(C, path, fileflags, op->reports); @@ -1513,6 +1559,7 @@ static void WM_OT_save_as_mainfile(wmOperatorType *ot) WM_operator_properties_filesel(ot, FOLDERFILE|BLENDERFILE, FILE_BLENDER); RNA_def_boolean(ot->srna, "compress", 0, "Compress", "Write compressed .blend file."); + RNA_def_boolean(ot->srna, "relative_remap", 0, "Remap Relative", "Remap relative paths when saving in a different directory."); } /* *************** save file directly ******** */ @@ -1551,6 +1598,7 @@ static void WM_OT_save_mainfile(wmOperatorType *ot) WM_operator_properties_filesel(ot, FOLDERFILE|BLENDERFILE, FILE_BLENDER); RNA_def_boolean(ot->srna, "compress", 0, "Compress", "Write compressed .blend file."); + RNA_def_boolean(ot->srna, "relative_remap", 0, "Remap Relative", "Remap relative paths when saving in a different directory."); } diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 54f6d58ced4..94248fb392c 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -307,12 +307,14 @@ static void wm_window_add_ghostwindow(wmWindowManager *wm, char *title, wmWindow inital_state += macPrefState; } #endif - + /* Disable AA for now, as GL_SELECT (used for border, lasso, ... select) + doesn't work well when AA is initialized, even if not used. */ ghostwin= GHOST_CreateWindow(g_system, title, win->posx, posy, win->sizex, win->sizey, inital_state, GHOST_kDrawingContextTypeOpenGL, - 0 /* no stereo */); + 0 /* no stereo */, + 0 /* no AA */); if (ghostwin) { diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c index ede1b865970..eddd85c6444 100644 --- a/source/blenderplayer/bad_level_call_stubs/stubs.c +++ b/source/blenderplayer/bad_level_call_stubs/stubs.c @@ -83,6 +83,7 @@ void WM_autosave_init(struct bContext *C){} void WM_jobs_stop_all(struct wmWindowManager *wm){} void WM_event_add_notifier(const struct bContext *C, unsigned int type, void *reference){} +void WM_main_add_notifier(unsigned int type, void *reference){} void ED_armature_bone_rename(struct bArmature *arm, char *oldnamep, char *newnamep){} void ED_armature_edit_bone_remove(struct bArmature *arm, struct EditBone *exBone){} void object_test_constraints (struct Object *owner){} @@ -110,10 +111,14 @@ struct wmKeyMap *WM_keymap_active(struct wmWindowManager *wm, struct wmKeyMap *k struct wmKeyMap *WM_keymap_find(struct wmKeyConfig *keyconf, char *idname, int spaceid, int regionid){return (struct wmKeyMap *) NULL;} struct wmKeyMap *WM_keymap_add_item(struct wmKeyMap *keymap, char *idname, int type, int val, int modifier, int keymodifier){return (struct wmKeyMap *) NULL;} struct wmKeyMap *WM_keymap_copy_to_user(struct wmKeyMap *kemap){return (struct wmKeyMap *) NULL;} +struct wmKeyMap *WM_keymap_list_find(struct ListBase *lb, char *idname, int spaceid, int regionid){return (struct wmKeyMap *) NULL;} struct wmKeyConfig *WM_keyconfig_add(struct wmWindowManager *wm, char *idname){return (struct wmKeyConfig *) NULL;} void WM_keymap_remove_item(struct wmKeyMap *keymap, struct wmKeyMapItem *kmi){} void WM_keymap_restore_to_default(struct wmKeyMap *keymap){} +void WM_keymap_restore_item_to_default(struct bContext *C, struct wmKeyMap *keymap, struct wmKeyMapItem *kmi){} +void WM_keymap_properties_reset(struct wmKeyMapItem *kmi){} int WM_keymap_user_init(struct wmWindowManager *wm, struct wmKeyMap *keymap) {return 0;} +int WM_keymap_item_compare(struct wmKeyMapItem *k1, struct wmKeyMapItem *k2){return 0;} /* rna editors */ @@ -127,6 +132,7 @@ void WM_event_add_fileselect(struct bContext *C, struct wmOperator *op){} void ED_node_texture_default(struct Tex *tx){} void ED_node_changed_update(struct bContext *C, struct bNode *node){} void ED_view3d_scene_layers_update(struct Main *bmain, struct Scene *scene){} +int ED_view3d_scene_layer_set(int lay, const int *values){return 0;} int text_file_modified(struct Text *text){return 0;} void ED_node_shader_default(struct Material *ma){} void ED_screen_animation_timer_update(struct bContext *C, int redraws){} @@ -153,12 +159,19 @@ void ED_mesh_geometry_add(struct Mesh *mesh, struct ReportList *reports, int ver void ED_mesh_material_add(struct Mesh *me, struct Material *ma){} void ED_mesh_transform(struct Mesh *me, float *mat){} void ED_mesh_update(struct Mesh *mesh, struct bContext *C){} +int ED_mesh_color_add(struct bContext *C, struct Scene *scene, struct Object *ob, struct Mesh *me){return 0;} int ED_mesh_uv_texture_add(struct bContext *C, struct Scene *scene, struct Object *ob, struct Mesh *me){return 0;} void ED_object_apply_obmat(struct Object *ob){} void ED_object_constraint_dependency_update(struct Scene *scene, struct Object *ob){} void ED_object_constraint_update(struct Object *ob){} struct bDeformGroup *ED_vgroup_add_name(struct Object *ob, char *name){return (struct bDeformGroup *) NULL;} void ED_vgroup_vert_add(struct Object *ob, struct bDeformGroup *dg, int vertnum, float weight, int assignmode){} +void ED_sequencer_update_view(struct bContext *C, int view){} +float ED_rollBoneToVector(struct EditBone *bone, float new_up_axis[3]){return 0.0f;} + +void EM_selectmode_set(struct EditMesh *em){} +void make_editMesh(struct Scene *scene, struct Object *ob){} +void load_editMesh(struct Scene *scene, struct Object *ob){} void uiItemR(struct uiLayout *layout, char *name, int icon, struct PointerRNA *ptr, char *propname, int flag){} @@ -184,6 +197,7 @@ void uiItemM(struct uiLayout *layout, struct bContext *C, char *name, int icon, void uiItemS(struct uiLayout *layout){} void uiItemFullR(struct uiLayout *layout, char *name, int icon, struct PointerRNA *ptr, struct PropertyRNA *prop, int index, int value, int flag){} void uiLayoutSetContextPointer(struct uiLayout *layout, char *name, struct PointerRNA *ptr){} +char *uiLayoutIntrospect(struct uiLayout *layout){return (char *)NULL;} /* rna template */ void uiTemplateAnyID(struct uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, char *propname, char *text){} @@ -193,6 +207,7 @@ void uiTemplateID(struct uiLayout *layout, struct bContext *C, struct PointerRNA struct uiLayout *uiTemplateModifier(struct uiLayout *layout, struct PointerRNA *ptr){return (struct uiLayout *) NULL;} struct uiLayout *uiTemplateConstraint(struct uiLayout *layout, struct PointerRNA *ptr){return (struct uiLayout *) NULL;} void uiTemplatePreview(struct uiLayout *layout, struct ID *id, struct ID *parent, struct MTex *slot){} +void uiTemplateIDPreview(struct uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, char *propname, char *newop, char *openop, char *unlinkop, int rows, int cols){} void uiTemplateCurveMapping(struct uiLayout *layout, struct CurveMapping *cumap, int type, int compact){} void uiTemplateColorRamp(struct uiLayout *layout, struct ColorBand *coba, int expand){} void uiTemplateLayers(struct uiLayout *layout, struct PointerRNA *ptr, char *propname){} @@ -204,6 +219,7 @@ void uiTemplateOperatorSearch(struct uiLayout *layout){} void uiTemplateHeader3D(struct uiLayout *layout, struct bContext *C){} void uiTemplateTextureImage(struct uiLayout *layout, struct bContext *C, struct Tex *tex){} void uiTemplateImage(struct uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, char *propname, struct PointerRNA *userptr, int compact){} +void uiTemplateDopeSheetFilter(struct uiLayout *layout, struct bContext *C, struct PointerRNA *ptr){} /* rna render */ struct RenderResult *RE_engine_begin_result(struct RenderEngine *engine, int x, int y, int w, int h){return (struct RenderResult *) NULL;} @@ -224,6 +240,7 @@ int RE_engine_test_break(struct RenderEngine *engine){return 0;} struct wmOperatorType *WM_operatortype_find(const char *idname, int quiet){return (struct wmOperatorType *) NULL;} struct wmOperatorType *WM_operatortype_first(){return (struct wmOperatorType *) NULL;} struct wmOperatorType *WM_operatortype_exists(const char *idname){return (struct wmOperatorType *) NULL;} +struct wmOperatorTypeMacro *WM_operatortype_macro_define(struct wmOperatorType *ot, const char *idname){return (struct wmOperatorTypeMacro *) NULL;} int WM_operator_call_py(struct bContext *C, struct wmOperatorType *ot, int context, struct PointerRNA *properties, struct ReportList *reports){return 0;} int WM_operatortype_remove(const char *idname){return 0;} int WM_operator_poll(struct bContext *C, struct wmOperatorType *ot){return 0;} @@ -235,6 +252,7 @@ void WM_operatortype_append_ptr(void (*opfunc)(struct wmOperatorType*, void*), v void WM_operatortype_append_macro_ptr(void (*opfunc)(struct wmOperatorType*, void*), void *userdata){} void WM_operator_bl_idname(char *to, const char *from){} void WM_operator_py_idname(char *to, const char *from){} +void WM_operator_ui_popup(struct bContext *C, struct wmOperator *op, int width, int height){} short insert_keyframe (struct ID *id, struct bAction *act, const char group[], const char rna_path[], int array_index, float cfra, short flag){return 0;} char *WM_operator_pystring(struct bContext *C, struct wmOperatorType *ot, struct PointerRNA *opptr, int all_args){return NULL;} struct wmKeyMapItem *WM_modalkeymap_add_item(struct wmKeyMap *km, int type, int val, int modifier, int keymodifier, int value){return NULL;} diff --git a/source/darwin/Makefile b/source/darwin/Makefile index 1431ab817ff..6007ff4d91c 100644 --- a/source/darwin/Makefile +++ b/source/darwin/Makefile @@ -31,7 +31,9 @@ include nan_definitions.mk DIR = $(OCGDIR)/$(DEBUG_DIR) -all:: +PYARCHIVE = python_$(MACOSX_ARCHITECTURE).zip + +all:: @# set up directory structure for the OSX aplication bundle @echo "---> creating directory structure for $(APPLICATION)" @rm -rf $(DIR)/bin/$(APPLICATION).app @@ -51,7 +53,7 @@ ifeq ($(APPLICATION), blender) @cp -R $(NANBLENDERHOME)/release/scripts $(DIR)/bin/$(APPLICATION).app/Contents/MacOS/.blender/ @echo "---> copying python modules" @mkdir $(DIR)/bin/$(APPLICATION).app/Contents/MacOS/.blender/python - @unzip -q $(LCGDIR)/release/python.zip -d $(DIR)/bin/$(APPLICATION).app/Contents/MacOS/.blender/python/ + @unzip -q $(LCGDIR)/release/$(PYARCHIVE) -d $(DIR)/bin/$(APPLICATION).app/Contents/MacOS/.blender/python/ endif @echo "---> removing SVN directories and Mac hidden files from distribution" @find $(DIR)/bin/$(APPLICATION).app -name CVS -prune -exec rm -rf {} \; diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index a7f8b5c5fdf..a54c229593f 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -1633,11 +1633,16 @@ static KX_LightObject *gamelight_from_blamp(Object *ob, Lamp *la, unsigned int l lightobj.m_nodiffuse = (la->mode & LA_NO_DIFF) != 0; lightobj.m_nospecular = (la->mode & LA_NO_SPEC) != 0; - if (la->mode & LA_NEG) - { - lightobj.m_red = -lightobj.m_red; - lightobj.m_green = -lightobj.m_green; - lightobj.m_blue = -lightobj.m_blue; + bool glslmat = converter->GetGLSLMaterials(); + + // in GLSL NEGATIVE LAMP is handled inside the lamp update function + if(glslmat==0) { + if (la->mode & LA_NEG) + { + lightobj.m_red = -lightobj.m_red; + lightobj.m_green = -lightobj.m_green; + lightobj.m_blue = -lightobj.m_blue; + } } if (la->type==LA_SUN) { @@ -1649,7 +1654,7 @@ static KX_LightObject *gamelight_from_blamp(Object *ob, Lamp *la, unsigned int l } gamelight = new KX_LightObject(kxscene, KX_Scene::m_callbacks, rendertools, - lightobj, converter->GetGLSLMaterials()); + lightobj, glslmat); BL_ConvertLampIpos(la, gamelight, converter); diff --git a/source/gameengine/GamePlayer/common/CMakeLists.txt b/source/gameengine/GamePlayer/common/CMakeLists.txt index c865cf5ce25..2898d07e63d 100644 --- a/source/gameengine/GamePlayer/common/CMakeLists.txt +++ b/source/gameengine/GamePlayer/common/CMakeLists.txt @@ -71,5 +71,7 @@ SET(INC ${ZLIB_INC} ) +ADD_DEFINITIONS(-DGLEW_STATIC) + BLENDERLIB_NOLIST(gp_common "${SRC}" "${INC}") #env.BlenderLib (libname='gp_common', sources=source_files, includes=incs, defines = [], libtype='player', priority=5, compileflags=cflags) diff --git a/source/gameengine/GamePlayer/common/SConscript b/source/gameengine/GamePlayer/common/SConscript index 51fc2fc7334..b66d644f9f5 100644 --- a/source/gameengine/GamePlayer/common/SConscript +++ b/source/gameengine/GamePlayer/common/SConscript @@ -58,7 +58,7 @@ incs = ['.', # 'unix/GPU_System.cpp'] # gp_common_env.Append ( CPPPATH = ['unix']) -defs = [] +defs = [ 'GLEW_STATIC' ] if env['WITH_BF_PYTHON']: incs += Split(env['BF_PYTHON_INC']) diff --git a/source/gameengine/GamePlayer/ghost/CMakeLists.txt b/source/gameengine/GamePlayer/ghost/CMakeLists.txt index d50784cb967..8d73a6f248b 100644 --- a/source/gameengine/GamePlayer/ghost/CMakeLists.txt +++ b/source/gameengine/GamePlayer/ghost/CMakeLists.txt @@ -66,6 +66,8 @@ SET(INC ${PYTHON_INC} ) +ADD_DEFINITIONS(-DGLEW_STATIC) + IF(WITH_FFMPEG) ADD_DEFINITIONS(-DWITH_FFMPEG) ENDIF(WITH_FFMPEG) diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp index e771d12988c..c6952a68a58 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp @@ -565,7 +565,10 @@ bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode) else m_rasterizer = new RAS_OpenGLRasterizer(m_canvas); + /* Stereo parameters - Eye Separation from the UI - stereomode from the command-line/UI */ m_rasterizer->SetStereoMode((RAS_IRasterizer::StereoMode) stereoMode); + m_rasterizer->SetEyeSeparation(m_startScene->gm.eyeseparation); + if (!m_rasterizer) goto initFailed; diff --git a/source/gameengine/GamePlayer/ghost/SConscript b/source/gameengine/GamePlayer/ghost/SConscript index 93769e60401..2269b6400e3 100644 --- a/source/gameengine/GamePlayer/ghost/SConscript +++ b/source/gameengine/GamePlayer/ghost/SConscript @@ -40,7 +40,7 @@ incs = ['.', '#source/blender/gpu', '#extern/glew/include'] -defs = [] +defs = [ 'GLEW_STATIC' ] if env['WITH_BF_PYTHON']: incs += Split(env['BF_PYTHON_INC']) diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index e64e0914b87..6865f9f04a2 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -2605,6 +2605,23 @@ static PyObject *none_tuple_4() return ret; } +static PyObject *none_tuple_5() +{ + PyObject *ret= PyTuple_New(5); + PyTuple_SET_ITEM(ret, 0, Py_None); + PyTuple_SET_ITEM(ret, 1, Py_None); + PyTuple_SET_ITEM(ret, 2, Py_None); + PyTuple_SET_ITEM(ret, 3, Py_None); + PyTuple_SET_ITEM(ret, 4, Py_None); + + Py_INCREF(Py_None); + Py_INCREF(Py_None); + Py_INCREF(Py_None); + Py_INCREF(Py_None); + Py_INCREF(Py_None); + return ret; +} + KX_PYMETHODDEF_DOC(KX_GameObject, rayCast, "rayCast(to,from,dist,prop,face,xray,poly): cast a ray and return 3-tuple (object,hit,normal) or 4-tuple (object,hit,normal,polygon) or 4-tuple (object,hit,normal,polygon,hituv) of contact point with object within dist that matches prop.\n" " If no hit, return (None,None,None) or (None,None,None,None) or (None,None,None,None,None).\n" @@ -2742,11 +2759,11 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast, return returnValue; } // no hit - if (poly) - //return Py_BuildValue("OOOO", Py_None, Py_None, Py_None, Py_None); + if (poly == 2) + return none_tuple_5(); + else if (poly) return none_tuple_4(); else - //return Py_BuildValue("OOO", Py_None, Py_None, Py_None); return none_tuple_3(); } diff --git a/source/gameengine/PyDoc/Rasterizer.py b/source/gameengine/PyDoc/Rasterizer.py index bafcfece473..8fd4d506bde 100644 --- a/source/gameengine/PyDoc/Rasterizer.py +++ b/source/gameengine/PyDoc/Rasterizer.py @@ -136,7 +136,7 @@ def disableMist(): def setEyeSeparation(eyesep): """ - Sets the eye separation for stereo mode. + Sets the eye separation for stereo mode. Usually Focal Length/30 provides a confortable value. @param eyesep: The distance between the left and right eye. @type eyesep: float @@ -151,7 +151,7 @@ def getEyeSeparation(): def setFocalLength(focallength): """ - Sets the focal length for stereo mode. + Sets the focal length for stereo mode. It uses the current camera focal length as initial value. @param focallength: The focal length. @type focallength: float diff --git a/source/nan_compile.mk b/source/nan_compile.mk index 03f5a0d1cd6..3255f102ab7 100644 --- a/source/nan_compile.mk +++ b/source/nan_compile.mk @@ -24,7 +24,7 @@ # # The Original Code is: all of this file. # -# Contributor(s): GSR +# Contributor(s): GSR, Stefan Gartner # # ***** END GPL LICENSE BLOCK ***** # @@ -70,21 +70,48 @@ DBG_CCFLAGS += -g # OS dependent parts --------------------------------------------------- ifeq ($(OS),darwin) - CC ?= gcc + CC ?= gcc CCC ?= g++ - ifeq ($(CPU),powerpc) - CFLAGS += -pipe -fPIC -ffast-math -mcpu=7450 -mtune=G5 -funsigned-char -fno-strict-aliasing -Wno-long-double - CCFLAGS += -pipe -fPIC -funsigned-char -fno-strict-aliasing -Wno-long-double + ifeq ($(MACOSX_DEPLOYMENT_TARGET), 10.4) + CC = gcc-4.0 + CCC = g++-4.0 else - CFLAGS += -pipe -fPIC -ffast-math -march=pentium-m -funsigned-char -fno-strict-aliasing + ifeq ($(MACOSX_DEPLOYMENT_TARGET), 10.5) + CC = gcc-4.2 + CCC = g++-4.2 + endif + endif + ifeq ($(CPU),powerpc) + CFLAGS += -pipe -fPIC -ffast-math -mcpu=7450 -mtune=G5 -funsigned-char -fno-strict-aliasing CCFLAGS += -pipe -fPIC -funsigned-char -fno-strict-aliasing + else + CFLAGS += -pipe -fPIC -ffast-math -funsigned-char + CCFLAGS += -pipe -fPIC -funsigned-char endif -# REL_CFLAGS += -O -# REL_CCFLAGS += -O2 - CPPFLAGS += -D_THREAD_SAFE + + + CFLAGS += -arch $(MACOSX_ARCHITECTURE) #-isysroot $(MACOSX_SDK) -mmacosx-version-min=$(MACOSX_MIN_VERS) + CCFLAGS += -arch $(MACOSX_ARCHITECTURE) #-isysroot $(MACOSX_SDK) -mmacosx-version-min=$(MACOSX_MIN_VERS) + + ifeq ($(MACOSX_ARCHITECTURE), $(findstring $(MACOSX_ARCHITECTURE), "i386 x86_64")) + REL_CFLAGS += -O2 -ftree-vectorize -msse -msse2 -msse3 + REL_CCFLAGS += -O2 -ftree-vectorize -msse -msse2 -msse3 + endif + + ifeq ($(MACOSX_ARCHITECTURE), x86_64) + REL_CFLAGS += -mssse3 + REL_CCFLAGS += -mssse3 + endif + + CPPFLAGS += -D_THREAD_SAFE -fpascal-strings + ifeq ($(WITH_COCOA), true) CPPFLAGS += -DGHOST_COCOA endif + ifeq ($(USE_QTKIT), true) + CPPFLAGS += -DUSE_QTKIT + endif + NAN_DEPEND = true OPENGL_HEADERS = /System/Library/Frameworks/OpenGL.framework AR = ar @@ -324,6 +351,21 @@ $(DIR)/$(DEBUG_DIR)%.o: %.mm $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ endif +$(DIR)/$(DEBUG_DIR)%.o: %.m + ifdef NAN_DEPEND + @set -e; $(CC) -M $(CPPFLAGS) $< 2>/dev/null \ + | sed 's@\($*\)\.o[ :]*@$(DIR)/$(DEBUG_DIR)\1.o : @g' \ + > $(DIR)/$(DEBUG_DIR)$*.d; \ + [ -s $(DIR)/$(DEBUG_DIR)$*.d ] || $(RM) $(DIR)/$(DEBUG_DIR)$*.d + endif + ifdef NAN_QUIET + @echo " -- $< -- " + @$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ + else + $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ + endif + + $(DIR)/$(DEBUG_DIR)%.res: %.rc ifeq ($(FREE_WINDOWS),true) windres $< -O coff -o $@ @@ -349,18 +391,20 @@ CCSRCS ?= $(wildcard *.cpp) JSRCS ?= $(wildcard *.java) ifdef NAN_DEPEND --include $(CSRCS:%.c=$(DIR)/$(DEBUG_DIR)%.d) $(CCSRCS:%.cpp=$(DIR)/$(DEBUG_DIR)%.d) $(OCSRCS:$.mm=$(DIR)/$(DEBUG_DIR)%.d) +-include $(CSRCS:%.c=$(DIR)/$(DEBUG_DIR)%.d) $(CCSRCS:%.cpp=$(DIR)/$(DEBUG_DIR)%.d) $(OCCSRCS:$.mm=$(DIR)/$(DEBUG_DIR)%.d) $(OCSRCS:$.m=$(DIR)/$(DEBUG_DIR)%.d) endif OBJS_AR := $(OBJS) OBJS_AR += $(CSRCS:%.c=%.o) OBJS_AR += $(CCSRCS:%.cpp=%.o) -OBJS_AR += $(OCSRCS:%.mm=%.o) +OBJS_AR += $(OCCSRCS:%.mm=%.o) +OBJS_AR += $(OCSRCS:%.m=%.o) OBJS_AR += $(WINRC:%.rc=%.res) OBJS += $(CSRCS:%.c=$(DIR)/$(DEBUG_DIR)%.o) OBJS += $(CCSRCS:%.cpp=$(DIR)/$(DEBUG_DIR)%.o) -OBJS += $(OCSRCS:%.mm=$(DIR)/$(DEBUG_DIR)%.o) +OBJS += $(OCCSRCS:%.mm=$(DIR)/$(DEBUG_DIR)%.o) +OBJS += $(OCSRCS:%.m=$(DIR)/$(DEBUG_DIR)%.o) OBJS += $(WINRC:%.rc=$(DIR)/$(DEBUG_DIR)%.res) JCLASS += $(JSRCS:%.java=$(DIR)/$(DEBUG_DIR)%.class) diff --git a/source/nan_definitions.mk b/source/nan_definitions.mk index 50df0e777cc..24fe489a26c 100644 --- a/source/nan_definitions.mk +++ b/source/nan_definitions.mk @@ -24,7 +24,7 @@ # # The Original Code is: all of this file. # -# Contributor(s): GSR +# Contributor(s): GSR, Stefan Gartner # # ***** END GPL LICENSE BLOCK ***** # @@ -108,7 +108,11 @@ ifndef CONFIG_GUESS export NAN_FFMPEGLIBS ?= $(NAN_FFMPEG)/lib/libavformat.a $(NAN_FFMPEG)/lib/libavutil.a $(NAN_FFMPEG)/lib/libavcodec.a $(NAN_FFMPEG)/lib/libavdevice.a else export NAN_FFMPEG ?= $(LCGDIR)/ffmpeg - export NAN_FFMPEGLIBS ?= $(NAN_FFMPEG)/lib/libavformat.a $(NAN_FFMPEG)/lib/libavcodec.a $(NAN_FFMPEG)/lib/libswscale.a $(NAN_FFMPEG)/lib/libavutil.a $(NAN_FFMPEG)/lib/libavdevice.a + ifeq ($(OS), darwin) + export NAN_FFMPEGLIBS ?= $(NAN_FFMPEG)/lib/libavformat.a $(NAN_FFMPEG)/lib/libavcodec.a $(NAN_FFMPEG)/lib/libswscale.a $(NAN_FFMPEG)/lib/libavutil.a $(NAN_FFMPEG)/lib/libavdevice.a $(NAN_FFMPEG)/lib/libmp3lame.a $(NAN_FFMPEG)/lib/libx264.a $(NAN_FFMPEG)/lib/libxvidcore.a + else + export NAN_FFMPEGLIBS ?= $(NAN_FFMPEG)/lib/libavformat.a $(NAN_FFMPEG)/lib/libavcodec.a $(NAN_FFMPEG)/lib/libswscale.a $(NAN_FFMPEG)/lib/libavutil.a $(NAN_FFMPEG)/lib/libavdevice.a + endif endif export NAN_FFMPEGCFLAGS ?= -I$(NAN_FFMPEG)/include -I$(NANBLENDERHOME)/extern/ffmpeg @@ -146,8 +150,17 @@ ifndef CONFIG_GUESS export NAN_FFMPEGCFLAGS = $(shell pkg-config --cflags libavcodec libavdevice libavformat libswscale libavutil) endif - # Compare recreated .mo files with committed ones - export BF_VERIFY_MO_FILES ?= true + ifeq ($(WITH_OPENCOLLADA), true) + export BF_OPENCOLLADA ?= $(LCGDIR)/opencollada + export BF_OPENCOLLADA_INC ?= $(BF_OPENCOLLADA)/include + export BF_OPENCOLLADA_LIBS ?= $(BF_OPENCOLLADA)/lib/libOpenCOLLADASaxFrameworkLoader.a $(BF_OPENCOLLADA)/lib/libOpenCOLLADAFramework.a $(BF_OPENCOLLADA)/lib/libOpenCOLLADABaseUtils.a $(BF_OPENCOLLADA)/lib/libOpenCOLLADAStreamWriter.a $(BF_OPENCOLLADA)/lib/libMathMLSolver.a $(BF_OPENCOLLADA)/lib/libGeneratedSaxParser.a $(BF_OPENCOLLADA)/lib/libUTF.a -lxml2 + export BF_PCRE ?= $(LCGDIR)/pcre + export BF_PCRE_LIBS ?= $(NAN_PCRE)/lib/libpcre.a + endif + + + # Compare recreated .mo files with committed ones + export BF_VERIFY_MO_FILES ?= true # Platform Dependent settings go below: ifeq ($(OS),darwin) @@ -155,6 +168,36 @@ ifndef CONFIG_GUESS export ID = $(shell whoami) export HOST = $(shell hostname -s) + # set target arch & os version + # architecture defaults to host arch, can be ppc, ppc64, i386, x86_64 + ifeq ($(CPU),powerpc) + export MACOSX_ARCHITECTURE ?= ppc + else + export MACOSX_ARCHITECTURE ?= i386 + endif + # target os version defaults to 10.4 for ppc & i386 (32 bit), 10.5 for ppc64, x86_64 + ifeq (64,$(findstring 64, $(MACOSX_ARCHITECTURE))) + export MACOSX_MIN_VERS ?= 10.5 + export MACOSX_DEPLOYMENT_TARGET ?= 10.5 + export MACOSX_SDK ?= /Developer/SDKs/MacOSX10.5.sdk + else + export MACOSX_MIN_VERS ?= 10.4 + export MACOSX_DEPLOYMENT_TARGET ?= 10.4 + export MACOSX_SDK ?= /Developer/SDKs/MacOSX10.4u.sdk + endif + + # useful for crosscompiling + ifeq ($(MACOSX_ARCHITECTURE),$(findstring $(MACOSX_ARCHITECTURE), "ppc ppc64")) + export CPU = powerpc + export LCGDIR = $(NAN_LIBDIR)/$(OS)-$(OS_VERSION)-$(CPU) + export OCGDIR = $(NAN_OBJDIR)/$(OS)-$(OS_VERSION)-$(CPU) + endif + ifeq ($(MACOSX_ARCHITECTURE),$(findstring $(MACOSX_ARCHITECTURE),"i386 x86_64")) + export CPU = i386 + export LCGDIR = $(NAN_LIBDIR)/$(OS)-$(OS_VERSION)-$(CPU) + export OCGDIR = $(NAN_OBJDIR)/$(OS)-$(OS_VERSION)-$(CPU) + endif + export NAN_PYTHON_VERSION = 3.1 ifeq ($(NAN_PYTHON_VERSION),3.1) @@ -199,9 +242,9 @@ ifndef CONFIG_GUESS export NAN_NO_KETSJI=false - ifeq ($(CPU), i386) - export WITH_OPENAL=false - endif + #ifeq ($(CPU), i386) + # export WITH_OPENAL=false + #endif # Location of MOZILLA/Netscape header files... export NAN_MOZILLA_INC ?= $(LCGDIR)/mozilla/include @@ -222,6 +265,17 @@ ifndef CONFIG_GUESS export NAN_SAMPLERATE ?= $(LCGDIR)/samplerate export NAN_SAMPLERATE_LIBS ?= $(NAN_SAMPLERATE)/lib/libsamplerate.a + # enable building with Cocoa + export WITH_COCOA ?= true + export USE_QTKIT ?= false + # use cocoa and qtkit for 64bit builds + ifeq (64, $(findstring 64, $(MACOSX_ARCHITECTURE))) + export WITH_COCOA = true + export USE_QTKIT = true + endif + + export NAN_PCRE = $(LCGDIR)/opencollada + else ifeq ($(OS),freebsd) diff --git a/source/nan_link.mk b/source/nan_link.mk index 0524ee7592d..54021ab016f 100644 --- a/source/nan_link.mk +++ b/source/nan_link.mk @@ -59,9 +59,19 @@ ifeq ($(OS),darwin) LLIBS += -framework Cocoa endif LLIBS += -framework Carbon -framework AGL -framework OpenGL - LLIBS += -framework QuickTime -framework CoreAudio - LLIBS += -framework AudioUnit -framework AudioToolbox + ifeq ($(WITH_QUICKTIME), true) + ifeq ($(USE_QTKIT), true) + LLIBS += -framework QTKit + else + LLIBS += -framework QuickTime + endif + endif + LLIBS += -framework CoreAudio + LLIBS += -framework AudioUnit -framework AudioToolbox LDFLAGS += -L/System/Library/Frameworks/OpenGL.framework/Libraries + # useful for crosscompiling + LDFLAGS += -arch $(MACOSX_ARCHITECTURE) #-isysroot $(MACOSX_SDK) -mmacosx-version-min=$(MACOSX_MIN_VERS) + DBG_LDFLAGS += -L/System/Library/Frameworks/OpenGL.framework/Libraries endif @@ -177,4 +187,8 @@ ifeq ($(WITH_FFTW3),true) LLIBS += $(BF_FFTW3_LIBS) endif +ifeq ($(WITH_OPENCOLLADA),true) + LLIBS += $(BF_OPENCOLLADA_LIBS) +endif + LLIBS += $(NAN_PYTHON_LIB) diff --git a/tools/btools.py b/tools/btools.py index 556cb9b901a..b3a97f96417 100644 --- a/tools/btools.py +++ b/tools/btools.py @@ -77,7 +77,8 @@ def validate_arguments(args, bc): 'BF_VERSION', 'BF_GHOST_DEBUG', 'WITH_BF_RAYOPTIMIZATION', - 'BF_RAYOPTIMIZATION_SSE_FLAGS' + 'BF_RAYOPTIMIZATION_SSE_FLAGS', + 'BF_NO_ELBEEM' ] # Have options here that scons expects to be lists |