#include "animation.hxx"
#include "flash.hxx"
+#include "personality.hxx"
\f
////////////////////////////////////////////////////////////////////////
// Initialize the static data member
double SGAnimation::sim_time_sec = 0.0;
-ssgBranch *SGAnimation::current_object = 0;
+SGPersonalityBranch *SGAnimation::current_object = 0;
SGAnimation::SGAnimation (SGPropertyNode_ptr props, ssgBranch * branch)
: _branch(branch)
SGTimedAnimation::SGTimedAnimation (SGPropertyNode_ptr props)
: SGAnimation(props, new ssgSelector),
+ _use_personality( props->getBoolValue("use-personality",false) ),
_duration_sec(props->getDoubleValue("duration-sec", 1.0)),
- _step( 0 ),
- _use_personality( props->getBoolValue("use-personality",false) )
+ _last_time_sec( sim_time_sec ),
+ _total_duration_sec( 0 ),
+ _step( 0 )
+
{
vector<SGPropertyNode_ptr> nodes = props->getChildren( "branch-duration-sec" );
size_t nb = nodes.size();
rNode->getDoubleValue( "max", 1.0 ) );
}
}
+ if ( !_use_personality ) {
+ for ( size_t i = 0; i < _branch_duration_specs.size(); i++ ) {
+ DurationSpec &sp = _branch_duration_specs[ i ];
+ double v = sp._min + sg_random() * ( sp._max - sp._min );
+ _branch_duration_sec.push_back( v );
+ _total_duration_sec += v;
+ }
+ }
((ssgSelector *)getBranch())->selectStep(_step);
}
int
SGTimedAnimation::update()
{
- ssgBranch *key = ( _use_personality ? current_object : 0 );
- PersonalityMap::iterator it = _branch_duration_sec.find( key );
- if ( it == _branch_duration_sec.end() ) {
- vector<double> durations;
- double total = 0;
- for ( size_t i = 0; i < _branch_duration_specs.size(); i++ ) {
- DurationSpec &sp = _branch_duration_specs[ i ];
- double v = sp._min + sg_random() * ( sp._max - sp._min );
- durations.push_back( v );
- total += v;
+ if ( _use_personality ) {
+ SGPersonalityBranch *key = current_object;
+ if ( !key->getIntValue( this, INIT ) ) {
+ double total = 0;
+ for ( size_t i = 0; i < _branch_duration_specs.size(); i++ ) {
+ DurationSpec &sp = _branch_duration_specs[ i ];
+ double v = sp._min + sg_random() * ( sp._max - sp._min );
+ key->setDoubleValue( v, this, BRANCH_DURATION_SEC, i );
+ total += v;
+ }
+ key->setDoubleValue( sim_time_sec, this, LAST_TIME_SEC );
+ key->setDoubleValue( total, this, TOTAL_DURATION_SEC );
+ key->setIntValue( 0, this, STEP );
+ key->setIntValue( 1, this, INIT );
}
- it = _branch_duration_sec.insert( PersonalityMap::value_type( key, durations ) ).first;
- _last_time_sec[ key ] = sim_time_sec;
- _total_duration_sec[ key ] = total;
- }
- while ( ( sim_time_sec - _last_time_sec[ key ] ) >= _total_duration_sec[ key ] ) {
- _last_time_sec[ key ] += _total_duration_sec[ key ];
- }
- double duration = _duration_sec;
- if ( _step < (int)it->second.size() ) {
- duration = it->second[ _step ];
- }
- if ( ( sim_time_sec - _last_time_sec[ key ] ) >= duration ) {
- _last_time_sec[ key ] += duration;
- _step += 1;
- if ( _step >= getBranch()->getNumKids() )
- _step = 0;
+ _step = key->getIntValue( this, STEP );
+ _last_time_sec = key->getDoubleValue( this, LAST_TIME_SEC );
+ _total_duration_sec = key->getDoubleValue( this, TOTAL_DURATION_SEC );
+ while ( ( sim_time_sec - _last_time_sec ) >= _total_duration_sec ) {
+ _last_time_sec += _total_duration_sec;
+ }
+ double duration = _duration_sec;
+ if ( _step < (int)_branch_duration_specs.size() ) {
+ duration = key->getDoubleValue( this, BRANCH_DURATION_SEC, _step );
+ }
+ if ( ( sim_time_sec - _last_time_sec ) >= duration ) {
+ _last_time_sec += duration;
+ _step += 1;
+ if ( _step >= getBranch()->getNumKids() )
+ _step = 0;
+ }
((ssgSelector *)getBranch())->selectStep( _step );
+ key->setDoubleValue( _last_time_sec, this, LAST_TIME_SEC );
+ key->setIntValue( _step, this, STEP );
+ } else {
+ while ( ( sim_time_sec - _last_time_sec ) >= _total_duration_sec ) {
+ _last_time_sec += _total_duration_sec;
+ }
+ double duration = _duration_sec;
+ if ( _step < (int)_branch_duration_sec.size() ) {
+ duration = _branch_duration_sec[ _step ];
+ }
+ if ( ( sim_time_sec - _last_time_sec ) >= duration ) {
+ _last_time_sec += duration;
+ _step += 1;
+ if ( _step >= getBranch()->getNumKids() )
+ _step = 0;
+ ((ssgSelector *)getBranch())->selectStep( _step );
+ }
}
return 1;
}
// Don't pull in the headers, since we don't need them here.
class SGInterpTable;
class SGCondition;
+class SGPersonalityBranch;
// Has anyone done anything *really* stupid, like making min and max macros?
* Current personality branch : enable animation to behave differently
* for similar objects
*/
- static ssgBranch *current_object;
+ static SGPersonalityBranch *current_object;
protected:
virtual ~SGTimedAnimation ();
virtual int update();
private:
+ bool _use_personality;
+ enum PersonalityVar { INIT, LAST_TIME_SEC, TOTAL_DURATION_SEC, BRANCH_DURATION_SEC, STEP };
double _duration_sec;
- map<ssgBranch *,double> _last_time_sec;
- map<ssgBranch *,double> _total_duration_sec;
+ double _last_time_sec;
+ double _total_duration_sec;
int _step;
struct DurationSpec {
DurationSpec( double m = 0.0 ) : _min(m), _max(m) {}
double _min, _max;
};
vector<DurationSpec> _branch_duration_specs;
- bool _use_personality;
- typedef map<ssgBranch *,vector<double> > PersonalityMap;
- PersonalityMap _branch_duration_sec;
+ vector<double> _branch_duration_sec;
};
--- /dev/null
+/**
+ * $Id$
+ */
+
+#include <simgear/compiler.h>
+
+#include "personality.hxx"
+
+void SGPersonalityBranch::setDoubleValue( double value, SGAnimation *anim, int var_id, int var_num )
+{
+ _doubleValues[ Key( anim, var_id, var_num ) ] = value;
+}
+
+void SGPersonalityBranch::setIntValue( int value, SGAnimation *anim, int var_id, int var_num )
+{
+ _intValues[ Key( anim, var_id, var_num ) ] = value;
+}
+
+double SGPersonalityBranch::getDoubleValue( SGAnimation *anim, int var_id, int var_num ) const
+{
+ map<Key,double>::const_iterator it = _doubleValues.find( Key( anim, var_id, var_num ) );
+ if ( it != _doubleValues.end() ) {
+ return it->second;
+ } else {
+ return 0;
+ }
+}
+
+int SGPersonalityBranch::getIntValue( SGAnimation *anim, int var_id, int var_num ) const
+{
+ map<Key,int>::const_iterator it = _intValues.find( Key( anim, var_id, var_num ) );
+ if ( it != _intValues.end() ) {
+ return it->second;
+ } else {
+ return 0;
+ }
+}
--- /dev/null
+/**
+ * $Id$
+ */
+
+#ifndef _SG_PERSONALITY_HXX
+#define _SG_PERSONALITY_HXX 1
+
+#include <map>
+
+SG_USING_STD(map);
+
+#include <plib/ssg.h>
+
+class SGAnimation;
+
+class SGPersonalityBranch : public ssgBranch {
+public:
+ void setDoubleValue( double value, SGAnimation *anim, int var_id, int var_num = 0 );
+ void setIntValue( int value, SGAnimation *anim, int var_id, int var_num = 0 );
+ double getDoubleValue( SGAnimation *anim, int var_id, int var_num = 0 ) const;
+ int getIntValue( SGAnimation *anim, int var_id, int var_num = 0 ) const;
+
+ SGPersonalityBranch *_old_current;
+
+private:
+ struct Key {
+ Key( SGAnimation *a, int i, int n = 0 ) : anim(a), var_id(i), var_num(n) {}
+ SGAnimation *anim;
+ int var_id;
+ int var_num;
+ bool operator<( const Key &r ) const {
+ return anim < r.anim ||
+ ( anim == r.anim && ( var_id < r.var_id ||
+ ( var_id == r.var_id && var_num < r.var_num ) ) );
+ }
+ };
+ map<Key,double> _doubleValues;
+ map<Key,int> _intValues;
+};
+
+#endif // _SG_PERSONALITY_HXX