diff options
190 files changed, 3903 insertions, 1614 deletions
diff --git a/intern/audaspace/FX/AUD_AccumulatorFactory.cpp b/intern/audaspace/FX/AUD_AccumulatorFactory.cpp index d60924958b1..207c2ee502b 100644 --- a/intern/audaspace/FX/AUD_AccumulatorFactory.cpp +++ b/intern/audaspace/FX/AUD_AccumulatorFactory.cpp @@ -52,14 +52,14 @@ sample_t accumulatorFilter(AUD_CallbackIIRFilterReader* reader, void* useless) return out; } -AUD_AccumulatorFactory::AUD_AccumulatorFactory(AUD_IFactory* factory, +AUD_AccumulatorFactory::AUD_AccumulatorFactory(AUD_Reference<AUD_IFactory> factory, bool additive) : AUD_EffectFactory(factory), m_additive(additive) { } -AUD_IReader* AUD_AccumulatorFactory::createReader() const +AUD_Reference<AUD_IReader> AUD_AccumulatorFactory::createReader() const { return new AUD_CallbackIIRFilterReader(getReader(), 2, 2, m_additive ? accumulatorFilterAdditive : accumulatorFilter); diff --git a/intern/audaspace/FX/AUD_AccumulatorFactory.h b/intern/audaspace/FX/AUD_AccumulatorFactory.h index 3c3b32ce071..becd5d9aaee 100644 --- a/intern/audaspace/FX/AUD_AccumulatorFactory.h +++ b/intern/audaspace/FX/AUD_AccumulatorFactory.h @@ -55,9 +55,9 @@ public: * \param factory The input factory. * \param additive Whether the accumulator is additive. */ - AUD_AccumulatorFactory(AUD_IFactory* factory, bool additive = false); + AUD_AccumulatorFactory(AUD_Reference<AUD_IFactory> factory, bool additive = false); - virtual AUD_IReader* createReader() const; + virtual AUD_Reference<AUD_IReader> createReader() const; }; #endif //AUD_ACCUMULATORFACTORY diff --git a/intern/audaspace/FX/AUD_BaseIIRFilterReader.cpp b/intern/audaspace/FX/AUD_BaseIIRFilterReader.cpp index 563722d9213..5ad5903141b 100644 --- a/intern/audaspace/FX/AUD_BaseIIRFilterReader.cpp +++ b/intern/audaspace/FX/AUD_BaseIIRFilterReader.cpp @@ -35,7 +35,7 @@ #define CC m_channels + m_channel -AUD_BaseIIRFilterReader::AUD_BaseIIRFilterReader(AUD_IReader* reader, int in, +AUD_BaseIIRFilterReader::AUD_BaseIIRFilterReader(AUD_Reference<AUD_IReader> reader, int in, int out) : AUD_EffectReader(reader), m_channels(reader->getSpecs().channels), diff --git a/intern/audaspace/FX/AUD_BaseIIRFilterReader.h b/intern/audaspace/FX/AUD_BaseIIRFilterReader.h index 436e6469a58..9f81e2d8a25 100644 --- a/intern/audaspace/FX/AUD_BaseIIRFilterReader.h +++ b/intern/audaspace/FX/AUD_BaseIIRFilterReader.h @@ -97,7 +97,7 @@ protected: * \param in The count of past input samples needed. * \param out The count of past output samples needed. */ - AUD_BaseIIRFilterReader(AUD_IReader* reader, int in, int out); + AUD_BaseIIRFilterReader(AUD_Reference<AUD_IReader> reader, int in, int out); public: inline sample_t x(int pos) diff --git a/intern/audaspace/FX/AUD_ButterworthFactory.cpp b/intern/audaspace/FX/AUD_ButterworthFactory.cpp index ea957c81ed3..1161a485fb1 100644 --- a/intern/audaspace/FX/AUD_ButterworthFactory.cpp +++ b/intern/audaspace/FX/AUD_ButterworthFactory.cpp @@ -41,16 +41,16 @@ #define BWPB41 0.76536686473 #define BWPB42 1.84775906502 -AUD_ButterworthFactory::AUD_ButterworthFactory(AUD_IFactory* factory, +AUD_ButterworthFactory::AUD_ButterworthFactory(AUD_Reference<AUD_IFactory> factory, float frequency) : AUD_EffectFactory(factory), m_frequency(frequency) { } -AUD_IReader* AUD_ButterworthFactory::createReader() const +AUD_Reference<AUD_IReader> AUD_ButterworthFactory::createReader() const { - AUD_IReader* reader = getReader(); + AUD_Reference<AUD_IReader> reader = getReader(); // calculate coefficients float omega = 2 * tan(m_frequency * M_PI / reader->getSpecs().rate); diff --git a/intern/audaspace/FX/AUD_ButterworthFactory.h b/intern/audaspace/FX/AUD_ButterworthFactory.h index c8b731449c4..c211a6df246 100644 --- a/intern/audaspace/FX/AUD_ButterworthFactory.h +++ b/intern/audaspace/FX/AUD_ButterworthFactory.h @@ -55,9 +55,9 @@ public: * \param factory The input factory. * \param frequency The cutoff frequency. */ - AUD_ButterworthFactory(AUD_IFactory* factory, float frequency); + AUD_ButterworthFactory(AUD_Reference<AUD_IFactory> factory, float frequency); - virtual AUD_IReader* createReader() const; + virtual AUD_Reference<AUD_IReader> createReader() const; }; #endif //AUD_BUTTERWORTHFACTORY diff --git a/intern/audaspace/FX/AUD_CallbackIIRFilterReader.cpp b/intern/audaspace/FX/AUD_CallbackIIRFilterReader.cpp index 2f9bb7762a0..e6c83322435 100644 --- a/intern/audaspace/FX/AUD_CallbackIIRFilterReader.cpp +++ b/intern/audaspace/FX/AUD_CallbackIIRFilterReader.cpp @@ -31,7 +31,7 @@ #include "AUD_CallbackIIRFilterReader.h" -AUD_CallbackIIRFilterReader::AUD_CallbackIIRFilterReader(AUD_IReader* reader, +AUD_CallbackIIRFilterReader::AUD_CallbackIIRFilterReader(AUD_Reference<AUD_IReader> reader, int in, int out, doFilterIIR doFilter, endFilterIIR endFilter, diff --git a/intern/audaspace/FX/AUD_CallbackIIRFilterReader.h b/intern/audaspace/FX/AUD_CallbackIIRFilterReader.h index a969db7297e..6d53edeecc2 100644 --- a/intern/audaspace/FX/AUD_CallbackIIRFilterReader.h +++ b/intern/audaspace/FX/AUD_CallbackIIRFilterReader.h @@ -76,7 +76,7 @@ public: * \param endFilter The finishing callback. * \param data Data pointer for the callbacks. */ - AUD_CallbackIIRFilterReader(AUD_IReader* reader, int in, int out, + AUD_CallbackIIRFilterReader(AUD_Reference<AUD_IReader> reader, int in, int out, doFilterIIR doFilter, endFilterIIR endFilter = 0, void* data = 0); diff --git a/intern/audaspace/FX/AUD_DelayFactory.cpp b/intern/audaspace/FX/AUD_DelayFactory.cpp index 1d2d99adc03..ceecd7a63c9 100644 --- a/intern/audaspace/FX/AUD_DelayFactory.cpp +++ b/intern/audaspace/FX/AUD_DelayFactory.cpp @@ -33,7 +33,7 @@ #include "AUD_DelayReader.h" #include "AUD_Space.h" -AUD_DelayFactory::AUD_DelayFactory(AUD_IFactory* factory, float delay) : +AUD_DelayFactory::AUD_DelayFactory(AUD_Reference<AUD_IFactory> factory, float delay) : AUD_EffectFactory(factory), m_delay(delay) { @@ -44,7 +44,7 @@ float AUD_DelayFactory::getDelay() const return m_delay; } -AUD_IReader* AUD_DelayFactory::createReader() const +AUD_Reference<AUD_IReader> AUD_DelayFactory::createReader() const { return new AUD_DelayReader(getReader(), m_delay); } diff --git a/intern/audaspace/FX/AUD_DelayFactory.h b/intern/audaspace/FX/AUD_DelayFactory.h index 1e67cd68990..6362bd19a70 100644 --- a/intern/audaspace/FX/AUD_DelayFactory.h +++ b/intern/audaspace/FX/AUD_DelayFactory.h @@ -55,14 +55,14 @@ public: * \param factory The input factory. * \param delay The desired delay in seconds. */ - AUD_DelayFactory(AUD_IFactory* factory, float delay = 0); + AUD_DelayFactory(AUD_Reference<AUD_IFactory> factory, float delay = 0); /** * Returns the delay in seconds. */ float getDelay() const; - virtual AUD_IReader* createReader() const; + virtual AUD_Reference<AUD_IReader> createReader() const; }; #endif //AUD_DELAYFACTORY diff --git a/intern/audaspace/FX/AUD_DelayReader.cpp b/intern/audaspace/FX/AUD_DelayReader.cpp index 374b876455d..a2224caf288 100644 --- a/intern/audaspace/FX/AUD_DelayReader.cpp +++ b/intern/audaspace/FX/AUD_DelayReader.cpp @@ -33,7 +33,7 @@ #include <cstring> -AUD_DelayReader::AUD_DelayReader(AUD_IReader* reader, float delay) : +AUD_DelayReader::AUD_DelayReader(AUD_Reference<AUD_IReader> reader, float delay) : AUD_EffectReader(reader), m_delay(int(delay * reader->getSpecs().rate)), m_remdelay(int(delay * reader->getSpecs().rate)), diff --git a/intern/audaspace/FX/AUD_DelayReader.h b/intern/audaspace/FX/AUD_DelayReader.h index 5f0af660bdf..695003a8c43 100644 --- a/intern/audaspace/FX/AUD_DelayReader.h +++ b/intern/audaspace/FX/AUD_DelayReader.h @@ -71,7 +71,7 @@ public: * \param reader The reader to read from. * \param delay The delay in seconds. */ - AUD_DelayReader(AUD_IReader* reader, float delay); + AUD_DelayReader(AUD_Reference<AUD_IReader> reader, float delay); virtual void seek(int position); virtual int getLength() const; diff --git a/intern/audaspace/FX/AUD_DoubleFactory.cpp b/intern/audaspace/FX/AUD_DoubleFactory.cpp index 7a40f1f8c96..5b72082f520 100644 --- a/intern/audaspace/FX/AUD_DoubleFactory.cpp +++ b/intern/audaspace/FX/AUD_DoubleFactory.cpp @@ -32,25 +32,15 @@ #include "AUD_DoubleFactory.h" #include "AUD_DoubleReader.h" -AUD_DoubleFactory::AUD_DoubleFactory(AUD_IFactory* factory1, AUD_IFactory* factory2) : +AUD_DoubleFactory::AUD_DoubleFactory(AUD_Reference<AUD_IFactory> factory1, AUD_Reference<AUD_IFactory> factory2) : m_factory1(factory1), m_factory2(factory2) { } -AUD_IReader* AUD_DoubleFactory::createReader() const +AUD_Reference<AUD_IReader> AUD_DoubleFactory::createReader() const { - AUD_IReader* reader1 = m_factory1->createReader(); - AUD_IReader* reader2; - - try - { - reader2 = m_factory2->createReader(); - } - catch(AUD_Exception&) - { - delete reader1; - throw; - } + AUD_Reference<AUD_IReader> reader1 = m_factory1->createReader(); + AUD_Reference<AUD_IReader> reader2 = m_factory2->createReader(); return new AUD_DoubleReader(reader1, reader2); } diff --git a/intern/audaspace/FX/AUD_DoubleFactory.h b/intern/audaspace/FX/AUD_DoubleFactory.h index 52a299c7157..acc9997deea 100644 --- a/intern/audaspace/FX/AUD_DoubleFactory.h +++ b/intern/audaspace/FX/AUD_DoubleFactory.h @@ -44,12 +44,12 @@ private: /** * First played factory. */ - AUD_IFactory* m_factory1; + AUD_Reference<AUD_IFactory> m_factory1; /** * Second played factory. */ - AUD_IFactory* m_factory2; + AUD_Reference<AUD_IFactory> m_factory2; // hide copy constructor and operator= AUD_DoubleFactory(const AUD_DoubleFactory&); @@ -61,9 +61,9 @@ public: * \param factory1 The first input factory. * \param factory2 The second input factory. */ - AUD_DoubleFactory(AUD_IFactory* factory1, AUD_IFactory* factory2); + AUD_DoubleFactory(AUD_Reference<AUD_IFactory> factory1, AUD_Reference<AUD_IFactory> factory2); - virtual AUD_IReader* createReader() const; + virtual AUD_Reference<AUD_IReader> createReader() const; }; #endif //AUD_DOUBLEFACTORY diff --git a/intern/audaspace/FX/AUD_DoubleReader.cpp b/intern/audaspace/FX/AUD_DoubleReader.cpp index 113bed14ce3..bf1c770a2ed 100644 --- a/intern/audaspace/FX/AUD_DoubleReader.cpp +++ b/intern/audaspace/FX/AUD_DoubleReader.cpp @@ -36,8 +36,8 @@ static const char* specs_error = "AUD_DoubleReader: Both readers have to have " "the same specs."; -AUD_DoubleReader::AUD_DoubleReader(AUD_IReader* reader1, - AUD_IReader* reader2) : +AUD_DoubleReader::AUD_DoubleReader(AUD_Reference<AUD_IReader> reader1, + AUD_Reference<AUD_IReader> reader2) : m_reader1(reader1), m_reader2(reader2), m_finished1(false) { AUD_Specs s1, s2; @@ -45,16 +45,12 @@ AUD_DoubleReader::AUD_DoubleReader(AUD_IReader* reader1, s2 = reader2->getSpecs(); if(memcmp(&s1, &s2, sizeof(AUD_Specs)) != 0) { - delete reader1; - delete reader2; AUD_THROW(AUD_ERROR_SPECS, specs_error); } } AUD_DoubleReader::~AUD_DoubleReader() { - delete m_reader1; - delete m_reader2; } bool AUD_DoubleReader::isSeekable() const diff --git a/intern/audaspace/FX/AUD_DoubleReader.h b/intern/audaspace/FX/AUD_DoubleReader.h index 7b3b812ef80..4f01c47d052 100644 --- a/intern/audaspace/FX/AUD_DoubleReader.h +++ b/intern/audaspace/FX/AUD_DoubleReader.h @@ -34,6 +34,7 @@ #include "AUD_IReader.h" #include "AUD_Buffer.h" +#include "AUD_Reference.h" /** * This reader plays two readers with the same specs sequently. @@ -44,12 +45,12 @@ private: /** * The first reader. */ - AUD_IReader* m_reader1; + AUD_Reference<AUD_IReader> m_reader1; /** * The second reader. */ - AUD_IReader* m_reader2; + AUD_Reference<AUD_IReader> m_reader2; /** * Whether we've reached the end of the first reader. @@ -72,7 +73,7 @@ public: * \param reader2 The second reader to read from. * \exception AUD_Exception Thrown if the specs from the readers differ. */ - AUD_DoubleReader(AUD_IReader* reader1, AUD_IReader* reader2); + AUD_DoubleReader(AUD_Reference<AUD_IReader> reader1, AUD_Reference<AUD_IReader> reader2); /** * Destroys the reader. diff --git a/intern/audaspace/FX/AUD_EffectFactory.cpp b/intern/audaspace/FX/AUD_EffectFactory.cpp index a0d9256e691..6173ffb5a97 100644 --- a/intern/audaspace/FX/AUD_EffectFactory.cpp +++ b/intern/audaspace/FX/AUD_EffectFactory.cpp @@ -32,7 +32,7 @@ #include "AUD_EffectFactory.h" #include "AUD_IReader.h" -AUD_EffectFactory::AUD_EffectFactory(AUD_IFactory* factory) +AUD_EffectFactory::AUD_EffectFactory(AUD_Reference<AUD_IFactory> factory) { m_factory = factory; } @@ -41,7 +41,7 @@ AUD_EffectFactory::~AUD_EffectFactory() { } -AUD_IFactory* AUD_EffectFactory::getFactory() const +AUD_Reference<AUD_IFactory> AUD_EffectFactory::getFactory() const { return m_factory; } diff --git a/intern/audaspace/FX/AUD_EffectFactory.h b/intern/audaspace/FX/AUD_EffectFactory.h index a6a28eea577..72fdb3f0833 100644 --- a/intern/audaspace/FX/AUD_EffectFactory.h +++ b/intern/audaspace/FX/AUD_EffectFactory.h @@ -49,7 +49,7 @@ protected: /** * If there is no reader it is created out of this factory. */ - AUD_IFactory* m_factory; + AUD_Reference<AUD_IFactory> m_factory; /** * Returns the reader created out of the factory. @@ -57,7 +57,7 @@ protected: * classes. * \return The reader created out of the factory. */ - inline AUD_IReader* getReader() const + inline AUD_Reference<AUD_IReader> getReader() const { return m_factory->createReader(); } @@ -67,7 +67,7 @@ public: * Creates a new factory. * \param factory The input factory. */ - AUD_EffectFactory(AUD_IFactory* factory); + AUD_EffectFactory(AUD_Reference<AUD_IFactory> factory); /** * Destroys the factory. @@ -78,7 +78,7 @@ public: * Returns the saved factory. * \return The factory or NULL if there has no factory been saved. */ - AUD_IFactory* getFactory() const; + AUD_Reference<AUD_IFactory> getFactory() const; }; #endif //AUD_EFFECTFACTORY diff --git a/intern/audaspace/FX/AUD_EffectReader.cpp b/intern/audaspace/FX/AUD_EffectReader.cpp index 3ad9f67bfd6..d7c4eeb2ee1 100644 --- a/intern/audaspace/FX/AUD_EffectReader.cpp +++ b/intern/audaspace/FX/AUD_EffectReader.cpp @@ -31,14 +31,13 @@ #include "AUD_EffectReader.h" -AUD_EffectReader::AUD_EffectReader(AUD_IReader* reader) +AUD_EffectReader::AUD_EffectReader(AUD_Reference<AUD_IReader> reader) { m_reader = reader; } AUD_EffectReader::~AUD_EffectReader() { - delete m_reader; } bool AUD_EffectReader::isSeekable() const diff --git a/intern/audaspace/FX/AUD_EffectReader.h b/intern/audaspace/FX/AUD_EffectReader.h index fb8066f36d8..6aa185edcd0 100644 --- a/intern/audaspace/FX/AUD_EffectReader.h +++ b/intern/audaspace/FX/AUD_EffectReader.h @@ -33,6 +33,7 @@ #define AUD_EFFECTREADER #include "AUD_IReader.h" +#include "AUD_Reference.h" /** * This reader is a base class for all effect readers that take one other reader @@ -49,14 +50,14 @@ protected: /** * The reader to read from. */ - AUD_IReader* m_reader; + AUD_Reference<AUD_IReader> m_reader; public: /** * Creates a new effect reader. * \param reader The reader to read from. */ - AUD_EffectReader(AUD_IReader* reader); + AUD_EffectReader(AUD_Reference<AUD_IReader> reader); /** * Destroys the reader. diff --git a/intern/audaspace/FX/AUD_EnvelopeFactory.cpp b/intern/audaspace/FX/AUD_EnvelopeFactory.cpp index 069317d1c8b..e36091950a5 100644 --- a/intern/audaspace/FX/AUD_EnvelopeFactory.cpp +++ b/intern/audaspace/FX/AUD_EnvelopeFactory.cpp @@ -56,7 +56,7 @@ void endEnvelopeFilter(EnvelopeParameters* param) delete param; } -AUD_EnvelopeFactory::AUD_EnvelopeFactory(AUD_IFactory* factory, float attack, +AUD_EnvelopeFactory::AUD_EnvelopeFactory(AUD_Reference<AUD_IFactory> factory, float attack, float release, float threshold, float arthreshold) : AUD_EffectFactory(factory), @@ -67,9 +67,9 @@ AUD_EnvelopeFactory::AUD_EnvelopeFactory(AUD_IFactory* factory, float attack, { } -AUD_IReader* AUD_EnvelopeFactory::createReader() const +AUD_Reference<AUD_IReader> AUD_EnvelopeFactory::createReader() const { - AUD_IReader* reader = getReader(); + AUD_Reference<AUD_IReader> reader = getReader(); EnvelopeParameters* param = new EnvelopeParameters(); param->arthreshold = m_arthreshold; diff --git a/intern/audaspace/FX/AUD_EnvelopeFactory.h b/intern/audaspace/FX/AUD_EnvelopeFactory.h index 45ee811b6e0..0a803f77aaf 100644 --- a/intern/audaspace/FX/AUD_EnvelopeFactory.h +++ b/intern/audaspace/FX/AUD_EnvelopeFactory.h @@ -73,10 +73,10 @@ public: * \param threshold The threshold value. * \param arthreshold The attack/release threshold value. */ - AUD_EnvelopeFactory(AUD_IFactory* factory, float attack, float release, + AUD_EnvelopeFactory(AUD_Reference<AUD_IFactory> factory, float attack, float release, float threshold, float arthreshold); - virtual AUD_IReader* createReader() const; + virtual AUD_Reference<AUD_IReader> createReader() const; }; #endif //AUD_ENVELOPEFACTORY diff --git a/intern/audaspace/FX/AUD_FaderFactory.cpp b/intern/audaspace/FX/AUD_FaderFactory.cpp index d887e9e68d9..e7fe5098d76 100644 --- a/intern/audaspace/FX/AUD_FaderFactory.cpp +++ b/intern/audaspace/FX/AUD_FaderFactory.cpp @@ -32,7 +32,7 @@ #include "AUD_FaderFactory.h" #include "AUD_FaderReader.h" -AUD_FaderFactory::AUD_FaderFactory(AUD_IFactory* factory, AUD_FadeType type, +AUD_FaderFactory::AUD_FaderFactory(AUD_Reference<AUD_IFactory> factory, AUD_FadeType type, float start, float length) : AUD_EffectFactory(factory), m_type(type), @@ -56,7 +56,7 @@ float AUD_FaderFactory::getLength() const return m_length; } -AUD_IReader* AUD_FaderFactory::createReader() const +AUD_Reference<AUD_IReader> AUD_FaderFactory::createReader() const { return new AUD_FaderReader(getReader(), m_type, m_start, m_length); } diff --git a/intern/audaspace/FX/AUD_FaderFactory.h b/intern/audaspace/FX/AUD_FaderFactory.h index b85475bc534..cc20245a267 100644 --- a/intern/audaspace/FX/AUD_FaderFactory.h +++ b/intern/audaspace/FX/AUD_FaderFactory.h @@ -69,7 +69,7 @@ public: * \param start The time where fading should start in seconds. * \param length How long fading should last in seconds. */ - AUD_FaderFactory(AUD_IFactory* factory, + AUD_FaderFactory(AUD_Reference<AUD_IFactory> factory, AUD_FadeType type = AUD_FADE_IN, float start = 0.0f, float length = 1.0f); @@ -88,7 +88,7 @@ public: */ float getLength() const; - virtual AUD_IReader* createReader() const; + virtual AUD_Reference<AUD_IReader> createReader() const; }; #endif //AUD_FADERFACTORY diff --git a/intern/audaspace/FX/AUD_FaderReader.cpp b/intern/audaspace/FX/AUD_FaderReader.cpp index 6114bb486fc..e319e205e5f 100644 --- a/intern/audaspace/FX/AUD_FaderReader.cpp +++ b/intern/audaspace/FX/AUD_FaderReader.cpp @@ -33,7 +33,7 @@ #include <cstring> -AUD_FaderReader::AUD_FaderReader(AUD_IReader* reader, AUD_FadeType type, +AUD_FaderReader::AUD_FaderReader(AUD_Reference<AUD_IReader> reader, AUD_FadeType type, float start,float length) : AUD_EffectReader(reader), m_type(type), diff --git a/intern/audaspace/FX/AUD_FaderReader.h b/intern/audaspace/FX/AUD_FaderReader.h index fb927192b45..b088477bce0 100644 --- a/intern/audaspace/FX/AUD_FaderReader.h +++ b/intern/audaspace/FX/AUD_FaderReader.h @@ -79,7 +79,7 @@ public: * \param start The time where fading should start in seconds. * \param length How long fading should last in seconds. */ - AUD_FaderReader(AUD_IReader* reader, AUD_FadeType type, + AUD_FaderReader(AUD_Reference<AUD_IReader> reader, AUD_FadeType type, float start,float length); virtual void read(int & length, sample_t* & buffer); diff --git a/intern/audaspace/FX/AUD_HighpassFactory.cpp b/intern/audaspace/FX/AUD_HighpassFactory.cpp index 61008eea44e..b8bfa6545ac 100644 --- a/intern/audaspace/FX/AUD_HighpassFactory.cpp +++ b/intern/audaspace/FX/AUD_HighpassFactory.cpp @@ -38,7 +38,7 @@ #define M_PI 3.14159265358979323846 #endif -AUD_HighpassFactory::AUD_HighpassFactory(AUD_IFactory* factory, float frequency, +AUD_HighpassFactory::AUD_HighpassFactory(AUD_Reference<AUD_IFactory> factory, float frequency, float Q) : AUD_EffectFactory(factory), m_frequency(frequency), @@ -46,9 +46,9 @@ AUD_HighpassFactory::AUD_HighpassFactory(AUD_IFactory* factory, float frequency, { } -AUD_IReader* AUD_HighpassFactory::createReader() const +AUD_Reference<AUD_IReader> AUD_HighpassFactory::createReader() const { - AUD_IReader* reader = getReader(); + AUD_Reference<AUD_IReader> reader = getReader(); // calculate coefficients float w0 = 2 * M_PI * m_frequency / reader->getSpecs().rate; diff --git a/intern/audaspace/FX/AUD_HighpassFactory.h b/intern/audaspace/FX/AUD_HighpassFactory.h index 48f4c1baefc..0089cc2c139 100644 --- a/intern/audaspace/FX/AUD_HighpassFactory.h +++ b/intern/audaspace/FX/AUD_HighpassFactory.h @@ -61,9 +61,9 @@ public: * \param frequency The cutoff frequency. * \param Q The Q factor. */ - AUD_HighpassFactory(AUD_IFactory* factory, float frequency, float Q = 1.0f); + AUD_HighpassFactory(AUD_Reference<AUD_IFactory> factory, float frequency, float Q = 1.0f); - virtual AUD_IReader* createReader() const; + virtual AUD_Reference<AUD_IReader> createReader() const; }; #endif //AUD_HIGHPASSFACTORY diff --git a/intern/audaspace/FX/AUD_IIRFilterFactory.cpp b/intern/audaspace/FX/AUD_IIRFilterFactory.cpp index ff90ce62739..e24a10266c9 100644 --- a/intern/audaspace/FX/AUD_IIRFilterFactory.cpp +++ b/intern/audaspace/FX/AUD_IIRFilterFactory.cpp @@ -32,14 +32,14 @@ #include "AUD_IIRFilterFactory.h" #include "AUD_IIRFilterReader.h" -AUD_IIRFilterFactory::AUD_IIRFilterFactory(AUD_IFactory* factory, +AUD_IIRFilterFactory::AUD_IIRFilterFactory(AUD_Reference<AUD_IFactory> factory, std::vector<float> b, std::vector<float> a) : AUD_EffectFactory(factory), m_a(a), m_b(b) { } -AUD_IReader* AUD_IIRFilterFactory::createReader() const +AUD_Reference<AUD_IReader> AUD_IIRFilterFactory::createReader() const { return new AUD_IIRFilterReader(getReader(), m_b, m_a); } diff --git a/intern/audaspace/FX/AUD_IIRFilterFactory.h b/intern/audaspace/FX/AUD_IIRFilterFactory.h index d48ad453ee4..ffcc70a8ecb 100644 --- a/intern/audaspace/FX/AUD_IIRFilterFactory.h +++ b/intern/audaspace/FX/AUD_IIRFilterFactory.h @@ -63,10 +63,10 @@ public: * \param b The input filter coefficients. * \param a The output filter coefficients. */ - AUD_IIRFilterFactory(AUD_IFactory* factory, std::vector<float> b, + AUD_IIRFilterFactory(AUD_Reference<AUD_IFactory> factory, std::vector<float> b, std::vector<float> a); - virtual AUD_IReader* createReader() const; + virtual AUD_Reference<AUD_IReader> createReader() const; }; #endif //AUD_IIRFILTERFACTORY diff --git a/intern/audaspace/FX/AUD_IIRFilterReader.cpp b/intern/audaspace/FX/AUD_IIRFilterReader.cpp index 0d55421d2b4..80252e68ce8 100644 --- a/intern/audaspace/FX/AUD_IIRFilterReader.cpp +++ b/intern/audaspace/FX/AUD_IIRFilterReader.cpp @@ -31,7 +31,7 @@ #include "AUD_IIRFilterReader.h" -AUD_IIRFilterReader::AUD_IIRFilterReader(AUD_IReader* reader, +AUD_IIRFilterReader::AUD_IIRFilterReader(AUD_Reference<AUD_IReader> reader, std::vector<float> b, std::vector<float> a) : AUD_BaseIIRFilterReader(reader, b.size(), a.size()), m_a(a), m_b(b) diff --git a/intern/audaspace/FX/AUD_IIRFilterReader.h b/intern/audaspace/FX/AUD_IIRFilterReader.h index af50b6f1cdc..db813d6bab6 100644 --- a/intern/audaspace/FX/AUD_IIRFilterReader.h +++ b/intern/audaspace/FX/AUD_IIRFilterReader.h @@ -63,7 +63,7 @@ public: * \param b The input filter coefficients. * \param a The output filter coefficients. */ - AUD_IIRFilterReader(AUD_IReader* reader, std::vector<float> b, + AUD_IIRFilterReader(AUD_Reference<AUD_IReader> reader, std::vector<float> b, std::vector<float> a); virtual sample_t filter(); diff --git a/intern/audaspace/FX/AUD_LimiterFactory.cpp b/intern/audaspace/FX/AUD_LimiterFactory.cpp index 62ea01bb761..e52cdd75d4d 100644 --- a/intern/audaspace/FX/AUD_LimiterFactory.cpp +++ b/intern/audaspace/FX/AUD_LimiterFactory.cpp @@ -33,7 +33,7 @@ #include "AUD_LimiterReader.h" #include "AUD_Space.h" -AUD_LimiterFactory::AUD_LimiterFactory(AUD_IFactory* factory, +AUD_LimiterFactory::AUD_LimiterFactory(AUD_Reference<AUD_IFactory> factory, float start, float end) : AUD_EffectFactory(factory), m_start(start), @@ -51,7 +51,7 @@ float AUD_LimiterFactory::getEnd() const return m_end; } -AUD_IReader* AUD_LimiterFactory::createReader() const +AUD_Reference<AUD_IReader> AUD_LimiterFactory::createReader() const { return new AUD_LimiterReader(getReader(), m_start, m_end); } diff --git a/intern/audaspace/FX/AUD_LimiterFactory.h b/intern/audaspace/FX/AUD_LimiterFactory.h index f93f4b3276c..c45b9da65fe 100644 --- a/intern/audaspace/FX/AUD_LimiterFactory.h +++ b/intern/audaspace/FX/AUD_LimiterFactory.h @@ -62,7 +62,7 @@ public: * \param end The desired end time, a negative value signals that it should * play to the end. */ - AUD_LimiterFactory(AUD_IFactory* factory, + AUD_LimiterFactory(AUD_Reference<AUD_IFactory> factory, float start = 0, float end = -1); /** @@ -75,7 +75,7 @@ public: */ float getEnd() const; - virtual AUD_IReader* createReader() const; + virtual AUD_Reference<AUD_IReader> createReader() const; }; #endif //AUD_LIMITERFACTORY diff --git a/intern/audaspace/FX/AUD_LimiterReader.cpp b/intern/audaspace/FX/AUD_LimiterReader.cpp index d67fbb4d0e5..d5a46568b3e 100644 --- a/intern/audaspace/FX/AUD_LimiterReader.cpp +++ b/intern/audaspace/FX/AUD_LimiterReader.cpp @@ -34,7 +34,7 @@ #include <iostream> -AUD_LimiterReader::AUD_LimiterReader(AUD_IReader* reader, +AUD_LimiterReader::AUD_LimiterReader(AUD_Reference<AUD_IReader> reader, float start, float end) : AUD_EffectReader(reader), m_start(int(start * reader->getSpecs().rate)), diff --git a/intern/audaspace/FX/AUD_LimiterReader.h b/intern/audaspace/FX/AUD_LimiterReader.h index 4375ed9e10d..f4502c33ae0 100644 --- a/intern/audaspace/FX/AUD_LimiterReader.h +++ b/intern/audaspace/FX/AUD_LimiterReader.h @@ -62,7 +62,7 @@ public: * \param end The desired end sample (exklusive), a negative value signals * that it should play to the end. */ - AUD_LimiterReader(AUD_IReader* reader, float start = 0, float end = -1); + AUD_LimiterReader(AUD_Reference<AUD_IReader> reader, float start = 0, float end = -1); virtual void seek(int position); virtual int getLength() const; diff --git a/intern/audaspace/FX/AUD_LoopFactory.cpp b/intern/audaspace/FX/AUD_LoopFactory.cpp index 49d3481757f..021e69901b2 100644 --- a/intern/audaspace/FX/AUD_LoopFactory.cpp +++ b/intern/audaspace/FX/AUD_LoopFactory.cpp @@ -32,7 +32,7 @@ #include "AUD_LoopFactory.h" #include "AUD_LoopReader.h" -AUD_LoopFactory::AUD_LoopFactory(AUD_IFactory* factory, int loop) : +AUD_LoopFactory::AUD_LoopFactory(AUD_Reference<AUD_IFactory> factory, int loop) : AUD_EffectFactory(factory), m_loop(loop) { @@ -43,7 +43,7 @@ int AUD_LoopFactory::getLoop() const return m_loop; } -AUD_IReader* AUD_LoopFactory::createReader() const +AUD_Reference<AUD_IReader> AUD_LoopFactory::createReader() const { return new AUD_LoopReader(getReader(), m_loop); } diff --git a/intern/audaspace/FX/AUD_LoopFactory.h b/intern/audaspace/FX/AUD_LoopFactory.h index dfbbbe4fd20..4d601d5a605 100644 --- a/intern/audaspace/FX/AUD_LoopFactory.h +++ b/intern/audaspace/FX/AUD_LoopFactory.h @@ -57,14 +57,14 @@ public: * \param loop The desired loop count, negative values result in endless * looping. */ - AUD_LoopFactory(AUD_IFactory* factory, int loop = -1); + AUD_LoopFactory(AUD_Reference<AUD_IFactory> factory, int loop = -1); /** * Returns the loop count. */ int getLoop() const; - virtual AUD_IReader* createReader() const; + virtual AUD_Reference<AUD_IReader> createReader() const; }; #endif //AUD_LOOPFACTORY diff --git a/intern/audaspace/FX/AUD_LoopReader.cpp b/intern/audaspace/FX/AUD_LoopReader.cpp index b2e8e97a602..b7b8937abb8 100644 --- a/intern/audaspace/FX/AUD_LoopReader.cpp +++ b/intern/audaspace/FX/AUD_LoopReader.cpp @@ -34,7 +34,7 @@ #include <cstring> -AUD_LoopReader::AUD_LoopReader(AUD_IReader* reader, int loop) : +AUD_LoopReader::AUD_LoopReader(AUD_Reference<AUD_IReader> reader, int loop) : AUD_EffectReader(reader), m_count(loop), m_left(loop) { } diff --git a/intern/audaspace/FX/AUD_LoopReader.h b/intern/audaspace/FX/AUD_LoopReader.h index 45017901c56..866d6f7885f 100644 --- a/intern/audaspace/FX/AUD_LoopReader.h +++ b/intern/audaspace/FX/AUD_LoopReader.h @@ -68,7 +68,7 @@ public: * \param loop The desired loop count, negative values result in endless * looping. */ - AUD_LoopReader(AUD_IReader* reader, int loop); + AUD_LoopReader(AUD_Reference<AUD_IReader> reader, int loop); virtual void seek(int position); virtual int getLength() const; diff --git a/intern/audaspace/FX/AUD_LowpassFactory.cpp b/intern/audaspace/FX/AUD_LowpassFactory.cpp index d24a04b5a94..d0f33c120d9 100644 --- a/intern/audaspace/FX/AUD_LowpassFactory.cpp +++ b/intern/audaspace/FX/AUD_LowpassFactory.cpp @@ -38,7 +38,7 @@ #define M_PI 3.14159265358979323846 #endif -AUD_LowpassFactory::AUD_LowpassFactory(AUD_IFactory* factory, float frequency, +AUD_LowpassFactory::AUD_LowpassFactory(AUD_Reference<AUD_IFactory> factory, float frequency, float Q) : AUD_EffectFactory(factory), m_frequency(frequency), @@ -46,9 +46,9 @@ AUD_LowpassFactory::AUD_LowpassFactory(AUD_IFactory* factory, float frequency, { } -AUD_IReader* AUD_LowpassFactory::createReader() const +AUD_Reference<AUD_IReader> AUD_LowpassFactory::createReader() const { - AUD_IReader* reader = getReader(); + AUD_Reference<AUD_IReader> reader = getReader(); // calculate coefficients float w0 = 2 * M_PI * m_frequency / reader->getSpecs().rate; diff --git a/intern/audaspace/FX/AUD_LowpassFactory.h b/intern/audaspace/FX/AUD_LowpassFactory.h index d60c0bd22d1..efe4dafc4e1 100644 --- a/intern/audaspace/FX/AUD_LowpassFactory.h +++ b/intern/audaspace/FX/AUD_LowpassFactory.h @@ -61,9 +61,9 @@ public: * \param frequency The cutoff frequency. * \param Q The Q factor. */ - AUD_LowpassFactory(AUD_IFactory* factory, float frequency, float Q = 1.0f); + AUD_LowpassFactory(AUD_Reference<AUD_IFactory> factory, float frequency, float Q = 1.0f); - virtual AUD_IReader* createReader() const; + virtual AUD_Reference<AUD_IReader> createReader() const; }; #endif //AUD_LOWPASSFACTORY diff --git a/intern/audaspace/FX/AUD_PingPongFactory.cpp b/intern/audaspace/FX/AUD_PingPongFactory.cpp index fa140555943..4f0d2a207ac 100644 --- a/intern/audaspace/FX/AUD_PingPongFactory.cpp +++ b/intern/audaspace/FX/AUD_PingPongFactory.cpp @@ -33,26 +33,16 @@ #include "AUD_DoubleReader.h" #include "AUD_ReverseFactory.h" -AUD_PingPongFactory::AUD_PingPongFactory(AUD_IFactory* factory) : +AUD_PingPongFactory::AUD_PingPongFactory(AUD_Reference<AUD_IFactory> factory) : AUD_EffectFactory(factory) { } -AUD_IReader* AUD_PingPongFactory::createReader() const +AUD_Reference<AUD_IReader> AUD_PingPongFactory::createReader() const { - AUD_IReader* reader = getReader(); - AUD_IReader* reader2; + AUD_Reference<AUD_IReader> reader = getReader(); AUD_ReverseFactory factory(m_factory); - - try - { - reader2 = factory.createReader(); - } - catch(AUD_Exception&) - { - delete reader; - throw; - } + AUD_Reference<AUD_IReader> reader2 = factory.createReader(); return new AUD_DoubleReader(reader, reader2); } diff --git a/intern/audaspace/FX/AUD_PingPongFactory.h b/intern/audaspace/FX/AUD_PingPongFactory.h index 4ae0c494eb7..1c88a5a7114 100644 --- a/intern/audaspace/FX/AUD_PingPongFactory.h +++ b/intern/audaspace/FX/AUD_PingPongFactory.h @@ -50,9 +50,9 @@ public: * Creates a new ping pong factory. * \param factory The input factory. */ - AUD_PingPongFactory(AUD_IFactory* factory); + AUD_PingPongFactory(AUD_Reference<AUD_IFactory> factory); - virtual AUD_IReader* createReader() const; + virtual AUD_Reference<AUD_IReader> createReader() const; }; #endif //AUD_PINGPONGFACTORY diff --git a/intern/audaspace/FX/AUD_PitchFactory.cpp b/intern/audaspace/FX/AUD_PitchFactory.cpp index b4ae8582caf..94a3fb8034e 100644 --- a/intern/audaspace/FX/AUD_PitchFactory.cpp +++ b/intern/audaspace/FX/AUD_PitchFactory.cpp @@ -33,13 +33,13 @@ #include "AUD_PitchReader.h" #include "AUD_Space.h" -AUD_PitchFactory::AUD_PitchFactory(AUD_IFactory* factory, float pitch) : +AUD_PitchFactory::AUD_PitchFactory(AUD_Reference<AUD_IFactory> factory, float pitch) : AUD_EffectFactory(factory), m_pitch(pitch) { } -AUD_IReader* AUD_PitchFactory::createReader() const +AUD_Reference<AUD_IReader> AUD_PitchFactory::createReader() const { return new AUD_PitchReader(getReader(), m_pitch); } diff --git a/intern/audaspace/FX/AUD_PitchFactory.h b/intern/audaspace/FX/AUD_PitchFactory.h index 8fa5be9293f..bbf08ef5993 100644 --- a/intern/audaspace/FX/AUD_PitchFactory.h +++ b/intern/audaspace/FX/AUD_PitchFactory.h @@ -55,9 +55,9 @@ public: * \param factory The input factory. * \param pitch The desired pitch. */ - AUD_PitchFactory(AUD_IFactory* factory, float pitch); + AUD_PitchFactory(AUD_Reference<AUD_IFactory> factory, float pitch); - virtual AUD_IReader* createReader() const; + virtual AUD_Reference<AUD_IReader> createReader() const; }; #endif //AUD_PITCHFACTORY diff --git a/intern/audaspace/FX/AUD_PitchReader.cpp b/intern/audaspace/FX/AUD_PitchReader.cpp index e2e89e2c457..7f8b8b53105 100644 --- a/intern/audaspace/FX/AUD_PitchReader.cpp +++ b/intern/audaspace/FX/AUD_PitchReader.cpp @@ -31,7 +31,7 @@ #include "AUD_PitchReader.h" -AUD_PitchReader::AUD_PitchReader(AUD_IReader* reader, float pitch) : +AUD_PitchReader::AUD_PitchReader(AUD_Reference<AUD_IReader> reader, float pitch) : AUD_EffectReader(reader), m_pitch(pitch) { } diff --git a/intern/audaspace/FX/AUD_PitchReader.h b/intern/audaspace/FX/AUD_PitchReader.h index 120cebc58be..7939027dca9 100644 --- a/intern/audaspace/FX/AUD_PitchReader.h +++ b/intern/audaspace/FX/AUD_PitchReader.h @@ -55,7 +55,7 @@ public: * \param reader The reader to read from. * \param pitch The size of the buffer. */ - AUD_PitchReader(AUD_IReader* reader, float pitch); + AUD_PitchReader(AUD_Reference<AUD_IReader> reader, float pitch); virtual AUD_Specs getSpecs() const; }; diff --git a/intern/audaspace/FX/AUD_RectifyFactory.cpp b/intern/audaspace/FX/AUD_RectifyFactory.cpp index 609d827cce4..3bacd033eb3 100644 --- a/intern/audaspace/FX/AUD_RectifyFactory.cpp +++ b/intern/audaspace/FX/AUD_RectifyFactory.cpp @@ -39,12 +39,12 @@ sample_t rectifyFilter(AUD_CallbackIIRFilterReader* reader, void* useless) return fabs(reader->x(0)); } -AUD_RectifyFactory::AUD_RectifyFactory(AUD_IFactory* factory) : +AUD_RectifyFactory::AUD_RectifyFactory(AUD_Reference<AUD_IFactory> factory) : AUD_EffectFactory(factory) { } -AUD_IReader* AUD_RectifyFactory::createReader() const +AUD_Reference<AUD_IReader> AUD_RectifyFactory::createReader() const { return new AUD_CallbackIIRFilterReader(getReader(), 1, 1, rectifyFilter); } diff --git a/intern/audaspace/FX/AUD_RectifyFactory.h b/intern/audaspace/FX/AUD_RectifyFactory.h index c3529c7beef..d8411186001 100644 --- a/intern/audaspace/FX/AUD_RectifyFactory.h +++ b/intern/audaspace/FX/AUD_RectifyFactory.h @@ -49,9 +49,9 @@ public: * Creates a new rectify factory. * \param factory The input factory. */ - AUD_RectifyFactory(AUD_IFactory* factory); + AUD_RectifyFactory(AUD_Reference<AUD_IFactory> factory); - virtual AUD_IReader* createReader() const; + virtual AUD_Reference<AUD_IReader> createReader() const; }; #endif //AUD_RECTIFYFACTORY diff --git a/intern/audaspace/FX/AUD_ReverseFactory.cpp b/intern/audaspace/FX/AUD_ReverseFactory.cpp index 22b12e31420..88d812d7f2a 100644 --- a/intern/audaspace/FX/AUD_ReverseFactory.cpp +++ b/intern/audaspace/FX/AUD_ReverseFactory.cpp @@ -33,12 +33,12 @@ #include "AUD_ReverseReader.h" #include "AUD_Space.h" -AUD_ReverseFactory::AUD_ReverseFactory(AUD_IFactory* factory) : +AUD_ReverseFactory::AUD_ReverseFactory(AUD_Reference<AUD_IFactory> factory) : AUD_EffectFactory(factory) { } -AUD_IReader* AUD_ReverseFactory::createReader() const +AUD_Reference<AUD_IReader> AUD_ReverseFactory::createReader() const { return new AUD_ReverseReader(getReader()); } diff --git a/intern/audaspace/FX/AUD_ReverseFactory.h b/intern/audaspace/FX/AUD_ReverseFactory.h index 7b20546302e..ae1fdd5a233 100644 --- a/intern/audaspace/FX/AUD_ReverseFactory.h +++ b/intern/audaspace/FX/AUD_ReverseFactory.h @@ -50,9 +50,9 @@ public: * Creates a new reverse factory. * \param factory The input factory. */ - AUD_ReverseFactory(AUD_IFactory* factory); + AUD_ReverseFactory(AUD_Reference<AUD_IFactory> factory); - virtual AUD_IReader* createReader() const; + virtual AUD_Reference<AUD_IReader> createReader() const; }; #endif //AUD_REVERSEFACTORY diff --git a/intern/audaspace/FX/AUD_ReverseReader.cpp b/intern/audaspace/FX/AUD_ReverseReader.cpp index a4a03936c76..8ca9f8609bb 100644 --- a/intern/audaspace/FX/AUD_ReverseReader.cpp +++ b/intern/audaspace/FX/AUD_ReverseReader.cpp @@ -36,7 +36,7 @@ static const char* props_error = "AUD_ReverseReader: The reader has to be " "seekable and a finite length."; -AUD_ReverseReader::AUD_ReverseReader(AUD_IReader* reader) : +AUD_ReverseReader::AUD_ReverseReader(AUD_Reference<AUD_IReader> reader) : AUD_EffectReader(reader), m_length(reader->getLength()), m_position(0) diff --git a/intern/audaspace/FX/AUD_ReverseReader.h b/intern/audaspace/FX/AUD_ReverseReader.h index e12f2b21191..d8086e08534 100644 --- a/intern/audaspace/FX/AUD_ReverseReader.h +++ b/intern/audaspace/FX/AUD_ReverseReader.h @@ -68,7 +68,7 @@ public: * \exception AUD_Exception Thrown if the reader specified has an * undeterminable/infinite length or is not seekable. */ - AUD_ReverseReader(AUD_IReader* reader); + AUD_ReverseReader(AUD_Reference<AUD_IReader> reader); virtual void seek(int position); virtual int getLength() const; diff --git a/intern/audaspace/FX/AUD_SquareFactory.cpp b/intern/audaspace/FX/AUD_SquareFactory.cpp index a075773d2cb..a3ea088a258 100644 --- a/intern/audaspace/FX/AUD_SquareFactory.cpp +++ b/intern/audaspace/FX/AUD_SquareFactory.cpp @@ -48,7 +48,7 @@ void endSquareFilter(float* threshold) delete threshold; } -AUD_SquareFactory::AUD_SquareFactory(AUD_IFactory* factory, float threshold) : +AUD_SquareFactory::AUD_SquareFactory(AUD_Reference<AUD_IFactory> factory, float threshold) : AUD_EffectFactory(factory), m_threshold(threshold) { @@ -59,7 +59,7 @@ float AUD_SquareFactory::getThreshold() const return m_threshold; } -AUD_IReader* AUD_SquareFactory::createReader() const +AUD_Reference<AUD_IReader> AUD_SquareFactory::createReader() const { return new AUD_CallbackIIRFilterReader(getReader(), 1, 1, (doFilterIIR) squareFilter, diff --git a/intern/audaspace/FX/AUD_SquareFactory.h b/intern/audaspace/FX/AUD_SquareFactory.h index 8060e98e281..60db49c48e5 100644 --- a/intern/audaspace/FX/AUD_SquareFactory.h +++ b/intern/audaspace/FX/AUD_SquareFactory.h @@ -55,14 +55,14 @@ public: * \param factory The input factory. * \param threshold The threshold. */ - AUD_SquareFactory(AUD_IFactory* factory, float threshold = 0.0f); + AUD_SquareFactory(AUD_Reference<AUD_IFactory> factory, float threshold = 0.0f); /** * Returns the threshold. */ float getThreshold() const; - virtual AUD_IReader* createReader() const; + virtual AUD_Reference<AUD_IReader> createReader() const; }; #endif //AUD_SQUAREFACTORY diff --git a/intern/audaspace/FX/AUD_SumFactory.cpp b/intern/audaspace/FX/AUD_SumFactory.cpp index 6d8368d6e35..582e2d75b7f 100644 --- a/intern/audaspace/FX/AUD_SumFactory.cpp +++ b/intern/audaspace/FX/AUD_SumFactory.cpp @@ -32,12 +32,12 @@ #include "AUD_SumFactory.h" #include "AUD_IIRFilterReader.h" -AUD_SumFactory::AUD_SumFactory(AUD_IFactory* factory) : +AUD_SumFactory::AUD_SumFactory(AUD_Reference<AUD_IFactory> factory) : AUD_EffectFactory(factory) { } -AUD_IReader* AUD_SumFactory::createReader() const +AUD_Reference<AUD_IReader> AUD_SumFactory::createReader() const { std::vector<float> a, b; a.push_back(1); diff --git a/intern/audaspace/FX/AUD_SumFactory.h b/intern/audaspace/FX/AUD_SumFactory.h index ed19a0f258a..948355e50fd 100644 --- a/intern/audaspace/FX/AUD_SumFactory.h +++ b/intern/audaspace/FX/AUD_SumFactory.h @@ -49,9 +49,9 @@ public: * Creates a new sum factory. * \param factory The input factory. */ - AUD_SumFactory(AUD_IFactory* factory); + AUD_SumFactory(AUD_Reference<AUD_IFactory> factory); - virtual AUD_IReader* createReader() const; + virtual AUD_Reference<AUD_IReader> createReader() const; }; #endif //AUD_SUMFACTORY diff --git a/intern/audaspace/FX/AUD_SuperposeFactory.cpp b/intern/audaspace/FX/AUD_SuperposeFactory.cpp index c13a0d0dd95..b5e816f66a8 100644 --- a/intern/audaspace/FX/AUD_SuperposeFactory.cpp +++ b/intern/audaspace/FX/AUD_SuperposeFactory.cpp @@ -32,24 +32,15 @@ #include "AUD_SuperposeFactory.h" #include "AUD_SuperposeReader.h" -AUD_SuperposeFactory::AUD_SuperposeFactory(AUD_IFactory* factory1, AUD_IFactory* factory2) : +AUD_SuperposeFactory::AUD_SuperposeFactory(AUD_Reference<AUD_IFactory> factory1, AUD_Reference<AUD_IFactory> factory2) : m_factory1(factory1), m_factory2(factory2) { } -AUD_IReader* AUD_SuperposeFactory::createReader() const +AUD_Reference<AUD_IReader> AUD_SuperposeFactory::createReader() const { - AUD_IReader* reader1 = m_factory1->createReader(); - AUD_IReader* reader2; - try - { - reader2 = m_factory2->createReader(); - } - catch(AUD_Exception&) - { - delete reader1; - throw; - } + AUD_Reference<AUD_IReader> reader1 = m_factory1->createReader(); + AUD_Reference<AUD_IReader> reader2 = m_factory2->createReader(); return new AUD_SuperposeReader(reader1, reader2); } diff --git a/intern/audaspace/FX/AUD_SuperposeFactory.h b/intern/audaspace/FX/AUD_SuperposeFactory.h index 32232012e4e..d302658097e 100644 --- a/intern/audaspace/FX/AUD_SuperposeFactory.h +++ b/intern/audaspace/FX/AUD_SuperposeFactory.h @@ -44,12 +44,12 @@ private: /** * First played factory. */ - AUD_IFactory* m_factory1; + AUD_Reference<AUD_IFactory> m_factory1; /** * Second played factory. */ - AUD_IFactory* m_factory2; + AUD_Reference<AUD_IFactory> m_factory2; // hide copy constructor and operator= AUD_SuperposeFactory(const AUD_SuperposeFactory&); @@ -61,9 +61,9 @@ public: * \param factory1 The first input factory. * \param factory2 The second input factory. */ - AUD_SuperposeFactory(AUD_IFactory* factory1, AUD_IFactory* factory2); + AUD_SuperposeFactory(AUD_Reference<AUD_IFactory> factory1, AUD_Reference<AUD_IFactory> factory2); - virtual AUD_IReader* createReader() const; + virtual AUD_Reference<AUD_IReader> createReader() const; }; #endif //AUD_SUPERPOSEFACTORY diff --git a/intern/audaspace/FX/AUD_SuperposeReader.cpp b/intern/audaspace/FX/AUD_SuperposeReader.cpp index e64cf79188e..6f39dcadf40 100644 --- a/intern/audaspace/FX/AUD_SuperposeReader.cpp +++ b/intern/audaspace/FX/AUD_SuperposeReader.cpp @@ -36,30 +36,18 @@ static const char* specs_error = "AUD_SuperposeReader: Both readers have to " "have the same specs."; -AUD_SuperposeReader::AUD_SuperposeReader(AUD_IReader* reader1, AUD_IReader* reader2) : +AUD_SuperposeReader::AUD_SuperposeReader(AUD_Reference<AUD_IReader> reader1, AUD_Reference<AUD_IReader> reader2) : m_reader1(reader1), m_reader2(reader2) { - try - { - AUD_Specs s1, s2; - s1 = reader1->getSpecs(); - s2 = reader2->getSpecs(); - if(memcmp(&s1, &s2, sizeof(AUD_Specs))) - AUD_THROW(AUD_ERROR_SPECS, specs_error); - } - catch(AUD_Exception&) - { - delete reader1; - delete reader2; - - throw; - } + AUD_Specs s1, s2; + s1 = reader1->getSpecs(); + s2 = reader2->getSpecs(); + if(memcmp(&s1, &s2, sizeof(AUD_Specs))) + AUD_THROW(AUD_ERROR_SPECS, specs_error); } AUD_SuperposeReader::~AUD_SuperposeReader() { - delete m_reader1; - delete m_reader2; } bool AUD_SuperposeReader::isSeekable() const diff --git a/intern/audaspace/FX/AUD_SuperposeReader.h b/intern/audaspace/FX/AUD_SuperposeReader.h index b256aade7ba..26e4b138dfa 100644 --- a/intern/audaspace/FX/AUD_SuperposeReader.h +++ b/intern/audaspace/FX/AUD_SuperposeReader.h @@ -34,6 +34,7 @@ #include "AUD_IReader.h" #include "AUD_Buffer.h" +#include "AUD_Reference.h" /** * This reader plays two readers with the same specs sequently. @@ -44,12 +45,12 @@ private: /** * The first reader. */ - AUD_IReader* m_reader1; + AUD_Reference<AUD_IReader> m_reader1; /** * The second reader. */ - AUD_IReader* m_reader2; + AUD_Reference<AUD_IReader> m_reader2; /** * The playback buffer for the intersecting part. @@ -67,7 +68,7 @@ public: * \param reader2 The second reader to read from. * \exception AUD_Exception Thrown if the specs from the readers differ. */ - AUD_SuperposeReader(AUD_IReader* reader1, AUD_IReader* reader2); + AUD_SuperposeReader(AUD_Reference<AUD_IReader> reader1, AUD_Reference<AUD_IReader> reader2); /** * Destroys the reader. diff --git a/intern/audaspace/FX/AUD_VolumeFactory.cpp b/intern/audaspace/FX/AUD_VolumeFactory.cpp index 166fbf61512..1249c4ab9bd 100644 --- a/intern/audaspace/FX/AUD_VolumeFactory.cpp +++ b/intern/audaspace/FX/AUD_VolumeFactory.cpp @@ -32,7 +32,7 @@ #include "AUD_VolumeFactory.h" #include "AUD_IIRFilterReader.h" -AUD_VolumeFactory::AUD_VolumeFactory(AUD_IFactory* factory, float volume) : +AUD_VolumeFactory::AUD_VolumeFactory(AUD_Reference<AUD_IFactory> factory, float volume) : AUD_EffectFactory(factory), m_volume(volume) { @@ -43,7 +43,7 @@ float AUD_VolumeFactory::getVolume() const return m_volume; } -AUD_IReader* AUD_VolumeFactory::createReader() const +AUD_Reference<AUD_IReader> AUD_VolumeFactory::createReader() const { std::vector<float> a, b; a.push_back(1); diff --git a/intern/audaspace/FX/AUD_VolumeFactory.h b/intern/audaspace/FX/AUD_VolumeFactory.h index fa40ca11082..3cb8bc1da17 100644 --- a/intern/audaspace/FX/AUD_VolumeFactory.h +++ b/intern/audaspace/FX/AUD_VolumeFactory.h @@ -57,14 +57,14 @@ public: * \param factory The input factory. * \param volume The desired volume. */ - AUD_VolumeFactory(AUD_IFactory* factory, float volume); + AUD_VolumeFactory(AUD_Reference<AUD_IFactory> factory, float volume); /** * Returns the volume. */ float getVolume() const; - virtual AUD_IReader* createReader() const; + virtual AUD_Reference<AUD_IReader> createReader() const; }; #endif //AUD_VOLUMEFACTORY diff --git a/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp b/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp index b9e30bbf62a..a3b0bff316e 100644 --- a/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp +++ b/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp @@ -52,7 +52,7 @@ struct AUD_OpenALHandle : AUD_Handle bool isBuffered; /// The reader source. - AUD_IReader* reader; + AUD_Reference<AUD_IReader> reader; /// Whether to keep the source if end of it is reached. bool keep; @@ -382,7 +382,6 @@ AUD_OpenALDevice::~AUD_OpenALDevice() alDeleteSources(1, &sound->source); if(!sound->isBuffered) { - delete sound->reader; alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers); } delete sound; @@ -396,7 +395,6 @@ AUD_OpenALDevice::~AUD_OpenALDevice() alDeleteSources(1, &sound->source); if(!sound->isBuffered) { - delete sound->reader; alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers); } delete sound; @@ -539,7 +537,7 @@ static const char* queue_error = "AUD_OpenALDevice: Buffer couldn't be " static const char* bufferdata_error = "AUD_OpenALDevice: Buffer couldn't be " "filled with data."; -AUD_Handle* AUD_OpenALDevice::play(AUD_IReader* reader, bool keep) +AUD_Handle* AUD_OpenALDevice::play(AUD_Reference<AUD_IReader> reader, bool keep) { AUD_OpenALHandle* sound = NULL; @@ -568,7 +566,6 @@ AUD_Handle* AUD_OpenALDevice::play(AUD_IReader* reader, bool keep) if(!valid) { delete sound; - delete reader; return NULL; } @@ -624,7 +621,6 @@ AUD_Handle* AUD_OpenALDevice::play(AUD_IReader* reader, bool keep) catch(AUD_Exception&) { delete sound; - delete reader; alcProcessContext(m_context); unlock(); throw; @@ -642,8 +638,9 @@ AUD_Handle* AUD_OpenALDevice::play(AUD_IReader* reader, bool keep) return sound; } -AUD_Handle* AUD_OpenALDevice::play(AUD_IFactory* factory, bool keep) +AUD_Handle* AUD_OpenALDevice::play(AUD_Reference<AUD_IFactory> factory, bool keep) { + /* AUD_XXX disabled AUD_OpenALHandle* sound = NULL; lock(); @@ -713,7 +710,7 @@ AUD_Handle* AUD_OpenALDevice::play(AUD_IFactory* factory, bool keep) unlock(); if(sound) - return sound; + return sound;*/ return play(factory->createReader(), keep); } @@ -785,7 +782,6 @@ bool AUD_OpenALDevice::stop(AUD_Handle* handle) alDeleteSources(1, &sound->source); if(!sound->isBuffered) { - delete sound->reader; alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers); } delete *i; @@ -805,7 +801,6 @@ bool AUD_OpenALDevice::stop(AUD_Handle* handle) alDeleteSources(1, &sound->source); if(!sound->isBuffered) { - delete sound->reader; alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers); } delete *i; @@ -1109,7 +1104,6 @@ bool AUD_OpenALDevice::bufferFactory(void *value) if(!getFormat(format, specs.specs)) { - delete reader; return false; } @@ -1147,7 +1141,6 @@ bool AUD_OpenALDevice::bufferFactory(void *value) catch(AUD_Exception&) { delete bf; - delete reader; alcProcessContext(m_context); unlock(); return false; diff --git a/intern/audaspace/OpenAL/AUD_OpenALDevice.h b/intern/audaspace/OpenAL/AUD_OpenALDevice.h index 3bbbe85d7e6..3bca47f1805 100644 --- a/intern/audaspace/OpenAL/AUD_OpenALDevice.h +++ b/intern/audaspace/OpenAL/AUD_OpenALDevice.h @@ -147,8 +147,8 @@ public: virtual ~AUD_OpenALDevice(); virtual AUD_DeviceSpecs getSpecs() const; - virtual AUD_Handle* play(AUD_IReader* reader, bool keep = false); - virtual AUD_Handle* play(AUD_IFactory* factory, bool keep = false); + virtual AUD_Handle* play(AUD_Reference<AUD_IReader> reader, bool keep = false); + virtual AUD_Handle* play(AUD_Reference<AUD_IFactory> factory, bool keep = false); virtual bool pause(AUD_Handle* handle); virtual bool resume(AUD_Handle* handle); virtual bool stop(AUD_Handle* handle); diff --git a/intern/audaspace/Python/AUD_PyAPI.cpp b/intern/audaspace/Python/AUD_PyAPI.cpp index 22376a2fcd1..ac25ab34a69 100644 --- a/intern/audaspace/Python/AUD_PyAPI.cpp +++ b/intern/audaspace/Python/AUD_PyAPI.cpp @@ -91,7 +91,7 @@ static void Factory_dealloc(Factory* self) { if(self->factory) - delete self->factory; + delete reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory); Py_XDECREF(self->child_list); Py_TYPE(self)->tp_free((PyObject*)self); } @@ -115,7 +115,7 @@ Factory_new(PyTypeObject *type, PyObject *args, PyObject *kwds) try { - self->factory = new AUD_FileFactory(filename); + self->factory = new AUD_Reference<AUD_IFactory>(new AUD_FileFactory(filename)); } catch(AUD_Exception& e) { @@ -155,7 +155,7 @@ Factory_sine(PyTypeObject* type, PyObject* args) { try { - self->factory = new AUD_SinusFactory(frequency, (AUD_SampleRate)rate); + self->factory = new AUD_Reference<AUD_IFactory>(new AUD_SinusFactory(frequency, (AUD_SampleRate)rate)); } catch(AUD_Exception& e) { @@ -194,7 +194,7 @@ Factory_file(PyTypeObject* type, PyObject* args) { try { - self->factory = new AUD_FileFactory(filename); + self->factory = new AUD_Reference<AUD_IFactory>(new AUD_FileFactory(filename)); } catch(AUD_Exception& e) { @@ -237,7 +237,7 @@ Factory_lowpass(Factory* self, PyObject* args) try { - parent->factory = new AUD_LowpassFactory(self->factory, frequency, Q); + parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_LowpassFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), frequency, Q)); } catch(AUD_Exception& e) { @@ -278,7 +278,7 @@ Factory_delay(Factory* self, PyObject* args) try { - parent->factory = new AUD_DelayFactory(self->factory, delay); + parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_DelayFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), delay)); } catch(AUD_Exception& e) { @@ -322,7 +322,7 @@ Factory_join(Factory* self, PyObject* object) try { - parent->factory = new AUD_DoubleFactory(self->factory, child->factory); + parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_DoubleFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), *reinterpret_cast<AUD_Reference<AUD_IFactory>*>(child->factory))); } catch(AUD_Exception& e) { @@ -365,7 +365,7 @@ Factory_highpass(Factory* self, PyObject* args) try { - parent->factory = new AUD_HighpassFactory(self->factory, frequency, Q); + parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_HighpassFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), frequency, Q)); } catch(AUD_Exception& e) { @@ -406,7 +406,7 @@ Factory_limit(Factory* self, PyObject* args) try { - parent->factory = new AUD_LimiterFactory(self->factory, start, end); + parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_LimiterFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), start, end)); } catch(AUD_Exception& e) { @@ -450,7 +450,7 @@ Factory_pitch(Factory* self, PyObject* args) try { - parent->factory = new AUD_PitchFactory(self->factory, factor); + parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_PitchFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), factor)); } catch(AUD_Exception& e) { @@ -492,7 +492,7 @@ Factory_volume(Factory* self, PyObject* args) try { - parent->factory = new AUD_VolumeFactory(self->factory, volume); + parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_VolumeFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), volume)); } catch(AUD_Exception& e) { @@ -535,7 +535,7 @@ Factory_fadein(Factory* self, PyObject* args) try { - parent->factory = new AUD_FaderFactory(self->factory, AUD_FADE_IN, start, length); + parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_FaderFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), AUD_FADE_IN, start, length)); } catch(AUD_Exception& e) { @@ -579,7 +579,7 @@ Factory_fadeout(Factory* self, PyObject* args) try { - parent->factory = new AUD_FaderFactory(self->factory, AUD_FADE_OUT, start, length); + parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_FaderFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), AUD_FADE_OUT, start, length)); } catch(AUD_Exception& e) { @@ -621,7 +621,7 @@ Factory_loop(Factory* self, PyObject* args) try { - parent->factory = new AUD_LoopFactory(self->factory, loop); + parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_LoopFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), loop)); } catch(AUD_Exception& e) { @@ -664,7 +664,7 @@ Factory_mix(Factory* self, PyObject* object) try { - parent->factory = new AUD_SuperposeFactory(self->factory, child->factory); + parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_SuperposeFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), *reinterpret_cast<AUD_Reference<AUD_IFactory>*>(child->factory))); } catch(AUD_Exception& e) { @@ -697,7 +697,7 @@ Factory_pingpong(Factory* self) try { - parent->factory = new AUD_PingPongFactory(self->factory); + parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_PingPongFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory))); } catch(AUD_Exception& e) { @@ -736,7 +736,7 @@ Factory_reverse(Factory* self) try { - parent->factory = new AUD_ReverseFactory(self->factory); + parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_ReverseFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory))); } catch(AUD_Exception& e) { @@ -771,7 +771,7 @@ Factory_buffer(Factory* self) { try { - parent->factory = new AUD_StreamBufferFactory(self->factory); + parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_StreamBufferFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory))); } catch(AUD_Exception& e) { @@ -813,7 +813,7 @@ Factory_square(Factory* self, PyObject* args) try { - parent->factory = new AUD_SquareFactory(self->factory, threshold); + parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_SquareFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), threshold)); } catch(AUD_Exception& e) { @@ -910,7 +910,7 @@ Factory_filter(Factory* self, PyObject* args) try { - parent->factory = new AUD_IIRFilterFactory(self->factory, b, a); + parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_IIRFilterFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), b, a)); } catch(AUD_Exception& e) { @@ -1050,7 +1050,7 @@ Handle_pause(Handle *self) try { - return PyBool_FromLong((long)device->device->pause(self->handle)); + return PyBool_FromLong((long)(*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(device->device))->pause(self->handle)); } catch(AUD_Exception& e) { @@ -1072,7 +1072,7 @@ Handle_resume(Handle *self) try { - return PyBool_FromLong((long)device->device->resume(self->handle)); + return PyBool_FromLong((long)(*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(device->device))->resume(self->handle)); } catch(AUD_Exception& e) { @@ -1095,7 +1095,7 @@ Handle_stop(Handle *self) try { - return PyBool_FromLong((long)device->device->stop(self->handle)); + return PyBool_FromLong((long)(*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(device->device))->stop(self->handle)); } catch(AUD_Exception& e) { @@ -1127,7 +1127,7 @@ Handle_get_position(Handle *self, void* nothing) try { - return Py_BuildValue("f", device->device->getPosition(self->handle)); + return Py_BuildValue("f", (*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(device->device))->getPosition(self->handle)); } catch(AUD_Exception& e) { @@ -1148,7 +1148,7 @@ Handle_set_position(Handle *self, PyObject* args, void* nothing) try { - if(device->device->seek(self->handle, position)) + if((*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(device->device))->seek(self->handle, position)) return 0; PyErr_SetString(AUDError, "Couldn't seek the sound!"); } @@ -1176,7 +1176,7 @@ Handle_get_keep(Handle *self, void* nothing) try { - return PyBool_FromLong((long)device->device->getKeep(self->handle)); + return PyBool_FromLong((long)(*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(device->device))->getKeep(self->handle)); } catch(AUD_Exception& e) { @@ -1199,7 +1199,7 @@ Handle_set_keep(Handle *self, PyObject* args, void* nothing) try { - if(device->device->setKeep(self->handle, keep)) + if((*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(device->device))->setKeep(self->handle, keep)) return 0; PyErr_SetString(AUDError, "Couldn't set keep of the sound!"); } @@ -1221,7 +1221,7 @@ Handle_get_status(Handle *self, void* nothing) try { - return PyBool_FromLong((long)device->device->getStatus(self->handle)); + return PyBool_FromLong((long)(*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(device->device))->getStatus(self->handle)); } catch(AUD_Exception& e) { @@ -1240,7 +1240,7 @@ Handle_get_volume(Handle *self, void* nothing) try { - return Py_BuildValue("f", device->device->getVolume(self->handle)); + return Py_BuildValue("f", (*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(device->device))->getVolume(self->handle)); } catch(AUD_Exception& e) { @@ -1261,7 +1261,7 @@ Handle_set_volume(Handle *self, PyObject* args, void* nothing) try { - if(device->device->setVolume(self->handle, volume)) + if((*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(device->device))->setVolume(self->handle, volume)) return 0; PyErr_SetString(AUDError, "Couldn't set the sound volume!"); } @@ -1283,7 +1283,7 @@ Handle_get_pitch(Handle *self, void* nothing) try { - return Py_BuildValue("f", device->device->getPitch(self->handle)); + return Py_BuildValue("f", (*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(device->device))->getPitch(self->handle)); } catch(AUD_Exception& e) { @@ -1304,7 +1304,7 @@ Handle_set_pitch(Handle *self, PyObject* args, void* nothing) try { - if(device->device->setPitch(self->handle, pitch)) + if((*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(device->device))->setPitch(self->handle, pitch)) return 0; PyErr_SetString(AUDError, "Couldn't set the sound pitch!"); } @@ -1326,7 +1326,7 @@ Handle_get_loop_count(Handle *self, void* nothing) try { - return Py_BuildValue("i", device->device->getLoopCount(self->handle)); + return Py_BuildValue("i", (*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(device->device))->getLoopCount(self->handle)); } catch(AUD_Exception& e) { @@ -1347,7 +1347,7 @@ Handle_set_loop_count(Handle *self, PyObject* args, void* nothing) try { - if(device->device->setLoopCount(self->handle, loops)) + if((*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(device->device))->setLoopCount(self->handle, loops)) return 0; PyErr_SetString(AUDError, "Couldn't set the loop count!"); } @@ -1369,7 +1369,7 @@ Handle_get_location(Handle *self, void* nothing) try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(dev->device)->get()); if(device) { AUD_Vector3 v = device->getSourceLocation(self->handle); @@ -1400,7 +1400,7 @@ Handle_set_location(Handle *self, PyObject* args, void* nothing) try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(dev->device)->get()); if(device) { AUD_Vector3 location(x, y, z); @@ -1429,7 +1429,7 @@ Handle_get_velocity(Handle *self, void* nothing) try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(dev->device)->get()); if(device) { AUD_Vector3 v = device->getSourceVelocity(self->handle); @@ -1460,7 +1460,7 @@ Handle_set_velocity(Handle *self, PyObject* args, void* nothing) try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(dev->device)->get()); if(device) { AUD_Vector3 velocity(x, y, z); @@ -1489,7 +1489,7 @@ Handle_get_orientation(Handle *self, void* nothing) try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(dev->device)->get()); if(device) { AUD_Quaternion o = device->getSourceOrientation(self->handle); @@ -1520,7 +1520,7 @@ Handle_set_orientation(Handle *self, PyObject* args, void* nothing) try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(dev->device)->get()); if(device) { AUD_Quaternion orientation(w, x, y, z); @@ -1549,7 +1549,7 @@ Handle_get_relative(Handle *self, void* nothing) try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(dev->device)->get()); if(device) { return PyBool_FromLong((long)device->isRelative(self->handle)); @@ -1581,7 +1581,7 @@ Handle_set_relative(Handle *self, PyObject* args, void* nothing) try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(dev->device)->get()); if(device) { if(device->setRelative(self->handle, relative)) @@ -1610,7 +1610,7 @@ Handle_get_volume_minimum(Handle *self, void* nothing) try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(dev->device)->get()); if(device) { return Py_BuildValue("f", device->getVolumeMinimum(self->handle)); @@ -1640,7 +1640,7 @@ Handle_set_volume_minimum(Handle *self, PyObject* args, void* nothing) try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(dev->device)->get()); if(device) { if(device->setVolumeMinimum(self->handle, volume)) @@ -1669,7 +1669,7 @@ Handle_get_volume_maximum(Handle *self, void* nothing) try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(dev->device)->get()); if(device) { return Py_BuildValue("f", device->getVolumeMaximum(self->handle)); @@ -1699,7 +1699,7 @@ Handle_set_volume_maximum(Handle *self, PyObject* args, void* nothing) try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(dev->device)->get()); if(device) { if(device->setVolumeMaximum(self->handle, volume)) @@ -1729,7 +1729,7 @@ Handle_get_distance_reference(Handle *self, void* nothing) try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(dev->device)->get()); if(device) { return Py_BuildValue("f", device->getDistanceReference(self->handle)); @@ -1759,7 +1759,7 @@ Handle_set_distance_reference(Handle *self, PyObject* args, void* nothing) try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(dev->device)->get()); if(device) { if(device->setDistanceReference(self->handle, distance)) @@ -1789,7 +1789,7 @@ Handle_get_distance_maximum(Handle *self, void* nothing) try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(dev->device)->get()); if(device) { return Py_BuildValue("f", device->getDistanceMaximum(self->handle)); @@ -1819,7 +1819,7 @@ Handle_set_distance_maximum(Handle *self, PyObject* args, void* nothing) try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(dev->device)->get()); if(device) { if(device->setDistanceMaximum(self->handle, distance)) @@ -1849,7 +1849,7 @@ Handle_get_attenuation(Handle *self, void* nothing) try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(dev->device)->get()); if(device) { return Py_BuildValue("f", device->getAttenuation(self->handle)); @@ -1879,7 +1879,7 @@ Handle_set_attenuation(Handle *self, PyObject* args, void* nothing) try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(dev->device)->get()); if(device) { if(device->setAttenuation(self->handle, factor)) @@ -1914,7 +1914,7 @@ Handle_get_cone_angle_inner(Handle *self, void* nothing) try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(dev->device)->get()); if(device) { return Py_BuildValue("f", device->getConeAngleInner(self->handle)); @@ -1944,7 +1944,7 @@ Handle_set_cone_angle_inner(Handle *self, PyObject* args, void* nothing) try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(dev->device)->get()); if(device) { if(device->setConeAngleInner(self->handle, angle)) @@ -1973,7 +1973,7 @@ Handle_get_cone_angle_outer(Handle *self, void* nothing) try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(dev->device)->get()); if(device) { return Py_BuildValue("f", device->getConeAngleOuter(self->handle)); @@ -2003,7 +2003,7 @@ Handle_set_cone_angle_outer(Handle *self, PyObject* args, void* nothing) try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(dev->device)->get()); if(device) { if(device->setConeAngleOuter(self->handle, angle)) @@ -2032,7 +2032,7 @@ Handle_get_cone_volume_outer(Handle *self, void* nothing) try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(dev->device)->get()); if(device) { return Py_BuildValue("f", device->getConeVolumeOuter(self->handle)); @@ -2062,7 +2062,7 @@ Handle_set_cone_volume_outer(Handle *self, PyObject* args, void* nothing) try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(dev->device)->get()); if(device) { if(device->setConeVolumeOuter(self->handle, volume)) @@ -2172,7 +2172,7 @@ static void Device_dealloc(Device* self) { if(self->device) - delete self->device; + delete reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device); Py_TYPE(self)->tp_free((PyObject*)self); } @@ -2215,21 +2215,21 @@ Device_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { case AUD_DEVICE_NULL: (void)specs; /* quiet warning when others disabled */ - self->device = new AUD_NULLDevice(); + self->device = new AUD_Reference<AUD_IDevice>(new AUD_NULLDevice()); break; case AUD_DEVICE_OPENAL: #ifdef WITH_OPENAL - self->device = new AUD_OpenALDevice(specs, buffersize); + self->device = new AUD_Reference<AUD_IDevice>(new AUD_OpenALDevice(specs, buffersize)); #endif break; case AUD_DEVICE_SDL: #ifdef WITH_SDL - self->device = new AUD_SDLDevice(specs, buffersize); + self->device = new AUD_Reference<AUD_IDevice>(new AUD_SDLDevice(specs, buffersize)); #endif break; case AUD_DEVICE_JACK: #ifdef WITH_JACK - self->device = new AUD_JackDevice(name, specs, buffersize); + self->device = new AUD_Reference<AUD_IDevice>(new AUD_JackDevice(name, specs, buffersize)); #endif break; case AUD_DEVICE_READ: @@ -2307,7 +2307,7 @@ Device_play(Device *self, PyObject *args, PyObject *kwds) try { - handle->handle = self->device->play(sound->factory, keep); + handle->handle = (*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device))->play(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(sound->factory), keep); } catch(AUD_Exception& e) { @@ -2336,7 +2336,7 @@ Device_lock(Device *self) { try { - self->device->lock(); + (*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device))->lock(); Py_RETURN_NONE; } catch(AUD_Exception& e) @@ -2356,7 +2356,7 @@ Device_unlock(Device *self) { try { - self->device->unlock(); + (*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device))->unlock(); Py_RETURN_NONE; } catch(AUD_Exception& e) @@ -2387,7 +2387,7 @@ Device_get_rate(Device *self, void* nothing) { try { - AUD_DeviceSpecs specs = self->device->getSpecs(); + AUD_DeviceSpecs specs = (*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device))->getSpecs(); return Py_BuildValue("i", specs.rate); } catch(AUD_Exception& e) @@ -2405,7 +2405,7 @@ Device_get_format(Device *self, void* nothing) { try { - AUD_DeviceSpecs specs = self->device->getSpecs(); + AUD_DeviceSpecs specs = (*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device))->getSpecs(); return Py_BuildValue("i", specs.format); } catch(AUD_Exception& e) @@ -2423,7 +2423,7 @@ Device_get_channels(Device *self, void* nothing) { try { - AUD_DeviceSpecs specs = self->device->getSpecs(); + AUD_DeviceSpecs specs = (*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device))->getSpecs(); return Py_BuildValue("i", specs.channels); } catch(AUD_Exception& e) @@ -2441,7 +2441,7 @@ Device_get_volume(Device *self, void* nothing) { try { - return Py_BuildValue("f", self->device->getVolume()); + return Py_BuildValue("f", (*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device))->getVolume()); } catch(AUD_Exception& e) { @@ -2460,7 +2460,7 @@ Device_set_volume(Device *self, PyObject* args, void* nothing) try { - self->device->setVolume(volume); + (*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device))->setVolume(volume); return 0; } catch(AUD_Exception& e) @@ -2478,7 +2478,7 @@ Device_get_listener_location(Device *self, void* nothing) { try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device)->get()); if(device) { AUD_Vector3 v = device->getListenerLocation(); @@ -2507,7 +2507,7 @@ Device_set_listener_location(Device *self, PyObject* args, void* nothing) try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device)->get()); if(device) { AUD_Vector3 location(x, y, z); @@ -2533,7 +2533,7 @@ Device_get_listener_velocity(Device *self, void* nothing) { try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device)->get()); if(device) { AUD_Vector3 v = device->getListenerVelocity(); @@ -2562,7 +2562,7 @@ Device_set_listener_velocity(Device *self, PyObject* args, void* nothing) try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device)->get()); if(device) { AUD_Vector3 velocity(x, y, z); @@ -2588,7 +2588,7 @@ Device_get_listener_orientation(Device *self, void* nothing) { try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device)->get()); if(device) { AUD_Quaternion o = device->getListenerOrientation(); @@ -2617,7 +2617,7 @@ Device_set_listener_orientation(Device *self, PyObject* args, void* nothing) try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device)->get()); if(device) { AUD_Quaternion orientation(w, x, y, z); @@ -2644,7 +2644,7 @@ Device_get_speed_of_sound(Device *self, void* nothing) { try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device)->get()); if(device) { return Py_BuildValue("f", device->getSpeedOfSound()); @@ -2672,7 +2672,7 @@ Device_set_speed_of_sound(Device *self, PyObject* args, void* nothing) try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device)->get()); if(device) { device->setSpeedOfSound(speed); @@ -2700,7 +2700,7 @@ Device_get_doppler_factor(Device *self, void* nothing) { try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device)->get()); if(device) { return Py_BuildValue("f", device->getDopplerFactor()); @@ -2728,7 +2728,7 @@ Device_set_doppler_factor(Device *self, PyObject* args, void* nothing) try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device)->get()); if(device) { device->setDopplerFactor(factor); @@ -2754,7 +2754,7 @@ Device_get_distance_model(Device *self, void* nothing) { try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device)->get()); if(device) { return Py_BuildValue("i", int(device->getDistanceModel())); @@ -2782,7 +2782,7 @@ Device_set_distance_model(Device *self, PyObject* args, void* nothing) try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device)->get()); if(device) { device->setDistanceModel(AUD_DistanceModel(model)); @@ -2875,6 +2875,12 @@ Device_empty() return DeviceType.tp_alloc(&DeviceType, 0); } +PyObject * +Factory_empty() +{ + return FactoryType.tp_alloc(&FactoryType, 0); +} + // ==================================================================== PyDoc_STRVAR(M_aud_doc, diff --git a/intern/audaspace/Python/AUD_PyAPI.h b/intern/audaspace/Python/AUD_PyAPI.h index 6e217b07213..97e1e63b6eb 100644 --- a/intern/audaspace/Python/AUD_PyAPI.h +++ b/intern/audaspace/Python/AUD_PyAPI.h @@ -36,17 +36,20 @@ #ifdef __cplusplus extern "C" { -#include "AUD_IDevice.h" +struct AUD_Handle; #else typedef void AUD_IFactory; typedef void AUD_IDevice; typedef void AUD_Handle; #endif +typedef void AUD_Reference_AUD_IFactory; +typedef void AUD_Reference_AUD_IDevice; + typedef struct { PyObject_HEAD PyObject* child_list; - AUD_IFactory* factory; + AUD_Reference_AUD_IFactory* factory; } Factory; typedef struct { @@ -57,14 +60,14 @@ typedef struct { typedef struct { PyObject_HEAD - AUD_IDevice* device; + AUD_Reference_AUD_IDevice* device; } Device; PyMODINIT_FUNC PyInit_aud(void); -extern PyObject * -Device_empty(); +extern PyObject* Device_empty(); +extern PyObject* Factory_empty(); #ifdef __cplusplus } diff --git a/intern/audaspace/SRC/AUD_SRCResampleFactory.cpp b/intern/audaspace/SRC/AUD_SRCResampleFactory.cpp index 17cf09efc1d..ca9c71e73b8 100644 --- a/intern/audaspace/SRC/AUD_SRCResampleFactory.cpp +++ b/intern/audaspace/SRC/AUD_SRCResampleFactory.cpp @@ -32,15 +32,15 @@ #include "AUD_SRCResampleFactory.h" #include "AUD_SRCResampleReader.h" -AUD_SRCResampleFactory::AUD_SRCResampleFactory(AUD_IFactory* factory, +AUD_SRCResampleFactory::AUD_SRCResampleFactory(AUD_Reference<AUD_IFactory> factory, AUD_DeviceSpecs specs) : AUD_ResampleFactory(factory, specs) { } -AUD_IReader* AUD_SRCResampleFactory::createReader() const +AUD_Reference<AUD_IReader> AUD_SRCResampleFactory::createReader() const { - AUD_IReader* reader = getReader(); + AUD_Reference<AUD_IReader> reader = getReader(); if(reader->getSpecs().rate != m_specs.rate) reader = new AUD_SRCResampleReader(reader, m_specs.specs); diff --git a/intern/audaspace/SRC/AUD_SRCResampleFactory.h b/intern/audaspace/SRC/AUD_SRCResampleFactory.h index 716def960fd..5d21584b4dc 100644 --- a/intern/audaspace/SRC/AUD_SRCResampleFactory.h +++ b/intern/audaspace/SRC/AUD_SRCResampleFactory.h @@ -46,9 +46,9 @@ private: AUD_SRCResampleFactory& operator=(const AUD_SRCResampleFactory&); public: - AUD_SRCResampleFactory(AUD_IFactory* factory, AUD_DeviceSpecs specs); + AUD_SRCResampleFactory(AUD_Reference<AUD_IFactory> factory, AUD_DeviceSpecs specs); - virtual AUD_IReader* createReader() const; + virtual AUD_Reference<AUD_IReader> createReader() const; }; #endif //AUD_SRCRESAMPLEFACTORY diff --git a/intern/audaspace/SRC/AUD_SRCResampleReader.cpp b/intern/audaspace/SRC/AUD_SRCResampleReader.cpp index 1026514a9b8..e9a94418b60 100644 --- a/intern/audaspace/SRC/AUD_SRCResampleReader.cpp +++ b/intern/audaspace/SRC/AUD_SRCResampleReader.cpp @@ -43,7 +43,7 @@ static long src_callback(void *cb_data, float **data) static const char* state_error = "AUD_SRCResampleReader: SRC State couldn't be " "created."; -AUD_SRCResampleReader::AUD_SRCResampleReader(AUD_IReader* reader, +AUD_SRCResampleReader::AUD_SRCResampleReader(AUD_Reference<AUD_IReader> reader, AUD_Specs specs) : AUD_EffectReader(reader), m_sspecs(reader->getSpecs()), diff --git a/intern/audaspace/SRC/AUD_SRCResampleReader.h b/intern/audaspace/SRC/AUD_SRCResampleReader.h index 27019c0ed9f..21193661911 100644 --- a/intern/audaspace/SRC/AUD_SRCResampleReader.h +++ b/intern/audaspace/SRC/AUD_SRCResampleReader.h @@ -85,7 +85,7 @@ public: * \exception AUD_Exception Thrown if the source specification cannot be * resampled to the target specification. */ - AUD_SRCResampleReader(AUD_IReader* reader, AUD_Specs specs); + AUD_SRCResampleReader(AUD_Reference<AUD_IReader> reader, AUD_Specs specs); /** * Destroys the reader. diff --git a/intern/audaspace/ffmpeg/AUD_FFMPEGFactory.cpp b/intern/audaspace/ffmpeg/AUD_FFMPEGFactory.cpp index 38de3e8867a..4e1eedd29ee 100644 --- a/intern/audaspace/ffmpeg/AUD_FFMPEGFactory.cpp +++ b/intern/audaspace/ffmpeg/AUD_FFMPEGFactory.cpp @@ -46,13 +46,13 @@ AUD_FFMPEGFactory::AUD_FFMPEGFactory(std::string filename) : AUD_FFMPEGFactory::AUD_FFMPEGFactory(const data_t* buffer, int size) : m_buffer(new AUD_Buffer(size)) { - memcpy(m_buffer.get()->getBuffer(), buffer, size); + memcpy(m_buffer->getBuffer(), buffer, size); } -AUD_IReader* AUD_FFMPEGFactory::createReader() const +AUD_Reference<AUD_IReader> AUD_FFMPEGFactory::createReader() const { - if(m_buffer.get()) - return new AUD_FFMPEGReader(m_buffer); - else + if(m_buffer.isNull()) return new AUD_FFMPEGReader(m_filename); + else + return new AUD_FFMPEGReader(m_buffer); } diff --git a/intern/audaspace/ffmpeg/AUD_FFMPEGFactory.h b/intern/audaspace/ffmpeg/AUD_FFMPEGFactory.h index 12687402fb6..8033836e80b 100644 --- a/intern/audaspace/ffmpeg/AUD_FFMPEGFactory.h +++ b/intern/audaspace/ffmpeg/AUD_FFMPEGFactory.h @@ -74,7 +74,7 @@ public: */ AUD_FFMPEGFactory(const data_t* buffer, int size); - virtual AUD_IReader* createReader() const; + virtual AUD_Reference<AUD_IReader> createReader() const; }; #endif //AUD_FFMPEGFACTORY diff --git a/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp index 4597432e7d1..ed6ca5d142f 100644 --- a/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp +++ b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp @@ -255,12 +255,12 @@ int AUD_FFMPEGReader::read_packet(void* opaque, uint8_t* buf, int buf_size) { AUD_FFMPEGReader* reader = reinterpret_cast<AUD_FFMPEGReader*>(opaque); - int size = AUD_MIN(buf_size, reader->m_membuffer.get()->getSize() - reader->m_membufferpos); + int size = AUD_MIN(buf_size, reader->m_membuffer->getSize() - reader->m_membufferpos); if(size < 0) return -1; - memcpy(buf, ((data_t*)reader->m_membuffer.get()->getBuffer()) + reader->m_membufferpos, size); + memcpy(buf, ((data_t*)reader->m_membuffer->getBuffer()) + reader->m_membufferpos, size); reader->m_membufferpos += size; return size; @@ -276,10 +276,10 @@ int64_t AUD_FFMPEGReader::seek_packet(void* opaque, int64_t offset, int whence) reader->m_membufferpos = 0; break; case SEEK_END: - reader->m_membufferpos = reader->m_membuffer.get()->getSize(); + reader->m_membufferpos = reader->m_membuffer->getSize(); break; case AVSEEK_SIZE: - return reader->m_membuffer.get()->getSize(); + return reader->m_membuffer->getSize(); } return (reader->m_membufferpos += offset); diff --git a/intern/audaspace/intern/AUD_BufferReader.cpp b/intern/audaspace/intern/AUD_BufferReader.cpp index 78111ba104c..0ac967b29b0 100644 --- a/intern/audaspace/intern/AUD_BufferReader.cpp +++ b/intern/audaspace/intern/AUD_BufferReader.cpp @@ -51,7 +51,7 @@ void AUD_BufferReader::seek(int position) int AUD_BufferReader::getLength() const { - return m_buffer.get()->getSize() / AUD_SAMPLE_SIZE(m_specs); + return m_buffer->getSize() / AUD_SAMPLE_SIZE(m_specs); } int AUD_BufferReader::getPosition() const @@ -68,11 +68,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 * m_specs.channels; + buffer = m_buffer->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->getSize() < (m_position + length) * sample_size) + length = m_buffer->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 0119bb105d8..08fb55f7605 100644 --- a/intern/audaspace/intern/AUD_C-API.cpp +++ b/intern/audaspace/intern/AUD_C-API.cpp @@ -37,9 +37,6 @@ #ifdef WITH_PYTHON #include "AUD_PyInit.h" #include "AUD_PyAPI.h" - -Device* g_device; -bool g_pyinitialized = false; #endif #include <cstdlib> @@ -90,9 +87,10 @@ extern "C" { #include <cassert> -typedef AUD_IFactory AUD_Sound; -typedef AUD_ReadDevice AUD_Device; +typedef AUD_Reference<AUD_IFactory> AUD_Sound; +typedef AUD_Reference<AUD_ReadDevice> AUD_Device; typedef AUD_Handle AUD_Channel; +typedef AUD_Reference<AUD_SequencerEntry> AUD_SEntry; #define AUD_CAPI_IMPLEMENTATION #include "AUD_C-API.h" @@ -101,8 +99,8 @@ typedef AUD_Handle AUD_Channel; #define NULL 0 #endif -static AUD_IDevice* AUD_device = NULL; -static AUD_I3DDevice* AUD_3ddevice = NULL; +static AUD_Reference<AUD_IDevice> AUD_device; +static AUD_I3DDevice* AUD_3ddevice; void AUD_initOnce() { @@ -113,9 +111,9 @@ void AUD_initOnce() int AUD_init(AUD_DeviceType device, AUD_DeviceSpecs specs, int buffersize) { - AUD_IDevice* dev = NULL; + AUD_Reference<AUD_IDevice> dev = NULL; - if(AUD_device) + if(!AUD_device.isNull()) AUD_exit(); try @@ -145,18 +143,7 @@ int AUD_init(AUD_DeviceType device, AUD_DeviceSpecs specs, int buffersize) } AUD_device = dev; - AUD_3ddevice = dynamic_cast<AUD_I3DDevice*>(AUD_device); - -#ifdef WITH_PYTHON - if(g_pyinitialized) - { - g_device = (Device*)Device_empty(); - if(g_device != NULL) - { - g_device->device = dev; - } - } -#endif + AUD_3ddevice = dynamic_cast<AUD_I3DDevice*>(AUD_device.get()); return true; } @@ -168,16 +155,6 @@ int AUD_init(AUD_DeviceType device, AUD_DeviceSpecs specs, int buffersize) void AUD_exit() { -#ifdef WITH_PYTHON - if(g_device) - { - Py_XDECREF(g_device); - g_device = NULL; - } - else -#endif - if(AUD_device) - delete AUD_device; AUD_device = NULL; AUD_3ddevice = NULL; } @@ -185,11 +162,16 @@ void AUD_exit() #ifdef WITH_PYTHON static PyObject* AUD_getCDevice(PyObject* self) { - if(g_device) + if(!AUD_device.isNull()) { - Py_INCREF(g_device); - return (PyObject*)g_device; + Device* device = (Device*)Device_empty(); + if(device != NULL) + { + device->device = new AUD_Reference<AUD_IDevice>(AUD_device); + return (PyObject*)device; + } } + Py_RETURN_NONE; } @@ -199,20 +181,49 @@ static PyMethodDef meth_getcdevice[] = {{ "device", (PyCFunction)AUD_getCDevice, ":return: The application's :class:`Device`.\n" ":rtype: :class:`Device`"}}; -PyObject* AUD_initPython() +extern "C" { +extern void* sound_get_factory(void* sound); +} + +static PyObject* AUD_getSoundFromPointer(PyObject* self, PyObject* args) { - PyObject* module = PyInit_aud(); - PyModule_AddObject(module, "device", (PyObject *)PyCFunction_New(meth_getcdevice, NULL)); - PyDict_SetItemString(PyImport_GetModuleDict(), "aud", module); - if(AUD_device) + long int lptr; + + if(PyArg_Parse(args, "l:_sound_from_pointer", &lptr)) { - g_device = (Device*)Device_empty(); - if(g_device != NULL) + if(lptr) { - g_device->device = AUD_device; + AUD_Reference<AUD_IFactory>* factory = (AUD_Reference<AUD_IFactory>*) sound_get_factory((void*) lptr); + + if(factory) + { + Factory* obj = (Factory*) Factory_empty(); + if(obj) + { + obj->factory = new AUD_Reference<AUD_IFactory>(*factory); + return (PyObject*) obj; + } + } } } - g_pyinitialized = true; + + Py_RETURN_NONE; +} + +static PyMethodDef meth_sound_from_pointer[] = {{ "_sound_from_pointer", (PyCFunction)AUD_getSoundFromPointer, METH_O, + "_sound_from_pointer(pointer)\n\n" + "Returns the corresponding :class:`Factory` object.\n\n" + ":arg pointer: The pointer to the bSound object as long.\n" + ":type pointer: long\n" + ":return: The corresponding :class:`Factory` object.\n" + ":rtype: :class:`Factory`"}}; + +PyObject* AUD_initPython() +{ + PyObject* module = PyInit_aud(); + PyModule_AddObject(module, "device", (PyObject*)PyCFunction_New(meth_getcdevice, NULL)); + PyModule_AddObject(module, "_sound_from_pointer", (PyObject*)PyCFunction_New(meth_sound_from_pointer, NULL)); + PyDict_SetItemString(PyImport_GetModuleDict(), "aud", module); return module; } @@ -220,13 +231,11 @@ PyObject* AUD_initPython() void AUD_lock() { - assert(AUD_device); AUD_device->lock(); } void AUD_unlock() { - assert(AUD_device); AUD_device->unlock(); } @@ -241,13 +250,12 @@ AUD_SoundInfo AUD_getInfo(AUD_Sound* sound) try { - AUD_IReader* reader = sound->createReader(); + AUD_Reference<AUD_IReader> reader = (*sound)->createReader(); - if(reader) + if(!reader.isNull()) { info.specs = reader->getSpecs(); info.length = reader->getLength() / (float) info.specs.rate; - delete reader; } } catch(AUD_Exception&) @@ -260,13 +268,13 @@ AUD_SoundInfo AUD_getInfo(AUD_Sound* sound) AUD_Sound* AUD_load(const char* filename) { assert(filename); - return new AUD_FileFactory(filename); + return new AUD_Sound(new AUD_FileFactory(filename)); } AUD_Sound* AUD_loadBuffer(unsigned char* buffer, int size) { assert(buffer); - return new AUD_FileFactory(buffer, size); + return new AUD_Sound(new AUD_FileFactory(buffer, size)); } AUD_Sound* AUD_bufferSound(AUD_Sound* sound) @@ -275,7 +283,7 @@ AUD_Sound* AUD_bufferSound(AUD_Sound* sound) try { - return new AUD_StreamBufferFactory(sound); + return new AUD_Sound(new AUD_StreamBufferFactory(*sound)); } catch(AUD_Exception&) { @@ -289,7 +297,7 @@ AUD_Sound* AUD_delaySound(AUD_Sound* sound, float delay) try { - return new AUD_DelayFactory(sound, delay); + return new AUD_Sound(new AUD_DelayFactory(*sound, delay)); } catch(AUD_Exception&) { @@ -303,7 +311,7 @@ AUD_Sound* AUD_limitSound(AUD_Sound* sound, float start, float end) try { - return new AUD_LimiterFactory(sound, start, end); + return new AUD_Sound(new AUD_LimiterFactory(*sound, start, end)); } catch(AUD_Exception&) { @@ -317,7 +325,7 @@ AUD_Sound* AUD_pingpongSound(AUD_Sound* sound) try { - return new AUD_PingPongFactory(sound); + return new AUD_Sound(new AUD_PingPongFactory(*sound)); } catch(AUD_Exception&) { @@ -331,7 +339,7 @@ AUD_Sound* AUD_loopSound(AUD_Sound* sound) try { - return new AUD_LoopFactory(sound); + return new AUD_Sound(new AUD_LoopFactory(*sound)); } catch(AUD_Exception&) { @@ -360,7 +368,7 @@ AUD_Sound* AUD_rectifySound(AUD_Sound* sound) try { - return new AUD_RectifyFactory(sound); + return new AUD_Sound(new AUD_RectifyFactory(*sound)); } catch(AUD_Exception&) { @@ -376,11 +384,10 @@ void AUD_unload(AUD_Sound* sound) AUD_Channel* AUD_play(AUD_Sound* sound, int keep) { - assert(AUD_device); assert(sound); try { - return AUD_device->play(sound, keep); + return AUD_device->play(*sound, keep); } catch(AUD_Exception&) { @@ -390,51 +397,43 @@ AUD_Channel* AUD_play(AUD_Sound* sound, int keep) int AUD_pause(AUD_Channel* handle) { - assert(AUD_device); return AUD_device->pause(handle); } int AUD_resume(AUD_Channel* handle) { - assert(AUD_device); return AUD_device->resume(handle); } int AUD_stop(AUD_Channel* handle) { - if(AUD_device) + if(!AUD_device.isNull()) return AUD_device->stop(handle); return false; } int AUD_setKeep(AUD_Channel* handle, int keep) { - assert(AUD_device); return AUD_device->setKeep(handle, keep); } int AUD_seek(AUD_Channel* handle, float seekTo) { - assert(AUD_device); return AUD_device->seek(handle, seekTo); } float AUD_getPosition(AUD_Channel* handle) { - assert(AUD_device); return AUD_device->getPosition(handle); } AUD_Status AUD_getStatus(AUD_Channel* handle) { - assert(AUD_device); return AUD_device->getStatus(handle); } int AUD_setListenerLocation(const float* location) { - assert(AUD_device); - if(AUD_3ddevice) { AUD_Vector3 v(location[0], location[1], location[2]); @@ -447,8 +446,6 @@ int AUD_setListenerLocation(const float* location) int AUD_setListenerVelocity(const float* velocity) { - assert(AUD_device); - if(AUD_3ddevice) { AUD_Vector3 v(velocity[0], velocity[1], velocity[2]); @@ -461,8 +458,6 @@ int AUD_setListenerVelocity(const float* velocity) int AUD_setListenerOrientation(const float* orientation) { - assert(AUD_device); - if(AUD_3ddevice) { AUD_Quaternion q(orientation[3], orientation[0], orientation[1], orientation[2]); @@ -475,8 +470,6 @@ int AUD_setListenerOrientation(const float* orientation) int AUD_setSpeedOfSound(float speed) { - assert(AUD_device); - if(AUD_3ddevice) { AUD_3ddevice->setSpeedOfSound(speed); @@ -488,8 +481,6 @@ int AUD_setSpeedOfSound(float speed) int AUD_setDopplerFactor(float factor) { - assert(AUD_device); - if(AUD_3ddevice) { AUD_3ddevice->setDopplerFactor(factor); @@ -501,8 +492,6 @@ int AUD_setDopplerFactor(float factor) int AUD_setDistanceModel(AUD_DistanceModel model) { - assert(AUD_device); - if(AUD_3ddevice) { AUD_3ddevice->setDistanceModel(model); @@ -514,8 +503,6 @@ int AUD_setDistanceModel(AUD_DistanceModel model) int AUD_setSourceLocation(AUD_Channel* handle, const float* location) { - assert(AUD_device); - if(AUD_3ddevice) { AUD_Vector3 v(location[0], location[1], location[2]); @@ -527,8 +514,6 @@ int AUD_setSourceLocation(AUD_Channel* handle, const float* location) int AUD_setSourceVelocity(AUD_Channel* handle, const float* velocity) { - assert(AUD_device); - if(AUD_3ddevice) { AUD_Vector3 v(velocity[0], velocity[1], velocity[2]); @@ -540,8 +525,6 @@ int AUD_setSourceVelocity(AUD_Channel* handle, const float* velocity) int AUD_setSourceOrientation(AUD_Channel* handle, const float* orientation) { - assert(AUD_device); - if(AUD_3ddevice) { AUD_Quaternion q(orientation[3], orientation[0], orientation[1], orientation[2]); @@ -553,8 +536,6 @@ int AUD_setSourceOrientation(AUD_Channel* handle, const float* orientation) int AUD_setRelative(AUD_Channel* handle, int relative) { - assert(AUD_device); - if(AUD_3ddevice) { return AUD_3ddevice->setRelative(handle, relative); @@ -565,8 +546,6 @@ int AUD_setRelative(AUD_Channel* handle, int relative) int AUD_setVolumeMaximum(AUD_Channel* handle, float volume) { - assert(AUD_device); - if(AUD_3ddevice) { return AUD_3ddevice->setVolumeMaximum(handle, volume); @@ -577,8 +556,6 @@ int AUD_setVolumeMaximum(AUD_Channel* handle, float volume) int AUD_setVolumeMinimum(AUD_Channel* handle, float volume) { - assert(AUD_device); - if(AUD_3ddevice) { return AUD_3ddevice->setVolumeMinimum(handle, volume); @@ -589,8 +566,6 @@ int AUD_setVolumeMinimum(AUD_Channel* handle, float volume) int AUD_setDistanceMaximum(AUD_Channel* handle, float distance) { - assert(AUD_device); - if(AUD_3ddevice) { return AUD_3ddevice->setDistanceMaximum(handle, distance); @@ -601,8 +576,6 @@ int AUD_setDistanceMaximum(AUD_Channel* handle, float distance) int AUD_setDistanceReference(AUD_Channel* handle, float distance) { - assert(AUD_device); - if(AUD_3ddevice) { return AUD_3ddevice->setDistanceReference(handle, distance); @@ -613,8 +586,6 @@ int AUD_setDistanceReference(AUD_Channel* handle, float distance) int AUD_setAttenuation(AUD_Channel* handle, float factor) { - assert(AUD_device); - if(AUD_3ddevice) { return AUD_3ddevice->setAttenuation(handle, factor); @@ -625,8 +596,6 @@ int AUD_setAttenuation(AUD_Channel* handle, float factor) int AUD_setConeAngleOuter(AUD_Channel* handle, float angle) { - assert(AUD_device); - if(AUD_3ddevice) { return AUD_3ddevice->setConeAngleOuter(handle, angle); @@ -637,8 +606,6 @@ int AUD_setConeAngleOuter(AUD_Channel* handle, float angle) int AUD_setConeAngleInner(AUD_Channel* handle, float angle) { - assert(AUD_device); - if(AUD_3ddevice) { return AUD_3ddevice->setConeAngleInner(handle, angle); @@ -649,8 +616,6 @@ int AUD_setConeAngleInner(AUD_Channel* handle, float angle) int AUD_setConeVolumeOuter(AUD_Channel* handle, float volume) { - assert(AUD_device); - if(AUD_3ddevice) { return AUD_3ddevice->setConeVolumeOuter(handle, volume); @@ -663,8 +628,6 @@ int AUD_setSoundVolume(AUD_Channel* handle, float volume) { if(handle) { - assert(AUD_device); - try { return AUD_device->setVolume(handle, volume); @@ -678,8 +641,6 @@ int AUD_setSoundPitch(AUD_Channel* handle, float pitch) { if(handle) { - assert(AUD_device); - try { return AUD_device->setPitch(handle, pitch); @@ -693,7 +654,7 @@ AUD_Device* AUD_openReadDevice(AUD_DeviceSpecs specs) { try { - return new AUD_ReadDevice(specs); + return new AUD_Device(new AUD_ReadDevice(specs)); } catch(AUD_Exception&) { @@ -708,8 +669,8 @@ AUD_Channel* AUD_playDevice(AUD_Device* device, AUD_Sound* sound, float seek) try { - AUD_Channel* handle = device->play(sound); - device->seek(handle, seek); + AUD_Channel* handle = (*device)->play(*sound); + (*device)->seek(handle, seek); return handle; } catch(AUD_Exception&) @@ -724,7 +685,7 @@ int AUD_setDeviceVolume(AUD_Device* device, float volume) try { - device->setVolume(volume); + (*device)->setVolume(volume); return true; } catch(AUD_Exception&) {} @@ -741,7 +702,7 @@ int AUD_setDeviceSoundVolume(AUD_Device* device, AUD_Channel* handle, try { - return device->setVolume(handle, volume); + return (*device)->setVolume(handle, volume); } catch(AUD_Exception&) {} } @@ -755,7 +716,7 @@ int AUD_readDevice(AUD_Device* device, data_t* buffer, int length) try { - return device->read(buffer, length); + return (*device)->read(buffer, length); } catch(AUD_Exception&) { @@ -785,38 +746,34 @@ float* AUD_readSoundBuffer(const char* filename, float low, float high, AUD_DeviceSpecs specs; specs.channels = AUD_CHANNELS_MONO; specs.rate = (AUD_SampleRate)samplerate; - AUD_Sound* sound; + AUD_Reference<AUD_IFactory> sound; - AUD_FileFactory file(filename); + AUD_Reference<AUD_IFactory> file = new AUD_FileFactory(filename); - AUD_IReader* reader = file.createReader(); + AUD_Reference<AUD_IReader> reader = file->createReader(); AUD_SampleRate rate = reader->getSpecs().rate; - delete reader; - AUD_ChannelMapperFactory mapper(&file, specs); - sound = &mapper; - AUD_LowpassFactory lowpass(sound, high); + sound = new AUD_ChannelMapperFactory(file, specs); + if(high < rate) - sound = &lowpass; - AUD_HighpassFactory highpass(sound, low); + sound = new AUD_LowpassFactory(sound, high); if(low > 0) - sound = &highpass; - AUD_EnvelopeFactory envelope(sound, attack, release, threshold, 0.1f); - AUD_LinearResampleFactory resampler(&envelope, specs); - sound = &resampler; - AUD_SquareFactory squaref(sound, sthreshold); + sound = new AUD_HighpassFactory(sound, low);; + + sound = new AUD_EnvelopeFactory(sound, attack, release, threshold, 0.1f); + sound = new AUD_LinearResampleFactory(sound, specs); + if(square) - sound = &squaref; - AUD_AccumulatorFactory accumulator(sound, additive); - AUD_SumFactory sum(sound); + sound = new AUD_SquareFactory(sound, sthreshold); + if(accumulate) - sound = &accumulator; + sound = new AUD_AccumulatorFactory(sound, additive); else if(additive) - sound = ∑ + sound = new AUD_SumFactory(sound); reader = sound->createReader(); - if(reader == NULL) + if(reader.isNull()) return NULL; int len; @@ -830,7 +787,6 @@ float* AUD_readSoundBuffer(const char* filename, float low, float high, 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)); @@ -840,21 +796,17 @@ float* AUD_readSoundBuffer(const char* filename, float low, float high, static void pauseSound(AUD_Channel* handle) { - assert(AUD_device); - AUD_device->pause(handle); } AUD_Channel* AUD_pauseAfter(AUD_Channel* handle, float seconds) { - assert(AUD_device); - - AUD_SilenceFactory silence; - AUD_LimiterFactory limiter(&silence, 0, seconds); + AUD_Reference<AUD_IFactory> silence = new AUD_SilenceFactory; + AUD_Reference<AUD_IFactory> limiter = new AUD_LimiterFactory(silence, 0, seconds); try { - AUD_Channel* channel = AUD_device->play(&limiter); + AUD_Channel* channel = AUD_device->play(limiter); AUD_device->setStopCallback(channel, (stopCallback)pauseSound, handle); return channel; } @@ -874,39 +826,42 @@ AUD_Sound* AUD_createSequencer(int muted, void* data, AUD_volumeFunction volume) AUD_Specs specs; specs.channels = AUD_CHANNELS_STEREO; specs.rate = AUD_RATE_44100; - return new AUD_SequencerFactory(specs, muted, data, volume); + AUD_Reference<AUD_SequencerFactory>* sequencer = new AUD_Reference<AUD_SequencerFactory>(new AUD_SequencerFactory(specs, muted, data, volume)); + (*sequencer)->setThis(sequencer); + return reinterpret_cast<AUD_Sound*>(sequencer); } void AUD_destroySequencer(AUD_Sound* sequencer) { - delete ((AUD_SequencerFactory*)sequencer); + delete sequencer; } void AUD_setSequencerMuted(AUD_Sound* sequencer, int muted) { - ((AUD_SequencerFactory*)sequencer)->mute(muted); + ((AUD_SequencerFactory*)sequencer->get())->mute(muted); } -AUD_SequencerEntry* AUD_addSequencer(AUD_Sound** sequencer, AUD_Sound* sound, +AUD_Reference<AUD_SequencerEntry>* AUD_addSequencer(AUD_Sound* sequencer, AUD_Sound** sound, float begin, float end, float skip, void* data) { - return ((AUD_SequencerFactory*)sequencer)->add((AUD_IFactory**) sound, begin, end, skip, data); + return new AUD_Reference<AUD_SequencerEntry>(((AUD_SequencerFactory*)sequencer->get())->add(sound, begin, end, skip, data)); } -void AUD_removeSequencer(AUD_Sound* sequencer, AUD_SequencerEntry* entry) +void AUD_removeSequencer(AUD_Sound* sequencer, AUD_Reference<AUD_SequencerEntry>* entry) { - ((AUD_SequencerFactory*)sequencer)->remove(entry); + ((AUD_SequencerFactory*)sequencer->get())->remove(*entry); + delete entry; } -void AUD_moveSequencer(AUD_Sound* sequencer, AUD_SequencerEntry* entry, +void AUD_moveSequencer(AUD_Sound* sequencer, AUD_Reference<AUD_SequencerEntry>* entry, float begin, float end, float skip) { - ((AUD_SequencerFactory*)sequencer)->move(entry, begin, end, skip); + ((AUD_SequencerFactory*)sequencer->get())->move(*entry, begin, end, skip); } -void AUD_muteSequencer(AUD_Sound* sequencer, AUD_SequencerEntry* entry, char mute) +void AUD_muteSequencer(AUD_Sound* sequencer, AUD_Reference<AUD_SequencerEntry>* entry, char mute) { - ((AUD_SequencerFactory*)sequencer)->mute(entry, mute); + ((AUD_SequencerFactory*)sequencer->get())->mute(*entry, mute); } int AUD_readSound(AUD_Sound* sound, sample_t* buffer, int length) @@ -918,9 +873,7 @@ int AUD_readSound(AUD_Sound* sound, sample_t* buffer, int length) specs.channels = AUD_CHANNELS_MONO; specs.format = AUD_FORMAT_INVALID; - AUD_ChannelMapperFactory mapper(sound, specs); - - AUD_IReader* reader = mapper.createReader(); + AUD_Reference<AUD_IReader> reader = AUD_ChannelMapperFactory(*sound, specs).createReader(); int len = reader->getLength(); float samplejump = (float)len / (float)length; @@ -949,15 +902,13 @@ int AUD_readSound(AUD_Sound* sound, sample_t* buffer, int length) } } - delete reader; - return length; } void AUD_startPlayback() { #ifdef WITH_JACK - AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device); + AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device.get()); if(device) device->startPlayback(); #endif @@ -966,7 +917,7 @@ void AUD_startPlayback() void AUD_stopPlayback() { #ifdef WITH_JACK - AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device); + AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device.get()); if(device) device->stopPlayback(); #endif @@ -975,7 +926,7 @@ void AUD_stopPlayback() void AUD_seekSequencer(AUD_Channel* handle, float time) { #ifdef WITH_JACK - AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device); + AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device.get()); if(device) device->seekPlayback(time); else @@ -988,7 +939,7 @@ void AUD_seekSequencer(AUD_Channel* handle, float time) float AUD_getSequencerPosition(AUD_Channel* handle) { #ifdef WITH_JACK - AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device); + AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device.get()); if(device) return device->getPlaybackPosition(); else @@ -1001,7 +952,7 @@ float AUD_getSequencerPosition(AUD_Channel* handle) #ifdef WITH_JACK void AUD_setSyncCallback(AUD_syncFunction function, void* data) { - AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device); + AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device.get()); if(device) device->setSyncCallback(function, data); } @@ -1010,7 +961,7 @@ void AUD_setSyncCallback(AUD_syncFunction function, void* data) int AUD_doesPlayback() { #ifdef WITH_JACK - AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device); + AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device.get()); if(device) return device->doesPlayback(); #endif diff --git a/intern/audaspace/intern/AUD_C-API.h b/intern/audaspace/intern/AUD_C-API.h index b2242f09547..47dadd05555 100644 --- a/intern/audaspace/intern/AUD_C-API.h +++ b/intern/audaspace/intern/AUD_C-API.h @@ -55,7 +55,7 @@ typedef struct typedef void AUD_Sound; typedef void AUD_Channel; typedef void AUD_Device; - typedef void AUD_SequencerEntry; + typedef void AUD_SEntry; typedef float (*AUD_volumeFunction)(void*, void*, float); typedef void (*AUD_syncFunction)(void*, int, float); #endif @@ -465,15 +465,15 @@ extern void AUD_destroySequencer(AUD_Sound* sequencer); extern void AUD_setSequencerMuted(AUD_Sound* sequencer, int muted); -extern AUD_SequencerEntry* AUD_addSequencer(AUD_Sound** sequencer, AUD_Sound* sound, +extern AUD_SEntry* AUD_addSequencer(AUD_Sound* sequencer, AUD_Sound** sound, float begin, float end, float skip, void* data); -extern void AUD_removeSequencer(AUD_Sound* sequencer, AUD_SequencerEntry* entry); +extern void AUD_removeSequencer(AUD_Sound* sequencer, AUD_SEntry* entry); -extern void AUD_moveSequencer(AUD_Sound* sequencer, AUD_SequencerEntry* entry, +extern void AUD_moveSequencer(AUD_Sound* sequencer, AUD_SEntry* entry, float begin, float end, float skip); -extern void AUD_muteSequencer(AUD_Sound* sequencer, AUD_SequencerEntry* entry, +extern void AUD_muteSequencer(AUD_Sound* sequencer, AUD_SEntry* entry, char mute); extern int AUD_readSound(AUD_Sound* sound, sample_t* buffer, int length); diff --git a/intern/audaspace/intern/AUD_ChannelMapperFactory.cpp b/intern/audaspace/intern/AUD_ChannelMapperFactory.cpp index b474fbad444..ea5e9519729 100644 --- a/intern/audaspace/intern/AUD_ChannelMapperFactory.cpp +++ b/intern/audaspace/intern/AUD_ChannelMapperFactory.cpp @@ -34,7 +34,7 @@ #include <cstring> -AUD_ChannelMapperFactory::AUD_ChannelMapperFactory(AUD_IFactory* factory, +AUD_ChannelMapperFactory::AUD_ChannelMapperFactory(AUD_Reference<AUD_IFactory> factory, AUD_DeviceSpecs specs) : AUD_MixerFactory(factory, specs) { @@ -102,9 +102,9 @@ void AUD_ChannelMapperFactory::deleteMapping(int ic) } } -AUD_IReader* AUD_ChannelMapperFactory::createReader() const +AUD_Reference<AUD_IReader> AUD_ChannelMapperFactory::createReader() const { - AUD_IReader* reader = getReader(); + AUD_Reference<AUD_IReader> reader = getReader(); int ic = reader->getSpecs().channels; return new AUD_ChannelMapperReader(reader, diff --git a/intern/audaspace/intern/AUD_ChannelMapperFactory.h b/intern/audaspace/intern/AUD_ChannelMapperFactory.h index 9d622f5e322..25b3e091d8d 100644 --- a/intern/audaspace/intern/AUD_ChannelMapperFactory.h +++ b/intern/audaspace/intern/AUD_ChannelMapperFactory.h @@ -51,7 +51,7 @@ private: AUD_ChannelMapperFactory& operator=(const AUD_ChannelMapperFactory&); public: - AUD_ChannelMapperFactory(AUD_IFactory* factory, AUD_DeviceSpecs specs); + AUD_ChannelMapperFactory(AUD_Reference<AUD_IFactory> factory, AUD_DeviceSpecs specs); virtual ~AUD_ChannelMapperFactory(); @@ -67,7 +67,7 @@ public: */ void deleteMapping(int ic); - virtual AUD_IReader* createReader() const; + virtual AUD_Reference<AUD_IReader> createReader() const; }; #endif //AUD_CHANNELMAPPERFACTORY diff --git a/intern/audaspace/intern/AUD_ChannelMapperReader.cpp b/intern/audaspace/intern/AUD_ChannelMapperReader.cpp index dec70aaecf6..3079d31c9e9 100644 --- a/intern/audaspace/intern/AUD_ChannelMapperReader.cpp +++ b/intern/audaspace/intern/AUD_ChannelMapperReader.cpp @@ -31,7 +31,7 @@ #include "AUD_ChannelMapperReader.h" -AUD_ChannelMapperReader::AUD_ChannelMapperReader(AUD_IReader* reader, +AUD_ChannelMapperReader::AUD_ChannelMapperReader(AUD_Reference<AUD_IReader> reader, float **mapping) : AUD_EffectReader(reader) { diff --git a/intern/audaspace/intern/AUD_ChannelMapperReader.h b/intern/audaspace/intern/AUD_ChannelMapperReader.h index 091ed06db15..1c7dba1df7c 100644 --- a/intern/audaspace/intern/AUD_ChannelMapperReader.h +++ b/intern/audaspace/intern/AUD_ChannelMapperReader.h @@ -72,7 +72,7 @@ public: * \param reader The reader to map. * \param mapping The mapping specification as two dimensional float array. */ - AUD_ChannelMapperReader(AUD_IReader* reader, float **mapping); + AUD_ChannelMapperReader(AUD_Reference<AUD_IReader> reader, float **mapping); /** * Destroys the reader. diff --git a/intern/audaspace/intern/AUD_ConverterFactory.cpp b/intern/audaspace/intern/AUD_ConverterFactory.cpp index cce0f273616..78602d2cfa9 100644 --- a/intern/audaspace/intern/AUD_ConverterFactory.cpp +++ b/intern/audaspace/intern/AUD_ConverterFactory.cpp @@ -32,15 +32,15 @@ #include "AUD_ConverterFactory.h" #include "AUD_ConverterReader.h" -AUD_ConverterFactory::AUD_ConverterFactory(AUD_IFactory* factory, +AUD_ConverterFactory::AUD_ConverterFactory(AUD_Reference<AUD_IFactory> factory, AUD_DeviceSpecs specs) : AUD_MixerFactory(factory, specs) { } -AUD_IReader* AUD_ConverterFactory::createReader() const +AUD_Reference<AUD_IReader> AUD_ConverterFactory::createReader() const { - AUD_IReader* reader = getReader(); + AUD_Reference<AUD_IReader> reader = getReader(); if(m_specs.format != AUD_FORMAT_FLOAT32) reader = new AUD_ConverterReader(reader, m_specs); diff --git a/intern/audaspace/intern/AUD_ConverterFactory.h b/intern/audaspace/intern/AUD_ConverterFactory.h index b9eac94de40..cc1fedb2a10 100644 --- a/intern/audaspace/intern/AUD_ConverterFactory.h +++ b/intern/audaspace/intern/AUD_ConverterFactory.h @@ -46,9 +46,9 @@ private: AUD_ConverterFactory& operator=(const AUD_ConverterFactory&); public: - AUD_ConverterFactory(AUD_IFactory* factory, AUD_DeviceSpecs specs); + AUD_ConverterFactory(AUD_Reference<AUD_IFactory> factory, AUD_DeviceSpecs specs); - virtual AUD_IReader* createReader() const; + virtual AUD_Reference<AUD_IReader> createReader() const; }; #endif //AUD_CONVERTERFACTORY diff --git a/intern/audaspace/intern/AUD_ConverterFunctions.cpp b/intern/audaspace/intern/AUD_ConverterFunctions.cpp index d3cc9fa8202..8f2ac21acd6 100644 --- a/intern/audaspace/intern/AUD_ConverterFunctions.cpp +++ b/intern/audaspace/intern/AUD_ConverterFunctions.cpp @@ -45,13 +45,13 @@ 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++) + for(int i = length - 1; i >= 0; i++) t[i] = (((int16_t)source[i]) - AUD_U8_0) << 8; } void AUD_convert_u8_s24_be(data_t* target, data_t* source, int length) { - for(int i = 0; i < length; i++) + for(int i = length - 1; i >= 0; i++) { target[i*3] = source[i] - AUD_U8_0; target[i*3+1] = 0; @@ -61,7 +61,7 @@ void AUD_convert_u8_s24_be(data_t* target, data_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++) + for(int i = length - 1; i >= 0; i++) { target[i*3+2] = source[i] - AUD_U8_0; target[i*3+1] = 0; @@ -72,21 +72,21 @@ void AUD_convert_u8_s24_le(data_t* target, data_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++) + for(int i = length - 1; i >= 0; i++) t[i] = (((int32_t)source[i]) - AUD_U8_0) << 24; } void AUD_convert_u8_float(data_t* target, data_t* source, int length) { float* t = (float*) target; - for(int i = 0; i < length; i++) + for(int i = length - 1; i >= 0; i++) t[i] = (((int32_t)source[i]) - AUD_U8_0) / ((float)AUD_U8_0); } void AUD_convert_u8_double(data_t* target, data_t* source, int length) { double* t = (double*) target; - for(int i = 0; i < length; i++) + for(int i = length - 1; i >= 0; i++) t[i] = (((int32_t)source[i]) - AUD_U8_0) / ((double)AUD_U8_0); } @@ -100,10 +100,12 @@ void AUD_convert_s16_u8(data_t* target, data_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++) + int16_t t; + for(int i = length - 1; i >= 0; i++) { - target[i*3] = s[i] >> 8 & 0xFF; - target[i*3+1] = s[i] & 0xFF; + t = s[i]; + target[i*3] = t >> 8 & 0xFF; + target[i*3+1] = t & 0xFF; target[i*3+2] = 0; } } @@ -111,10 +113,12 @@ void AUD_convert_s16_s24_be(data_t* target, data_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++) + int16_t t; + for(int i = length - 1; i >= 0; i++) { - target[i*3+2] = s[i] >> 8 & 0xFF; - target[i*3+1] = s[i] & 0xFF; + t = s[i]; + target[i*3+2] = t >> 8 & 0xFF; + target[i*3+1] = t & 0xFF; target[i*3] = 0; } } @@ -123,7 +127,7 @@ 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; - for(int i = 0; i < length; i++) + for(int i = length - 1; i >= 0; i++) t[i] = ((int32_t)s[i]) << 16; } @@ -131,7 +135,7 @@ void AUD_convert_s16_float(data_t* target, data_t* source, int length) { int16_t* s = (int16_t*) source; float* t = (float*) target; - for(int i = 0; i < length; i++) + for(int i = length - 1; i >= 0; i++) t[i] = s[i] / AUD_S16_FLT; } @@ -139,7 +143,7 @@ void AUD_convert_s16_double(data_t* target, data_t* source, int length) { int16_t* s = (int16_t*) source; double* t = (double*) target; - for(int i = 0; i < length; i++) + for(int i = length - 1; i >= 0; i++) t[i] = s[i] / AUD_S16_FLT; } @@ -177,14 +181,14 @@ void AUD_convert_s24_s24(data_t* target, data_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++) + for(int i = length - 1; i >= 0; i++) t[i] = source[i*3] << 24 | source[i*3+1] << 16 | source[i*3+2] << 8; } 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++) + for(int i = length - 1; i >= 0; i++) t[i] = source[i*3+2] << 24 | source[i*3+1] << 16 | source[i*3] << 8; } @@ -192,7 +196,7 @@ void AUD_convert_s24_float_be(data_t* target, data_t* source, int length) { float* t = (float*) target; int32_t s; - for(int i = 0; i < length; i++) + for(int i = length - 1; i >= 0; i++) { s = source[i*3] << 24 | source[i*3+1] << 16 | source[i*3+2] << 8; t[i] = s / AUD_S32_FLT; @@ -203,7 +207,7 @@ void AUD_convert_s24_float_le(data_t* target, data_t* source, int length) { float* t = (float*) target; int32_t s; - for(int i = 0; i < length; i++) + for(int i = length - 1; i >= 0; i++) { s = source[i*3+2] << 24 | source[i*3+1] << 16 | source[i*3] << 8; t[i] = s / AUD_S32_FLT; @@ -214,7 +218,7 @@ void AUD_convert_s24_double_be(data_t* target, data_t* source, int length) { double* t = (double*) target; int32_t s; - for(int i = 0; i < length; i++) + for(int i = length - 1; i >= 0; i++) { s = source[i*3] << 24 | source[i*3+1] << 16 | source[i*3+2] << 8; t[i] = s / AUD_S32_FLT; @@ -225,7 +229,7 @@ void AUD_convert_s24_double_le(data_t* target, data_t* source, int length) { double* t = (double*) target; int32_t s; - for(int i = 0; i < length; i++) + for(int i = length - 1; i >= 0; i++) { s = source[i*3+2] << 24 | source[i*3+1] << 16 | source[i*3] << 8; t[i] = s / AUD_S32_FLT; @@ -250,22 +254,26 @@ void AUD_convert_s32_s16(data_t* target, data_t* source, int length) void AUD_convert_s32_s24_be(data_t* target, data_t* source, int length) { int32_t* s = (int32_t*) source; + int32_t t; for(int i = 0; i < length; i++) { - target[i*3] = s[i] >> 24 & 0xFF; - target[i*3+1] = s[i] >> 16 & 0xFF; - target[i*3+2] = s[i] >> 8 & 0xFF; + t = s[i]; + target[i*3] = t >> 24 & 0xFF; + target[i*3+1] = t >> 16 & 0xFF; + target[i*3+2] = t >> 8 & 0xFF; } } void AUD_convert_s32_s24_le(data_t* target, data_t* source, int length) { - int16_t* s = (int16_t*) source; + int32_t* s = (int32_t*) source; + int32_t t; for(int i = 0; i < length; i++) { - target[i*3+2] = s[i] >> 24 & 0xFF; - target[i*3+1] = s[i] >> 16 & 0xFF; - target[i*3] = s[i] >> 8 & 0xFF; + t = s[i]; + target[i*3+2] = t >> 24 & 0xFF; + target[i*3+1] = t >> 16 & 0xFF; + target[i*3] = t >> 8 & 0xFF; } } @@ -281,7 +289,7 @@ void AUD_convert_s32_double(data_t* target, data_t* source, int length) { int32_t* s = (int32_t*) source; double* t = (double*) target; - for(int i = 0; i < length; i++) + for(int i = length - 1; i >= 0; i++) t[i] = s[i] / AUD_S32_FLT; } @@ -371,7 +379,7 @@ void AUD_convert_float_double(data_t* target, data_t* source, int length) { float* s = (float*) source; double* t = (double*) target; - for(int i = 0; i < length; i++) + for(int i = length - 1; i >= 0; i++) t[i] = s[i]; } diff --git a/intern/audaspace/intern/AUD_ConverterReader.cpp b/intern/audaspace/intern/AUD_ConverterReader.cpp index 70297b8f5e8..6927f3e969c 100644 --- a/intern/audaspace/intern/AUD_ConverterReader.cpp +++ b/intern/audaspace/intern/AUD_ConverterReader.cpp @@ -31,7 +31,7 @@ #include "AUD_ConverterReader.h" -AUD_ConverterReader::AUD_ConverterReader(AUD_IReader* reader, +AUD_ConverterReader::AUD_ConverterReader(AUD_Reference<AUD_IReader> reader, AUD_DeviceSpecs specs) : AUD_EffectReader(reader) { diff --git a/intern/audaspace/intern/AUD_ConverterReader.h b/intern/audaspace/intern/AUD_ConverterReader.h index a7a425adc54..6f252b5f9f9 100644 --- a/intern/audaspace/intern/AUD_ConverterReader.h +++ b/intern/audaspace/intern/AUD_ConverterReader.h @@ -67,7 +67,7 @@ public: * \param reader The reader to convert. * \param specs The target specification. */ - AUD_ConverterReader(AUD_IReader* reader, AUD_DeviceSpecs specs); + AUD_ConverterReader(AUD_Reference<AUD_IReader> reader, AUD_DeviceSpecs specs); virtual AUD_Specs getSpecs() const; virtual void read(int & length, sample_t* & buffer); diff --git a/intern/audaspace/intern/AUD_DefaultMixer.cpp b/intern/audaspace/intern/AUD_DefaultMixer.cpp index 20471d6e874..24fea6527ba 100644 --- a/intern/audaspace/intern/AUD_DefaultMixer.cpp +++ b/intern/audaspace/intern/AUD_DefaultMixer.cpp @@ -45,7 +45,7 @@ AUD_DefaultMixer::AUD_DefaultMixer(AUD_DeviceSpecs specs) : { } -AUD_IReader* AUD_DefaultMixer::prepare(AUD_IReader* reader) +AUD_Reference<AUD_IReader> AUD_DefaultMixer::prepare(AUD_Reference<AUD_IReader> reader) { // hacky for now, until a better channel mapper reader is available AUD_ChannelMapperFactory cmf(NULL, m_specs); diff --git a/intern/audaspace/intern/AUD_DefaultMixer.h b/intern/audaspace/intern/AUD_DefaultMixer.h index a347141b5e0..2600a6fc05d 100644 --- a/intern/audaspace/intern/AUD_DefaultMixer.h +++ b/intern/audaspace/intern/AUD_DefaultMixer.h @@ -53,7 +53,7 @@ public: * \param reader The reader to prepare. * \return The reader that should be used for playback. */ - virtual AUD_IReader* prepare(AUD_IReader* reader); + virtual AUD_Reference<AUD_IReader> prepare(AUD_Reference<AUD_IReader> reader); }; #endif //AUD_DEFAULTMIXER diff --git a/intern/audaspace/intern/AUD_FileFactory.cpp b/intern/audaspace/intern/AUD_FileFactory.cpp index 1c8bb03bc92..2f02d4a55e1 100644 --- a/intern/audaspace/intern/AUD_FileFactory.cpp +++ b/intern/audaspace/intern/AUD_FileFactory.cpp @@ -54,20 +54,20 @@ AUD_FileFactory::AUD_FileFactory(std::string filename) : AUD_FileFactory::AUD_FileFactory(const data_t* buffer, int size) : m_buffer(new AUD_Buffer(size)) { - memcpy(m_buffer.get()->getBuffer(), buffer, size); + memcpy(m_buffer->getBuffer(), buffer, size); } static const char* read_error = "AUD_FileFactory: File couldn't be read."; -AUD_IReader* AUD_FileFactory::createReader() const +AUD_Reference<AUD_IReader> AUD_FileFactory::createReader() const { #ifdef WITH_SNDFILE try { - if(m_buffer.get()) - return new AUD_SndFileReader(m_buffer); - else + if(m_buffer.isNull()) return new AUD_SndFileReader(m_filename); + else + return new AUD_SndFileReader(m_buffer); } catch(AUD_Exception&) {} #endif @@ -75,10 +75,10 @@ AUD_IReader* AUD_FileFactory::createReader() const #ifdef WITH_FFMPEG try { - if(m_buffer.get()) - return new AUD_FFMPEGReader(m_buffer); - else + if(m_buffer.isNull()) return new AUD_FFMPEGReader(m_filename); + else + return new AUD_FFMPEGReader(m_buffer); } catch(AUD_Exception&) {} #endif diff --git a/intern/audaspace/intern/AUD_FileFactory.h b/intern/audaspace/intern/AUD_FileFactory.h index a2ab94ae148..c63e50b3b0d 100644 --- a/intern/audaspace/intern/AUD_FileFactory.h +++ b/intern/audaspace/intern/AUD_FileFactory.h @@ -72,7 +72,7 @@ public: */ AUD_FileFactory(const data_t* buffer, int size); - virtual AUD_IReader* createReader() const; + virtual AUD_Reference<AUD_IReader> createReader() const; }; #endif //AUD_FILEFACTORY diff --git a/intern/audaspace/intern/AUD_IDevice.h b/intern/audaspace/intern/AUD_IDevice.h index 4856b913b38..88c9aa5e8d9 100644 --- a/intern/audaspace/intern/AUD_IDevice.h +++ b/intern/audaspace/intern/AUD_IDevice.h @@ -33,6 +33,7 @@ #define AUD_IDEVICE #include "AUD_Space.h" +#include "AUD_Reference.h" class AUD_IFactory; class AUD_IReader; @@ -74,7 +75,7 @@ public: * \exception AUD_Exception Thrown if there's an unexpected (from the * device side) error during creation of the reader. */ - virtual AUD_Handle* play(AUD_IReader* reader, bool keep = false)=0; + virtual AUD_Handle* play(AUD_Reference<AUD_IReader> reader, bool keep = false)=0; /** * Plays a sound source. @@ -86,7 +87,7 @@ public: * \exception AUD_Exception Thrown if there's an unexpected (from the * device side) error during creation of the reader. */ - virtual AUD_Handle* play(AUD_IFactory* factory, bool keep = false)=0; + virtual AUD_Handle* play(AUD_Reference<AUD_IFactory> factory, bool keep = false)=0; /** * Pauses a played back sound. diff --git a/intern/audaspace/intern/AUD_IFactory.h b/intern/audaspace/intern/AUD_IFactory.h index 40a61279a55..48f2802f871 100644 --- a/intern/audaspace/intern/AUD_IFactory.h +++ b/intern/audaspace/intern/AUD_IFactory.h @@ -33,6 +33,7 @@ #define AUD_IFACTORY #include "AUD_Space.h" +#include "AUD_Reference.h" class AUD_IReader; /** @@ -55,7 +56,7 @@ public: * \exception AUD_Exception An exception may be thrown if there has been * a more unexpected error during reader creation. */ - virtual AUD_IReader* createReader() const=0; + virtual AUD_Reference<AUD_IReader> createReader() const=0; }; #endif //AUD_IFACTORY diff --git a/intern/audaspace/intern/AUD_LinearResampleFactory.cpp b/intern/audaspace/intern/AUD_LinearResampleFactory.cpp index a90dc5cb860..f7ac9e1e83e 100644 --- a/intern/audaspace/intern/AUD_LinearResampleFactory.cpp +++ b/intern/audaspace/intern/AUD_LinearResampleFactory.cpp @@ -32,15 +32,15 @@ #include "AUD_LinearResampleFactory.h" #include "AUD_LinearResampleReader.h" -AUD_LinearResampleFactory::AUD_LinearResampleFactory(AUD_IFactory* factory, +AUD_LinearResampleFactory::AUD_LinearResampleFactory(AUD_Reference<AUD_IFactory> factory, AUD_DeviceSpecs specs) : AUD_ResampleFactory(factory, specs) { } -AUD_IReader* AUD_LinearResampleFactory::createReader() const +AUD_Reference<AUD_IReader> AUD_LinearResampleFactory::createReader() const { - AUD_IReader* reader = getReader(); + AUD_Reference<AUD_IReader> reader = getReader(); if(reader->getSpecs().rate != m_specs.rate) reader = new AUD_LinearResampleReader(reader, m_specs.specs); diff --git a/intern/audaspace/intern/AUD_LinearResampleFactory.h b/intern/audaspace/intern/AUD_LinearResampleFactory.h index 678aa0b80cb..6a593b11f28 100644 --- a/intern/audaspace/intern/AUD_LinearResampleFactory.h +++ b/intern/audaspace/intern/AUD_LinearResampleFactory.h @@ -45,9 +45,9 @@ private: AUD_LinearResampleFactory& operator=(const AUD_LinearResampleFactory&); public: - AUD_LinearResampleFactory(AUD_IFactory* factory, AUD_DeviceSpecs specs); + AUD_LinearResampleFactory(AUD_Reference<AUD_IFactory> factory, AUD_DeviceSpecs specs); - virtual AUD_IReader* createReader() const; + virtual AUD_Reference<AUD_IReader> createReader() const; }; #endif //AUD_LINEARRESAMPLEFACTORY diff --git a/intern/audaspace/intern/AUD_LinearResampleReader.cpp b/intern/audaspace/intern/AUD_LinearResampleReader.cpp index 05fb39b2cca..6217826eeec 100644 --- a/intern/audaspace/intern/AUD_LinearResampleReader.cpp +++ b/intern/audaspace/intern/AUD_LinearResampleReader.cpp @@ -36,7 +36,7 @@ #define CC channels + channel -AUD_LinearResampleReader::AUD_LinearResampleReader(AUD_IReader* reader, +AUD_LinearResampleReader::AUD_LinearResampleReader(AUD_Reference<AUD_IReader> reader, AUD_Specs specs) : AUD_EffectReader(reader), m_sspecs(reader->getSpecs()), diff --git a/intern/audaspace/intern/AUD_LinearResampleReader.h b/intern/audaspace/intern/AUD_LinearResampleReader.h index 419c96be2fa..fdf7858f97f 100644 --- a/intern/audaspace/intern/AUD_LinearResampleReader.h +++ b/intern/audaspace/intern/AUD_LinearResampleReader.h @@ -86,7 +86,7 @@ public: * \param reader The reader to mix. * \param specs The target specification. */ - AUD_LinearResampleReader(AUD_IReader* reader, AUD_Specs specs); + AUD_LinearResampleReader(AUD_Reference<AUD_IReader> reader, AUD_Specs specs); virtual void seek(int position); virtual int getLength() const; diff --git a/intern/audaspace/intern/AUD_Mixer.h b/intern/audaspace/intern/AUD_Mixer.h index 277d5bfe2bd..d8c4dde2685 100644 --- a/intern/audaspace/intern/AUD_Mixer.h +++ b/intern/audaspace/intern/AUD_Mixer.h @@ -34,6 +34,7 @@ #include "AUD_ConverterFunctions.h" #include "AUD_Buffer.h" +#include "AUD_Reference.h" class AUD_IReader; #include <list> @@ -94,7 +95,7 @@ public: * \param reader The reader to prepare. * \return The reader that should be used for playback. */ - virtual AUD_IReader* prepare(AUD_IReader* reader)=0; + virtual AUD_Reference<AUD_IReader> prepare(AUD_Reference<AUD_IReader> reader)=0; /** * Adds a buffer for superposition. diff --git a/intern/audaspace/intern/AUD_MixerFactory.cpp b/intern/audaspace/intern/AUD_MixerFactory.cpp index e65b149b94c..c3bf6b4fa99 100644 --- a/intern/audaspace/intern/AUD_MixerFactory.cpp +++ b/intern/audaspace/intern/AUD_MixerFactory.cpp @@ -32,12 +32,12 @@ #include "AUD_MixerFactory.h" #include "AUD_IReader.h" -AUD_IReader* AUD_MixerFactory::getReader() const +AUD_Reference<AUD_IReader> AUD_MixerFactory::getReader() const { return m_factory->createReader(); } -AUD_MixerFactory::AUD_MixerFactory(AUD_IFactory* factory, +AUD_MixerFactory::AUD_MixerFactory(AUD_Reference<AUD_IFactory> factory, AUD_DeviceSpecs specs) : m_specs(specs), m_factory(factory) { @@ -48,7 +48,7 @@ AUD_DeviceSpecs AUD_MixerFactory::getSpecs() const return m_specs; } -AUD_IFactory* AUD_MixerFactory::getFactory() const +AUD_Reference<AUD_IFactory> AUD_MixerFactory::getFactory() const { return m_factory; } diff --git a/intern/audaspace/intern/AUD_MixerFactory.h b/intern/audaspace/intern/AUD_MixerFactory.h index 2adabbd13ca..27c703b1898 100644 --- a/intern/audaspace/intern/AUD_MixerFactory.h +++ b/intern/audaspace/intern/AUD_MixerFactory.h @@ -48,7 +48,7 @@ protected: /** * If there is no reader it is created out of this factory. */ - AUD_IFactory* m_factory; + AUD_Reference<AUD_IFactory> m_factory; /** * Returns the reader created out of the factory. @@ -56,7 +56,7 @@ protected: * classes. * \return The reader to mix. */ - AUD_IReader* getReader() const; + AUD_Reference<AUD_IReader> getReader() const; public: /** @@ -64,7 +64,7 @@ public: * \param factory The factory to create the readers to mix out of. * \param specs The target specification. */ - AUD_MixerFactory(AUD_IFactory* factory, AUD_DeviceSpecs specs); + AUD_MixerFactory(AUD_Reference<AUD_IFactory> factory, AUD_DeviceSpecs specs); /** * Returns the target specification for resampling. @@ -75,7 +75,7 @@ public: * Returns the saved factory. * \return The factory. */ - AUD_IFactory* getFactory() const; + AUD_Reference<AUD_IFactory> getFactory() const; }; #endif //AUD_MIXERFACTORY diff --git a/intern/audaspace/intern/AUD_NULLDevice.cpp b/intern/audaspace/intern/AUD_NULLDevice.cpp index ab824799d88..09fc4835978 100644 --- a/intern/audaspace/intern/AUD_NULLDevice.cpp +++ b/intern/audaspace/intern/AUD_NULLDevice.cpp @@ -48,12 +48,12 @@ AUD_DeviceSpecs AUD_NULLDevice::getSpecs() const return specs; } -AUD_Handle* AUD_NULLDevice::play(AUD_IReader* reader, bool keep) +AUD_Handle* AUD_NULLDevice::play(AUD_Reference<AUD_IReader> reader, bool keep) { return 0; } -AUD_Handle* AUD_NULLDevice::play(AUD_IFactory* factory, bool keep) +AUD_Handle* AUD_NULLDevice::play(AUD_Reference<AUD_IFactory> factory, bool keep) { return 0; } diff --git a/intern/audaspace/intern/AUD_NULLDevice.h b/intern/audaspace/intern/AUD_NULLDevice.h index f700bea477b..6a10267bbe0 100644 --- a/intern/audaspace/intern/AUD_NULLDevice.h +++ b/intern/audaspace/intern/AUD_NULLDevice.h @@ -32,6 +32,7 @@ #ifndef AUD_NULLDEVICE #define AUD_NULLDEVICE +#include "AUD_IReader.h" #include "AUD_IDevice.h" /** @@ -46,8 +47,8 @@ public: AUD_NULLDevice(); virtual AUD_DeviceSpecs getSpecs() const; - virtual AUD_Handle* play(AUD_IReader* reader, bool keep = false); - virtual AUD_Handle* play(AUD_IFactory* factory, bool keep = false); + virtual AUD_Handle* play(AUD_Reference<AUD_IReader> reader, bool keep = false); + virtual AUD_Handle* play(AUD_Reference<AUD_IFactory> factory, bool keep = false); virtual bool pause(AUD_Handle* handle); virtual bool resume(AUD_Handle* handle); virtual bool stop(AUD_Handle* handle); diff --git a/intern/audaspace/intern/AUD_Reference.h b/intern/audaspace/intern/AUD_Reference.h index 3232ca3b609..22abb29bdbb 100644 --- a/intern/audaspace/intern/AUD_Reference.h +++ b/intern/audaspace/intern/AUD_Reference.h @@ -75,10 +75,7 @@ public: (*m_refcount)--; if(*m_refcount == 0) { - if(m_reference) - { - delete m_reference; - } + delete m_reference; delete m_refcount; } } @@ -95,10 +92,7 @@ public: (*m_refcount)--; if(*m_refcount == 0) { - if(m_reference) - { - delete m_reference; - } + delete m_reference; delete m_refcount; } @@ -110,12 +104,70 @@ public: } /** + * Returns whether the reference is NULL. + */ + bool isNull() const + { + return m_reference == 0; + } + + /** * Returns the reference. */ T* get() const { return m_reference; } + + /** + * Returns the reference. + */ + T& operator*() const + { + return *m_reference; + } + + /** + * Returns the reference. + */ + T* operator->() const + { + return m_reference; + } + + template <class U> + explicit AUD_Reference(U* reference, int* refcount) + { + m_reference = dynamic_cast<T*>(reference); + if(m_reference) + { + m_refcount = refcount; + (*m_refcount)++; + } + else + { + m_refcount = new int; + *m_refcount = 1; + } + } + + template <class U> + AUD_Reference<U> convert() + { + return AUD_Reference<U>(m_reference, m_refcount); + } }; +template<class T, class U> +bool operator==(const AUD_Reference<T>& a, const AUD_Reference<U>& b) +{ + return a.get() == b.get(); +} + +template<class T, class U> +bool operator!=(const AUD_Reference<T>& a, const AUD_Reference<U>& b) +{ + return a.get() == b.get(); +} + #endif // AUD_REFERENCE diff --git a/intern/audaspace/intern/AUD_SequencerFactory.cpp b/intern/audaspace/intern/AUD_SequencerFactory.cpp index f49dd94fe11..ee0af900b04 100644 --- a/intern/audaspace/intern/AUD_SequencerFactory.cpp +++ b/intern/audaspace/intern/AUD_SequencerFactory.cpp @@ -32,7 +32,7 @@ #include "AUD_SequencerFactory.h" #include "AUD_SequencerReader.h" -typedef std::list<AUD_SequencerReader*>::iterator AUD_ReaderIterator; +typedef std::list<AUD_Reference<AUD_SequencerReader> >::iterator AUD_ReaderIterator; AUD_SequencerFactory::AUD_SequencerFactory(AUD_Specs specs, bool muted, void* data, @@ -46,22 +46,11 @@ AUD_SequencerFactory::AUD_SequencerFactory(AUD_Specs specs, bool muted, AUD_SequencerFactory::~AUD_SequencerFactory() { - AUD_SequencerReader* reader; - AUD_SequencerEntry* entry; - - while(!m_readers.empty()) - { - reader = m_readers.front(); - m_readers.pop_front(); - reader->destroy(); - } - - while(!m_entries.empty()) - { - entry = m_entries.front(); - m_entries.pop_front(); - delete entry; - } +} + +void AUD_SequencerFactory::setThis(AUD_Reference<AUD_SequencerFactory>* self) +{ + m_this = self; } void AUD_SequencerFactory::mute(bool muted) @@ -74,19 +63,19 @@ bool AUD_SequencerFactory::getMute() const return m_muted; } -AUD_IReader* AUD_SequencerFactory::newReader() +AUD_Reference<AUD_IReader> AUD_SequencerFactory::newReader() { - AUD_SequencerReader* reader = new AUD_SequencerReader(this, m_entries, + AUD_Reference<AUD_SequencerReader> reader = new AUD_SequencerReader(*m_this, m_entries, m_specs, m_data, m_volume); m_readers.push_front(reader); - return reader; + return reader.convert<AUD_IReader>(); } -AUD_SequencerEntry* AUD_SequencerFactory::add(AUD_IFactory** sound, float begin, float end, float skip, void* data) +AUD_Reference<AUD_SequencerEntry> AUD_SequencerFactory::add(AUD_Reference<AUD_IFactory>** sound, float begin, float end, float skip, void* data) { - AUD_SequencerEntry* entry = new AUD_SequencerEntry; + AUD_Reference<AUD_SequencerEntry> entry = new AUD_SequencerEntry; entry->sound = sound; entry->begin = begin; entry->skip = skip; @@ -102,34 +91,32 @@ AUD_SequencerEntry* AUD_SequencerFactory::add(AUD_IFactory** sound, float begin, return entry; } -void AUD_SequencerFactory::remove(AUD_SequencerEntry* entry) +void AUD_SequencerFactory::remove(AUD_Reference<AUD_SequencerEntry> entry) { for(AUD_ReaderIterator i = m_readers.begin(); i != m_readers.end(); i++) (*i)->remove(entry); m_entries.remove(entry); - - delete entry; } -void AUD_SequencerFactory::move(AUD_SequencerEntry* entry, float begin, float end, float skip) +void AUD_SequencerFactory::move(AUD_Reference<AUD_SequencerEntry> entry, float begin, float end, float skip) { entry->begin = begin; entry->skip = skip; entry->end = end; } -void AUD_SequencerFactory::mute(AUD_SequencerEntry* entry, bool mute) +void AUD_SequencerFactory::mute(AUD_Reference<AUD_SequencerEntry> entry, bool mute) { entry->muted = mute; } -AUD_IReader* AUD_SequencerFactory::createReader() const +AUD_Reference<AUD_IReader> AUD_SequencerFactory::createReader() const { return const_cast<AUD_SequencerFactory*>(this)->newReader(); } -void AUD_SequencerFactory::removeReader(AUD_SequencerReader* reader) +void AUD_SequencerFactory::removeReader(AUD_Reference<AUD_SequencerReader> reader) { m_readers.remove(reader); } diff --git a/intern/audaspace/intern/AUD_SequencerFactory.h b/intern/audaspace/intern/AUD_SequencerFactory.h index 8f3466f75ce..b0393297622 100644 --- a/intern/audaspace/intern/AUD_SequencerFactory.h +++ b/intern/audaspace/intern/AUD_SequencerFactory.h @@ -40,7 +40,7 @@ typedef float (*AUD_volumeFunction)(void*, void*, float); struct AUD_SequencerEntry { - AUD_IFactory** sound; + AUD_Reference<AUD_IFactory>** sound; float begin; float end; float skip; @@ -61,13 +61,14 @@ private: */ AUD_Specs m_specs; - std::list<AUD_SequencerEntry*> m_entries; - std::list<AUD_SequencerReader*> m_readers; + std::list<AUD_Reference<AUD_SequencerEntry> > m_entries; + std::list<AUD_Reference<AUD_SequencerReader> > m_readers; bool m_muted; void* m_data; AUD_volumeFunction m_volume; + AUD_Reference<AUD_SequencerFactory>* m_this; - AUD_IReader* newReader(); + AUD_Reference<AUD_IReader> newReader(); // hide copy constructor and operator= AUD_SequencerFactory(const AUD_SequencerFactory&); @@ -77,16 +78,18 @@ public: AUD_SequencerFactory(AUD_Specs specs, bool muted, void* data, AUD_volumeFunction volume); ~AUD_SequencerFactory(); + void setThis(AUD_Reference<AUD_SequencerFactory>* self); + void mute(bool muted); bool getMute() const; - AUD_SequencerEntry* add(AUD_IFactory** sound, float begin, float end, float skip, void* data); - void remove(AUD_SequencerEntry* entry); - void move(AUD_SequencerEntry* entry, float begin, float end, float skip); - void mute(AUD_SequencerEntry* entry, bool mute); + AUD_Reference<AUD_SequencerEntry> add(AUD_Reference<AUD_IFactory>** sound, float begin, float end, float skip, void* data); + void remove(AUD_Reference<AUD_SequencerEntry> entry); + void move(AUD_Reference<AUD_SequencerEntry> entry, float begin, float end, float skip); + void mute(AUD_Reference<AUD_SequencerEntry> entry, bool mute); - virtual AUD_IReader* createReader() const; + virtual AUD_Reference<AUD_IReader> createReader() const; - void removeReader(AUD_SequencerReader* reader); + void removeReader(AUD_Reference<AUD_SequencerReader> reader); }; #endif //AUD_SEQUENCERFACTORY diff --git a/intern/audaspace/intern/AUD_SequencerReader.cpp b/intern/audaspace/intern/AUD_SequencerReader.cpp index 95e0dca6323..b7cbdda544e 100644 --- a/intern/audaspace/intern/AUD_SequencerReader.cpp +++ b/intern/audaspace/intern/AUD_SequencerReader.cpp @@ -34,23 +34,21 @@ #include <math.h> -typedef std::list<AUD_SequencerStrip*>::iterator AUD_StripIterator; -typedef std::list<AUD_SequencerEntry*>::iterator AUD_EntryIterator; +typedef std::list<AUD_Reference<AUD_SequencerStrip> >::iterator AUD_StripIterator; +typedef std::list<AUD_Reference<AUD_SequencerEntry> >::iterator AUD_EntryIterator; -AUD_SequencerReader::AUD_SequencerReader(AUD_SequencerFactory* factory, - std::list<AUD_SequencerEntry*> &entries, AUD_Specs specs, - void* data, AUD_volumeFunction volume) +AUD_SequencerReader::AUD_SequencerReader(AUD_Reference<AUD_SequencerFactory> factory, + std::list<AUD_Reference<AUD_SequencerEntry> > &entries, AUD_Specs specs, + void* data, AUD_volumeFunction volume) : + m_position(0), m_factory(factory), m_data(data), m_volume(volume) { AUD_DeviceSpecs dspecs; dspecs.specs = specs; dspecs.format = AUD_FORMAT_FLOAT32; m_mixer = new AUD_DefaultMixer(dspecs); - m_factory = factory; - m_data = data; - m_volume = volume; - AUD_SequencerStrip* strip; + AUD_Reference<AUD_SequencerStrip> strip; for(AUD_EntryIterator i = entries.begin(); i != entries.end(); i++) { @@ -58,84 +56,33 @@ AUD_SequencerReader::AUD_SequencerReader(AUD_SequencerFactory* factory, strip->entry = *i; strip->old_sound = NULL; - if(strip->old_sound) - strip->reader = m_mixer->prepare(strip->old_sound->createReader()); - else - strip->reader = NULL; - m_strips.push_front(strip); } - - m_position = 0; } AUD_SequencerReader::~AUD_SequencerReader() { - if(m_factory != NULL) - m_factory->removeReader(this); - - AUD_SequencerStrip* strip; - - while(!m_strips.empty()) - { - strip = m_strips.front(); - m_strips.pop_front(); - if(strip->reader) - { - delete strip->reader; - } - delete strip; - } - - delete m_mixer; -} - -void AUD_SequencerReader::destroy() -{ - m_factory = NULL; - AUD_SequencerStrip* strip; - - while(!m_strips.empty()) - { - strip = m_strips.front(); - m_strips.pop_front(); - delete strip; - } + m_factory->removeReader(this); } -void AUD_SequencerReader::add(AUD_SequencerEntry* entry) +void AUD_SequencerReader::add(AUD_Reference<AUD_SequencerEntry> entry) { - AUD_SequencerStrip* strip = new AUD_SequencerStrip; + AUD_Reference<AUD_SequencerStrip> strip = new AUD_SequencerStrip; strip->entry = entry; - if(*strip->entry->sound) - { - strip->old_sound = *strip->entry->sound; - strip->reader = m_mixer->prepare(strip->old_sound->createReader()); - } - else - { - strip->reader = NULL; - strip->old_sound = NULL; - } m_strips.push_front(strip); } -void AUD_SequencerReader::remove(AUD_SequencerEntry* entry) +void AUD_SequencerReader::remove(AUD_Reference<AUD_SequencerEntry> entry) { - AUD_SequencerStrip* strip; + AUD_Reference<AUD_SequencerStrip> strip; for(AUD_StripIterator i = m_strips.begin(); i != m_strips.end(); i++) { strip = *i; if(strip->entry == entry) { i++; - if(strip->reader) - { - delete strip->reader; - } m_strips.remove(strip); - delete strip; return; } } @@ -175,7 +122,7 @@ void AUD_SequencerReader::read(int & length, sample_t* & buffer) int size = length * samplesize; int start, end, current, skip, len; - AUD_SequencerStrip* strip; + AUD_Reference<AUD_SequencerStrip> strip; sample_t* buf; if(m_buffer.getSize() < size) @@ -192,14 +139,12 @@ void AUD_SequencerReader::read(int & length, sample_t* & buffer) if(strip->old_sound != *strip->entry->sound) { strip->old_sound = *strip->entry->sound; - if(strip->reader) - delete strip->reader; if(strip->old_sound) { try { - strip->reader = m_mixer->prepare(strip->old_sound->createReader()); + strip->reader = m_mixer->prepare((*strip->old_sound)->createReader()); } catch(AUD_Exception) { @@ -210,7 +155,7 @@ void AUD_SequencerReader::read(int & length, sample_t* & buffer) strip->reader = NULL; } - if(strip->reader) + if(!strip->reader.isNull()) { end = floor(strip->entry->end * rate); if(m_position < end) diff --git a/intern/audaspace/intern/AUD_SequencerReader.h b/intern/audaspace/intern/AUD_SequencerReader.h index 53baf521acc..2efb94aa1fb 100644 --- a/intern/audaspace/intern/AUD_SequencerReader.h +++ b/intern/audaspace/intern/AUD_SequencerReader.h @@ -39,9 +39,9 @@ class AUD_Mixer; struct AUD_SequencerStrip { - AUD_IFactory* old_sound; - AUD_IReader* reader; - AUD_SequencerEntry* entry; + AUD_Reference<AUD_IReader> reader; + AUD_Reference<AUD_SequencerEntry> entry; + AUD_Reference<AUD_IFactory>* old_sound; }; /** @@ -63,14 +63,14 @@ private: /** * The target specification. */ - AUD_Mixer* m_mixer; + AUD_Reference<AUD_Mixer> m_mixer; /** * Saves the SequencerFactory the reader belongs to. */ - AUD_SequencerFactory* m_factory; + AUD_Reference<AUD_SequencerFactory> m_factory; - std::list<AUD_SequencerStrip*> m_strips; + std::list<AUD_Reference<AUD_SequencerStrip> > m_strips; void* m_data; AUD_volumeFunction m_volume; @@ -85,17 +85,15 @@ public: * \param reader The reader to mix. * \param specs The target specification. */ - AUD_SequencerReader(AUD_SequencerFactory* factory, std::list<AUD_SequencerEntry*> &entries, const AUD_Specs specs, void* data, AUD_volumeFunction volume); + AUD_SequencerReader(AUD_Reference<AUD_SequencerFactory> factory, std::list<AUD_Reference<AUD_SequencerEntry> > &entries, const AUD_Specs specs, void* data, AUD_volumeFunction volume); /** * Destroys the reader. */ ~AUD_SequencerReader(); - void destroy(); - - void add(AUD_SequencerEntry* entry); - void remove(AUD_SequencerEntry* entry); + void add(AUD_Reference<AUD_SequencerEntry> entry); + void remove(AUD_Reference<AUD_SequencerEntry> entry); virtual bool isSeekable() const; virtual void seek(int position); diff --git a/intern/audaspace/intern/AUD_SilenceFactory.cpp b/intern/audaspace/intern/AUD_SilenceFactory.cpp index dc3f0626591..f1eae1889a2 100644 --- a/intern/audaspace/intern/AUD_SilenceFactory.cpp +++ b/intern/audaspace/intern/AUD_SilenceFactory.cpp @@ -37,7 +37,7 @@ AUD_SilenceFactory::AUD_SilenceFactory() { } -AUD_IReader* AUD_SilenceFactory::createReader() const +AUD_Reference<AUD_IReader> AUD_SilenceFactory::createReader() const { return new AUD_SilenceReader(); } diff --git a/intern/audaspace/intern/AUD_SilenceFactory.h b/intern/audaspace/intern/AUD_SilenceFactory.h index fb6afc34189..0920c1267ab 100644 --- a/intern/audaspace/intern/AUD_SilenceFactory.h +++ b/intern/audaspace/intern/AUD_SilenceFactory.h @@ -50,7 +50,7 @@ public: */ AUD_SilenceFactory(); - virtual AUD_IReader* createReader() const; + virtual AUD_Reference<AUD_IReader> createReader() const; }; #endif //AUD_SILENCEFACTORY diff --git a/intern/audaspace/intern/AUD_SinusFactory.cpp b/intern/audaspace/intern/AUD_SinusFactory.cpp index 9ea7a031b16..8276856b9e2 100644 --- a/intern/audaspace/intern/AUD_SinusFactory.cpp +++ b/intern/audaspace/intern/AUD_SinusFactory.cpp @@ -44,7 +44,7 @@ float AUD_SinusFactory::getFrequency() const return m_frequency; } -AUD_IReader* AUD_SinusFactory::createReader() const +AUD_Reference<AUD_IReader> AUD_SinusFactory::createReader() const { return new AUD_SinusReader(m_frequency, m_sampleRate); } diff --git a/intern/audaspace/intern/AUD_SinusFactory.h b/intern/audaspace/intern/AUD_SinusFactory.h index 6d8b355784b..a440d7b7535 100644 --- a/intern/audaspace/intern/AUD_SinusFactory.h +++ b/intern/audaspace/intern/AUD_SinusFactory.h @@ -68,7 +68,7 @@ public: */ float getFrequency() const; - virtual AUD_IReader* createReader() const; + virtual AUD_Reference<AUD_IReader> createReader() const; }; #endif //AUD_SINUSFACTORY diff --git a/intern/audaspace/intern/AUD_SoftwareDevice.cpp b/intern/audaspace/intern/AUD_SoftwareDevice.cpp index b44b2f02d29..82bb5841580 100644 --- a/intern/audaspace/intern/AUD_SoftwareDevice.cpp +++ b/intern/audaspace/intern/AUD_SoftwareDevice.cpp @@ -41,7 +41,7 @@ struct AUD_SoftwareHandle : AUD_Handle { /// The reader source. - AUD_IReader* reader; + AUD_Reference<AUD_IReader> reader; /// Whether to keep the source if end of it is reached. bool keep; @@ -81,8 +81,6 @@ void AUD_SoftwareDevice::destroy() if(m_playback) playing(m_playback = false); - delete m_mixer; - AUD_SoftwareHandle* handle; // delete all playing sounds @@ -90,7 +88,6 @@ void AUD_SoftwareDevice::destroy() { handle = m_playingSounds.front(); m_playingSounds.pop_front(); - delete handle->reader; delete handle; } @@ -99,7 +96,6 @@ void AUD_SoftwareDevice::destroy() { handle = m_pausedSounds.front(); m_pausedSounds.pop_front(); - delete handle->reader; delete handle; } @@ -213,11 +209,11 @@ AUD_DeviceSpecs AUD_SoftwareDevice::getSpecs() const return m_specs; } -AUD_Handle* AUD_SoftwareDevice::play(AUD_IReader* reader, bool keep) +AUD_Handle* AUD_SoftwareDevice::play(AUD_Reference<AUD_IReader> reader, bool keep) { // prepare the reader reader = m_mixer->prepare(reader); - if(reader == NULL) + if(reader.isNull()) return NULL; // play sound @@ -239,7 +235,7 @@ AUD_Handle* AUD_SoftwareDevice::play(AUD_IReader* reader, bool keep) return sound; } -AUD_Handle* AUD_SoftwareDevice::play(AUD_IFactory* factory, bool keep) +AUD_Handle* AUD_SoftwareDevice::play(AUD_Reference<AUD_IFactory> factory, bool keep) { return play(factory->createReader(), keep); } @@ -307,7 +303,6 @@ bool AUD_SoftwareDevice::stop(AUD_Handle* handle) { if(*i == handle) { - delete (*i)->reader; delete *i; m_playingSounds.erase(i); if(m_playingSounds.empty()) @@ -323,7 +318,6 @@ bool AUD_SoftwareDevice::stop(AUD_Handle* handle) { if(*i == handle) { - delete (*i)->reader; delete *i; m_pausedSounds.erase(i); result = true; @@ -376,7 +370,7 @@ bool AUD_SoftwareDevice::seek(AUD_Handle* handle, float position) if(isValid(handle)) { - AUD_IReader* reader = ((AUD_SoftwareHandle*)handle)->reader; + AUD_Reference<AUD_IReader> reader = ((AUD_SoftwareHandle*)handle)->reader; reader->seek((int)(position * reader->getSpecs().rate)); result = true; } diff --git a/intern/audaspace/intern/AUD_SoftwareDevice.h b/intern/audaspace/intern/AUD_SoftwareDevice.h index 1f6a5ead6e0..6cbc6e3ddc6 100644 --- a/intern/audaspace/intern/AUD_SoftwareDevice.h +++ b/intern/audaspace/intern/AUD_SoftwareDevice.h @@ -33,8 +33,8 @@ #define AUD_SOFTWAREDEVICE #include "AUD_IDevice.h" +#include "AUD_Mixer.h" struct AUD_SoftwareHandle; -class AUD_Mixer; class AUD_Buffer; #include <list> @@ -59,7 +59,7 @@ protected: /** * The mixer. */ - AUD_Mixer* m_mixer; + AUD_Reference<AUD_Mixer> m_mixer; /** * Initializes member variables. @@ -119,8 +119,8 @@ private: public: virtual AUD_DeviceSpecs getSpecs() const; - virtual AUD_Handle* play(AUD_IReader* reader, bool keep = false); - virtual AUD_Handle* play(AUD_IFactory* factory, bool keep = false); + virtual AUD_Handle* play(AUD_Reference<AUD_IReader> reader, bool keep = false); + virtual AUD_Handle* play(AUD_Reference<AUD_IFactory> factory, bool keep = false); virtual bool pause(AUD_Handle* handle); virtual bool resume(AUD_Handle* handle); virtual bool stop(AUD_Handle* handle); diff --git a/intern/audaspace/intern/AUD_StreamBufferFactory.cpp b/intern/audaspace/intern/AUD_StreamBufferFactory.cpp index c25442b6f26..5c4e024917b 100644 --- a/intern/audaspace/intern/AUD_StreamBufferFactory.cpp +++ b/intern/audaspace/intern/AUD_StreamBufferFactory.cpp @@ -35,10 +35,10 @@ #include <cstring> -AUD_StreamBufferFactory::AUD_StreamBufferFactory(AUD_IFactory* factory) : +AUD_StreamBufferFactory::AUD_StreamBufferFactory(AUD_Reference<AUD_IFactory> factory) : m_buffer(new AUD_Buffer()) { - AUD_IReader* reader = factory->createReader(); + AUD_Reference<AUD_IReader> reader = factory->createReader(); m_specs = reader->getSpecs(); @@ -56,26 +56,25 @@ AUD_StreamBufferFactory::AUD_StreamBufferFactory(AUD_IFactory* factory) : size += m_specs.rate; // as long as we fill our buffer to the end - while(index == m_buffer.get()->getSize() / sample_size) + while(index == m_buffer->getSize() / sample_size) { // increase - m_buffer.get()->resize(size*sample_size, true); + m_buffer->resize(size*sample_size, true); // read more length = size-index; reader->read(length, buffer); - memcpy(m_buffer.get()->getBuffer() + index * m_specs.channels, + memcpy(m_buffer->getBuffer() + index * m_specs.channels, buffer, length * sample_size); size += AUD_BUFFER_RESIZE_BYTES / sample_size; index += length; } - m_buffer.get()->resize(index * sample_size, true); - delete reader; + m_buffer->resize(index * sample_size, true); } -AUD_IReader* AUD_StreamBufferFactory::createReader() const +AUD_Reference<AUD_IReader> AUD_StreamBufferFactory::createReader() const { return new AUD_BufferReader(m_buffer, m_specs); } diff --git a/intern/audaspace/intern/AUD_StreamBufferFactory.h b/intern/audaspace/intern/AUD_StreamBufferFactory.h index b6a44d95744..fc5f103d99b 100644 --- a/intern/audaspace/intern/AUD_StreamBufferFactory.h +++ b/intern/audaspace/intern/AUD_StreamBufferFactory.h @@ -64,9 +64,9 @@ public: * \param factory The factory that creates the reader for buffering. * \exception AUD_Exception Thrown if the reader cannot be created. */ - AUD_StreamBufferFactory(AUD_IFactory* factory); + AUD_StreamBufferFactory(AUD_Reference<AUD_IFactory> factory); - virtual AUD_IReader* createReader() const; + virtual AUD_Reference<AUD_IReader> createReader() const; }; #endif //AUD_STREAMBUFFERFACTORY diff --git a/intern/audaspace/sndfile/AUD_SndFileFactory.cpp b/intern/audaspace/sndfile/AUD_SndFileFactory.cpp index 2d1d29e50f5..7ab3308f01b 100644 --- a/intern/audaspace/sndfile/AUD_SndFileFactory.cpp +++ b/intern/audaspace/sndfile/AUD_SndFileFactory.cpp @@ -43,13 +43,13 @@ AUD_SndFileFactory::AUD_SndFileFactory(std::string filename) : AUD_SndFileFactory::AUD_SndFileFactory(const data_t* buffer, int size) : m_buffer(new AUD_Buffer(size)) { - memcpy(m_buffer.get()->getBuffer(), buffer, size); + memcpy(m_buffer->getBuffer(), buffer, size); } -AUD_IReader* AUD_SndFileFactory::createReader() const +AUD_Reference<AUD_IReader> AUD_SndFileFactory::createReader() const { - if(m_buffer.get()) - return new AUD_SndFileReader(m_buffer); - else + if(m_buffer.isNull()) return new AUD_SndFileReader(m_filename); + else + return new AUD_SndFileReader(m_buffer); } diff --git a/intern/audaspace/sndfile/AUD_SndFileFactory.h b/intern/audaspace/sndfile/AUD_SndFileFactory.h index 9c747e1df01..3a1037e5587 100644 --- a/intern/audaspace/sndfile/AUD_SndFileFactory.h +++ b/intern/audaspace/sndfile/AUD_SndFileFactory.h @@ -72,7 +72,7 @@ public: */ AUD_SndFileFactory(const data_t* buffer, int size); - virtual AUD_IReader* createReader() const; + virtual AUD_Reference<AUD_IReader> createReader() const; }; #endif //AUD_SNDFILEFACTORY diff --git a/intern/audaspace/sndfile/AUD_SndFileReader.cpp b/intern/audaspace/sndfile/AUD_SndFileReader.cpp index f226d2eee4d..7b5fd7b0f45 100644 --- a/intern/audaspace/sndfile/AUD_SndFileReader.cpp +++ b/intern/audaspace/sndfile/AUD_SndFileReader.cpp @@ -36,7 +36,7 @@ sf_count_t AUD_SndFileReader::vio_get_filelen(void *user_data) { AUD_SndFileReader* reader = (AUD_SndFileReader*)user_data; - return reader->m_membuffer.get()->getSize(); + return reader->m_membuffer->getSize(); } sf_count_t AUD_SndFileReader::vio_seek(sf_count_t offset, int whence, @@ -53,7 +53,7 @@ sf_count_t AUD_SndFileReader::vio_seek(sf_count_t offset, int whence, reader->m_memoffset = reader->m_memoffset + offset; break; case SEEK_END: - reader->m_memoffset = reader->m_membuffer.get()->getSize() + offset; + reader->m_memoffset = reader->m_membuffer->getSize() + offset; break; } @@ -65,10 +65,10 @@ sf_count_t AUD_SndFileReader::vio_read(void *ptr, sf_count_t count, { 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; + if(reader->m_memoffset + count > reader->m_membuffer->getSize()) + count = reader->m_membuffer->getSize() - reader->m_memoffset; - memcpy(ptr, ((data_t*)reader->m_membuffer.get()->getBuffer()) + + memcpy(ptr, ((data_t*)reader->m_membuffer->getBuffer()) + reader->m_memoffset, count); reader->m_memoffset += count; diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py index 3c1b454e72e..c30c893c9cc 100644 --- a/release/scripts/modules/bpy_types.py +++ b/release/scripts/modules/bpy_types.py @@ -409,6 +409,16 @@ class Text(bpy_types.ID): TypeMap = {} +class Sound(bpy_types.ID): + __slots__ = () + + @property + def factory(self): + """The aud.Factory object of the sound.""" + import aud + return aud._sound_from_pointer(self.as_pointer()) + + class RNAMeta(type): def __new__(cls, name, bases, classdict, **args): result = type.__new__(cls, name, bases, classdict) diff --git a/release/scripts/modules/mocap_tools.py b/release/scripts/modules/mocap_tools.py new file mode 100644 index 00000000000..739dc40b272 --- /dev/null +++ b/release/scripts/modules/mocap_tools.py @@ -0,0 +1,451 @@ +from math import hypot, sqrt, isfinite +import bpy +import time +from mathutils import Vector + +#Vector utility functions +class NdVector: + vec = [] + + def __init__(self,vec): + self.vec = vec[:] + + def __len__(self): + return len(self.vec) + + def __mul__(self,otherMember): + if type(otherMember)==type(1) or type(otherMember)==type(1.0): + return NdVector([otherMember*x for x in self.vec]) + else: + a = self.vec + b = otherMember.vec + n = len(self) + return sum([a[i]*b[i] for i in range(n)]) + + def __sub__(self,otherVec): + a = self.vec + b = otherVec.vec + n = len(self) + return NdVector([a[i]-b[i] for i in range(n)]) + + def __add__(self,otherVec): + a = self.vec + b = otherVec.vec + n = len(self) + return NdVector([a[i]+b[i] for i in range(n)]) + + def vecLength(self): + return sqrt(self * self) + + def vecLengthSq(self): + return (self * self) + + def __getitem__(self,i): + return self.vec[i] + + length = property(vecLength) + lengthSq = property(vecLengthSq) + +class dataPoint: + index = 0 + co = Vector((0,0,0,0)) # x,y1,y2,y3 coordinate of original point + u = 0 #position according to parametric view of original data, [0,1] range + temp = 0 #use this for anything + + def __init__(self,index,co,u=0): + self.index = index + self.co = co + self.u = u + +def autoloop_anim(): + context = bpy.context + obj = context.active_object + fcurves = [x for x in obj.animation_data.action.fcurves if x.select] + + data = [] + end = len(fcurves[0].keyframe_points) + + for i in range(1,end): + vec = [] + for fcurve in fcurves: + vec.append(fcurve.evaluate(i)) + data.append(NdVector(vec)) + + def comp(a,b): + return a*b + + N = len(data) + Rxy = [0.0] * N + for i in range(N): + for j in range(i,min(i+N,N)): + Rxy[i]+=comp(data[j],data[j-i]) + for j in range(i): + Rxy[i]+=comp(data[j],data[j-i+N]) + Rxy[i]/=float(N) + + def bestLocalMaximum(Rxy): + Rxyd = [Rxy[i]-Rxy[i-1] for i in range(1,len(Rxy))] + maxs = [] + for i in range(1,len(Rxyd)-1): + a = Rxyd[i-1] + b = Rxyd[i] + print(a,b) + if (a>=0 and b<0) or (a<0 and b>=0): #sign change (zerocrossing) at point i, denoting max point (only) + maxs.append((i,max(Rxy[i],Rxy[i-1]))) + return max(maxs,key=lambda x: x[1])[0] + flm = bestLocalMaximum(Rxy[0:int(len(Rxy))]) + + diff = [] + + for i in range(len(data)-flm): + diff.append((data[i]-data[i+flm]).lengthSq) + + def lowerErrorSlice(diff,e): + bestSlice = (0,100000) #index, error at index + for i in range(e,len(diff)-e): + errorSlice = sum(diff[i-e:i+e+1]) + if errorSlice<bestSlice[1]: + bestSlice = (i,errorSlice) + return bestSlice[0] + + margin = 2 + + s = lowerErrorSlice(diff,margin) + + print(flm,s) + loop = data[s:s+flm+margin] + + #find *all* loops, s:s+flm, s+flm:s+2flm, etc... and interpolate between all + # to find "the perfect loop". Maybe before finding s? interp(i,i+flm,i+2flm).... + for i in range(1,margin+1): + w1 = sqrt(float(i)/margin) + loop[-i] = (loop[-i]*w1)+(loop[0]*(1-w1)) + + + for curve in fcurves: + pts = curve.keyframe_points + for i in range(len(pts)-1,-1,-1): + pts.remove(pts[i]) + + for c,curve in enumerate(fcurves): + pts = curve.keyframe_points + for i in range(len(loop)): + pts.insert(i+1,loop[i][c]) + + context.scene.frame_end = flm+1 + + + + + + +def simplifyCurves(curveGroup, error, reparaError, maxIterations, group_mode): + + def unitTangent(v,data_pts): + tang = Vector((0,0,0,0)) # + if v!=0: + #If it's not the first point, we can calculate a leftside tangent + tang+= data_pts[v].co-data_pts[v-1].co + if v!=len(data_pts)-1: + #If it's not the last point, we can calculate a rightside tangent + tang+= data_pts[v+1].co-data_pts[v].co + tang.normalize() + return tang + + #assign parametric u value for each point in original data + def chordLength(data_pts,s,e): + totalLength = 0 + for pt in data_pts[s:e+1]: + i = pt.index + if i==s: + chordLength = 0 + else: + chordLength = (data_pts[i].co-data_pts[i-1].co).length + totalLength+= chordLength + pt.temp = totalLength + for pt in data_pts[s:e+1]: + if totalLength==0: + print(s,e) + pt.u = (pt.temp/totalLength) + + # get binomial coefficient, this function/table is only called with args (3,0),(3,1),(3,2),(3,3),(2,0),(2,1),(2,2)! + binomDict = {(3,0): 1, (3,1): 3, (3,2): 3, (3,3): 1, (2,0): 1, (2,1): 2, (2,2): 1} + #value at pt t of a single bernstein Polynomial + + def bernsteinPoly(n,i,t): + binomCoeff = binomDict[(n,i)] + return binomCoeff * pow(t,i) * pow(1-t,n-i) + + # fit a single cubic to data points in range [s(tart),e(nd)]. + def fitSingleCubic(data_pts,s,e): + + # A - matrix used for calculating C matrices for fitting + def A(i,j,s,e,t1,t2): + if j==1: + t = t1 + if j==2: + t = t2 + u = data_pts[i].u + return t * bernsteinPoly(3,j,u) + + # X component, used for calculating X matrices for fitting + def xComponent(i,s,e): + di = data_pts[i].co + u = data_pts[i].u + v0 = data_pts[s].co + v3 = data_pts[e].co + a = v0*bernsteinPoly(3,0,u) + b = v0*bernsteinPoly(3,1,u) # + c = v3*bernsteinPoly(3,2,u) + d = v3*bernsteinPoly(3,3,u) + return (di -(a+b+c+d)) + + t1 = unitTangent(s,data_pts) + t2 = unitTangent(e,data_pts) + c11 = sum([A(i,1,s,e,t1,t2)*A(i,1,s,e,t1,t2) for i in range(s,e+1)]) + c12 = sum([A(i,1,s,e,t1,t2)*A(i,2,s,e,t1,t2) for i in range(s,e+1)]) + c21 = c12 + c22 = sum([A(i,2,s,e,t1,t2)*A(i,2,s,e,t1,t2) for i in range(s,e+1)]) + + x1 = sum([xComponent(i,s,e)*A(i,1,s,e,t1,t2) for i in range(s,e+1)]) + x2 = sum([xComponent(i,s,e)*A(i,2,s,e,t1,t2) for i in range(s,e+1)]) + + # calculate Determinate of the 3 matrices + det_cc = c11 * c22 - c21 * c12 + det_cx = c11 * x2 - c12 * x1 + det_xc = x1 * c22 - x2 * c12 + + # if matrix is not homogenous, fudge the data a bit + if det_cc == 0: + det_cc=0.01 + + # alpha's are the correct offset for bezier handles + alpha0 = det_xc / det_cc #offset from right (first) point + alpha1 = det_cx / det_cc #offset from left (last) point + + sRightHandle = data_pts[s].co.copy() + sTangent = t1*abs(alpha0) + sRightHandle+= sTangent #position of first pt's handle + eLeftHandle = data_pts[e].co.copy() + eTangent = t2*abs(alpha1) + eLeftHandle+= eTangent #position of last pt's handle. + + #return a 4 member tuple representing the bezier + return (data_pts[s].co, + sRightHandle, + eLeftHandle, + data_pts[e].co) + + # convert 2 given data points into a cubic bezier. + # handles are offset along the tangent at a 3rd of the length between the points. + def fitSingleCubic2Pts(data_pts,s,e): + alpha0 = alpha1 = (data_pts[s].co-data_pts[e].co).length / 3 + + sRightHandle = data_pts[s].co.copy() + sTangent = unitTangent(s,data_pts)*abs(alpha0) + sRightHandle+= sTangent #position of first pt's handle + eLeftHandle = data_pts[e].co.copy() + eTangent = unitTangent(e,data_pts)*abs(alpha1) + eLeftHandle+= eTangent #position of last pt's handle. + + #return a 4 member tuple representing the bezier + return (data_pts[s].co, + sRightHandle, + eLeftHandle, + data_pts[e].co) + + #evaluate bezier, represented by a 4 member tuple (pts) at point t. + def bezierEval(pts,t): + sumVec = Vector((0,0,0,0)) + for i in range(4): + sumVec+=pts[i]*bernsteinPoly(3,i,t) + return sumVec + + #calculate the highest error between bezier and original data + #returns the distance and the index of the point where max error occurs. + def maxErrorAmount(data_pts,bez,s,e): + maxError = 0 + maxErrorPt = s + if e-s<3: return 0, None + for pt in data_pts[s:e+1]: + bezVal = bezierEval(bez,pt.u) + tmpError = (pt.co-bezVal).length/pt.co.length + if tmpError >= maxError: + maxError = tmpError + maxErrorPt = pt.index + return maxError,maxErrorPt + + + #calculated bezier derivative at point t. + #That is, tangent of point t. + def getBezDerivative(bez,t): + n = len(bez)-1 + sumVec = Vector((0,0,0,0)) + for i in range(n-1): + sumVec+=bernsteinPoly(n-1,i,t)*(bez[i+1]-bez[i]) + return sumVec + + + #use Newton-Raphson to find a better paramterization of datapoints, + #one that minimizes the distance (or error) between bezier and original data. + def newtonRaphson(data_pts,s,e,bez): + for pt in data_pts[s:e+1]: + if pt.index==s: + pt.u=0 + elif pt.index==e: + pt.u=1 + else: + u = pt.u + qu = bezierEval(bez,pt.u) + qud = getBezDerivative(bez,u) + #we wish to minimize f(u), the squared distance between curve and data + fu = (qu-pt.co).length**2 + fud = (2*(qu.x-pt.co.x)*(qud.x))-(2*(qu.y-pt.co.y)*(qud.y)) + if fud==0: + fu = 0 + fud = 1 + pt.u=pt.u-(fu/fud) + + def createDataPts(curveGroup, group_mode): + data_pts = [] + if group_mode: + for i in range(len(curveGroup[0].keyframe_points)): + x = curveGroup[0].keyframe_points[i].co.x + y1 = curveGroup[0].keyframe_points[i].co.y + y2 = curveGroup[1].keyframe_points[i].co.y + y3 = curveGroup[2].keyframe_points[i].co.y + data_pts.append(dataPoint(i,Vector((x,y1,y2,y3)))) + else: + for i in range(len(curveGroup.keyframe_points)): + x = curveGroup.keyframe_points[i].co.x + y1 = curveGroup.keyframe_points[i].co.y + y2 = 0 + y3 = 0 + data_pts.append(dataPoint(i,Vector((x,y1,y2,y3)))) + return data_pts + + def fitCubic(data_pts,s,e): + + if e-s<3: # if there are less than 3 points, fit a single basic bezier + bez = fitSingleCubic2Pts(data_pts,s,e) + else: + #if there are more, parameterize the points and fit a single cubic bezier + chordLength(data_pts,s,e) + bez = fitSingleCubic(data_pts,s,e) + + #calculate max error and point where it occurs + maxError,maxErrorPt = maxErrorAmount(data_pts,bez,s,e) + #if error is small enough, reparameterization might be enough + if maxError<reparaError and maxError>error: + for i in range(maxIterations): + newtonRaphson(data_pts,s,e,bez) + if e-s<3: + bez = fitSingleCubic2Pts(data_pts,s,e) + else: + bez = fitSingleCubic(data_pts,s,e) + + + #recalculate max error and point where it occurs + maxError,maxErrorPt = maxErrorAmount(data_pts,bez,s,e) + + #repara wasn't enough, we need 2 beziers for this range. + #Split the bezier at point of maximum error + if maxError>error: + fitCubic(data_pts,s,maxErrorPt) + fitCubic(data_pts,maxErrorPt,e) + else: + #error is small enough, return the beziers. + beziers.append(bez) + return + + def createNewCurves(curveGroup,beziers,group_mode): + #remove all existing data points + if group_mode: + for fcurve in curveGroup: + for i in range(len(fcurve.keyframe_points)-1,0,-1): + fcurve.keyframe_points.remove(fcurve.keyframe_points[i]) + else: + fcurve = curveGroup + for i in range(len(fcurve.keyframe_points)-1,0,-1): + fcurve.keyframe_points.remove(fcurve.keyframe_points[i]) + + #insert the calculated beziers to blender data.\ + if group_mode: + for fullbez in beziers: + for i,fcurve in enumerate(curveGroup): + bez = [Vector((vec[0],vec[i+1])) for vec in fullbez] + newKey = fcurve.keyframe_points.insert(frame=bez[0].x,value=bez[0].y) + newKey.handle_right = (bez[1].x,bez[1].y) + + newKey = fcurve.keyframe_points.insert(frame=bez[3].x,value=bez[3].y) + newKey.handle_left= (bez[2].x,bez[2].y) + else: + for bez in beziers: + for vec in bez: + vec.resize_2d() + newKey = fcurve.keyframe_points.insert(frame=bez[0].x,value=bez[0].y) + newKey.handle_right = (bez[1].x,bez[1].y) + + newKey = fcurve.keyframe_points.insert(frame=bez[3].x,value=bez[3].y) + newKey.handle_left= (bez[2].x,bez[2].y) + + #indices are detached from data point's frame (x) value and stored in the dataPoint object, represent a range + + data_pts = createDataPts(curveGroup,group_mode) + + s = 0 #start + e = len(data_pts)-1 #end + + beziers = [] + + #begin the recursive fitting algorithm. + fitCubic(data_pts,s,e) + #remove old Fcurves and insert the new ones + createNewCurves(curveGroup,beziers,group_mode) + +#Main function of simplification +#sel_opt: either "sel" or "all" for which curves to effect +#error: maximum error allowed, in fraction (20% = 0.0020), i.e. divide by 10000 from percentage wanted. +#group_mode: boolean, to analyze each curve seperately or in groups, where group is all curves that effect the same property (e.g. a bone's x,y,z rotation) + +def fcurves_simplify(sel_opt="all", error=0.002, group_mode=True): + # main vars + context = bpy.context + obj = context.active_object + fcurves = obj.animation_data.action.fcurves + + if sel_opt=="sel": + sel_fcurves = [fcurve for fcurve in fcurves if fcurve.select] + else: + sel_fcurves = fcurves[:] + + #Error threshold for Newton Raphson reparamatizing + reparaError = error*32 + maxIterations = 16 + + if group_mode: + fcurveDict = {} + #this loop sorts all the fcurves into groups of 3, based on their RNA Data path, which corresponds to which property they effect + for curve in sel_fcurves: + if curve.data_path in fcurveDict: #if this bone has been added, append the curve to its list + fcurveDict[curve.data_path].append(curve) + else: + fcurveDict[curve.data_path] = [curve] #new bone, add a new dict value with this first curve + fcurveGroups = fcurveDict.values() + else: + fcurveGroups = sel_fcurves + + if error>0.00000: + #simplify every selected curve. + totalt = 0 + for i,fcurveGroup in enumerate(fcurveGroups): + print("Processing curve "+str(i+1)+"/"+str(len(fcurveGroups))) + t = time.clock() + simplifyCurves(fcurveGroup,error,reparaError,maxIterations,group_mode) + t = time.clock() - t + print(str(t)[:5]+" seconds to process last curve") + totalt+=t + print(str(totalt)[:5]+" seconds, total time elapsed") + + return + diff --git a/release/scripts/modules/retarget.py b/release/scripts/modules/retarget.py new file mode 100644 index 00000000000..b081191d9a6 --- /dev/null +++ b/release/scripts/modules/retarget.py @@ -0,0 +1,198 @@ +import bpy +from mathutils import * +from math import radians, acos +performer_obj = bpy.data.objects["performer"] +enduser_obj = bpy.data.objects["enduser"] +end_arm = bpy.data.armatures["enduser_arm"] +scene = bpy.context.scene + +#TODO: Only selected bones get retargeted. +# Selected Bones/chains get original pos empties, if ppl want IK instead of FK +# Some "magic" numbers - frame start and end, eulers of all orders instead of just quats keyframed + + + +# dictionary of mapping +# this is currently manuall input'ed, but will +# be created from a more comfortable UI in the future +bonemap = { "LeftFoot": ("DEF_Foot.L","DEF_Toes.L"), + "LeftUpLeg": "DEF_Thigh.L", + "Hips": "DEF_Hip", + "LowerBack": "DEF_Spine", + "Spine": "DEF_Torso", + "Neck": "DEF_Neck", + "Neck1": "DEF_Neck", + "Head": "DEF_Head", + "LeftShoulder": "DEF_Shoulder.L", + "LeftArm": "DEF_Forearm.L", + "LeftForeArm": "DEF_Arm.L", + "LeftHand": "DEF_Hand.L", + "RightShoulder": "DEF_Shoulder.R", + "RightArm": "DEF_Forearm.R", + "RightForeArm": "DEF_Arm.R", + "RightHand": "DEF_Hand.R", + "RightFoot": ("DEF_Foot.R","DEF_Toes.R"), + "RightUpLeg": "DEF_Thigh.R", + "RightLeg": "DEF_Shin.R", + "LeftLeg": "DEF_Shin.L"} + +# creation of a reverse map +# multiple keys get mapped to list values +bonemapr = {} +for key in bonemap.keys(): + if not bonemap[key] in bonemapr: + if type(bonemap[key])==type((0,0)): + for key_x in bonemap[key]: + bonemapr[key_x] = [key] + else: + bonemapr[bonemap[key]] = [key] + else: + bonemapr[bonemap[key]].append(key) + +# list of empties created to keep track of "original" +# position data +# in final product, these locations can be stored as custom props +# these help with constraining, etc. + +constraints = [] + + +#creation of intermediate armature +# the intermediate armature has the hiearchy of the end user, +# does not have rotation inheritence +# and bone roll is identical to the performer +# its purpose is to copy over the rotations +# easily while concentrating on the hierarchy changes +def createIntermediate(): + + #creates and keyframes an empty with its location + #the original position of the tail bone + #useful for storing the important data in the original motion + #i.e. using this empty to IK the chain to that pos. + def locOfOriginal(inter_bone,perf_bone): + if not perf_bone.name+"Org" in bpy.data.objects: + bpy.ops.object.add() + empty = bpy.context.active_object + empty.name = perf_bone.name+"Org" + empty = bpy.data.objects[perf_bone.name+"Org"] + offset = perf_bone.vector + scaling = perf_bone.length / inter_bone.length + offset/=scaling + empty.location = inter_bone.head + offset + empty.keyframe_insert("location") + + #Simple 1to1 retarget of a bone + def singleBoneRetarget(inter_bone,perf_bone): + perf_world_rotation = perf_bone.matrix * performer_obj.matrix_world + inter_world_base_rotation = inter_bone.bone.matrix_local * inter_obj.matrix_world + inter_world_base_inv = Matrix(inter_world_base_rotation) + inter_world_base_inv.invert() + return (inter_world_base_inv.to_3x3() * perf_world_rotation.to_3x3()).to_4x4() + + #uses 1to1 and interpolation/averaging to match many to 1 retarget + def manyPerfToSingleInterRetarget(inter_bone,performer_bones_s): + retarget_matrices = [singleBoneRetarget(inter_bone,perf_bone) for perf_bone in performer_bones_s] + lerp_matrix = Matrix() + for i in range(len(retarget_matrices)-1): + first_mat = retarget_matrices[i] + next_mat = retarget_matrices[i+1] + lerp_matrix = first_mat.lerp(next_mat,0.5) + return lerp_matrix + + #determines the type of hierachy change needed and calls the + #right function + def retargetPerfToInter(inter_bone): + if inter_bone.name in bonemapr.keys(): + perf_bone_name = bonemapr[inter_bone.name] + #is it a 1 to many? + if type(bonemap[perf_bone_name[0]])==type((0,0)): + perf_bone = performer_bones[perf_bone_name[0]] + if inter_bone.name == bonemap[perf_bone_name[0]][0]: + locOfOriginal(inter_bone,perf_bone) + else: + # then its either a many to 1 or 1 to 1 + + if len(perf_bone_name) > 1: + performer_bones_s = [performer_bones[name] for name in perf_bone_name] + #we need to map several performance bone to a single + for perf_bone in performer_bones_s: + locOfOriginal(inter_bone,perf_bone) + inter_bone.matrix_basis = manyPerfToSingleInterRetarget(inter_bone,performer_bones_s) + else: + perf_bone = performer_bones[perf_bone_name[0]] + locOfOriginal(inter_bone,perf_bone) + inter_bone.matrix_basis = singleBoneRetarget(inter_bone,perf_bone) + + inter_bone.keyframe_insert("rotation_quaternion") + for child in inter_bone.children: + retargetPerfToInter(child) + + #creates the intermediate armature object + bpy.ops.object.select_name(name="enduser",extend=False) + bpy.ops.object.duplicate(linked=False) + bpy.context.active_object.name = "intermediate" + inter_obj = bpy.context.active_object + bpy.ops.object.mode_set(mode='EDIT') + #resets roll + bpy.ops.armature.calculate_roll(type='Z') + bpy.ops.object.mode_set(mode="OBJECT") + inter_arm = bpy.data.armatures["enduser_arm.001"] + inter_arm.name = "inter_arm" + performer_bones = performer_obj.pose.bones + inter_bones = inter_obj.pose.bones + + #clears inheritance + for inter_bone in inter_bones: + inter_bone.bone.use_inherit_rotation = False + + for t in range(1,150): + scene.frame_set(t) + inter_bone = inter_bones["DEF_Hip"] + retargetPerfToInter(inter_bone) + + return inter_obj,inter_arm + +# this procedure copies the rotations over from the intermediate +# armature to the end user one. +# As the hierarchies are 1 to 1, this is a simple matter of +# copying the rotation, while keeping in mind bone roll, parenting, etc. +# TODO: Control Bones: If a certain bone is constrained in a way +# that its rotation is determined by another (a control bone) +# We should determine the right pos of the control bone. +# Scale: ? Should work but needs testing. +def retargetEnduser(): + inter_bones = inter_obj.pose.bones + end_bones = enduser_obj.pose.bones + + def bakeTransform(end_bone): + src_bone = inter_bones[end_bone.name] + trg_bone = end_bone + bake_matrix = src_bone.matrix + rest_matrix = trg_bone.bone.matrix_local + + if trg_bone.parent and trg_bone.bone.use_inherit_rotation: + parent_mat = src_bone.parent.matrix + parent_rest = trg_bone.parent.bone.matrix_local + parent_rest_inv = parent_rest.copy() + parent_rest_inv.invert() + parent_mat_inv = parent_mat.copy() + parent_mat_inv.invert() + bake_matrix = parent_mat_inv * bake_matrix + rest_matrix = parent_rest_inv * rest_matrix + + rest_matrix_inv = rest_matrix.copy() + rest_matrix_inv.invert() + bake_matrix = rest_matrix_inv * bake_matrix + trg_bone.matrix_basis = bake_matrix + end_bone.keyframe_insert("rotation_quaternion") + + for bone in end_bone.children: + bakeTransform(bone) + + for t in range(1,150): + scene.frame_set(t) + end_bone = end_bones["DEF_Hip"] + bakeTransform(end_bone) + +inter_obj, inter_arm = createIntermediate() +retargetEnduser()
\ No newline at end of file diff --git a/release/scripts/startup/bl_operators/nla.py b/release/scripts/startup/bl_operators/nla.py index 923ca92a162..82849cca2cc 100644 --- a/release/scripts/startup/bl_operators/nla.py +++ b/release/scripts/startup/bl_operators/nla.py @@ -168,3 +168,37 @@ class BakeAction(bpy.types.Operator): def invoke(self, context, event): wm = context.window_manager return wm.invoke_props_dialog(self) + +################################# + +class ClearUselessActions(bpy.types.Operator): + '''Mark actions with no F-Curves for deletion after save+reload of file preserving "action libraries"''' + bl_idname = "anim.clear_useless_actions" + bl_label = "Clear Useless Actions" + bl_options = {'REGISTER', 'UNDO'} + + only_unused = BoolProperty(name="Only Unused", + description="Only unused (Fake User only) actions get considered", + default=True) + + @classmethod + def poll(cls, context): + return len(bpy.data.actions) != 0 + + def execute(self, context): + removed = 0 + + for action in bpy.data.actions: + # if only user is "fake" user... + if ((self.only_unused is False) or + (action.use_fake_user and action.users == 1)): + + # if it has F-Curves, then it's a "action library" (i.e. walk, wave, jump, etc.) + # and should be left alone as that's what fake users are for! + if not action.fcurves: + # mark action for deletion + action.user_clear() + removed += 1 + + self.report({'INFO'}, "Removed %d empty and/or fake-user only Actions" % (removed)) + return {'FINISHED'} diff --git a/release/scripts/startup/bl_operators/object.py b/release/scripts/startup/bl_operators/object.py index 0342a14a1b2..7a9a9d41939 100644 --- a/release/scripts/startup/bl_operators/object.py +++ b/release/scripts/startup/bl_operators/object.py @@ -564,3 +564,44 @@ class ClearAllRestrictRender(bpy.types.Operator): for obj in context.scene.objects: obj.hide_render = False return {'FINISHED'} + +class TransformsToDeltasAnim(bpy.types.Operator): + '''Convert object animation for normal transforms to delta transforms''' + bl_idname = "object.anim_transforms_to_deltas" + bl_label = "Animated Transforms to Deltas" + bl_options = {'REGISTER', 'UNDO'} + + @classmethod + def poll(cls, context): + obs = context.selected_editable_objects + return (obs is not None) + + def execute(self, context): + for obj in context.selected_editable_objects: + # get animation data + adt = obj.animation_data + if (adt is None) or (adt.action is None): + self.report({'WARNING'}, "No animation data to convert on object: " + obj.name) + continue + + # if F-Curve uses standard transform path, just append "delta_" to this path + for fcu in adt.action.fcurves: + if fcu.data_path == "location": + fcu.data_path = "delta_location" + obj.location.zero() + elif fcu.data_path == "rotation_euler": + fcu.data_path = "delta_rotation_euler" + obj.rotation_euler.zero() + elif fcu.data_path == "rotation_quaternion": + fcu.data_path = "delta_rotation_quaternion" + obj.rotation_quaternion.identity() + #elif fcu.data_path == "rotation_axis_angle": # XXX: currently not implemented + # fcu.data_path = "delta_rotation_axis_angle" + elif fcu.data_path == "scale": + fcu.data_path = "delta_scale" + obj.scale = (1, 1, 1) + + # hack: force animsys flush by changing frame, so that deltas get run + context.scene.frame_set(context.scene.frame_current) + + return {'FINISHED'} diff --git a/release/scripts/startup/bl_ui/properties_object_constraint.py b/release/scripts/startup/bl_ui/properties_object_constraint.py index 03823ad7345..8e175244216 100644 --- a/release/scripts/startup/bl_ui/properties_object_constraint.py +++ b/release/scripts/startup/bl_ui/properties_object_constraint.py @@ -476,6 +476,11 @@ class ConstraintButtonsPanel(): row.label(text="Clamp Region:") row.prop(con, "limit_mode", text="") + row = layout.row() + row.prop(con, "use_transform_limit") + row.label() + + def STRETCH_TO(self, context, layout, con): self.target_template(layout, con) diff --git a/release/scripts/startup/bl_ui/properties_scene.py b/release/scripts/startup/bl_ui/properties_scene.py index 7725f661693..e2dc9de064f 100644 --- a/release/scripts/startup/bl_ui/properties_scene.py +++ b/release/scripts/startup/bl_ui/properties_scene.py @@ -76,6 +76,7 @@ class SCENE_PT_keying_sets(SceneButtonsPanel, bpy.types.Panel): col = row.column(align=True) col.operator("anim.keying_set_add", icon='ZOOMIN', text="") col.operator("anim.keying_set_remove", icon='ZOOMOUT', text="") + col.menu("SCENE_MT_keying_set_specials", icon='DOWNARROW_HLT', text="") ks = scene.keying_sets.active if ks and ks.is_path_absolute: @@ -94,6 +95,14 @@ class SCENE_PT_keying_sets(SceneButtonsPanel, bpy.types.Panel): col.prop(ks, "bl_options") +class SCENE_MT_keying_set_specials(bpy.types.Menu): + bl_label = "Keying Set Specials" + + def draw(self, context): + layout = self.layout + + layout.operator("anim.keying_set_import", text="Import From File") + class SCENE_PT_keying_set_paths(SceneButtonsPanel, bpy.types.Panel): bl_label = "Active Keying Set" @@ -198,6 +207,36 @@ class SCENE_PT_custom_props(SceneButtonsPanel, PropertyPanel, bpy.types.Panel): # XXX, move operator to op/ dir +class ANIM_OT_keying_set_import(bpy.types.Operator): + "Import Keying Set from a python script." + bl_idname = "anim.keying_set_import" + bl_label = "Import Keying Set from File" + + filepath = bpy.props.StringProperty(name="File Path", description="Filepath to read file from.") + filter_folder = bpy.props.BoolProperty(name="Filter folders", description="", default=True, options={'HIDDEN'}) + filter_text = bpy.props.BoolProperty(name="Filter text", description="", default=True, options={'HIDDEN'}) + filter_python = bpy.props.BoolProperty(name="Filter python", description="", default=True, options={'HIDDEN'}) + + def execute(self, context): + if not self.filepath: + raise Exception("Filepath not set.") + + f = open(self.filepath, "r") + if not f: + raise Exception("Could not open file.") + + # lazy way of loading and running this file... + exec(compile(f.read(), self.filepath, 'exec')) + + f.close() + + return {'FINISHED'} + + def invoke(self, context, event): + wm = context.window_manager + wm.fileselect_add(self) + return {'RUNNING_MODAL'} + class ANIM_OT_keying_set_export(bpy.types.Operator): "Export Keying Set to a python script." bl_idname = "anim.keying_set_export" diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index 2e9448cca27..222f2735a3e 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -743,6 +743,7 @@ class USERPREF_PT_file(bpy.types.Panel): col.prop(paths, "save_version") col.prop(paths, "recent_files") + col.prop(paths, "use_update_recent_files_on_load") col.prop(paths, "use_save_preview_images") col.label(text="Auto Save:") col.prop(paths, "use_auto_save_temporary_files") diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 02004283264..6d1caa5111d 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -181,6 +181,10 @@ class VIEW3D_MT_transform(bpy.types.Menu): layout.operator("object.randomize_transform") layout.operator("object.align") + + layout.separator() + + layout.operator("object.anim_transforms_to_deltas") class VIEW3D_MT_mirror(bpy.types.Menu): diff --git a/source/blender/blenkernel/BKE_constraint.h b/source/blender/blenkernel/BKE_constraint.h index 7c0e7050a9f..ddff45c5422 100644 --- a/source/blender/blenkernel/BKE_constraint.h +++ b/source/blender/blenkernel/BKE_constraint.h @@ -154,6 +154,7 @@ void constraints_clear_evalob(struct bConstraintOb *cob); void constraint_mat_convertspace(struct Object *ob, struct bPoseChannel *pchan, float mat[][4], short from, short to); void get_constraint_target_matrix(struct Scene *scene, struct bConstraint *con, int n, short ownertype, void *ownerdata, float mat[][4], float ctime); +void get_constraint_targets_for_solving(struct bConstraint *con, struct bConstraintOb *ob, struct ListBase *targets, float ctime); void solve_constraints(struct ListBase *conlist, struct bConstraintOb *cob, float ctime); #ifdef __cplusplus diff --git a/source/blender/blenkernel/BKE_sound.h b/source/blender/blenkernel/BKE_sound.h index 04597fd666e..7402d501120 100644 --- a/source/blender/blenkernel/BKE_sound.h +++ b/source/blender/blenkernel/BKE_sound.h @@ -104,4 +104,6 @@ int sound_read_sound_buffer(struct bSound* sound, float* buffer, int length, flo int sound_get_channels(struct bSound* sound); +void* sound_get_factory(void* sound); + #endif diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 77f56058a4f..21d9701004b 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -85,8 +85,6 @@ bAction *add_empty_action(const char name[]) bAction *act; act= alloc_libblock(&G.main->action, ID_AC, name); - act->id.flag |= LIB_FAKEUSER; // XXX this is nasty for new users... maybe we don't want this anymore - act->id.us++; return act; } @@ -200,9 +198,6 @@ bAction *copy_action (bAction *src) } } - dst->id.flag |= LIB_FAKEUSER; // XXX this is nasty for new users... maybe we don't want this anymore - dst->id.us++; - return dst; } diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index d3c14a9dd12..fe3286dcc2b 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -2648,7 +2648,7 @@ static void distlimit_evaluate (bConstraint *con, bConstraintOb *cob, ListBase * /* if inside, then move to surface */ if (dist <= data->dist) { clamp_surf= 1; - sfac= data->dist / dist; + if (dist != 0.0f) sfac= data->dist / dist; } /* if soft-distance is enabled, start fading once owner is dist+softdist from the target */ else if (data->flag & LIMITDIST_USESOFT) { @@ -2661,14 +2661,14 @@ static void distlimit_evaluate (bConstraint *con, bConstraintOb *cob, ListBase * /* if outside, then move to surface */ if (dist >= data->dist) { clamp_surf= 1; - sfac= data->dist / dist; + if (dist != 0.0f) sfac= data->dist / dist; } /* if soft-distance is enabled, start fading once owner is dist-soft from the target */ else if (data->flag & LIMITDIST_USESOFT) { // FIXME: there's a problem with "jumping" when this kicks in if (dist >= (data->dist - data->soft)) { sfac = (float)( data->soft*(1.0f - expf(-(dist - data->dist)/data->soft)) + data->dist ); - sfac /= dist; + if (dist != 0.0f) sfac /= dist; clamp_surf= 1; } @@ -2677,7 +2677,7 @@ static void distlimit_evaluate (bConstraint *con, bConstraintOb *cob, ListBase * else { if (IS_EQF(dist, data->dist)==0) { clamp_surf= 1; - sfac= data->dist / dist; + if (dist != 0.0f) sfac= data->dist / dist; } } @@ -4427,6 +4427,34 @@ void get_constraint_target_matrix (struct Scene *scene, bConstraint *con, int n, unit_m4(mat); } } + +/* Get the list of targets required for solving a constraint */ +void get_constraint_targets_for_solving (bConstraint *con, bConstraintOb *cob, ListBase *targets, float ctime) +{ + bConstraintTypeInfo *cti= constraint_get_typeinfo(con); + + if (cti && cti->get_constraint_targets) { + bConstraintTarget *ct; + + /* get targets + * - constraints should use ct->matrix, not directly accessing values + * - ct->matrix members have not yet been calculated here! + */ + cti->get_constraint_targets(con, targets); + + /* set matrices + * - calculate if possible, otherwise just initialise as identity matrix + */ + if (cti->get_target_matrix) { + for (ct= targets->first; ct; ct= ct->next) + cti->get_target_matrix(con, cob, ct, ctime); + } + else { + for (ct= targets->first; ct; ct= ct->next) + unit_m4(ct->matrix); + } + } +} /* ---------- Evaluation ----------- */ @@ -4471,27 +4499,7 @@ void solve_constraints (ListBase *conlist, bConstraintOb *cob, float ctime) constraint_mat_convertspace(cob->ob, cob->pchan, cob->matrix, CONSTRAINT_SPACE_WORLD, con->ownspace); /* prepare targets for constraint solving */ - if (cti->get_constraint_targets) { - bConstraintTarget *ct; - - /* get targets - * - constraints should use ct->matrix, not directly accessing values - * - ct->matrix members have not yet been calculated here! - */ - cti->get_constraint_targets(con, &targets); - - /* set matrices - * - calculate if possible, otherwise just initialise as identity matrix - */ - if (cti->get_target_matrix) { - for (ct= targets.first; ct; ct= ct->next) - cti->get_target_matrix(con, cob, ct, ctime); - } - else { - for (ct= targets.first; ct; ct= ct->next) - unit_m4(ct->matrix); - } - } + get_constraint_targets_for_solving(con, cob, &targets, ctime); /* Solve the constraint and put result in cob->matrix */ cti->evaluate_constraint(con, cob, &targets); diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index d6a9d950015..1f45cc56117 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -42,6 +42,7 @@ #include "MEM_guardedalloc.h" #include "DNA_anim_types.h" +#include "DNA_constraint_types.h" #include "DNA_object_types.h" #include "BLI_blenlib.h" @@ -52,6 +53,7 @@ #include "BKE_animsys.h" #include "BKE_action.h" #include "BKE_armature.h" +#include "BKE_constraint.h" #include "BKE_curve.h" #include "BKE_global.h" #include "BKE_object.h" @@ -1151,25 +1153,50 @@ static float dvar_eval_locDiff (ChannelDriver *driver, DriverVar *dvar) /* check if object or bone */ if (pchan) { /* bone */ - if ((dtar->flag & DTAR_FLAG_LOCALSPACE) == 0) { + if (dtar->flag & DTAR_FLAG_LOCALSPACE) { + if (dtar->flag & DTAR_FLAG_LOCAL_CONSTS) { + float mat[4][4]; + + /* extract transform just like how the constraints do it! */ + copy_m4_m4(mat, pchan->pose_mat); + constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL); + + /* ... and from that, we get our transform */ + VECCOPY(tmp_loc, mat[3]); + } + else { + /* transform space (use transform values directly) */ + VECCOPY(tmp_loc, pchan->loc); + } + } + else { /* 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]); + if (dtar->flag & DTAR_FLAG_LOCALSPACE) { + if (dtar->flag & DTAR_FLAG_LOCAL_CONSTS) { + // XXX: this should practically be the same as transform space... + float mat[4][4]; + + /* extract transform just like how the constraints do it! */ + copy_m4_m4(mat, ob->obmat); + constraint_mat_convertspace(ob, NULL, mat, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL); + + /* ... and from that, we get our transform */ + VECCOPY(tmp_loc, mat[3]); + } + else { + /* transform space (use transform values directly) */ + VECCOPY(tmp_loc, ob->loc); + } } else { - /* local (use transform values directly) */ - VECCOPY(tmp_loc, ob->loc); + /* worldspace */ + VECCOPY(tmp_loc, ob->obmat[3]); } } @@ -1197,7 +1224,7 @@ static float dvar_eval_transChan (ChannelDriver *driver, DriverVar *dvar) Object *ob= (Object *)dtar_id_ensure_proxy_from(dtar->id); bPoseChannel *pchan; float mat[4][4]; - float eul[3] = {0.0f,0.0f,0.0f}; + float oldEul[3] = {0.0f,0.0f,0.0f}; short useEulers=0, rotOrder=ROT_MODE_EUL; /* check if this target has valid data */ @@ -1210,36 +1237,62 @@ static float dvar_eval_transChan (ChannelDriver *driver, DriverVar *dvar) /* try to get posechannel */ pchan= get_pose_channel(ob->pose, dtar->pchan_name); - /* check if object or bone, and get transform matrix accordingly */ + /* check if object or bone, and get transform matrix accordingly + * - "useEulers" code is used to prevent the problems associated with non-uniqueness + * of euler decomposition from matrices [#20870] + * - localspace is for [#21384], where parent results are not wanted + * but local-consts is for all the common "corrective-shapes-for-limbs" situations + */ if (pchan) { /* bone */ if (pchan->rotmode > 0) { - VECCOPY(eul, pchan->eul); + VECCOPY(oldEul, pchan->eul); rotOrder= pchan->rotmode; useEulers = 1; } if (dtar->flag & DTAR_FLAG_LOCALSPACE) { - /* specially calculate local matrix, since chan_mat is not valid - * since it stores delta transform of pose_mat so that deforms work - */ - pchan_to_mat4(pchan, mat); + if (dtar->flag & DTAR_FLAG_LOCAL_CONSTS) { + /* just like how the constraints do it! */ + copy_m4_m4(mat, pchan->pose_mat); + constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL); + } + else { + /* specially calculate local matrix, since chan_mat is not valid + * since it stores delta transform of pose_mat so that deforms work + * so it cannot be used here for "transform" space + */ + pchan_to_mat4(pchan, mat); + } } - else + else { + /* worldspace matrix */ mul_m4_m4m4(mat, pchan->pose_mat, ob->obmat); + } } else { /* object */ if (ob->rotmode > 0) { - VECCOPY(eul, ob->rot); + VECCOPY(oldEul, ob->rot); rotOrder= ob->rotmode; useEulers = 1; } - if (dtar->flag & DTAR_FLAG_LOCALSPACE) - object_to_mat4(ob, mat); - else + if (dtar->flag & DTAR_FLAG_LOCALSPACE) { + if (dtar->flag & DTAR_FLAG_LOCAL_CONSTS) { + /* just like how the constraints do it! */ + copy_m4_m4(mat, ob->obmat); + constraint_mat_convertspace(ob, NULL, mat, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL); + } + else { + /* transforms to matrix */ + object_to_mat4(ob, mat); + } + } + else { + /* worldspace matrix - just the good-old one */ copy_m4_m4(mat, ob->obmat); + } } /* check which transform */ @@ -1255,9 +1308,21 @@ static float dvar_eval_transChan (ChannelDriver *driver, DriverVar *dvar) return scale[dtar->transChan - DTAR_TRANSCHAN_SCALEX]; } else if (dtar->transChan >= DTAR_TRANSCHAN_ROTX) { - /* extract euler rotation (if needed), and choose the right axis */ - if ((dtar->flag & DTAR_FLAG_LOCALSPACE)==0 || (useEulers == 0)) - mat4_to_eulO(eul, rotOrder, mat); + /* extract rotation as eulers (if needed) + * - definitely if rotation order isn't eulers already + * - if eulers, then we have 2 options: + * a) decompose transform matrix as required, then try to make eulers from + * there compatible with original values + * b) [NOT USED] directly use the original values (no decomposition) + * - only an option for "transform space", if quality is really bad with a) + */ + float eul[3]; + + mat4_to_eulO(eul, rotOrder, mat); + + if (useEulers) { + compatible_eul(eul, oldEul); + } return eul[dtar->transChan - DTAR_TRANSCHAN_ROTX]; } diff --git a/source/blender/blenkernel/intern/fmodifier.c b/source/blender/blenkernel/intern/fmodifier.c index 844f25e6d21..dcf81c19479 100644 --- a/source/blender/blenkernel/intern/fmodifier.c +++ b/source/blender/blenkernel/intern/fmodifier.c @@ -1013,6 +1013,7 @@ FModifier *add_fmodifier (ListBase *modifiers, int type) fcm= MEM_callocN(sizeof(FModifier), "F-Curve Modifier"); fcm->type = type; fcm->flag = FMODIFIER_FLAG_EXPANDED; + fcm->influence = 1.0f; BLI_addtail(modifiers, fcm); /* tag modifier as "active" if no other modifiers exist in the stack yet */ @@ -1200,6 +1201,47 @@ short list_has_suitable_fmodifier (ListBase *modifiers, int mtype, short acttype /* Evaluation API --------------------------- */ +/* helper function - calculate influence of FModifier */ +static float eval_fmodifier_influence (FModifier *fcm, float evaltime) +{ + float influence; + + /* sanity check */ + if (fcm == NULL) + return 0.0f; + + /* should we use influence stored in modifier or not + * NOTE: this is really just a hack so that we don't need to version patch old files ;) + */ + if (fcm->flag & FMODIFIER_FLAG_USEINFLUENCE) + influence = fcm->influence; + else + influence = 1.0f; + + /* restricted range or full range? */ + if (fcm->flag & FMODIFIER_FLAG_RANGERESTRICT) { + if ((evaltime <= fcm->sfra) || (evaltime >= fcm->efra)) { + /* out of range */ + return 0.0f; + } + else if ((evaltime > fcm->sfra) && (evaltime < fcm->sfra + fcm->blendin)) { + /* blend in range */ + float a = fcm->sfra; + float b = fcm->sfra + fcm->blendin; + return influence * (evaltime - a) / (b - a); + } + else if ((evaltime < fcm->efra) && (evaltime > fcm->efra - fcm->blendout)) { + /* blend out range */ + float a = fcm->efra; + float b = fcm->efra - fcm->blendout; + return influence * (evaltime - a) / (b - a); + } + } + + /* just return the influence of the modifier */ + return influence; +} + /* evaluate time modifications imposed by some F-Curve Modifiers * - this step acts as an optimisation to prevent the F-Curve stack being evaluated * several times by modifiers requesting the time be modified, as the final result @@ -1230,11 +1272,24 @@ float evaluate_time_fmodifiers (ListBase *modifiers, FCurve *fcu, float cvalue, for (fcm= modifiers->last; fcm; fcm= fcm->prev) { FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); - /* only evaluate if there's a callback for this */ - // TODO: implement the 'influence' control feature... - if (fmi && fmi->evaluate_modifier_time) { - if ((fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) == 0) - evaltime= fmi->evaluate_modifier_time(fcu, fcm, cvalue, evaltime); + if (fmi == NULL) + continue; + + /* if modifier cannot be applied on this frame (whatever scale it is on, it won't affect the results) + * hence we shouldn't bother seeing what it would do given the chance + */ + if ((fcm->flag & FMODIFIER_FLAG_RANGERESTRICT)==0 || + ((fcm->sfra <= evaltime) && (fcm->efra >= evaltime)) ) + { + /* only evaluate if there's a callback for this */ + if (fmi->evaluate_modifier_time) { + if ((fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) == 0) { + float influence = eval_fmodifier_influence(fcm, evaltime); + float nval = fmi->evaluate_modifier_time(fcu, fcm, cvalue, evaltime); + + evaltime = interpf(nval, evaltime, influence); + } + } } } @@ -1257,11 +1312,22 @@ void evaluate_value_fmodifiers (ListBase *modifiers, FCurve *fcu, float *cvalue, for (fcm= modifiers->first; fcm; fcm= fcm->next) { FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); - /* only evaluate if there's a callback for this */ - // TODO: implement the 'influence' control feature... - if (fmi && fmi->evaluate_modifier) { - if ((fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) == 0) - fmi->evaluate_modifier(fcu, fcm, cvalue, evaltime); + if (fmi == NULL) + continue; + + /* only evaluate if there's a callback for this, and if F-Modifier can be evaluated on this frame */ + if ((fcm->flag & FMODIFIER_FLAG_RANGERESTRICT)==0 || + ((fcm->sfra <= evaltime) && (fcm->efra >= evaltime)) ) + { + if (fmi->evaluate_modifier) { + if ((fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) == 0) { + float influence = eval_fmodifier_influence(fcm, evaltime); + float nval = *cvalue; + + fmi->evaluate_modifier(fcu, fcm, &nval, evaltime); + *cvalue = interpf(nval, *cvalue, influence); + } + } } } } diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index e0e456a371e..f42492ef713 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -502,3 +502,8 @@ int sound_get_channels(struct bSound* sound) return info.specs.channels; } + +void* sound_get_factory(void* sound) +{ + return ((struct bSound*) sound)->playback_handle; +} diff --git a/source/blender/collada/AnimationExporter.cpp b/source/blender/collada/AnimationExporter.cpp new file mode 100644 index 00000000000..98699e22030 --- /dev/null +++ b/source/blender/collada/AnimationExporter.cpp @@ -0,0 +1,800 @@ +/* + * $Id: DocumentExporter.cpp 36898 2011-05-25 17:14:31Z phabtar $ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Chingiz Dyussenov, Arystanbek Dyussenov, Jan Diederich, Tod Liverseed. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "GeometryExporter.h" +#include "AnimationExporter.h" + +template<class Functor> +void forEachObjectInScene(Scene *sce, Functor &f) +{ + Base *base= (Base*) sce->base.first; + while(base) { + Object *ob = base->object; + + f(ob); + + base= base->next; + } +} + +void AnimationExporter::exportAnimations(Scene *sce) + { + if(hasAnimations(sce)) { + this->scene = sce; + + openLibrary(); + + forEachObjectInScene(sce, *this); + + closeLibrary(); + } + } + + // called for each exported object + void AnimationExporter::operator() (Object *ob) + { + if (!ob->adt || !ob->adt->action) return; //this is already checked in hasAnimations() + FCurve *fcu = (FCurve*)ob->adt->action->curves.first; + char * transformName = extract_transform_name( fcu->rna_path ); + + //if (ob->type == OB_ARMATURE) { + // if (!ob->data) return; + // bArmature *arm = (bArmature*)ob->data; + // while(fcu) + // { + // transformName = extract_transform_name( fcu->rna_path ); + // // std::string ob_name = getObjectBoneName( ob , fcu); + // // for (Bone *bone = (Bone*)arm->bonebase.first; bone; bone = bone->next) + // // write_bone_animation(ob, bone); + // dae_animation(ob, fcu, ob_name, transformName); + // fcu = fcu->next; + // } + //} + //else { + while (fcu) { + transformName = extract_transform_name( fcu->rna_path ); + printf("fcu -> rna _path : %s \n transformName : %s\n", fcu->rna_path, transformName); + if ((!strcmp(transformName, "location") || !strcmp(transformName, "scale")) || + (!strcmp(transformName, "rotation_euler") && ob->rotmode == ROT_MODE_EUL)|| + (!strcmp(transformName, "rotation_quaternion"))) + dae_animation(ob ,fcu,/* id_name(ob),*/ transformName); + + fcu = fcu->next; + } + //} + } + + std::string AnimationExporter::getObjectBoneName( Object* ob,const FCurve* fcu ) + { + //hard-way to derive the bone name from rna_path. Must find more compact method + std::string rna_path = std::string(fcu->rna_path); + + char* boneName = strtok((char *)rna_path.c_str(), "\""); + boneName = strtok(NULL,"\""); + + if( boneName != NULL ) + return id_name(ob) + "_" + std::string(boneName); + else + return id_name(ob); + } + + void AnimationExporter::dae_animation(Object* ob, FCurve *fcu/*, std::string ob_name*/ , char* transformName) + { + printf("in dae animation\n"); + const char *axis_name = NULL; + char anim_id[200]; + bool has_tangents = false; + + if ( !strcmp(transformName, "rotation_quaternion") ) + { + const char *axis_names[] = {"W", "X", "Y", "Z"}; + if (fcu->array_index < 4) + axis_name = axis_names[fcu->array_index]; + } + + else + { + const char *axis_names[] = {"X", "Y", "Z"}; + if (fcu->array_index < 3) + axis_name = axis_names[fcu->array_index]; + + + } + std::string ob_name = std::string("null"); + if (ob->type == OB_ARMATURE) + { + ob_name = getObjectBoneName( ob , fcu); + BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s.%s", (char*)translate_id(ob_name).c_str(), + transformName, axis_name); + } + else + { + ob_name = id_name(ob); + BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s_%s", (char*)translate_id(ob_name).c_str(), + fcu->rna_path, axis_name); + } + + // check rna_path is one of: rotation, scale, location + + openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING); + + // create input source + std::string input_id = create_source_from_fcurve(COLLADASW::InputSemantic::INPUT, fcu, anim_id, axis_name); + + // create output source + std::string output_id = create_source_from_fcurve(COLLADASW::InputSemantic::OUTPUT, fcu, anim_id, axis_name); + + // create interpolations source + std::string interpolation_id = create_interpolation_source(fcu, anim_id, axis_name, &has_tangents); + + // handle tangents (if required) + std::string intangent_id; + std::string outtangent_id; + + if (has_tangents) { + // create in_tangent source + intangent_id = create_source_from_fcurve(COLLADASW::InputSemantic::IN_TANGENT, fcu, anim_id, axis_name); + + // create out_tangent source + outtangent_id = create_source_from_fcurve(COLLADASW::InputSemantic::OUT_TANGENT, fcu, anim_id, axis_name); + } + + + std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX; + COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id); + std::string empty; + sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id)); + sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id)); + + // this input is required + sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id)); + + if (has_tangents) { + sampler.addInput(COLLADASW::InputSemantic::IN_TANGENT, COLLADABU::URI(empty, intangent_id)); + sampler.addInput(COLLADASW::InputSemantic::OUT_TANGENT, COLLADABU::URI(empty, outtangent_id)); + } + + addSampler(sampler); + + std::string target = translate_id(ob_name) + + "/" + get_transform_sid(fcu->rna_path, -1, axis_name, true); + addChannel(COLLADABU::URI(empty, sampler_id), target); + + closeAnimation(); + } + + void AnimationExporter::write_bone_animation(Object *ob_arm, Bone *bone) + { + if (!ob_arm->adt) + return; + + //write bone animations for 3 transform types + //i=0 --> rotations + //i=1 --> scale + //i=2 --> location + 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 AnimationExporter::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; + //Fill frame array with key frame values framed at @param:transform_type + 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; + } + + // exit rest position + if (flag & ARM_RESTPOS) { + arm->flag &= ~ARM_RESTPOS; + where_is_pose(scene, ob_arm); + } + //v array will hold all values which will be exported. + if (fra.size()) { + float *values = (float*)MEM_callocN(sizeof(float) * 3 * fra.size(), "temp. anim frames"); + sample_animation(values, fra, transform_type, bone, ob_arm, pchan); + + if (transform_type == 0) { + // write x, y, z curves separately if it is rotation + float *axisValues = (float*)MEM_callocN(sizeof(float) * fra.size(), "temp. anim frames"); + + for (int i = 0; i < 3; i++) { + for (unsigned int j = 0; j < fra.size(); j++) + axisValues[j] = values[j * 3 + i]; + + dae_bone_animation(fra, axisValues, transform_type, i, id_name(ob_arm), bone->name); + } + MEM_freeN(axisValues); + } + else { + // write xyz at once if it is location or scale + dae_bone_animation(fra, values, transform_type, -1, id_name(ob_arm), bone->name); + } + + MEM_freeN(values); + } + + // restore restpos + if (flag & ARM_RESTPOS) + arm->flag = flag; + where_is_pose(scene, ob_arm); + } + + void AnimationExporter::sample_animation(float *v, std::vector<float> &frames, int type, Bone *bone, Object *ob_arm, bPoseChannel *pchan) + { + bPoseChannel *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, 1); + + // 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 AnimationExporter::dae_bone_animation(std::vector<float> &fra, float *values, 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]; + 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, false); + + 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()); + + openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING); + + // create input source + std::string input_id = create_source_from_vector(COLLADASW::InputSemantic::INPUT, fra, is_rot, anim_id, axis_name); + + // create output source + std::string output_id; + if (axis == -1) + output_id = create_xyz_source(values, fra.size(), anim_id); + else + output_id = create_source_from_array(COLLADASW::InputSemantic::OUTPUT, values, fra.size(), is_rot, anim_id, axis_name); + + // create interpolations source + std::string interpolation_id = fake_interpolation_source(fra.size(), anim_id, axis_name); + + std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX; + COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id); + std::string empty; + sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id)); + sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id)); + + // TODO create in/out tangents source + + // this input is required + sampler.addInput(COLLADASW::InputSemantic::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 AnimationExporter::convert_time(float frame) + { + return FRA2TIME(frame); + } + + float AnimationExporter::convert_angle(float angle) + { + return COLLADABU::Math::Utils::radToDegF(angle); + } + + std::string AnimationExporter::get_semantic_suffix(COLLADASW::InputSemantic::Semantics semantic) + { + switch(semantic) { + case COLLADASW::InputSemantic::INPUT: + return INPUT_SOURCE_ID_SUFFIX; + case COLLADASW::InputSemantic::OUTPUT: + return OUTPUT_SOURCE_ID_SUFFIX; + case COLLADASW::InputSemantic::INTERPOLATION: + return INTERPOLATION_SOURCE_ID_SUFFIX; + case COLLADASW::InputSemantic::IN_TANGENT: + return INTANGENT_SOURCE_ID_SUFFIX; + case COLLADASW::InputSemantic::OUT_TANGENT: + return OUTTANGENT_SOURCE_ID_SUFFIX; + default: + break; + } + return ""; + } + + void AnimationExporter::add_source_parameters(COLLADASW::SourceBase::ParameterNameList& param, + COLLADASW::InputSemantic::Semantics semantic, bool is_rot, const char *axis) + { + switch(semantic) { + case COLLADASW::InputSemantic::INPUT: + param.push_back("TIME"); + break; + case COLLADASW::InputSemantic::OUTPUT: + if (is_rot) { + param.push_back("ANGLE"); + } + else { + if (axis) { + param.push_back(axis); + } + else { //assumes if axis isn't specified all axi are added + param.push_back("X"); + param.push_back("Y"); + param.push_back("Z"); + } + } + break; + case COLLADASW::InputSemantic::IN_TANGENT: + case COLLADASW::InputSemantic::OUT_TANGENT: + param.push_back("X"); + param.push_back("Y"); + break; + default: + break; + } + } + + void AnimationExporter::get_source_values(BezTriple *bezt, COLLADASW::InputSemantic::Semantics semantic, bool rotation, float *values, int *length) + { + switch (semantic) { + case COLLADASW::InputSemantic::INPUT: + *length = 1; + values[0] = convert_time(bezt->vec[1][0]); + break; + case COLLADASW::InputSemantic::OUTPUT: + *length = 1; + if (rotation) { + values[0] = convert_angle(bezt->vec[1][1]); + } + else { + values[0] = bezt->vec[1][1]; + } + break; + + case COLLADASW::InputSemantic::IN_TANGENT: + *length = 2; + values[0] = convert_time(bezt->vec[0][0]); + if (bezt->ipo != BEZT_IPO_BEZ) { + // We're in a mixed interpolation scenario, set zero as it's irrelevant but value might contain unused data + values[0] = 0; + values[1] = 0; + } else if (rotation) { + values[1] = convert_angle(bezt->vec[0][1]); + } else { + values[1] = bezt->vec[0][1]; + } + break; + + case COLLADASW::InputSemantic::OUT_TANGENT: + *length = 2; + values[0] = convert_time(bezt->vec[2][0]); + if (bezt->ipo != BEZT_IPO_BEZ) { + // We're in a mixed interpolation scenario, set zero as it's irrelevant but value might contain unused data + values[0] = 0; + values[1] = 0; + } else if (rotation) { + values[1] = convert_angle(bezt->vec[2][1]); + } else { + values[1] = bezt->vec[2][1]; + } + break; + break; + default: + *length = 0; + break; + } + } + + std::string AnimationExporter::create_source_from_fcurve(COLLADASW::InputSemantic::Semantics semantic, FCurve *fcu, const std::string& anim_id, const char *axis_name) + { + std::string source_id = anim_id + get_semantic_suffix(semantic); + + //bool is_rotation = !strcmp(fcu->rna_path, "rotation"); + bool is_rotation = false; + + if (strstr(fcu->rna_path, "rotation")) is_rotation = true; + + COLLADASW::FloatSourceF source(mSW); + source.setId(source_id); + source.setArrayId(source_id + ARRAY_ID_SUFFIX); + source.setAccessorCount(fcu->totvert); + + switch (semantic) { + case COLLADASW::InputSemantic::INPUT: + case COLLADASW::InputSemantic::OUTPUT: + source.setAccessorStride(1); + break; + case COLLADASW::InputSemantic::IN_TANGENT: + case COLLADASW::InputSemantic::OUT_TANGENT: + source.setAccessorStride(2); + break; + } + + + COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); + add_source_parameters(param, semantic, is_rotation, axis_name); + + source.prepareToAppendValues(); + + for (unsigned int i = 0; i < fcu->totvert; i++) { + float values[3]; // be careful! + int length = 0; + + get_source_values(&fcu->bezt[i], semantic, is_rotation, values, &length); + for (int j = 0; j < length; j++) + source.appendValues(values[j]); + } + + source.finish(); + + return source_id; + } + //Currently called only to get OUTPUT source values ( if rotation and hence the axis is also specified ) + std::string AnimationExporter::create_source_from_array(COLLADASW::InputSemantic::Semantics 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(semantic); + + COLLADASW::FloatSourceF source(mSW); + source.setId(source_id); + source.setArrayId(source_id + ARRAY_ID_SUFFIX); + source.setAccessorCount(tot); + source.setAccessorStride(1); + + COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); + add_source_parameters(param, semantic, is_rot, axis_name); + + source.prepareToAppendValues(); + + for (int i = 0; i < tot; i++) { + float val = v[i]; + ////if (semantic == COLLADASW::InputSemantic::INPUT) + // val = convert_time(val); + //else + if (is_rot) + val = convert_angle(val); + source.appendValues(val); + } + + source.finish(); + + return source_id; + } +// only used for sources with INPUT semantic + std::string AnimationExporter::create_source_from_vector(COLLADASW::InputSemantic::Semantics semantic, std::vector<float> &fra, bool is_rot, const std::string& anim_id, const char *axis_name) + { + std::string source_id = anim_id + get_semantic_suffix(semantic); + + COLLADASW::FloatSourceF source(mSW); + source.setId(source_id); + source.setArrayId(source_id + ARRAY_ID_SUFFIX); + source.setAccessorCount(fra.size()); + source.setAccessorStride(1); + + COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); + add_source_parameters(param, semantic, is_rot, axis_name); + + source.prepareToAppendValues(); + + std::vector<float>::iterator it; + for (it = fra.begin(); it != fra.end(); it++) { + float val = *it; + //if (semantic == COLLADASW::InputSemantic::INPUT) + val = convert_time(val); + /*else if (is_rot) + val = convert_angle(val);*/ + source.appendValues(val); + } + + source.finish(); + + return source_id; + } + + // only used for sources with OUTPUT semantic ( locations and scale) + std::string AnimationExporter::create_xyz_source(float *v, int tot, const std::string& anim_id) + { + COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT; + std::string source_id = anim_id + get_semantic_suffix(semantic); + + 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); + + source.prepareToAppendValues(); + + for (int i = 0; i < tot; i++) { + source.appendValues(*v, *(v + 1), *(v + 2)); + v += 3; + } + + source.finish(); + + return source_id; + } + + std::string AnimationExporter::create_interpolation_source(FCurve *fcu, const std::string& anim_id, const char *axis_name, bool *has_tangents) + { + std::string source_id = anim_id + get_semantic_suffix(COLLADASW::InputSemantic::INTERPOLATION); + + COLLADASW::NameSource source(mSW); + source.setId(source_id); + source.setArrayId(source_id + ARRAY_ID_SUFFIX); + source.setAccessorCount(fcu->totvert); + source.setAccessorStride(1); + + COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); + param.push_back("INTERPOLATION"); + + source.prepareToAppendValues(); + + *has_tangents = false; + + for (unsigned int i = 0; i < fcu->totvert; i++) { + if (fcu->bezt[i].ipo==BEZT_IPO_BEZ) { + source.appendValues(BEZIER_NAME); + *has_tangents = true; + } else if (fcu->bezt[i].ipo==BEZT_IPO_CONST) { + source.appendValues(STEP_NAME); + } else { // BEZT_IPO_LIN + source.appendValues(LINEAR_NAME); + } + } + // unsupported? -- HERMITE, CARDINAL, BSPLINE, NURBS + + source.finish(); + + return source_id; + } + + std::string AnimationExporter::fake_interpolation_source(int tot, const std::string& anim_id, const char *axis_name) + { + std::string source_id = anim_id + get_semantic_suffix(COLLADASW::InputSemantic::INTERPOLATION); + + COLLADASW::NameSource source(mSW); + source.setId(source_id); + source.setArrayId(source_id + ARRAY_ID_SUFFIX); + source.setAccessorCount(tot); + source.setAccessorStride(1); + + COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); + param.push_back("INTERPOLATION"); + + source.prepareToAppendValues(); + + for (int i = 0; i < tot; i++) { + source.appendValues(LINEAR_NAME); + } + + source.finish(); + + return source_id; + } + + // for rotation, axis name is always appended and the value of append_axis is ignored + std::string AnimationExporter::get_transform_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis) + { + std::string tm_name; + + // when given rna_path, determine tm_type from it + if (rna_path) { + char *name = extract_transform_name(rna_path); + + if (!strcmp(name, "rotation_euler")) + tm_type = 0; + else if (!strcmp(name, "rotation_quaternion")) + tm_type = 1; + else if (!strcmp(name, "scale")) + tm_type = 2; + else if (!strcmp(name, "location")) + tm_type = 3; + else + tm_type = -1; + } + + switch (tm_type) { + case 0: + return std::string("rotation_euler.") + std::string(axis_name) + ".ANGLE"; + case 1: + return std::string("rotation_quaternion.") + std::string(axis_name) + ".ANGLE"; + case 2: + tm_name = "scale"; + break; + case 3: + tm_name = "location"; + break; + default: + tm_name = ""; + break; + } + + if (tm_name.size()) { + if (append_axis) + return tm_name + std::string(".") + std::string(axis_name); + else + return tm_name; + } + + return std::string(""); + } + + char* AnimationExporter::extract_transform_name(char *rna_path) + { + char *dot = strrchr(rna_path, '.'); + return dot ? (dot + 1) : rna_path; + } + + void AnimationExporter::find_frames(Object *ob, std::vector<float> &fra, const char *prefix, const char *tm_name) + { + 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 (unsigned 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); + } + } + } + + // keep the keys in ascending order + std::sort(fra.begin(), fra.end()); + } + + void AnimationExporter::find_rotation_frames(Object *ob, std::vector<float> &fra, const char *prefix, int rotmode) + { + 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 AnimationExporter::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 { + fcu->flag &= ~FCURVE_DISABLED; + } + } + } + + bool AnimationExporter::hasAnimations(Scene *sce) + { + Base *base= (Base*) sce->base.first; + while(base) { + Object *ob = base->object; + + FCurve *fcu = 0; + if(ob->adt && ob->adt->action) + fcu = (FCurve*)ob->adt->action->curves.first; + + //The Scene has animations if object type is armature or object has f-curve + if ((ob->type == OB_ARMATURE && ob->data) || fcu) { + return true; + } + base= base->next; + } + return false; + } diff --git a/source/blender/collada/AnimationExporter.h b/source/blender/collada/AnimationExporter.h new file mode 100644 index 00000000000..0368e34dc42 --- /dev/null +++ b/source/blender/collada/AnimationExporter.h @@ -0,0 +1,142 @@ +/* + * $Id: DocumentExporter.cpp 36898 2011-05-25 17:14:31Z phabtar $ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Chingiz Dyussenov, Arystanbek Dyussenov, Jan Diederich, Tod Liverseed. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include <stdlib.h> +#include <stdio.h> +#include <math.h> +extern "C" +{ +#include "DNA_scene_types.h" +#include "DNA_object_types.h" +#include "DNA_anim_types.h" +#include "DNA_action_types.h" +#include "DNA_curve_types.h" +#include "DNA_armature_types.h" + +#include "BKE_DerivedMesh.h" +#include "BKE_fcurve.h" +#include "BKE_animsys.h" +#ifdef NAN_BUILDINFO +extern char build_rev[]; +#endif +} + +#include "MEM_guardedalloc.h" + +#include "BKE_action.h" // pose functions +#include "BKE_armature.h" +#include "BKE_object.h" + +#include "BLI_math.h" +#include "BLI_string.h" +#include "BLI_listbase.h" + +#include "RNA_access.h" + +#include "COLLADASWSource.h" +#include "COLLADASWInstanceGeometry.h" +#include "COLLADASWInputList.h" +#include "COLLADASWPrimitves.h" +#include "COLLADASWVertices.h" +#include "COLLADASWLibraryAnimations.h" +#include "COLLADASWParamTemplate.h" +#include "COLLADASWParamBase.h" +#include "COLLADASWSampler.h" +#include "COLLADASWConstants.h" +#include "COLLADASWBaseInputElement.h" + +#include "collada_internal.h" + +#include <vector> +#include <algorithm> // std::find + +class AnimationExporter: COLLADASW::LibraryAnimations +{ +private: + Scene *scene; + COLLADASW::StreamWriter *sw; + +public: + + AnimationExporter(COLLADASW::StreamWriter *sw): COLLADASW::LibraryAnimations(sw) { this->sw = sw; } + + + void exportAnimations(Scene *sce); + + // called for each exported object + void operator() (Object *ob); + +protected: + + void dae_animation(Object* ob, FCurve *fcu, char* transformName); + + void write_bone_animation(Object *ob_arm, Bone *bone); + + void sample_and_write_bone_animation(Object *ob_arm, Bone *bone, int transform_type); + + void sample_animation(float *v, std::vector<float> &frames, int type, Bone *bone, Object *ob_arm, bPoseChannel *pChan); + + // 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); + + float convert_time(float frame); + + float convert_angle(float angle); + + std::string get_semantic_suffix(COLLADASW::InputSemantic::Semantics semantic); + + void add_source_parameters(COLLADASW::SourceBase::ParameterNameList& param, + COLLADASW::InputSemantic::Semantics semantic, bool is_rot, const char *axis); + + void get_source_values(BezTriple *bezt, COLLADASW::InputSemantic::Semantics semantic, bool rotation, float *values, int *length); + + std::string create_source_from_fcurve(COLLADASW::InputSemantic::Semantics semantic, FCurve *fcu, const std::string& anim_id, const char *axis_name); + + std::string create_source_from_array(COLLADASW::InputSemantic::Semantics semantic, float *v, int tot, bool is_rot, const std::string& anim_id, const char *axis_name); + + std::string create_source_from_vector(COLLADASW::InputSemantic::Semantics semantic, std::vector<float> &fra, bool is_rot, const std::string& anim_id, const char *axis_name); + + std::string create_xyz_source(float *v, int tot, const std::string& anim_id); + + std::string create_interpolation_source(FCurve *fcu, const std::string& anim_id, const char *axis_name, bool *has_tangents); + + std::string fake_interpolation_source(int tot, const std::string& anim_id, const char *axis_name); + // for rotation, axis name is always appended and the value of append_axis is ignored + std::string get_transform_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis); + + void find_frames(Object *ob, std::vector<float> &fra, const char *prefix, const char *tm_name); + + void find_rotation_frames(Object *ob, std::vector<float> &fra, const char *prefix, int rotmode); + + // 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); + + bool hasAnimations(Scene *sce); + + char* extract_transform_name(char *rna_path); + + std::string getObjectBoneName ( Object *ob,const FCurve * fcu); +};
\ No newline at end of file diff --git a/source/blender/collada/CMakeLists.txt b/source/blender/collada/CMakeLists.txt index a7e7c973f36..7c43c09bc12 100644 --- a/source/blender/collada/CMakeLists.txt +++ b/source/blender/collada/CMakeLists.txt @@ -62,6 +62,7 @@ endif() set(SRC AnimationImporter.cpp + AnimationExporter.cpp ArmatureExporter.cpp ArmatureImporter.cpp CameraExporter.cpp @@ -84,6 +85,7 @@ set(SRC collada_utils.cpp AnimationImporter.h + AnimationExporter.h ArmatureExporter.h ArmatureImporter.h CameraExporter.h diff --git a/source/blender/collada/DocumentExporter.cpp b/source/blender/collada/DocumentExporter.cpp index 00daac60281..0bdf41f15eb 100644 --- a/source/blender/collada/DocumentExporter.cpp +++ b/source/blender/collada/DocumentExporter.cpp @@ -114,6 +114,7 @@ extern char build_rev[]; #include "TransformWriter.h" #include "ArmatureExporter.h" +#include "AnimationExporter.h" #include "CameraExporter.h" #include "EffectExporter.h" #include "GeometryExporter.h" @@ -298,636 +299,6 @@ public: // TODO: it would be better to instantiate animations rather than create a new one per object // COLLADA allows this through multiple <channel>s in <animation>. // For this to work, we need to know objects that use a certain action. -class AnimationExporter: COLLADASW::LibraryAnimations -{ - Scene *scene; - COLLADASW::StreamWriter *sw; - -public: - - AnimationExporter(COLLADASW::StreamWriter *sw): COLLADASW::LibraryAnimations(sw) { this->sw = sw; } - - - - void exportAnimations(Scene *sce) - { - if(hasAnimations(sce)) { - this->scene = sce; - - openLibrary(); - - forEachObjectInScene(sce, *this); - - closeLibrary(); - } - } - - // 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]; - - 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]); - - // check rna_path is one of: rotation, scale, location - - openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING); - - // create input source - std::string input_id = create_source_from_fcurve(COLLADASW::InputSemantic::INPUT, fcu, anim_id, axis_name); - - // create output source - std::string output_id = create_source_from_fcurve(COLLADASW::InputSemantic::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(sw, sampler_id); - std::string empty; - sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id)); - sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id)); - - // this input is required - sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id)); - - addSampler(sampler); - - std::string target = translate_id(ob_name) - + "/" + get_transform_sid(fcu->rna_path, -1, axis_name, true); - 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; - } - - // 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 (unsigned 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, 1); - - // 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]; - 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, false); - - 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()); - - openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING); - - // create input source - std::string input_id = create_source_from_vector(COLLADASW::InputSemantic::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(COLLADASW::InputSemantic::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(sw, sampler_id); - std::string empty; - sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id)); - sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id)); - - // TODO create in/out tangents source - - // this input is required - sampler.addInput(COLLADASW::InputSemantic::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) - { - return COLLADABU::Math::Utils::radToDegF(angle); - } - - std::string get_semantic_suffix(COLLADASW::InputSemantic::Semantics semantic) - { - switch(semantic) { - case COLLADASW::InputSemantic::INPUT: - return INPUT_SOURCE_ID_SUFFIX; - case COLLADASW::InputSemantic::OUTPUT: - return OUTPUT_SOURCE_ID_SUFFIX; - case COLLADASW::InputSemantic::INTERPOLATION: - return INTERPOLATION_SOURCE_ID_SUFFIX; - case COLLADASW::InputSemantic::IN_TANGENT: - return INTANGENT_SOURCE_ID_SUFFIX; - case COLLADASW::InputSemantic::OUT_TANGENT: - return OUTTANGENT_SOURCE_ID_SUFFIX; - default: - break; - } - return ""; - } - - void add_source_parameters(COLLADASW::SourceBase::ParameterNameList& param, - COLLADASW::InputSemantic::Semantics semantic, bool is_rot, const char *axis) - { - switch(semantic) { - case COLLADASW::InputSemantic::INPUT: - param.push_back("TIME"); - break; - case COLLADASW::InputSemantic::OUTPUT: - if (is_rot) { - param.push_back("ANGLE"); - } - else { - if (axis) { - param.push_back(axis); - } - else { - param.push_back("X"); - param.push_back("Y"); - param.push_back("Z"); - } - } - break; - case COLLADASW::InputSemantic::IN_TANGENT: - case COLLADASW::InputSemantic::OUT_TANGENT: - param.push_back("X"); - param.push_back("Y"); - break; - default: - break; - } - } - - void get_source_values(BezTriple *bezt, COLLADASW::InputSemantic::Semantics semantic, bool rotation, float *values, int *length) - { - switch (semantic) { - case COLLADASW::InputSemantic::INPUT: - *length = 1; - values[0] = convert_time(bezt->vec[1][0]); - break; - case COLLADASW::InputSemantic::OUTPUT: - *length = 1; - if (rotation) { - values[0] = convert_angle(bezt->vec[1][1]); - } - else { - values[0] = bezt->vec[1][1]; - } - break; - case COLLADASW::InputSemantic::IN_TANGENT: - case COLLADASW::InputSemantic::OUT_TANGENT: - // XXX - *length = 2; - break; - default: - *length = 0; - break; - } - } - - std::string create_source_from_fcurve(COLLADASW::InputSemantic::Semantics semantic, FCurve *fcu, const std::string& anim_id, const char *axis_name) - { - std::string source_id = anim_id + get_semantic_suffix(semantic); - - //bool is_rotation = !strcmp(fcu->rna_path, "rotation"); - bool is_rotation = false; - - if (strstr(fcu->rna_path, "rotation")) is_rotation = true; - - COLLADASW::FloatSourceF source(mSW); - source.setId(source_id); - source.setArrayId(source_id + ARRAY_ID_SUFFIX); - source.setAccessorCount(fcu->totvert); - source.setAccessorStride(1); - - COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); - add_source_parameters(param, semantic, is_rotation, axis_name); - - source.prepareToAppendValues(); - - for (unsigned int i = 0; i < fcu->totvert; i++) { - float values[3]; // be careful! - int length = 0; - - get_source_values(&fcu->bezt[i], semantic, is_rotation, values, &length); - for (int j = 0; j < length; j++) - source.appendValues(values[j]); - } - - source.finish(); - - return source_id; - } - - std::string create_source_from_array(COLLADASW::InputSemantic::Semantics 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(semantic); - - COLLADASW::FloatSourceF source(mSW); - source.setId(source_id); - source.setArrayId(source_id + ARRAY_ID_SUFFIX); - source.setAccessorCount(tot); - source.setAccessorStride(1); - - COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); - add_source_parameters(param, semantic, is_rot, axis_name); - - source.prepareToAppendValues(); - - for (int i = 0; i < tot; i++) { - float val = v[i]; - if (semantic == COLLADASW::InputSemantic::INPUT) - val = convert_time(val); - else if (is_rot) - val = convert_angle(val); - source.appendValues(val); - } - - source.finish(); - - return source_id; - } - - std::string create_source_from_vector(COLLADASW::InputSemantic::Semantics semantic, std::vector<float> &fra, bool is_rot, const std::string& anim_id, const char *axis_name) - { - std::string source_id = anim_id + get_semantic_suffix(semantic); - - COLLADASW::FloatSourceF source(mSW); - source.setId(source_id); - source.setArrayId(source_id + ARRAY_ID_SUFFIX); - source.setAccessorCount(fra.size()); - source.setAccessorStride(1); - - COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); - add_source_parameters(param, semantic, is_rot, axis_name); - - source.prepareToAppendValues(); - - std::vector<float>::iterator it; - for (it = fra.begin(); it != fra.end(); it++) { - float val = *it; - if (semantic == COLLADASW::InputSemantic::INPUT) - val = convert_time(val); - else if (is_rot) - val = convert_angle(val); - source.appendValues(val); - } - - source.finish(); - - return source_id; - } - - // only used for sources with OUTPUT semantic - std::string create_xyz_source(float *v, int tot, const std::string& anim_id) - { - COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT; - std::string source_id = anim_id + get_semantic_suffix(semantic); - - 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); - - source.prepareToAppendValues(); - - for (int i = 0; i < tot; i++) { - source.appendValues(*v, *(v + 1), *(v + 2)); - v += 3; - } - - source.finish(); - - return source_id; - } - - std::string create_interpolation_source(int tot, const std::string& anim_id, const char *axis_name) - { - std::string source_id = anim_id + get_semantic_suffix(COLLADASW::InputSemantic::INTERPOLATION); - - COLLADASW::NameSource source(mSW); - source.setId(source_id); - source.setArrayId(source_id + ARRAY_ID_SUFFIX); - source.setAccessorCount(tot); - source.setAccessorStride(1); - - COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); - param.push_back("INTERPOLATION"); - - source.prepareToAppendValues(); - - for (int i = 0; i < tot; i++) { - source.appendValues(LINEAR_NAME); - } - - source.finish(); - - return source_id; - } - - // for rotation, axis name is always appended and the value of append_axis is ignored - std::string get_transform_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis) - { - std::string tm_name; - - // when given rna_path, determine tm_type from it - if (rna_path) { - char *name = extract_transform_name(rna_path); - - if (strstr(name, "rotation")) - tm_type = 0; - else if (!strcmp(name, "scale")) - tm_type = 1; - else if (!strcmp(name, "location")) - tm_type = 2; - else - tm_type = -1; - } - - switch (tm_type) { - case 0: - return std::string("rotation") + std::string(axis_name) + ".ANGLE"; - case 1: - tm_name = "scale"; - break; - case 2: - tm_name = "location"; - break; - default: - tm_name = ""; - break; - } - - if (tm_name.size()) { - if (append_axis) - return tm_name + std::string(".") + std::string(axis_name); - else - return tm_name; - } - - return std::string(""); - } - - char *extract_transform_name(char *rna_path) - { - char *dot = strrchr(rna_path, '.'); - return dot ? (dot + 1) : rna_path; - } - - void find_frames(Object *ob, std::vector<float> &fra, const char *prefix, const char *tm_name) - { - 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 (unsigned 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); - } - } - } - - // keep the keys in ascending order - std::sort(fra.begin(), fra.end()); - } - - void find_rotation_frames(Object *ob, std::vector<float> &fra, const char *prefix, int rotmode) - { - 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 { - fcu->flag &= ~FCURVE_DISABLED; - } - } - } - - bool hasAnimations(Scene *sce) - { - Base *base= (Base*) sce->base.first; - while(base) { - Object *ob = base->object; - - FCurve *fcu = 0; - if(ob->adt && ob->adt->action) - fcu = (FCurve*)ob->adt->action->curves.first; - - if ((ob->type == OB_ARMATURE && ob->data) || fcu) { - return true; - } - base= base->next; - } - return false; - } -}; void DocumentExporter::exportCurrentScene(Scene *sce, const char* filename) { diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index 9145cc2b79d..9eb9e3ecd9a 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -38,7 +38,7 @@ #include "BLI_blenlib.h" #include "BLI_utildefines.h" - +#include "BKE_library.h" #include "DNA_anim_types.h" #include "DNA_object_types.h" @@ -515,12 +515,34 @@ void ANIM_fcurve_delete_from_animdata (bAnimContext *ac, AnimData *adt, FCurve * * - Drivers * - TODO... some others? */ - if (fcu->grp) - action_groups_remove_channel(adt->action, fcu); - else if ((ac) && (ac->datatype == ANIMCONT_DRIVERS)) + if ((ac) && (ac->datatype == ANIMCONT_DRIVERS)) { + /* driver F-Curve */ BLI_remlink(&adt->drivers, fcu); - else if (adt->action) - BLI_remlink(&adt->action->curves, fcu); + } + else if (adt->action) { + /* remove from group or action, whichever one "owns" the F-Curve */ + if (fcu->grp) + action_groups_remove_channel(adt->action, fcu); + else + BLI_remlink(&adt->action->curves, fcu); + + /* if action has no more F-Curves as a result of this, unlink it from + * AnimData if it did not come from a NLA Strip being tweaked. + * + * This is done so that we don't have dangling Object+Action entries in + * channel list that are empty, and linger around long after the data they + * are for has disappeared (and probably won't come back). + */ + // XXX: does everybody always want this? + /* XXX: there's a problem where many actions could build up in the file if multiple + * full add/delete cycles are performed on the same objects, but assume that this is rare + */ + if ((adt->action->curves.first == NULL) && (adt->flag & ADT_NLA_EDIT_ON)==0) + { + id_us_min(&adt->action->id); + adt->action = NULL; + } + } /* free the F-Curve itself */ free_fcurve(fcu); diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c index c6e55427034..1fb2317cdbb 100644 --- a/source/blender/editors/animation/anim_markers.c +++ b/source/blender/editors/animation/anim_markers.c @@ -1500,3 +1500,14 @@ void ED_marker_keymap(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "MARKER_OT_camera_bind", BKEY, KM_PRESS, KM_CTRL, 0); #endif } + +/* to be called from animation editor keymaps, see note below */ +void ED_marker_keymap_animedit_conflictfree(wmKeyMap *keymap) +{ + /* duplicate of some marker-hotkeys but without the bounds checking + * since these are handy to be able to do unrestricted and won't conflict + * with primary function hotkeys (Usability tweak [#27469]) + */ + WM_keymap_add_item(keymap, "MARKER_OT_add", MKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "MARKER_OT_rename", MKEY, KM_PRESS, KM_CTRL, 0); +} diff --git a/source/blender/editors/animation/fmodifier_ui.c b/source/blender/editors/animation/fmodifier_ui.c index 954928fc486..8197d6b25dd 100644 --- a/source/blender/editors/animation/fmodifier_ui.c +++ b/source/blender/editors/animation/fmodifier_ui.c @@ -604,7 +604,7 @@ static void draw_modifier__stepped(uiLayout *layout, ID *id, FModifier *fcm, sho void ANIM_uiTemplate_fmodifier_draw (uiLayout *layout, ID *id, ListBase *modifiers, FModifier *fcm) { FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); - uiLayout *box, *row, *subrow; + uiLayout *box, *row, *subrow, *col; uiBlock *block; uiBut *but; short width= 314; @@ -622,7 +622,7 @@ void ANIM_uiTemplate_fmodifier_draw (uiLayout *layout, ID *id, ListBase *modifie block= uiLayoutGetBlock(row); // err... /* left-align -------------------------------------------- */ - subrow= uiLayoutRow(row, 0); + subrow= uiLayoutRow(row, 1); uiLayoutSetAlignment(subrow, UI_LAYOUT_ALIGN_LEFT); uiBlockSetEmboss(block, UI_EMBOSSN); @@ -640,7 +640,7 @@ void ANIM_uiTemplate_fmodifier_draw (uiLayout *layout, ID *id, ListBase *modifie uiItemL(subrow, "<Unknown Modifier>", ICON_NONE); /* right-align ------------------------------------------- */ - subrow= uiLayoutRow(row, 0); + subrow= uiLayoutRow(row, 1); uiLayoutSetAlignment(subrow, UI_LAYOUT_ALIGN_RIGHT); @@ -694,6 +694,44 @@ void ANIM_uiTemplate_fmodifier_draw (uiLayout *layout, ID *id, ListBase *modifie default: /* unknown type */ break; } + + /* one last panel below this: FModifier range */ + // TODO: experiment with placement of this + { + box = uiLayoutBox(layout); + + /* restricted range ----------------------------------------------------- */ + col = uiLayoutColumn(box, 1); + + /* top row: use restricted range */ + row= uiLayoutRow(col, 1); + uiItemR(row, &ptr, "use_restricted_range", 0, NULL, ICON_NONE); + + if (fcm->flag & FMODIFIER_FLAG_RANGERESTRICT) { + /* second row: settings */ + row = uiLayoutRow(col, 1); + + uiItemR(row, &ptr, "frame_start", 0, "Start", ICON_NONE); + uiItemR(row, &ptr, "frame_end", 0, "End", ICON_NONE); + + /* third row: blending influence */ + row = uiLayoutRow(col, 1); + + uiItemR(row, &ptr, "blend_in", 0, "In", ICON_NONE); + uiItemR(row, &ptr, "blend_out", 0, "Out", ICON_NONE); + } + + /* influence -------------------------------------------------------------- */ + col = uiLayoutColumn(box, 1); + + /* top row: use influence */ + uiItemR(col, &ptr, "use_influence", 0, NULL, ICON_NONE); + + if (fcm->flag & FMODIFIER_FLAG_USEINFLUENCE) { + /* second row: influence value */ + uiItemR(col, &ptr, "influence", 0, NULL, ICON_NONE); + } + } } } diff --git a/source/blender/editors/animation/keyframes_general.c b/source/blender/editors/animation/keyframes_general.c index f111339b963..e2afda04d30 100644 --- a/source/blender/editors/animation/keyframes_general.c +++ b/source/blender/editors/animation/keyframes_general.c @@ -111,7 +111,7 @@ void delete_fcurve_keys(FCurve *fcu) { int i; - if(fcu->bezt==NULL) /* ignore baked curves */ + if (fcu->bezt==NULL) /* ignore baked curves */ return; /* Delete selected BezTriples */ @@ -124,7 +124,7 @@ void delete_fcurve_keys(FCurve *fcu) } /* Free the array of BezTriples if there are not keyframes */ - if(fcu->totvert == 0) + if (fcu->totvert == 0) clear_fcurve_keys(fcu); } diff --git a/source/blender/editors/animation/keyingsets.c b/source/blender/editors/animation/keyingsets.c index c525c9af626..69e7c4eb73a 100644 --- a/source/blender/editors/animation/keyingsets.c +++ b/source/blender/editors/animation/keyingsets.c @@ -224,6 +224,7 @@ static int add_empty_ks_path_exec (bContext *C, wmOperator *op) ksp->groupmode= KSP_GROUP_KSNAME; // XXX? ksp->idtype= ID_OB; + ksp->flag= KSP_FLAG_WHOLE_ARRAY; return OPERATOR_FINISHED; } @@ -782,19 +783,19 @@ void ANIM_keying_sets_menu_setup (bContext *C, const char title[], const char op * - these are listed in the order in which they were defined for the active scene */ if (scene->keyingsets.first) { - for (ks= scene->keyingsets.first; ks; ks= ks->next) { + for (ks= scene->keyingsets.first; ks; ks=ks->next, i++) { if (ANIM_keyingset_context_ok_poll(C, ks)) - uiItemIntO(layout, ks->name, ICON_NONE, op_name, "type", i++); + uiItemIntO(layout, ks->name, ICON_NONE, op_name, "type", i); } uiItemS(layout); } /* builtin Keying Sets */ i= -1; - for (ks= builtin_keyingsets.first; ks; ks= ks->next) { + for (ks= builtin_keyingsets.first; ks; ks=ks->next, i--) { /* only show KeyingSet if context is suitable */ if (ANIM_keyingset_context_ok_poll(C, ks)) - uiItemEnumO_value(layout, ks->name, ICON_NONE, op_name, "type", i--); + uiItemEnumO_value(layout, ks->name, ICON_NONE, op_name, "type", i); } uiPupMenuEnd(C, pup); diff --git a/source/blender/editors/armature/poseobject.c b/source/blender/editors/armature/poseobject.c index 8176aa5893b..fa5fecbd9d0 100644 --- a/source/blender/editors/armature/poseobject.c +++ b/source/blender/editors/armature/poseobject.c @@ -1002,6 +1002,14 @@ static int pose_paste_exec (bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } + /* if selOnly option is enabled, if user hasn't selected any bones, + * just go back to default behaviour to be more in line with other pose tools + */ + if (selOnly) { + if (CTX_DATA_COUNT(C, selected_pose_bones) == 0) + selOnly = 0; + } + /* Safely merge all of the channels in the buffer pose into any existing pose */ for (chan= g_posebuf->chanbase.first; chan; chan=chan->next) { if (chan->flag & POSE_KEY) { @@ -1169,7 +1177,7 @@ void POSE_OT_paste (wmOperatorType *ot) /* properties */ RNA_def_boolean(ot->srna, "flipped", 0, "Flipped on X-Axis", "Paste the stored pose flipped on to current pose"); - RNA_def_boolean(ot->srna, "selected_mask", 0, "On Selected Only", "Only paste the stored pose on to selected bones in the current pose"); + RNA_def_boolean(ot->srna, "selected_mask", 1, "On Selected Only", "Only paste the stored pose on to selected bones in the current pose"); } /* ********************************************** */ diff --git a/source/blender/editors/include/ED_markers.h b/source/blender/editors/include/ED_markers.h index f804e052301..a8e91add348 100644 --- a/source/blender/editors/include/ED_markers.h +++ b/source/blender/editors/include/ED_markers.h @@ -34,6 +34,7 @@ #define ED_MARKERS_H struct wmKeyConfig; +struct wmKeyMap; struct bContext; struct bAnimContext; struct Scene; @@ -72,6 +73,9 @@ void ED_operatortypes_marker(void); /* called in screen_ops.c:ED_keymap_screen() */ void ED_marker_keymap(struct wmKeyConfig *keyconf); +/* called in animation editors - keymap defines */ +void ED_marker_keymap_animedit_conflictfree(struct wmKeyMap *keymap); + /* debugging only */ void debug_markers_print_list(struct ListBase *markers); diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index 6527e0140b8..bbabe968bb2 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -663,7 +663,7 @@ void ui_theme_init_default(void) SETCOL(btheme->tipo.handle_vertex, 0, 0, 0, 255); SETCOL(btheme->tipo.handle_vertex_select, 255, 133, 0, 255); - btheme->tipo.handle_vertex_size= 3; + btheme->tipo.handle_vertex_size= 4; SETCOL(btheme->tipo.ds_channel, 82, 96, 110, 255); SETCOL(btheme->tipo.ds_subchannel, 124, 137, 150, 255); diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c index 450bd70a568..a3df25824a4 100644 --- a/source/blender/editors/object/object_constraint.c +++ b/source/blender/editors/object/object_constraint.c @@ -567,7 +567,8 @@ static bConstraint *edit_constraint_property_get(wmOperator *op, Object *ob, int } con = constraints_findByName(list, constraint_name); - printf("constraint found = %p, %s\n", (void *)con, (con)?con->name:"<Not found>"); + //if (G.f & G_DEBUG) + //printf("constraint found = %p, %s\n", (void *)con, (con)?con->name:"<Not found>"); if (con && (type != 0) && (con->type != type)) con = NULL; diff --git a/source/blender/editors/space_action/action_ops.c b/source/blender/editors/space_action/action_ops.c index 6c3f80cda41..2ccad308676 100644 --- a/source/blender/editors/space_action/action_ops.c +++ b/source/blender/editors/space_action/action_ops.c @@ -40,6 +40,7 @@ #include "BLI_blenlib.h" #include "ED_anim_api.h" +#include "ED_markers.h" #include "ED_transform.h" #include "action_intern.h" @@ -162,7 +163,7 @@ static void action_keymap_keyframes (wmKeyConfig *keyconf, wmKeyMap *keymap) /* menu + set setting */ WM_keymap_add_item(keymap, "ACTION_OT_handle_type", VKEY, KM_PRESS, 0, 0); - WM_keymap_add_item(keymap, "ACTION_OT_interpolation_type", TKEY, KM_PRESS, KM_SHIFT, 0); + WM_keymap_add_item(keymap, "ACTION_OT_interpolation_type", TKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "ACTION_OT_extrapolation_type", EKEY, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "ACTION_OT_keyframe_type", RKEY, KM_PRESS, 0, 0); @@ -193,6 +194,9 @@ static void action_keymap_keyframes (wmKeyConfig *keyconf, wmKeyMap *keymap) /* transform system */ transform_keymap_for_space(keyconf, keymap, SPACE_ACTION); + + /* special markers hotkeys for anim editors: see note in definition of this function */ + ED_marker_keymap_animedit_conflictfree(keymap); } /* --------------- */ diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c index fb1144b4fa8..3073ff13075 100644 --- a/source/blender/editors/space_graph/graph_buttons.c +++ b/source/blender/editors/space_graph/graph_buttons.c @@ -472,7 +472,7 @@ static void graph_panel_driverVar__locDiff(uiLayout *layout, ID *id, DriverVar * uiItemPointerR(col, &dtar_ptr, "bone_target", &tar_ptr, "bones", "", ICON_BONE_DATA); } - uiItemR(col, &dtar_ptr, "use_local_space_transform", 0, NULL, ICON_NONE); + uiItemR(col, &dtar_ptr, "transform_space", 0, NULL, ICON_NONE); col= uiLayoutColumn(layout, 1); uiTemplateAnyID(col, &dtar2_ptr, "id", "id_type", "Ob/Bone 2:"); @@ -484,7 +484,7 @@ static void graph_panel_driverVar__locDiff(uiLayout *layout, ID *id, DriverVar * uiItemPointerR(col, &dtar2_ptr, "bone_target", &tar_ptr, "bones", "", ICON_BONE_DATA); } - uiItemR(col, &dtar2_ptr, "use_local_space_transform", 0, NULL, ICON_NONE); + uiItemR(col, &dtar2_ptr, "transform_space", 0, NULL, ICON_NONE); } /* settings for 'transform channel' driver variable type */ @@ -493,7 +493,7 @@ static void graph_panel_driverVar__transChan(uiLayout *layout, ID *id, DriverVar DriverTarget *dtar= &dvar->targets[0]; Object *ob = (Object *)dtar->id; PointerRNA dtar_ptr; - uiLayout *col, *row; + uiLayout *col, *subcol; /* initialise RNA pointer to the target */ RNA_pointer_create(id, &RNA_DriverTarget, dtar, &dtar_ptr); @@ -509,9 +509,9 @@ static void graph_panel_driverVar__transChan(uiLayout *layout, ID *id, DriverVar uiItemPointerR(col, &dtar_ptr, "bone_target", &tar_ptr, "bones", "", ICON_BONE_DATA); } - row= uiLayoutRow(layout, 1); - uiItemR(row, &dtar_ptr, "transform_type", 0, "", ICON_NONE); - uiItemR(row, &dtar_ptr, "use_local_space_transform", 0, NULL, ICON_NONE); + subcol= uiLayoutColumn(layout, 1); + uiItemR(subcol, &dtar_ptr, "transform_type", 0, NULL, ICON_NONE); + uiItemR(subcol, &dtar_ptr, "transform_space", 0, "Space", ICON_NONE); } /* driver settings for active F-Curve (only for 'Drivers' mode) */ diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index 962cadba1f3..0da03832d15 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -2248,7 +2248,7 @@ void GRAPH_OT_fmodifier_paste (wmOperatorType *ot) /* api callbacks */ ot->exec= graph_fmodifier_paste_exec; - ot->poll= graphop_editable_keyframes_poll; + ot->poll= graphop_active_fcurve_poll; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c index 03cc8bb9e80..0d7cdf94bc7 100644 --- a/source/blender/editors/space_graph/graph_ops.c +++ b/source/blender/editors/space_graph/graph_ops.c @@ -46,6 +46,7 @@ #include "UI_view2d.h" #include "ED_anim_api.h" +#include "ED_markers.h" #include "ED_screen.h" #include "ED_transform.h" @@ -361,7 +362,7 @@ static void graphedit_keymap_keyframes (wmKeyConfig *keyconf, wmKeyMap *keymap) WM_keymap_add_item(keymap, "GRAPH_OT_handle_type", VKEY, KM_PRESS, 0, 0); - WM_keymap_add_item(keymap, "GRAPH_OT_interpolation_type", TKEY, KM_PRESS, KM_SHIFT, 0); + WM_keymap_add_item(keymap, "GRAPH_OT_interpolation_type", TKEY, KM_PRESS, 0, 0); /* destructive */ WM_keymap_add_item(keymap, "GRAPH_OT_clean", OKEY, KM_PRESS, 0, 0); @@ -399,6 +400,9 @@ static void graphedit_keymap_keyframes (wmKeyConfig *keyconf, wmKeyMap *keymap) /* transform system */ transform_keymap_for_space(keyconf, keymap, SPACE_IPO); + + /* special markers hotkeys for anim editors: see note in definition of this function */ + ED_marker_keymap_animedit_conflictfree(keymap); } /* --------------- */ diff --git a/source/blender/editors/space_logic/logic_window.c b/source/blender/editors/space_logic/logic_window.c index 019ce2a714a..a45e7d39c76 100644 --- a/source/blender/editors/space_logic/logic_window.c +++ b/source/blender/editors/space_logic/logic_window.c @@ -3679,10 +3679,6 @@ static void draw_actuator_action(uiLayout *layout, PointerRNA *ptr) PointerRNA settings_ptr; uiLayout *row; - if(ob->type != OB_ARMATURE){ - uiItemL(layout, "Actuator only available for armatures", ICON_NONE); - return; - } RNA_pointer_create((ID *)ob, &RNA_GameObjectSettings, ob, &settings_ptr); row= uiLayoutRow(layout, 0); @@ -3704,6 +3700,9 @@ static void draw_actuator_action(uiLayout *layout, PointerRNA *ptr) uiItemR(row, ptr, "priority", 0, NULL, ICON_NONE); row= uiLayoutRow(layout, 0); + uiItemR(row, ptr, "layer", 0, NULL, ICON_NONE); + + row= uiLayoutRow(layout, 0); uiItemPointerR(layout, ptr, "frame_property", &settings_ptr, "properties", NULL, ICON_NONE); #ifdef __NLA_ACTION_BY_MOTION_ACTUATOR diff --git a/source/blender/editors/space_nla/nla_ops.c b/source/blender/editors/space_nla/nla_ops.c index 85dcf14adac..ea8e8961f02 100644 --- a/source/blender/editors/space_nla/nla_ops.c +++ b/source/blender/editors/space_nla/nla_ops.c @@ -45,6 +45,7 @@ #include "BKE_screen.h" #include "ED_anim_api.h" +#include "ED_markers.h" #include "ED_screen.h" #include "ED_transform.h" @@ -262,6 +263,9 @@ static void nla_keymap_main (wmKeyConfig *keyconf, wmKeyMap *keymap) /* transform system */ transform_keymap_for_space(keyconf, keymap, SPACE_NLA); + + /* special markers hotkeys for anim editors: see note in definition of this function */ + ED_marker_keymap_animedit_conflictfree(keymap); } /* --------------- */ diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c index 625e5561389..28230b7a48b 100644 --- a/source/blender/editors/space_text/text_draw.c +++ b/source/blender/editors/space_text/text_draw.c @@ -907,9 +907,12 @@ static void text_update_drawcache(SpaceText *st, ARegion *ar) void text_drawcache_tag_update(SpaceText *st, int full) { - DrawCache *drawcache= (DrawCache *)st->drawcache; - - if(drawcache) { + /* this happens if text editor ops are caled from python */ + if (st == NULL) + return; + + if(st->drawcache) { + DrawCache *drawcache= (DrawCache *)st->drawcache; Text *txt= st->text; if(drawcache->update_flag) { diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c index 7c66cec5730..f42fd461510 100644 --- a/source/blender/editors/space_view3d/drawarmature.c +++ b/source/blender/editors/space_view3d/drawarmature.c @@ -1217,6 +1217,87 @@ static void draw_b_bone(int dt, int armflag, int boneflag, int constflag, unsign } } +static void draw_wire_bone_segments(bPoseChannel *pchan, Mat4 *bbones, float length, int segments) +{ + if ((segments > 1) && (pchan)) { + float dlen= length/(float)segments; + Mat4 *bbone = bbones; + int a; + + for (a=0; a<segments; a++, bbone++) { + glPushMatrix(); + glMultMatrixf(bbone->mat); + + glBegin(GL_LINES); + glVertex3f(0.0f, 0.0f, 0.0f); + glVertex3f(0.0f, dlen, 0.0f); + glEnd(); // GL_LINES + + glPopMatrix(); + } + } + else { + glPushMatrix(); + + glBegin(GL_LINES); + glVertex3f(0.0f, 0.0f, 0.0f); + glVertex3f(0.0f, length, 0.0f); + glEnd(); + + glPopMatrix(); + } +} + +static void draw_wire_bone(int dt, int armflag, int boneflag, int constflag, unsigned int id, bPoseChannel *pchan, EditBone *ebone) +{ + Mat4 *bbones = NULL; + int segments = 0; + float length; + + if (pchan) { + segments= pchan->bone->segments; + length= pchan->bone->length; + + if (segments > 1) + bbones = b_bone_spline_setup(pchan, 0); + } + else + length= ebone->length; + + /* draw points only if... */ + if (armflag & ARM_EDITMODE) { + /* move to unitspace */ + glPushMatrix(); + glScalef(length, length, length); + draw_bone_points(dt, armflag, boneflag, id); + glPopMatrix(); + length *= 0.95f; // make vertices visible + } + + /* this chunk not in object mode */ + if (armflag & (ARM_EDITMODE|ARM_POSEMODE)) { + if (id != -1) + glLoadName((GLuint) id|BONESEL_BONE); + + draw_wire_bone_segments(pchan, bbones, length, segments); + + /* further we send no names */ + if (id != -1) + glLoadName(id & 0xFFFF); /* object tag, for bordersel optim */ + } + + /* colors for modes */ + if (armflag & ARM_POSEMODE) { + set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag); + } + else if (armflag & ARM_EDITMODE) { + set_ebone_glColor(boneflag); + } + + /* draw normal */ + draw_wire_bone_segments(pchan, bbones, length, segments); +} + static void draw_bone(int dt, int armflag, int boneflag, int constflag, unsigned int id, float length) { @@ -1656,7 +1737,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, int use_custom = (pchan->custom) && !(arm->flag & ARM_NO_CUSTOM); glPushMatrix(); - if(use_custom && pchan->custom_tx) { + if (use_custom && pchan->custom_tx) { glMultMatrixf(pchan->custom_tx->pose_mat); } else { @@ -1684,6 +1765,8 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, } else if (arm->drawtype==ARM_LINE) ; /* nothing in solid */ + else if (arm->drawtype==ARM_WIRE) + ; /* nothing in solid */ else if (arm->drawtype==ARM_ENVELOPE) draw_sphere_bone(OB_SOLID, arm->flag, flag, 0, index, pchan, NULL); else if (arm->drawtype==ARM_B_BONE) @@ -1702,7 +1785,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, /* very very confusing... but in object mode, solid draw, we cannot do glLoadName yet, * stick bones and/or wire custom-shapes are drawn in next loop */ - if ((arm->drawtype != ARM_LINE) && (draw_wire == 0)) { + if (ELEM(arm->drawtype,ARM_LINE,ARM_WIRE)==0 && (draw_wire == 0)) { /* object tag, for bordersel optim */ glLoadName(index & 0xFFFF); index= -1; @@ -1773,8 +1856,8 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, if (index != -1) index+= 0x10000; // pose bones count in higher 2 bytes only } - /* stick bones have not been drawn yet so dont clear object selection in this case */ - if ((arm->drawtype != ARM_LINE) && draw_wire) { + /* stick or wire bones have not been drawn yet so dont clear object selection in this case */ + if (ELEM(arm->drawtype, ARM_LINE, ARM_WIRE)==0 && draw_wire) { /* object tag, for bordersel optim */ glLoadName(index & 0xFFFF); index= -1; @@ -1784,7 +1867,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, /* wire draw over solid only in posemode */ if ((dt <= OB_WIRE) || (arm->flag & ARM_POSEMODE) || (arm->drawtype==ARM_LINE)) { /* draw line check first. we do selection indices */ - if (arm->drawtype==ARM_LINE) { + if ELEM(arm->drawtype, ARM_LINE, ARM_WIRE) { if (arm->flag & ARM_POSEMODE) index= base->selcol; } @@ -1879,6 +1962,8 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, } else if (arm->drawtype==ARM_LINE) draw_line_bone(arm->flag, flag, constflag, index, pchan, NULL); + else if (arm->drawtype==ARM_WIRE) + draw_wire_bone(dt, arm->flag, flag, constflag, index, pchan, NULL); else if (arm->drawtype==ARM_B_BONE) draw_b_bone(OB_WIRE, arm->flag, flag, constflag, index, pchan, NULL); else @@ -2013,7 +2098,7 @@ static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, int dt) } /* if solid we draw it first */ - if ((dt > OB_WIRE) && (arm->drawtype!=ARM_LINE)) { + if ((dt > OB_WIRE) && (arm->drawtype != ARM_LINE)) { for (eBone=arm->edbo->first, index=0; eBone; eBone=eBone->next, index++) { if (eBone->layer & arm->layer) { if ((eBone->flag & BONE_HIDDEN_A)==0) { @@ -2034,6 +2119,8 @@ static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, int dt) draw_sphere_bone(OB_SOLID, arm->flag, flag, 0, index, NULL, eBone); else if(arm->drawtype==ARM_B_BONE) draw_b_bone(OB_SOLID, arm->flag, flag, 0, index, NULL, eBone); + else if (arm->drawtype==ARM_WIRE) + draw_wire_bone(OB_SOLID, arm->flag, flag, 0, index, NULL, eBone); else { draw_bone(OB_SOLID, arm->flag, flag, 0, index, eBone->length); } @@ -2047,7 +2134,7 @@ static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, int dt) /* if wire over solid, set offset */ index= -1; glLoadName(-1); - if (arm->drawtype==ARM_LINE) { + if ELEM(arm->drawtype, ARM_LINE, ARM_WIRE) { if(G.f & G_PICKSEL) index= 0; } @@ -2081,6 +2168,8 @@ static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, int dt) if (arm->drawtype == ARM_LINE) draw_line_bone(arm->flag, flag, 0, index, NULL, eBone); + else if (arm->drawtype==ARM_WIRE) + draw_wire_bone(OB_WIRE, arm->flag, flag, 0, index, NULL, eBone); else if (arm->drawtype == ARM_B_BONE) draw_b_bone(OB_WIRE, arm->flag, flag, 0, index, NULL, eBone); else @@ -2109,7 +2198,7 @@ static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, int dt) /* restore */ if(index!=-1) glLoadName(-1); - if (arm->drawtype==ARM_LINE); + if ELEM(arm->drawtype,ARM_LINE,ARM_WIRE); else if (dt>OB_WIRE) bglPolygonOffset(rv3d->dist, 0.0f); /* finally names and axes */ diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 181fb0f0aac..b8369d8cbff 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -1982,12 +1982,15 @@ static void protectedQuaternionBits(short protectflag, float *quat, float *oldqu /* ******************* TRANSFORM LIMITS ********************** */ -static void constraintTransLim(TransInfo *UNUSED(t), TransData *td) +static void constraintTransLim(TransInfo *t, TransData *td) { if (td->con) { - bConstraintTypeInfo *cti= get_constraint_typeinfo(CONSTRAINT_TYPE_LOCLIMIT); + bConstraintTypeInfo *ctiLoc= get_constraint_typeinfo(CONSTRAINT_TYPE_LOCLIMIT); + bConstraintTypeInfo *ctiDist= get_constraint_typeinfo(CONSTRAINT_TYPE_DISTLIMIT); + bConstraintOb cob= {NULL}; bConstraint *con; + float ctime = (float)(t->scene->r.cfra); /* Make a temporary bConstraintOb for using these limit constraints * - they only care that cob->matrix is correctly set ;-) @@ -1998,6 +2001,8 @@ static void constraintTransLim(TransInfo *UNUSED(t), TransData *td) /* Evaluate valid constraints */ for (con= td->con; con; con= con->next) { + bConstraintTypeInfo *cti = NULL; + ListBase targets = {NULL, NULL}; float tmat[4][4]; /* only consider constraint if enabled */ @@ -2010,7 +2015,17 @@ static void constraintTransLim(TransInfo *UNUSED(t), TransData *td) if ((data->flag2 & LIMIT_TRANSFORM)==0) continue; + cti = ctiLoc; + } + else if (con->type == CONSTRAINT_TYPE_DISTLIMIT) { + bDistLimitConstraint *data= con->data; + if ((data->flag & LIMITDIST_TRANSFORM)==0) + continue; + cti = ctiDist; + } + + if (cti) { /* do space conversions */ if (con->ownspace == CONSTRAINT_SPACE_WORLD) { /* just multiply by td->mtx (this should be ok) */ @@ -2022,8 +2037,11 @@ static void constraintTransLim(TransInfo *UNUSED(t), TransData *td) continue; } + /* get constraint targets if needed */ + get_constraint_targets_for_solving(con, &cob, &targets, ctime); + /* do constraint */ - cti->evaluate_constraint(con, &cob, NULL); + cti->evaluate_constraint(con, &cob, &targets); /* convert spaces again */ if (con->ownspace == CONSTRAINT_SPACE_WORLD) { @@ -2031,6 +2049,9 @@ static void constraintTransLim(TransInfo *UNUSED(t), TransData *td) copy_m4_m4(tmat, cob.matrix); mul_m4_m3m4(cob.matrix, td->smtx, tmat); } + + /* free targets list */ + BLI_freelistN(&targets); } } @@ -5783,8 +5804,8 @@ int TimeSlide(TransInfo *t, const int mval[2]) char str[200]; /* calculate mouse co-ordinates */ - UI_view2d_region_to_view(v2d, mval[0], mval[0], &cval[0], &cval[1]); - UI_view2d_region_to_view(v2d, t->imval[0], t->imval[0], &sval[0], &sval[1]); + UI_view2d_region_to_view(v2d, mval[0], mval[1], &cval[0], &cval[1]); + UI_view2d_region_to_view(v2d, t->imval[0], t->imval[1], &sval[0], &sval[1]); /* t->values[0] stores cval[0], which is the current mouse-pointer location (in frames) */ // XXX Need to be able to repeat this diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 68aa27a7b62..e0250829a66 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -3131,12 +3131,18 @@ static void createTransActionData(bContext *C, TransInfo *t) float min=999999999.0f, max=-999999999.0f; int i; - td= (t->data + 1); - for (i=1; i < count; i+=3, td+=3) { + td= t->data; + for (i=0; i < count; i++, td++) { if (min > *(td->val)) min= *(td->val); if (max < *(td->val)) max= *(td->val); } + if (min == max) { + /* just use the current frame ranges */ + min = (float)PSFRA; + max = (float)PEFRA; + } + /* minx/maxx values used by TimeSlide are stored as a * calloced 2-float array in t->customData. This gets freed * in postTrans (T_FREE_CUSTOMDATA). diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index 7bdf6c909d9..4b0a734a98e 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -897,7 +897,7 @@ void transform_keymap_for_space(wmKeyConfig *keyconf, wmKeyMap *keymap, int spac km= WM_keymap_add_item(keymap, "TRANSFORM_OT_transform", SKEY, KM_PRESS, 0, 0); RNA_enum_set(km->ptr, "mode", TFM_TIME_SCALE); - km= WM_keymap_add_item(keymap, "TRANSFORM_OT_transform", TKEY, KM_PRESS, 0, 0); + km= WM_keymap_add_item(keymap, "TRANSFORM_OT_transform", TKEY, KM_PRESS, KM_SHIFT, 0); RNA_enum_set(km->ptr, "mode", TFM_TIME_SLIDE); break; case SPACE_IPO: diff --git a/source/blender/makesdna/DNA_actuator_types.h b/source/blender/makesdna/DNA_actuator_types.h index 887a0300ee2..b368aadf4c2 100644 --- a/source/blender/makesdna/DNA_actuator_types.h +++ b/source/blender/makesdna/DNA_actuator_types.h @@ -56,8 +56,10 @@ typedef struct bActionActuator { char frameProp[32]; /* Set this property to the actions current frame */ short blendin; /* Number of frames of blending */ short priority; /* Execution priority */ + short layer; /* Animation layer */ short end_reset; /* Ending the actuator (negative pulse) wont reset the the action to its starting frame */ short strideaxis; /* Displacement axis */ + short pad[3]; float stridelength; /* Displacement incurred by cycle */ // not in use } bActionActuator; diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h index 4b649031f97..00a9786fc6f 100644 --- a/source/blender/makesdna/DNA_anim_types.h +++ b/source/blender/makesdna/DNA_anim_types.h @@ -62,6 +62,11 @@ typedef struct FModifier { short flag; /* settings for the modifier */ float influence; /* the amount that the modifier should influence the value */ + + float sfra; /* start frame of restricted frame-range */ + float efra; /* end frame of restricted frame-range */ + float blendin; /* number of frames from sfra before modifier takes full influence */ + float blendout; /* number of frames from efra before modifier fades out */ } FModifier; /* Types of F-Curve modifier @@ -86,13 +91,17 @@ typedef enum eFModifier_Types { /* F-Curve Modifier Settings */ typedef enum eFModifier_Flags { /* modifier is not able to be evaluated for some reason, and should be skipped (internal) */ - FMODIFIER_FLAG_DISABLED = (1<<0), + FMODIFIER_FLAG_DISABLED = (1<<0), /* modifier's data is expanded (in UI) */ - FMODIFIER_FLAG_EXPANDED = (1<<1), + FMODIFIER_FLAG_EXPANDED = (1<<1), /* modifier is active one (in UI) for editing purposes */ - FMODIFIER_FLAG_ACTIVE = (1<<2), + FMODIFIER_FLAG_ACTIVE = (1<<2), /* user wants modifier to be skipped */ - FMODIFIER_FLAG_MUTED = (1<<3) + FMODIFIER_FLAG_MUTED = (1<<3), + /* restrict range that F-Modifier can be considered over */ + FMODIFIER_FLAG_RANGERESTRICT = (1<<4), + /* use influence control */ + FMODIFIER_FLAG_USEINFLUENCE = (1<<5) } eFModifier_Flags; /* --- */ @@ -280,8 +289,12 @@ typedef enum eDriverTarget_Flag { 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) */ + + /* "localspace" flags */ + /* base flag - basically "pre parent+constraints" */ DTAR_FLAG_LOCALSPACE = (1<<2), + /* include constraints transformed to space including parents */ + DTAR_FLAG_LOCAL_CONSTS = (1<<3), } eDriverTarget_Flag; /* Transform Channels for Driver Targets */ diff --git a/source/blender/makesdna/DNA_armature_types.h b/source/blender/makesdna/DNA_armature_types.h index 3547101612f..808db1f4843 100644 --- a/source/blender/makesdna/DNA_armature_types.h +++ b/source/blender/makesdna/DNA_armature_types.h @@ -136,7 +136,8 @@ typedef enum eArmature_Drawtype { ARM_OCTA = 0, ARM_LINE, ARM_B_BONE, - ARM_ENVELOPE + ARM_ENVELOPE, + ARM_WIRE } eArmature_Drawtype; /* armature->deformflag */ diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h index 1d752fce4ef..c2c0c6f1611 100644 --- a/source/blender/makesdna/DNA_constraint_types.h +++ b/source/blender/makesdna/DNA_constraint_types.h @@ -677,7 +677,10 @@ typedef enum eRotLimit_Flags { /* distance limit constraint */ /* bDistLimitConstraint->flag */ typedef enum eDistLimit_Flag { - LIMITDIST_USESOFT = (1<<0) + /* "soft" cushion effect when reaching the limit sphere */ // NOT IMPLEMENTED! + LIMITDIST_USESOFT = (1<<0), + /* as for all Limit constraints - allow to be used during transform? */ + LIMITDIST_TRANSFORM = (1<<1) } eDistLimit_Flag; /* bDistLimitConstraint->mode */ diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 907710ae4cd..cf416bf9d5b 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -436,6 +436,7 @@ extern UserDef U; /* from blenkernel blender.c */ #define USER_NONEGFRAMES (1 << 24) #define USER_TXT_TABSTOSPACES_DISABLE (1 << 25) #define USER_TOOLTIPS_PYTHON (1 << 26) +#define USER_NO_RECENTLOAD_UPDATE (1 << 27) /* helper macro for checking frame clamping */ #define FRAMENUMBER_MIN_CLAMP(cfra) \ diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index ab11f88e0f6..91f88a26987 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -3114,7 +3114,7 @@ static char *rna_path_token(const char **path, char *fixedbuf, int fixedlen, int /* 2 kinds of lookups now, quoted or unquoted */ quote= *p; - if(quote != '"') + if(quote != '"') /* " - this comment is hack for Aligorith's text editor's sanity */ quote= 0; if(quote==0) { diff --git a/source/blender/makesrna/intern/rna_actuator.c b/source/blender/makesrna/intern/rna_actuator.c index cddba59f979..75c884a5fbb 100644 --- a/source/blender/makesrna/intern/rna_actuator.c +++ b/source/blender/makesrna/intern/rna_actuator.c @@ -426,11 +426,11 @@ EnumPropertyItem *rna_Actuator_type_itemf(bContext *C, PointerRNA *ptr, Property if (ob != NULL) { if (ob->type==OB_ARMATURE) { - RNA_enum_items_add_value(&item, &totitem, actuator_type_items, ACT_ACTION); RNA_enum_items_add_value(&item, &totitem, actuator_type_items, ACT_ARMATURE); } } - + + RNA_enum_items_add_value(&item, &totitem, actuator_type_items, ACT_ACTION); RNA_enum_items_add_value(&item, &totitem, actuator_type_items, ACT_CAMERA); RNA_enum_items_add_value(&item, &totitem, actuator_type_items, ACT_CONSTRAINT); RNA_enum_items_add_value(&item, &totitem, actuator_type_items, ACT_EDIT_OBJECT); @@ -616,6 +616,11 @@ static void rna_def_action_actuator(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Priority", "Execution priority - lower numbers will override actions with higher numbers. With 2 or more actions at once, the overriding channels must be lower in the stack"); RNA_def_property_update(prop, NC_LOGIC, NULL); + prop= RNA_def_property(srna, "layer", PROP_INT, PROP_NONE); + RNA_def_property_range(prop, 0, 4); /* This should match BL_ActionManager::MAX_ACTION_LAYERS */ + RNA_def_property_ui_text(prop, "Layer", "The animation layer to play the action on"); + RNA_def_property_update(prop, NC_LOGIC, NULL); + prop= RNA_def_property(srna, "frame_property", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "frameProp"); RNA_def_property_ui_text(prop, "Frame Property", "Assign the action's current frame number to this property"); diff --git a/source/blender/makesrna/intern/rna_animation.c b/source/blender/makesrna/intern/rna_animation.c index 7f817aa5b4b..d523a01dc2c 100644 --- a/source/blender/makesrna/intern/rna_animation.c +++ b/source/blender/makesrna/intern/rna_animation.c @@ -76,6 +76,10 @@ static void rna_AnimData_action_set(PointerRNA *ptr, PointerRNA value) ID *ownerId = (ID *)ptr->id.data; AnimData *adt = (AnimData *)ptr->data; + /* manage usercount for current action */ + if (adt->action) + id_us_min((ID*)adt->action); + /* assume that AnimData's action can in fact be edited... */ if ((value.data) && (ownerId)) { bAction *act = (bAction *)value.data; @@ -85,6 +89,7 @@ static void rna_AnimData_action_set(PointerRNA *ptr, PointerRNA value) if (ELEM(act->idroot, 0, GS(ownerId->name))) { /* can set */ adt->action = act; + id_us_plus((ID*)adt->action); } else { /* cannot set */ @@ -98,6 +103,7 @@ static void rna_AnimData_action_set(PointerRNA *ptr, PointerRNA value) act->id.name+2); adt->action = act; + id_us_plus((ID*)adt->action); } } else { diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c index 2060f75f9de..41d169a8870 100644 --- a/source/blender/makesrna/intern/rna_armature.c +++ b/source/blender/makesrna/intern/rna_armature.c @@ -814,6 +814,7 @@ static void rna_def_armature(BlenderRNA *brna) {ARM_LINE, "STICK", 0, "Stick", "Display bones as simple 2D lines with dots"}, {ARM_B_BONE, "BBONE", 0, "B-Bone", "Display bones as boxes, showing subdivision and B-Splines"}, {ARM_ENVELOPE, "ENVELOPE", 0, "Envelope", "Display bones as extruded spheres, showing deformation influence volume"}, + {ARM_WIRE, "WIRE", 0, "Wire", "Display bones as thin wires, showing subdivision and B-Splines"}, {0, NULL, 0, NULL, NULL}}; static EnumPropertyItem prop_ghost_type_items[] = { {ARM_GHOST_CUR, "CURRENT_FRAME", 0, "Around Frame", "Display Ghosts of poses within a fixed number of frames around the current frame"}, diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c index a75ff601d08..4e178e77fd9 100644 --- a/source/blender/makesrna/intern/rna_constraint.c +++ b/source/blender/makesrna/intern/rna_constraint.c @@ -85,7 +85,7 @@ static EnumPropertyItem target_space_pchan_items[] = { static EnumPropertyItem owner_space_pchan_items[] = { {0, "WORLD", 0, "World Space", "The constraint is applied relative to the world coordinate system"}, {2, "POSE", 0, "Pose Space", "The constraint is applied in Pose Space, the object transformation is ignored"}, - {3, "LOCAL_WITH_PARENT", 0, "The constraint is applied relative to the local coordinate system of the object, with the parent transformation added"}, + {3, "LOCAL_WITH_PARENT", 0, "Local With Parent", "The constraint is applied relative to the local coordinate system of the object, with the parent transformation added"}, {1, "LOCAL", 0, "Local Space", "The constraint is applied relative to the local coordinate sytem of the object"}, {0, NULL, 0, NULL, NULL}}; @@ -1787,6 +1787,11 @@ static void rna_def_constraint_distance_limit(BlenderRNA *brna) RNA_def_property_enum_items(prop, constraint_distance_items); RNA_def_property_ui_text(prop, "Limit Mode", "Distances in relation to sphere of influence to allow"); RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update"); + + prop= RNA_def_property(srna, "use_transform_limit", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", LIMITDIST_TRANSFORM); + RNA_def_property_ui_text(prop, "For Transform", "Transforms are affected by this constraint as well"); + RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update"); } static void rna_def_constraint_shrinkwrap(BlenderRNA *brna) diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c index a46f84a22d2..ab3665fb8ff 100644 --- a/source/blender/makesrna/intern/rna_fcurve.c +++ b/source/blender/makesrna/intern/rna_fcurve.c @@ -454,6 +454,30 @@ static void rna_FModifier_active_set(PointerRNA *ptr, int UNUSED(value)) fm->flag |= FMODIFIER_FLAG_ACTIVE; } +static void rna_FModifier_start_frame_range(PointerRNA *ptr, float *min, float *max) +{ + FModifier *fcm= (FModifier*)ptr->data; + + *min= MINAFRAMEF; + *max= (fcm->flag & FMODIFIER_FLAG_RANGERESTRICT)? fcm->efra : MAXFRAMEF; +} + +static void rna_FModifier_end_frame_range(PointerRNA *ptr, float *min, float *max) +{ + FModifier *fcm= (FModifier*)ptr->data; + + *min= (fcm->flag & FMODIFIER_FLAG_RANGERESTRICT)? fcm->sfra : MINAFRAMEF; + *max= MAXFRAMEF; +} + +static void rna_FModifier_blending_range(PointerRNA *ptr, float *min, float *max) +{ + FModifier *fcm= (FModifier*)ptr->data; + + *min= 0.0f; + *max= fcm->efra - fcm->sfra; +} + static void rna_FModifier_active_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { FModifier *fm, *fmo= (FModifier*)ptr->data; @@ -1015,6 +1039,51 @@ static void rna_def_fmodifier(BlenderRNA *brna) RNA_def_property_boolean_funcs(prop, NULL, "rna_FModifier_active_set"); RNA_def_property_update(prop, NC_ANIMATION|ND_KEYFRAME_PROP, "rna_FModifier_active_update"); RNA_def_property_ui_icon(prop, ICON_RADIOBUT_OFF, 1); + + /* restricted range */ + prop= RNA_def_property(srna, "use_restricted_range", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", FMODIFIER_FLAG_RANGERESTRICT); + RNA_def_property_ui_text(prop, "Restrict Frame Range", "F-Curve Modifier is only applied for the specified frame range to help mask off effects in order to chain them"); + RNA_def_property_update(prop, NC_ANIMATION|ND_KEYFRAME_PROP, NULL); + RNA_def_property_ui_icon(prop, ICON_TRIA_RIGHT, 1); // XXX: depends on UI implementation + + prop= RNA_def_property(srna, "frame_start", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "sfra"); + RNA_def_property_float_funcs(prop, NULL, NULL, "rna_FModifier_start_frame_range"); + RNA_def_property_ui_text(prop, "Start Frame", "Frame that modifier's influence starts (if Restrict Frame Range is in use)"); + RNA_def_property_update(prop, NC_ANIMATION|ND_KEYFRAME_PROP, NULL); + + prop= RNA_def_property(srna, "frame_end", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "efra"); + RNA_def_property_float_funcs(prop, NULL, NULL, "rna_FModifier_end_frame_range"); + RNA_def_property_ui_text(prop, "End Frame", "Frame that modifier's influence ends (if Restrict Frame Range is in use)"); + RNA_def_property_update(prop, NC_ANIMATION|ND_KEYFRAME_PROP, NULL); + + prop= RNA_def_property(srna, "blend_in", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "blendin"); + RNA_def_property_float_funcs(prop, NULL, NULL, "rna_FModifier_blending_range"); + RNA_def_property_ui_text(prop, "Blend In", "Number of frames from start frame for influence to take effect"); + RNA_def_property_update(prop, NC_ANIMATION|ND_KEYFRAME_PROP, NULL); + + prop= RNA_def_property(srna, "blend_out", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "blendout"); + RNA_def_property_float_funcs(prop, NULL, NULL, "rna_FModifier_blending_range"); + RNA_def_property_ui_text(prop, "Blend Out", "Number of frames from start frame for influence to fade out"); + RNA_def_property_update(prop, NC_ANIMATION|ND_KEYFRAME_PROP, NULL); + + /* influence */ + prop= RNA_def_property(srna, "use_influence", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", FMODIFIER_FLAG_USEINFLUENCE); + RNA_def_property_ui_text(prop, "Use Influence", "F-Curve Modifier's effects will be tempered by a default factor"); + RNA_def_property_update(prop, NC_ANIMATION|ND_KEYFRAME_PROP, NULL); + RNA_def_property_ui_icon(prop, ICON_TRIA_RIGHT, 1); // XXX: depends on UI implementation + + prop= RNA_def_property(srna, "influence", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "influence"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_float_default(prop, 1.0f); + RNA_def_property_ui_text(prop, "Influence", "Amount of influence F-Curve Modifier will have when not fading in/out"); + RNA_def_property_update(prop, NC_ANIMATION|ND_KEYFRAME_PROP, NULL); } /* *********************** */ @@ -1035,6 +1104,12 @@ static void rna_def_drivertarget(BlenderRNA *brna) {DTAR_TRANSCHAN_SCALEY, "SCALE_Y", 0, "Y Scale", ""}, {DTAR_TRANSCHAN_SCALEZ, "SCALE_Z", 0, "Z Scale", ""}, {0, NULL, 0, NULL, NULL}}; + + static EnumPropertyItem prop_local_space_items[] = { + {0, "WORLD_SPACE", 0, "World Space", "Transforms include effects of parenting/restpose and constraints"}, + {DTAR_FLAG_LOCALSPACE, "TRANSFORM_SPACE", 0, "Transform Space", "Transforms don't include parenting/restpose or constraints"}, + {DTAR_FLAG_LOCALSPACE|DTAR_FLAG_LOCAL_CONSTS, "LOCAL_SPACE", 0, "Local Space", "Transforms include effects of constraints but not parenting/restpose"}, + {0, NULL, 0, NULL, NULL}}; srna= RNA_def_struct(brna, "DriverTarget", NULL); RNA_def_struct_ui_text(srna, "Driver Target", "Source of input values for driver variables"); @@ -1075,9 +1150,10 @@ static void rna_def_drivertarget(BlenderRNA *brna) 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_transform", 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)"); + prop= RNA_def_property(srna, "transform_space", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag"); + RNA_def_property_enum_items(prop, prop_local_space_items); + RNA_def_property_ui_text(prop, "Transform Space", "Space in which transforms are used"); RNA_def_property_update(prop, 0, "rna_DriverTarget_update_data"); } diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 14af5ed7a3f..cb50b99c05d 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -2878,7 +2878,11 @@ static void rna_def_userdef_filepaths(BlenderRNA *brna) prop= RNA_def_property(srna, "recent_files", PROP_INT, PROP_NONE); RNA_def_property_range(prop, 0, 30); RNA_def_property_ui_text(prop, "Recent Files", "Maximum number of recently opened files to remember"); - + + prop= RNA_def_property(srna, "use_update_recent_files_on_load", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", USER_NO_RECENTLOAD_UPDATE); + RNA_def_property_ui_text(prop, "Update Recent on Load", "When enabled, opening files will update the recent files list. Otherwise, updates only occur when saving"); + prop= RNA_def_property(srna, "use_save_preview_images", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_SAVE_PREVIEWS); RNA_def_property_ui_text(prop, "Save Preview Images", "Enables automatic saving of preview images in the .blend file"); diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index c088d0d2d43..79ec0360ac6 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -376,7 +376,12 @@ void WM_read_file(bContext *C, const char *filepath, ReportList *reports) if (retval != BKE_READ_FILE_FAIL) { G.relbase_valid = 1; - if(!G.background) /* assume automated tasks with background, dont write recent file list */ + + /* dont write recent file list if: + * 1) assuming automated tasks with background + * 2) user preference to not do this is enabled (i.e. developer testing mode) + */ + if (!G.background && !(U.flag & USER_NO_RECENTLOAD_UPDATE)) write_history(); } diff --git a/source/gameengine/Converter/BL_ActionActuator.cpp b/source/gameengine/Converter/BL_ActionActuator.cpp index c00e7ec7e29..6230f03c4ed 100644 --- a/source/gameengine/Converter/BL_ActionActuator.cpp +++ b/source/gameengine/Converter/BL_ActionActuator.cpp @@ -36,6 +36,7 @@ #include "BL_ActionActuator.h" #include "BL_ArmatureObject.h" #include "BL_SkinDeformer.h" +#include "BL_Action.h" #include "KX_GameObject.h" #include "STR_HashedString.h" #include "MEM_guardedalloc.h" @@ -143,7 +144,86 @@ void BL_ActionActuator::SetLocalTime(float curtime) m_localtime = m_endframe - delta_time; } +bool BL_ActionActuator::Update(double curtime, bool frame) +{ + bool bNegativeEvent = false; + bool bPositiveEvent = false; + KX_GameObject *obj = (KX_GameObject*)GetParent(); + short play_mode = BL_Action::ACT_MODE_PLAY; + float start = m_startframe, end = m_endframe; + + // Don't do anything if we're not "active" + if (!frame) + return true; + + // Convert playmode + if (m_playtype == ACT_ACTION_LOOP_END) + play_mode = BL_Action::ACT_MODE_LOOP; + else if (m_playtype == ACT_ACTION_LOOP_STOP) + play_mode = BL_Action::ACT_MODE_LOOP; + else if (m_playtype == ACT_ACTION_PINGPONG) + play_mode = BL_Action::ACT_MODE_PING_PONG; + else if (m_playtype == ACT_ACTION_FROM_PROP) + { + CValue* prop = GetParent()->GetProperty(m_propname); + + play_mode = BL_Action::ACT_MODE_PLAY; + start = end = prop->GetNumber(); + m_is_going = false; + } + + // Handle events + bNegativeEvent = m_negevent; + bPositiveEvent = m_posevent; + RemoveAllEvents(); + + if (!m_is_going && bPositiveEvent) + { + m_is_going = true; + obj->PlayAction(m_action->id.name+2, start, end, m_layer, m_blendin, play_mode); + if (m_end_reset) + obj->SetActionFrame(m_layer, m_localtime); + } + else if (m_is_going && bNegativeEvent) + { + m_is_going = false; + + if (!m_end_reset) + { + obj->StopAction(m_layer); + return false; + } + + m_localtime = obj->GetActionFrame(m_layer); + obj->StopAction(m_layer); // Stop the action after getting the frame + } + + // Handle a frame property if it's defined + if (m_framepropname[0] != 0) + { + CValue* oldprop = obj->GetProperty(m_framepropname); + CValue* newval = new CFloatValue(obj->GetActionFrame(m_layer)); + if (oldprop) + oldprop->SetValue(newval); + else + obj->SetProperty(m_framepropname, newval); + + newval->Release(); + } + if (m_playtype == ACT_ACTION_FROM_PROP) + { + return true; + } + // Handle a finished animation + else if (m_is_going && obj->IsActionDone(m_layer)) + { + return false; + } + return true; +} + +#if 0 // Kept around as reference for now bool BL_ActionActuator::Update(double curtime, bool frame) { bool bNegativeEvent = false; @@ -449,6 +529,7 @@ bool BL_ActionActuator::Update(double curtime, bool frame) } return keepgoing; }; +#endif #ifdef WITH_PYTHON diff --git a/source/gameengine/Converter/BL_ActionActuator.h b/source/gameengine/Converter/BL_ActionActuator.h index ff4ca785a96..6daf412d9a3 100644 --- a/source/gameengine/Converter/BL_ActionActuator.h +++ b/source/gameengine/Converter/BL_ActionActuator.h @@ -52,6 +52,7 @@ public: short playtype, short blendin, short priority, + short layer, short end_reset, float stride) : SCA_IActuator(gameobj, KX_ACT_ACTION), @@ -69,7 +70,9 @@ public: m_stridelength(stride), m_playtype(playtype), m_priority(priority), + m_layer(layer), m_end_reset(end_reset), + m_is_going(false), m_pose(NULL), m_blendpose(NULL), m_userpose(NULL), @@ -162,7 +165,9 @@ protected: float m_stridelength; short m_playtype; short m_priority; + short m_layer; bool m_end_reset; + bool m_is_going; struct bPose* m_pose; struct bPose* m_blendpose; struct bPose* m_userpose; diff --git a/source/gameengine/Converter/KX_BlenderScalarInterpolator.cpp b/source/gameengine/Converter/KX_BlenderScalarInterpolator.cpp index a9a3e66f996..75c0e012226 100644 --- a/source/gameengine/Converter/KX_BlenderScalarInterpolator.cpp +++ b/source/gameengine/Converter/KX_BlenderScalarInterpolator.cpp @@ -47,11 +47,11 @@ float BL_ScalarInterpolator::GetValue(float currentTime) const { return evaluate_fcurve(m_fcu, currentTime); } -BL_InterpolatorList::BL_InterpolatorList(struct AnimData *adt) { - if(adt->action==NULL) +BL_InterpolatorList::BL_InterpolatorList(bAction *action) { + if(action==NULL) return; - for(FCurve *fcu= (FCurve *)adt->action->curves.first; fcu; fcu= (FCurve *)fcu->next) { + for(FCurve *fcu= (FCurve *)action->curves.first; fcu; fcu= (FCurve *)fcu->next) { if(fcu->rna_path) { BL_ScalarInterpolator *new_ipo = new BL_ScalarInterpolator(fcu); //assert(new_ipo); diff --git a/source/gameengine/Converter/KX_BlenderScalarInterpolator.h b/source/gameengine/Converter/KX_BlenderScalarInterpolator.h index bd786bae969..cca66b3771c 100644 --- a/source/gameengine/Converter/KX_BlenderScalarInterpolator.h +++ b/source/gameengine/Converter/KX_BlenderScalarInterpolator.h @@ -66,7 +66,7 @@ public: class BL_InterpolatorList : public std::vector<KX_IScalarInterpolator *> { public: - BL_InterpolatorList(struct AnimData *adt); + BL_InterpolatorList(struct bAction *action); ~BL_InterpolatorList(); KX_IScalarInterpolator *GetScalarInterpolator(const char *rna_path, int array_index); diff --git a/source/gameengine/Converter/KX_ConvertActuators.cpp b/source/gameengine/Converter/KX_ConvertActuators.cpp index 7da474241a0..1a8368a12fa 100644 --- a/source/gameengine/Converter/KX_ConvertActuators.cpp +++ b/source/gameengine/Converter/KX_ConvertActuators.cpp @@ -192,30 +192,27 @@ void BL_ConvertActuators(char* maggiename, } case ACT_ACTION: { - if (blenderobject->type==OB_ARMATURE){ - bActionActuator* actact = (bActionActuator*) bact->data; - STR_String propname = (actact->name ? actact->name : ""); - STR_String propframe = (actact->frameProp ? actact->frameProp : ""); + bActionActuator* actact = (bActionActuator*) bact->data; + STR_String propname = (actact->name ? actact->name : ""); + STR_String propframe = (actact->frameProp ? actact->frameProp : ""); - BL_ActionActuator* tmpbaseact = new BL_ActionActuator( - gameobj, - propname, - propframe, - actact->sta, - actact->end, - actact->act, - actact->type, // + 1, because Blender starts to count at zero, - actact->blendin, - actact->priority, - actact->end_reset, - actact->stridelength - // Ketsji at 1, because zero is reserved for "NoDef" - ); - baseact= tmpbaseact; - break; - } - else - printf ("Discarded action actuator from non-armature object [%s]\n", blenderobject->id.name+2); + BL_ActionActuator* tmpbaseact = new BL_ActionActuator( + gameobj, + propname, + propframe, + actact->sta, + actact->end, + actact->act, + actact->type, // + 1, because Blender starts to count at zero, + actact->blendin, + actact->priority, + actact->layer, + actact->end_reset, + actact->stridelength + // Ketsji at 1, because zero is reserved for "NoDef" + ); + baseact= tmpbaseact; + break; } case ACT_SHAPEACTION: { diff --git a/source/gameengine/Converter/KX_IpoConvert.cpp b/source/gameengine/Converter/KX_IpoConvert.cpp index 2ad56717e26..27ae857f45c 100644 --- a/source/gameengine/Converter/KX_IpoConvert.cpp +++ b/source/gameengine/Converter/KX_IpoConvert.cpp @@ -54,6 +54,7 @@ #include "DNA_object_types.h" #include "DNA_action_types.h" +#include "DNA_anim_types.h" #include "DNA_ipo_types.h" #include "DNA_lamp_types.h" #include "DNA_world_types.h" @@ -76,133 +77,134 @@ static BL_InterpolatorList *GetAdtList(struct AnimData *for_adt, KX_BlenderScene BL_InterpolatorList *adtList= converter->FindInterpolatorList(for_adt); if (!adtList) { - adtList = new BL_InterpolatorList(for_adt); + adtList = new BL_InterpolatorList(for_adt->action); converter->RegisterInterpolatorList(adtList, for_adt); } return adtList; } -void BL_ConvertIpos(struct Object* blenderobject,KX_GameObject* gameobj,KX_BlenderSceneConverter *converter) +SG_Controller *BL_CreateIPO(struct bAction *action, KX_GameObject* gameobj, KX_BlenderSceneConverter *converter) { - if (blenderobject->adt) { - - KX_IpoSGController* ipocontr = new KX_IpoSGController(); - gameobj->GetSGNode()->AddSGController(ipocontr); - ipocontr->SetObject(gameobj->GetSGNode()); - - // For ipo_as_force, we need to know which SM object and Scene the - // object associated with this ipo is in. Is this already known here? - // I think not.... then it must be done later :( -// ipocontr->SetSumoReference(gameobj->GetSumoScene(), -// gameobj->GetSumoObject()); - - ipocontr->SetGameObject(gameobj); - - ipocontr->GetIPOTransform().SetPosition( - MT_Point3( - blenderobject->loc[0]/*+blenderobject->dloc[0]*/, - blenderobject->loc[1]/*+blenderobject->dloc[1]*/, - blenderobject->loc[2]/*+blenderobject->dloc[2]*/ - ) - ); - ipocontr->GetIPOTransform().SetEulerAngles( - MT_Vector3( - blenderobject->rot[0], - blenderobject->rot[1], - blenderobject->rot[2] - ) - ); - ipocontr->GetIPOTransform().SetScaling( - MT_Vector3( - blenderobject->size[0], - blenderobject->size[1], - blenderobject->size[2] - ) - ); - - const char *rotmode, *drotmode; - - switch(blenderobject->rotmode) - { - case ROT_MODE_AXISANGLE: - rotmode = "rotation_axis_angle"; - drotmode = "delta_rotation_axis_angle"; - case ROT_MODE_QUAT: - rotmode = "rotation_quaternion"; - drotmode = "delta_rotation_quaternion"; - default: - rotmode = "rotation_euler"; - drotmode = "delta_rotation_euler"; - } + KX_IpoSGController* ipocontr = new KX_IpoSGController(); + ipocontr->SetGameObject(gameobj); + + Object* blenderobject = gameobj->GetBlenderObject(); + + ipocontr->GetIPOTransform().SetPosition( + MT_Point3( + blenderobject->loc[0]/*+blenderobject->dloc[0]*/, + blenderobject->loc[1]/*+blenderobject->dloc[1]*/, + blenderobject->loc[2]/*+blenderobject->dloc[2]*/ + ) + ); + ipocontr->GetIPOTransform().SetEulerAngles( + MT_Vector3( + blenderobject->rot[0], + blenderobject->rot[1], + blenderobject->rot[2] + ) + ); + ipocontr->GetIPOTransform().SetScaling( + MT_Vector3( + blenderobject->size[0], + blenderobject->size[1], + blenderobject->size[2] + ) + ); + + const char *rotmode, *drotmode; + + switch(blenderobject->rotmode) + { + case ROT_MODE_AXISANGLE: + rotmode = "rotation_axis_angle"; + drotmode = "delta_rotation_axis_angle"; + case ROT_MODE_QUAT: + rotmode = "rotation_quaternion"; + drotmode = "delta_rotation_quaternion"; + default: + rotmode = "rotation_euler"; + drotmode = "delta_rotation_euler"; + } - BL_InterpolatorList *adtList= GetAdtList(blenderobject->adt, converter); + BL_InterpolatorList *adtList= GetAdtList(blenderobject->adt, converter); - // For each active channel in the adtList add an - // interpolator to the game object. + // For each active channel in the adtList add an + // interpolator to the game object. - KX_IInterpolator *interpolator; - KX_IScalarInterpolator *interp; + KX_IInterpolator *interpolator; + KX_IScalarInterpolator *interp; - for(int i=0; i<3; i++) { - if ((interp = adtList->GetScalarInterpolator("location", i))) { - interpolator= new KX_ScalarInterpolator(&(ipocontr->GetIPOTransform().GetPosition()[i]), interp); - ipocontr->AddInterpolator(interpolator); - ipocontr->SetIPOChannelActive(OB_LOC_X+i, true); - } + for(int i=0; i<3; i++) { + if ((interp = adtList->GetScalarInterpolator("location", i))) { + interpolator= new KX_ScalarInterpolator(&(ipocontr->GetIPOTransform().GetPosition()[i]), interp); + ipocontr->AddInterpolator(interpolator); + ipocontr->SetIPOChannelActive(OB_LOC_X+i, true); } - for(int i=0; i<3; i++) { - if ((interp = adtList->GetScalarInterpolator("delta_location", i))) { - interpolator= new KX_ScalarInterpolator(&(ipocontr->GetIPOTransform().GetDeltaPosition()[i]), interp); - ipocontr->AddInterpolator(interpolator); - ipocontr->SetIPOChannelActive(OB_DLOC_X+i, true); - } + } + for(int i=0; i<3; i++) { + if ((interp = adtList->GetScalarInterpolator("delta_location", i))) { + interpolator= new KX_ScalarInterpolator(&(ipocontr->GetIPOTransform().GetDeltaPosition()[i]), interp); + ipocontr->AddInterpolator(interpolator); + ipocontr->SetIPOChannelActive(OB_DLOC_X+i, true); } - for(int i=0; i<3; i++) { - if ((interp = adtList->GetScalarInterpolator(rotmode, i))) { - interpolator= new KX_ScalarInterpolator(&(ipocontr->GetIPOTransform().GetEulerAngles()[i]), interp); - ipocontr->AddInterpolator(interpolator); - ipocontr->SetIPOChannelActive(OB_ROT_X+i, true); - } + } + for(int i=0; i<3; i++) { + if ((interp = adtList->GetScalarInterpolator(rotmode, i))) { + interpolator= new KX_ScalarInterpolator(&(ipocontr->GetIPOTransform().GetEulerAngles()[i]), interp); + ipocontr->AddInterpolator(interpolator); + ipocontr->SetIPOChannelActive(OB_ROT_X+i, true); } - for(int i=0; i<3; i++) { - if ((interp = adtList->GetScalarInterpolator(drotmode, i))) { - interpolator= new KX_ScalarInterpolator(&(ipocontr->GetIPOTransform().GetDeltaEulerAngles()[i]), interp); - ipocontr->AddInterpolator(interpolator); - ipocontr->SetIPOChannelActive(OB_DROT_X+i, true); - } + } + for(int i=0; i<3; i++) { + if ((interp = adtList->GetScalarInterpolator(drotmode, i))) { + interpolator= new KX_ScalarInterpolator(&(ipocontr->GetIPOTransform().GetDeltaEulerAngles()[i]), interp); + ipocontr->AddInterpolator(interpolator); + ipocontr->SetIPOChannelActive(OB_DROT_X+i, true); } - for(int i=0; i<3; i++) { - if ((interp = adtList->GetScalarInterpolator("scale", i))) { - interpolator= new KX_ScalarInterpolator(&(ipocontr->GetIPOTransform().GetScaling()[i]), interp); - ipocontr->AddInterpolator(interpolator); - ipocontr->SetIPOChannelActive(OB_SIZE_X+i, true); - } + } + for(int i=0; i<3; i++) { + if ((interp = adtList->GetScalarInterpolator("scale", i))) { + interpolator= new KX_ScalarInterpolator(&(ipocontr->GetIPOTransform().GetScaling()[i]), interp); + ipocontr->AddInterpolator(interpolator); + ipocontr->SetIPOChannelActive(OB_SIZE_X+i, true); } - for(int i=0; i<3; i++) { - if ((interp = adtList->GetScalarInterpolator("delta_scale", i))) { - interpolator= new KX_ScalarInterpolator(&(ipocontr->GetIPOTransform().GetDeltaScaling()[i]), interp); - ipocontr->AddInterpolator(interpolator); - ipocontr->SetIPOChannelActive(OB_DSIZE_X+i, true); - } + } + for(int i=0; i<3; i++) { + if ((interp = adtList->GetScalarInterpolator("delta_scale", i))) { + interpolator= new KX_ScalarInterpolator(&(ipocontr->GetIPOTransform().GetDeltaScaling()[i]), interp); + ipocontr->AddInterpolator(interpolator); + ipocontr->SetIPOChannelActive(OB_DSIZE_X+i, true); } + } - { - KX_ObColorIpoSGController* ipocontr_obcol=NULL; + { + KX_ObColorIpoSGController* ipocontr_obcol=NULL; - for(int i=0; i<4; i++) { - if ((interp = adtList->GetScalarInterpolator("color", i))) { - if (!ipocontr_obcol) { - ipocontr_obcol = new KX_ObColorIpoSGController(); - gameobj->GetSGNode()->AddSGController(ipocontr_obcol); - ipocontr_obcol->SetObject(gameobj->GetSGNode()); - } - interpolator= new KX_ScalarInterpolator(&ipocontr_obcol->m_rgba[i], interp); - ipocontr_obcol->AddInterpolator(interpolator); + for(int i=0; i<4; i++) { + if ((interp = adtList->GetScalarInterpolator("color", i))) { + if (!ipocontr_obcol) { + ipocontr_obcol = new KX_ObColorIpoSGController(); + gameobj->GetSGNode()->AddSGController(ipocontr_obcol); + ipocontr_obcol->SetObject(gameobj->GetSGNode()); } + interpolator= new KX_ScalarInterpolator(&ipocontr_obcol->m_rgba[i], interp); + ipocontr_obcol->AddInterpolator(interpolator); } } } + + return ipocontr; +} + +void BL_ConvertIpos(struct Object* blenderobject,KX_GameObject* gameobj,KX_BlenderSceneConverter *converter) +{ + if (blenderobject->adt) { + SG_Controller *ipocontr = BL_CreateIPO(blenderobject->adt->action, gameobj, converter); + gameobj->GetSGNode()->AddSGController(ipocontr); + ipocontr->SetObject(gameobj->GetSGNode()); + } } void BL_ConvertLampIpos(struct Lamp* blenderlamp, KX_GameObject *lightobj,KX_BlenderSceneConverter *converter) diff --git a/source/gameengine/Converter/KX_IpoConvert.h b/source/gameengine/Converter/KX_IpoConvert.h index d77a72a82e2..914422ba83f 100644 --- a/source/gameengine/Converter/KX_IpoConvert.h +++ b/source/gameengine/Converter/KX_IpoConvert.h @@ -36,6 +36,10 @@ struct Object; +class SG_Controller *BL_CreateIPO(struct bAction *action, + class KX_GameObject* gameobj, + class KX_BlenderSceneConverter *converter); + void BL_ConvertIpos(struct Object* blenderobject, class KX_GameObject* gameobj, class KX_BlenderSceneConverter *converter); diff --git a/source/gameengine/Expressions/PyObjectPlus.h b/source/gameengine/Expressions/PyObjectPlus.h index 157124ebc81..88a9f3afd7d 100644 --- a/source/gameengine/Expressions/PyObjectPlus.h +++ b/source/gameengine/Expressions/PyObjectPlus.h @@ -254,12 +254,15 @@ typedef struct PyObjectPlus_Proxy { #define KX_PYMETHODTABLE_NOARGS(class_name, method_name) \ {#method_name , (PyCFunction) class_name::sPy##method_name, METH_NOARGS, (const char *)class_name::method_name##_doc} +#define KX_PYMETHODTABLE_KEYWORDS(class_name, method_name) \ + {#method_name , (PyCFunction) class_name::sPy##method_name, METH_VARARGS|METH_KEYWORDS, (const char *)class_name::method_name##_doc} + /** * Function implementation macro */ #define KX_PYMETHODDEF_DOC(class_name, method_name, doc_string) \ const char class_name::method_name##_doc[] = doc_string; \ -PyObject* class_name::Py##method_name(PyObject* args, PyObject*) +PyObject* class_name::Py##method_name(PyObject* args, PyObject* kwds) #define KX_PYMETHODDEF_DOC_VARARGS(class_name, method_name, doc_string) \ const char class_name::method_name##_doc[] = doc_string; \ diff --git a/source/gameengine/Ketsji/BL_Action.cpp b/source/gameengine/Ketsji/BL_Action.cpp new file mode 100644 index 00000000000..bd65c7d45d8 --- /dev/null +++ b/source/gameengine/Ketsji/BL_Action.cpp @@ -0,0 +1,266 @@ +/** + * $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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include <cstdlib> + +#include "BL_Action.h" +#include "BL_ArmatureObject.h" +#include "KX_IpoConvert.h" +#include "KX_GameObject.h" + +// These three are for getting the action from the logic manager +#include "KX_Scene.h" +#include "KX_PythonInit.h" +#include "SCA_LogicManager.h" + +extern "C" { +#include "BKE_animsys.h" +#include "BKE_action.h" +#include "RNA_access.h" +#include "RNA_define.h" +} + +BL_Action::BL_Action(class KX_GameObject* gameobj) +: + m_obj(gameobj), + m_startframe(0.f), + m_endframe(0.f), + m_blendin(0.f), + m_playmode(0), + m_endtime(0.f), + m_localtime(0.f), + m_blendframe(0.f), + m_blendstart(0.f), + m_speed(0.f), + m_pose(NULL), + m_blendpose(NULL), + m_sg_contr(NULL), + m_done(true) +{ + +} + +BL_Action::~BL_Action() +{ + if (m_pose) + game_free_pose(m_pose); + if (m_blendpose) + game_free_pose(m_blendpose); + if (m_sg_contr) + { + m_obj->GetSGNode()->RemoveSGController(m_sg_contr); + delete m_sg_contr; + } +} + +void BL_Action::Play(const char* name, + float start, + float end, + float blendin, + short play_mode, + short blend_mode, + float playback_speed) +{ + bAction* prev_action = m_action; + + // First try to load the action + m_action = (bAction*)KX_GetActiveScene()->GetLogicManager()->GetActionByName(name); + if (!m_action) + { + printf("Failed to load action: %s\n", name); + m_done = true; + return; + } + + //if (m_obj->GetGameObjectType() != SCA_IObject::OBJ_ARMATURE) + if (prev_action != m_action) + { + // Create an SG_Controller + m_sg_contr = BL_CreateIPO(m_action, m_obj, KX_GetActiveScene()->GetSceneConverter()); + m_obj->GetSGNode()->AddSGController(m_sg_contr); + m_sg_contr->SetObject(m_obj->GetSGNode()); + InitIPO(); + } + + // Now that we have an action, we have something we can play + m_starttime = KX_GetActiveEngine()->GetFrameTime(); + m_startframe = m_localtime = start; + m_endframe = end; + m_blendin = blendin; + m_playmode = play_mode; + m_endtime = 0.f; + m_blendframe = 0.f; + m_blendstart = 0.f; + m_speed = playback_speed; + + m_done = false; +} + +void BL_Action::Stop() +{ + m_done = true; +} + +void BL_Action::InitIPO() +{ + // Initialize the IPO + m_sg_contr->SetOption(SG_Controller::SG_CONTR_IPO_RESET, true); + m_sg_contr->SetOption(SG_Controller::SG_CONTR_IPO_IPO_AS_FORCE, false); + m_sg_contr->SetOption(SG_Controller::SG_CONTR_IPO_IPO_ADD, false); + m_sg_contr->SetOption(SG_Controller::SG_CONTR_IPO_LOCAL, false); +} + +float BL_Action::GetFrame() +{ + return m_localtime; +} + +void BL_Action::SetFrame(float frame) +{ + float dt; + + // Clamp the frame to the start and end frame + if (frame < min(m_startframe, m_endframe)) + frame = min(m_startframe, m_endframe); + else if (frame > max(m_startframe, m_endframe)) + frame = max(m_startframe, m_endframe); + + // We don't set m_localtime directly since it's recalculated + // in the next update. So, we modify the value (m_starttime) + // used to calculate m_localtime the next time SetLocalTime() is called. + + dt = frame-m_startframe; + + if (m_endframe < m_startframe) + dt = -dt; + + m_starttime -= dt / (KX_KetsjiEngine::GetAnimFrameRate()*m_speed); +} + +void BL_Action::SetLocalTime(float curtime) +{ + float dt = (curtime-m_starttime)*KX_KetsjiEngine::GetAnimFrameRate()*m_speed; + + if (m_endframe < m_startframe) + dt = -dt; + + m_localtime = m_startframe + dt; +} + +void BL_Action::Update(float curtime) +{ + // Don't bother if we're done with the animation + if (m_done) + return; + + curtime -= KX_KetsjiEngine::GetSuspendedDelta(); + + SetLocalTime(curtime); + + // Handle wrap around + if (m_localtime < min(m_startframe, m_endframe) || m_localtime > max(m_startframe, m_endframe)) + { + switch(m_playmode) + { + case ACT_MODE_PLAY: + // Clamp + m_localtime = m_endframe; + m_done = true; + break; + case ACT_MODE_LOOP: + // Put the time back to the beginning + m_localtime = m_startframe; + m_starttime = curtime; + break; + case ACT_MODE_PING_PONG: + // Swap the start and end frames + float temp = m_startframe; + m_startframe = m_endframe; + m_endframe = temp; + + m_starttime = curtime; + + break; + } + + if (!m_done && m_sg_contr) + InitIPO(); + } + + if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE) + { + BL_ArmatureObject *obj = (BL_ArmatureObject*)m_obj; + obj->GetPose(&m_pose); + + // Extract the pose from the action + { + struct PointerRNA id_ptr; + Object *arm = obj->GetArmatureObject(); + bPose *temp = arm->pose; + + arm->pose = m_pose; + RNA_id_pointer_create((ID*)arm, &id_ptr); + animsys_evaluate_action(&id_ptr, m_action, NULL, m_localtime); + + arm->pose = temp; + } + + // Handle blending between actions + if (m_blendin && m_blendframe<m_blendin) + { + if (!m_blendpose) + { + obj->GetMRDPose(&m_blendpose); + m_blendstart = curtime; + } + + // Calculate weight + float weight = 1.f - (m_blendframe/m_blendin); + game_blend_poses(m_pose, m_blendpose, weight); + + // Bump the blend frame + m_blendframe = (curtime - m_blendstart)*KX_KetsjiEngine::GetAnimFrameRate(); + + // Clamp + if (m_blendframe>m_blendin) + m_blendframe = m_blendin; + } + + obj->SetPose(m_pose); + + obj->SetActiveAction(NULL, 0, curtime); + } + else + { + InitIPO(); + m_sg_contr->SetSimulatedTime(m_localtime); + m_obj->GetSGNode()->UpdateWorldData(m_localtime); + m_obj->UpdateTransform(); + } +} diff --git a/source/gameengine/Ketsji/BL_Action.h b/source/gameengine/Ketsji/BL_Action.h new file mode 100644 index 00000000000..1eb4483eb37 --- /dev/null +++ b/source/gameengine/Ketsji/BL_Action.h @@ -0,0 +1,110 @@ +/** + * $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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ +#ifndef __BL_ACTION +#define __BL_ACTION + +#ifdef WITH_CXX_GUARDEDALLOC +#include "MEM_guardedalloc.h" +#endif + + +class BL_Action +{ +private: + struct bAction* m_action; + struct bPose* m_pose; + struct bPose* m_blendpose; + struct PointerRNA *m_ptrrna; + class SG_Controller *m_sg_contr; + class KX_GameObject* m_obj; + + float m_startframe; + float m_endframe; + float m_starttime; + float m_endtime; + float m_localtime; + + float m_blendin; + float m_blendframe; + float m_blendstart; + + float m_speed; + + short m_playmode; + short m_blendmode; + + bool m_done; + + void InitIPO(); + void SetLocalTime(float curtime); +public: + BL_Action(class KX_GameObject* gameobj); + ~BL_Action(); + + void Play(const char* name, + float start, + float end, + float blendin, + short play_mode, + short blend_mode, + float playback_speed); + void Stop(); + bool IsDone() {return m_done;} + void Update(float curtime); + + // Accessors + float GetFrame(); + + // Mutators + void SetFrame(float frame); + + enum + { + ACT_MODE_PLAY = 0, + ACT_MODE_LOOP, + ACT_MODE_PING_PONG, + ACT_MODE_MAX, + }; + + enum + { + ACT_BLEND_NONE = 0, + ACT_BLEND_MIX, + ACT_BLEND_MAX, + }; + +#ifdef WITH_CXX_GUARDEDALLOC +public: + void *operator new(size_t num_bytes) { return MEM_mallocN(num_bytes, "GE:BL_Action"); } + void operator delete( void *mem ) { MEM_freeN(mem); } +#endif +}; + +#endif //BL_ACTION + diff --git a/source/gameengine/Ketsji/BL_ActionManager.cpp b/source/gameengine/Ketsji/BL_ActionManager.cpp new file mode 100644 index 00000000000..0a99a5a43a9 --- /dev/null +++ b/source/gameengine/Ketsji/BL_ActionManager.cpp @@ -0,0 +1,98 @@ +/** + * $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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "BL_ActionManager.h" + +BL_ActionManager::BL_ActionManager(class KX_GameObject *obj) +{ + for (int i=0; i<MAX_ACTION_LAYERS; ++i) + m_layers[i] = new BL_Action(obj); +} + +BL_ActionManager::~BL_ActionManager() +{ + for (int i=0; i<MAX_ACTION_LAYERS; ++i) + if (m_layers[i]) + delete m_layers[i]; +} + +float BL_ActionManager::GetActionFrame(short layer) +{ + if (m_layers[layer]) + return m_layers[layer]->GetFrame(); + + return 0.f; +} + +void BL_ActionManager::SetActionFrame(short layer, float frame) +{ + if (m_layers[layer]) + m_layers[layer]->SetFrame(frame); +} + +void BL_ActionManager::PlayAction(const char* name, + float start, + float end, + short layer, + float blendin, + short play_mode, + short blend_mode, + float playback_speed) +{ + // Remove a currently running action on this layer if there is one + if (m_layers[layer]) + StopAction(layer); + + // Create a new action + m_layers[layer]->Play(name, start, end, blendin, play_mode, blend_mode, playback_speed); +} + +void BL_ActionManager::StopAction(short layer) +{ + m_layers[layer]->Stop(); +} + +bool BL_ActionManager::IsActionDone(short layer) +{ + if (m_layers[layer]) + return m_layers[layer]->IsDone(); + + return true; +} + +void BL_ActionManager::Update(float curtime) +{ + for (int i=0; i<MAX_ACTION_LAYERS; ++i) + { + if (!m_layers[i]->IsDone()) + { + m_layers[i]->Update(curtime); + } + } +} diff --git a/source/gameengine/Ketsji/BL_ActionManager.h b/source/gameengine/Ketsji/BL_ActionManager.h new file mode 100644 index 00000000000..b769db02bf9 --- /dev/null +++ b/source/gameengine/Ketsji/BL_ActionManager.h @@ -0,0 +1,69 @@ +/** + * $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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ +#ifndef __BL_ACTIONMANAGER +#define __BL_ACTIONMANAGER + +#include "BL_Action.h" + +#define MAX_ACTION_LAYERS 4 + +class BL_ActionManager +{ +private: + BL_Action* m_layers[MAX_ACTION_LAYERS]; + +public: + BL_ActionManager(class KX_GameObject* obj); + ~BL_ActionManager(); + + void PlayAction(const char* name, + float start, + float end, + short layer=0, + float blendin=0.f, + short play_mode=0, + short blend_mode=0, + float playback_speed=1.f); + + float GetActionFrame(short layer); + void SetActionFrame(short layer, float frame); + + void StopAction(short layer); + bool IsActionDone(short layer); + void Update(float); + +#ifdef WITH_CXX_GUARDEDALLOC +public: + void *operator new(size_t num_bytes) { return MEM_mallocN(num_bytes, "GE:BL_ActionManager"); } + void operator delete( void *mem ) { MEM_freeN(mem); } +#endif +}; + +#endif //BL_ACTIONMANAGER + diff --git a/source/gameengine/Ketsji/CMakeLists.txt b/source/gameengine/Ketsji/CMakeLists.txt index a6339439bea..6fe793bd475 100644 --- a/source/gameengine/Ketsji/CMakeLists.txt +++ b/source/gameengine/Ketsji/CMakeLists.txt @@ -29,25 +29,26 @@ set(INC ../../../intern/string ../../../intern/guardedalloc ../../../intern/container - ../../../source/gameengine/Rasterizer/RAS_OpenGLRasterizer + ../../../source/gameengine/Rasterizer/RAS_OpenGLRasterizer ../../../source/gameengine/Converter ../../../source/gameengine/BlenderRoutines ../../../source/blender/imbuf ../../../intern/moto/include - ../../../source/gameengine/Ketsji + ../../../source/gameengine/Ketsji ../../../source/blender/blenlib ../../../source/blender/blenfont ../../../source/blender/blenkernel ../../../source/blender/python ../../../source/blender/python/generic - ../../../source/blender - ../../../source/blender/makesdna - ../../../source/gameengine/Rasterizer + ../../../source/blender + ../../../source/blender/makesdna + ../../../source/blender/makesrna + ../../../source/gameengine/Rasterizer ../../../source/gameengine/GameLogic - ../../../source/gameengine/Expressions + ../../../source/gameengine/Expressions ../../../source/gameengine/Ketsji/KXNetwork ../../../source/gameengine/Network - ../../../source/gameengine/SceneGraph + ../../../source/gameengine/SceneGraph ../../../source/gameengine/Physics/common ../../../source/gameengine/Network/LoopBackNetwork ../../../intern/audaspace/intern @@ -60,6 +61,8 @@ set(INC_SYS ) set(SRC + BL_Action.cpp + BL_ActionManager.cpp BL_BlenderShader.cpp BL_Material.cpp BL_Shader.cpp @@ -129,6 +132,8 @@ set(SRC KX_WorldInfo.cpp KX_WorldIpoController.cpp + BL_Action.h + BL_ActionManager.h KX_ArmatureSensor.h KX_BlenderMaterial.h KX_BulletPhysicsController.h diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index 47d83c16659..27f4a72ccdf 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -74,6 +74,8 @@ typedef unsigned long uint_ptr; #include "SCA_IController.h" #include "NG_NetworkScene.h" //Needed for sendMessage() +#include "BL_ActionManager.h" + #include "PyObjectPlus.h" /* python stuff */ // This file defines relationships between parents and children @@ -107,7 +109,8 @@ KX_GameObject::KX_GameObject( m_pGraphicController(NULL), m_xray(false), m_pHitObject(NULL), - m_isDeformable(false) + m_isDeformable(false), + m_actionManager(NULL) #ifdef WITH_PYTHON , m_attr_dict(NULL) #endif @@ -154,6 +157,10 @@ KX_GameObject::~KX_GameObject() { delete m_pGraphicController; } + if (m_actionManager) + { + delete m_actionManager; + } #ifdef WITH_PYTHON if (m_attr_dict) { PyDict_Clear(m_attr_dict); /* incase of circular refs or other weird cases */ @@ -344,6 +351,52 @@ void KX_GameObject::RemoveParent(KX_Scene *scene) } } +BL_ActionManager* KX_GameObject::GetActionManager() +{ + // We only want to create an action manager if we need it + if (!m_actionManager) + m_actionManager = new BL_ActionManager(this); + + return m_actionManager; +} + +void KX_GameObject::PlayAction(const char* name, + float start, + float end, + short layer, + float blendin, + short play_mode, + short blend_mode, + float playback_speed) +{ + GetActionManager()->PlayAction(name, start, end, layer, blendin, play_mode, blend_mode, playback_speed); +} + +void KX_GameObject::StopAction(short layer) +{ + GetActionManager()->StopAction(layer); +} + +bool KX_GameObject::IsActionDone(short layer) +{ + return GetActionManager()->IsActionDone(layer); +} + +void KX_GameObject::UpdateActionManager(float curtime) +{ + GetActionManager()->Update(curtime); +} + +float KX_GameObject::GetActionFrame(short layer) +{ + return GetActionManager()->GetActionFrame(layer); +} + +void KX_GameObject::SetActionFrame(short layer, float frame) +{ + GetActionManager()->SetActionFrame(layer, frame); +} + void KX_GameObject::ProcessReplica() { SCA_IObject::ProcessReplica(); @@ -353,6 +406,8 @@ void KX_GameObject::ProcessReplica() m_pSGNode = NULL; m_pClient_info = new KX_ClientObjectInfo(*m_pClient_info); m_pClient_info->m_gameobject = this; + if (m_actionManager) + m_actionManager = new BL_ActionManager(this); m_state = 0; #ifdef WITH_PYTHON @@ -1497,6 +1552,8 @@ PyMethodDef KX_GameObject::Methods[] = { KX_PYMETHODTABLE_O(KX_GameObject, getDistanceTo), KX_PYMETHODTABLE_O(KX_GameObject, getVectTo), KX_PYMETHODTABLE(KX_GameObject, sendMessage), + + KX_PYMETHODTABLE_KEYWORDS(KX_GameObject, playAction), // dict style access for props {"get",(PyCFunction) KX_GameObject::sPyget, METH_VARARGS}, @@ -2975,6 +3032,43 @@ KX_PYMETHODDEF_DOC_VARARGS(KX_GameObject, sendMessage, Py_RETURN_NONE; } +KX_PYMETHODDEF_DOC(KX_GameObject, playAction, + "playAction(name, start_frame, end_frame, layer=0, blendin=0, play_mode=ACT_MODE_PLAY, blend_mode=ACT_BLEND_NONE, speed=1.0)\n" + "plays an action\n") +{ + const char* name; + float start, end, blendin=0.f, speed=1.f; + short layer=0; + short play_mode=0, blend_mode=0; + + static const char *kwlist[] = {"name", "start_frame", "end_frame", "layer", "blendin", "play_mode", "blend_mode", "speed", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "sff|hfhhf", const_cast<char**>(kwlist), + &name, &start, &end, &layer, &blendin, &play_mode, &blend_mode, &speed)) + return NULL; + + if (layer < 0 || layer > MAX_ACTION_LAYERS) + { + printf("KX_GameObject.playAction(): given layer (%d) is out of range (0 - %d), setting to 0", layer, MAX_ACTION_LAYERS-1); + layer = 0; + } + + if (play_mode < 0 || play_mode > BL_Action::ACT_MODE_MAX) + { + printf("KX_GameObject.playAction(): given play_mode (%d) is out of range (0 - %d), setting to ACT_MODE_PLAY", play_mode, BL_Action::ACT_MODE_MAX-1); + play_mode = BL_Action::ACT_MODE_MAX; + } + + if (blend_mode < 0 || blend_mode > BL_Action::ACT_BLEND_MAX) + { + printf("KX_GameObject.playAction(): given blend_mode (%d) is out of range (0 - %d), setting to ACT_BLEND_NONE", blend_mode, BL_Action::ACT_BLEND_MAX-1); + blend_mode = BL_Action::ACT_BLEND_NONE; + } + + PlayAction(name, start, end, layer, blendin, play_mode, blend_mode, speed); + + Py_RETURN_NONE; +} /* dict style access */ diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index 50fbebe1341..0ff0ec84529 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -63,6 +63,7 @@ class RAS_MeshObject; class KX_IPhysicsController; class PHY_IGraphicController; class PHY_IPhysicsEnvironment; +class BL_ActionManager; struct Object; #ifdef WITH_PYTHON @@ -112,6 +113,11 @@ protected: SG_Node* m_pSGNode; MT_CmMatrix4x4 m_OpenGL_4x4Matrix; + + // The action manager is used to play/stop/update actions + BL_ActionManager* m_actionManager; + + BL_ActionManager* GetActionManager(); public: bool m_isDeformable; @@ -198,6 +204,51 @@ public: */ void RemoveParent(KX_Scene *scene); + /********************************* + * Animation API + *********************************/ + + /** + * Adds an action to the object's action manager + */ + void PlayAction(const char* name, + float start, + float end, + short layer=0, + float blendin=0.f, + short play_mode=0, + short blend_mode=0, + float playback_speed=1.f); + + /** + * Gets the current frame of an action + */ + float GetActionFrame(short layer); + + /** + * Sets the current frame of an action + */ + void SetActionFrame(short layer, float frame); + + /** + * Remove an action from the object's action manager + */ + void StopAction(short layer); + + /** + * Check if an action has finished playing + */ + bool IsActionDone(short layer); + + /** + * Kick the object's action manager + */ + void UpdateActionManager(float curtime); + + /********************************* + * End Animation API + *********************************/ + /** * Construct a game object. This class also inherits the * default constructors - use those with care! @@ -853,6 +904,8 @@ public: KX_PYMETHOD_DOC_O(KX_GameObject,getVectTo); KX_PYMETHOD_DOC_VARARGS(KX_GameObject, sendMessage); KX_PYMETHOD_VARARGS(KX_GameObject, ReinstancePhysicsMesh); + + KX_PYMETHOD_DOC(KX_GameObject, playAction); /* Dict access */ KX_PYMETHOD_VARARGS(KX_GameObject,get); diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index 28dc660037c..27bf5d19b14 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -1506,6 +1506,9 @@ void KX_Scene::LogicBeginFrame(double curtime) void KX_Scene::LogicUpdateFrame(double curtime, bool frame) { + // Update any animations + for (int i=0; i<GetObjectList()->GetCount(); ++i) + ((KX_GameObject*)GetObjectList()->GetValue(i))->UpdateActionManager(curtime); m_logicmgr->UpdateFrame(curtime, frame); } diff --git a/source/gameengine/Ketsji/SConscript b/source/gameengine/Ketsji/SConscript index 08642262724..da6361952e0 100644 --- a/source/gameengine/Ketsji/SConscript +++ b/source/gameengine/Ketsji/SConscript @@ -14,7 +14,7 @@ incs += ' #intern/audaspace/intern #source/gameengine/Converter' incs += ' #source/gameengine/BlenderRoutines #source/blender/imbuf #intern/moto/include' incs += ' #source/gameengine/Ketsji #source/gameengine/Ketsji/KXNetwork #source/blender/blenlib #source/blender/blenfont' incs += ' #source/blender/blenkernel #source/blender #source/blender/editors/include' -incs += ' #source/blender/makesdna #source/blender/python #source/gameengine/Rasterizer' +incs += ' #source/blender/makesdna #source/blender/makesrna #source/blender/python #source/gameengine/Rasterizer' incs += ' #source/gameengine/GameLogic #source/gameengine/Expressions #source/gameengine/Network' incs += ' #source/gameengine/SceneGraph #source/gameengine/Physics/common' incs += ' #source/gameengine/Physics/Dummy' @@ -34,7 +34,7 @@ if env['WITH_BF_PYTHON']: if env['WITH_BF_FFMPEG']: defs.append('WITH_FFMPEG') - + if env['OURPLATFORM'] in ('win32-vc', 'win64-vc', 'win32-mingw'): if env['BF_DEBUG']: defs.append('_DEBUG') # for Python diff --git a/source/gameengine/SceneGraph/SG_IObject.cpp b/source/gameengine/SceneGraph/SG_IObject.cpp index 3064e6662b9..b22d210984d 100644 --- a/source/gameengine/SceneGraph/SG_IObject.cpp +++ b/source/gameengine/SceneGraph/SG_IObject.cpp @@ -34,6 +34,8 @@ #include "SG_IObject.h" #include "SG_Controller.h" +#include <algorithm> + SG_Stage gSG_Stage = SG_STAGE_UNKNOWN; SG_IObject:: @@ -71,6 +73,16 @@ AddSGController( void SG_IObject:: +RemoveSGController( + SG_Controller* cont +) { + SGControllerList::iterator contit; + + m_SGcontrollers.erase(std::remove(m_SGcontrollers.begin(), m_SGcontrollers.end(), cont)); +} + + void +SG_IObject:: RemoveAllControllers( ) { m_SGcontrollers.clear(); diff --git a/source/gameengine/SceneGraph/SG_IObject.h b/source/gameengine/SceneGraph/SG_IObject.h index 26e317bdcd9..e709699c08a 100644 --- a/source/gameengine/SceneGraph/SG_IObject.h +++ b/source/gameengine/SceneGraph/SG_IObject.h @@ -180,6 +180,16 @@ public: SG_Controller* cont ); + /** + * Remove a pointer to a controller from this node. + * This does not delete the controller itself! Be careful to + * avoid memory leaks. + */ + void + RemoveSGController( + SG_Controller* cont + ); + /** * Clear the array of pointers to controllers associated with * this node. This does not delete the controllers themselves! |