diff --git a/panda/src/egg2pg/eggLoader.cxx b/panda/src/egg2pg/eggLoader.cxx index a2504d441f..f6db77b446 100644 --- a/panda/src/egg2pg/eggLoader.cxx +++ b/panda/src/egg2pg/eggLoader.cxx @@ -202,6 +202,7 @@ build_graph() { make_node(_data, _root); reparent_decals(); + start_sequences(); apply_deferred_nodes(_root, DeferredNodeProperty()); } @@ -217,7 +218,7 @@ build_graph() { //////////////////////////////////////////////////////////////////// void EggLoader:: reparent_decals() { - Decals::const_iterator di; + ExtraNodes::const_iterator di; for (di = _decals.begin(); di != _decals.end(); ++di) { PandaNode *node = (*di); nassertv(node != (PandaNode *)NULL); @@ -271,6 +272,24 @@ reparent_decals() { } } +//////////////////////////////////////////////////////////////////// +// Function: EggLoader::start_sequences +// Access: Public +// Description: Starts all of the SequenceNodes we created looping. +// We have to wait until the entire graph is built up to +// do this, because the SequenceNode needs its full set +// of children before it can know how many frames to +// loop. +//////////////////////////////////////////////////////////////////// +void EggLoader:: +start_sequences() { + ExtraNodes::const_iterator ni; + for (ni = _sequences.begin(); ni != _sequences.end(); ++ni) { + SequenceNode *node = DCAST(SequenceNode, (*ni)); + node->loop(true); + } +} + //////////////////////////////////////////////////////////////////// // Function: EggLoader::make_polyset // Access: Public @@ -1593,8 +1612,9 @@ make_node(EggGroup *egg_group, PandaNode *parent) { } else if (egg_group->get_switch_flag()) { if (egg_group->get_switch_fps() != 0.0) { // Create a sequence node. - node = new SequenceNode(egg_group->get_switch_fps(), - egg_group->get_name()); + node = new SequenceNode(egg_group->get_name()); + ((SequenceNode *)node.p())->set_frame_rate(egg_group->get_switch_fps()); + _sequences.insert(node); } else { // Create a switch node. node = new SwitchNode(egg_group->get_name()); diff --git a/panda/src/egg2pg/eggLoader.h b/panda/src/egg2pg/eggLoader.h index 4dac3b2105..ceeac507ef 100644 --- a/panda/src/egg2pg/eggLoader.h +++ b/panda/src/egg2pg/eggLoader.h @@ -75,6 +75,7 @@ public: void build_graph(); void reparent_decals(); + void start_sequences(); void make_polyset(EggBin *egg_bin, PandaNode *parent, const LMatrix4d *transform, bool is_dynamic, @@ -212,8 +213,9 @@ private: Materials _materials; Materials _materials_bface; - typedef pset Decals; - Decals _decals; + typedef pset ExtraNodes; + ExtraNodes _decals; + ExtraNodes _sequences; class VertexPoolTransform { public: diff --git a/panda/src/pgraph/sequenceNode.I b/panda/src/pgraph/sequenceNode.I index 6a67e2521d..066f4d4056 100644 --- a/panda/src/pgraph/sequenceNode.I +++ b/panda/src/pgraph/sequenceNode.I @@ -17,113 +17,26 @@ //////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////// -// Function: SequenceNode::CData::Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE SequenceNode::CData:: -CData() { - _cycle_rate = 0.0f; - _frame_offset = 0.0f; - _start_time = 0.0f; -} - -//////////////////////////////////////////////////////////////////// -// Function: SequenceNode::CData::Copy Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE SequenceNode::CData:: -CData(const SequenceNode::CData ©) : - _cycle_rate(copy._cycle_rate), - _frame_offset(copy._frame_offset), - _start_time(copy._start_time) -{ -} - //////////////////////////////////////////////////////////////////// // Function: SequenceNode::Constructor // Access: Published // Description: //////////////////////////////////////////////////////////////////// INLINE SequenceNode:: -SequenceNode(float cycle_rate, const string &name) : +SequenceNode(const string &name) : SelectiveChildNode(name) { - CDWriter cdata(_cycler); - cdata->_cycle_rate = cycle_rate; - cdata->_frame_offset = 0.0f; - - float now = ClockObject::get_global_clock()->get_frame_time(); - cdata->_start_time = now; } //////////////////////////////////////////////////////////////////// -// Function: SequenceNode::set_cycle_rate +// Function: SequenceNode::set_frame_rate // Access: Published -// Description: Sets the rate of cycling for the children of the -// SequenceNode, in cycles per second. +// Description: Changes the advertised frame rate of the +// SequenceNode. This can be used in conjunction with +// get_play_rate() to change the effective frame rate of +// the node. //////////////////////////////////////////////////////////////////// INLINE void SequenceNode:: -set_cycle_rate(float cycle_rate) { - // Do some fussing so we keep the same frame visible while we - // change this. - CDWriter cdata(_cycler); - float now = ClockObject::get_global_clock()->get_frame_time(); - cdata->_frame_offset = calc_frame(now); - cdata->_start_time = now; - cdata->_cycle_rate = cycle_rate; -} - -//////////////////////////////////////////////////////////////////// -// Function: SequenceNode::get_cycle_rate -// Access: Published -// Description: Returns the rate of cycling for the children of the -// SequenceNode, in cycles per second. -//////////////////////////////////////////////////////////////////// -INLINE float SequenceNode:: -get_cycle_rate() const { - CDReader cdata(_cycler); - return cdata->_cycle_rate; -} - -//////////////////////////////////////////////////////////////////// -// Function: SequenceNode::set_visible_child -// Access: Published -// Description: Sets the particular child that this SequenceNode will -// display this frame. Future frames will proceed from -// here. -//////////////////////////////////////////////////////////////////// -INLINE void SequenceNode:: -set_visible_child(int index) { - int num_children = get_num_children(); - if (num_children != 0) { - CDWriter cdata(_cycler); - float now = ClockObject::get_global_clock()->get_frame_time(); - cdata->_frame_offset = (index - (now - cdata->_start_time) * cdata->_cycle_rate); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: SequenceNode::calc_frame -// Access: Private -// Description: Returns the floating-point frame number at the -// indicated time. -//////////////////////////////////////////////////////////////////// -INLINE float SequenceNode:: -calc_frame(float now) const { - CDReader cdata(_cycler); - return (now - cdata->_start_time) * cdata->_cycle_rate + cdata->_frame_offset; -} - -//////////////////////////////////////////////////////////////////// -// Function: SequenceNode::calc_frame -// Access: Private -// Description: Returns the floating-point frame number at the -// current time. -//////////////////////////////////////////////////////////////////// -INLINE float SequenceNode:: -calc_frame() const { - return calc_frame(ClockObject::get_global_clock()->get_frame_time()); +set_frame_rate(double frame_rate) { + AnimInterface::set_frame_rate(frame_rate); } diff --git a/panda/src/pgraph/sequenceNode.cxx b/panda/src/pgraph/sequenceNode.cxx index f5b6afa9b6..75b9485153 100644 --- a/panda/src/pgraph/sequenceNode.cxx +++ b/panda/src/pgraph/sequenceNode.cxx @@ -23,13 +23,30 @@ TypeHandle SequenceNode::_type_handle; //////////////////////////////////////////////////////////////////// -// Function: SequenceNode::CData::make_copy -// Access: Public, Virtual +// Function: SequenceNode::Copy Constructor +// Access: Protected // Description: //////////////////////////////////////////////////////////////////// -CycleData *SequenceNode::CData:: -make_copy() const { - return new CData(*this); +SequenceNode:: +SequenceNode(const SequenceNode ©) : + SelectiveChildNode(copy), + AnimInterface(copy) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: SequenceNode::get_num_frames +// Access: Published, Virtual +// Description: Returns the number of frames in the animation. This +// is a property of the animation and may not be +// directly adjusted by the user (although it may change +// without warning with certain kinds of animations, +// since this is a virtual method that may be +// overridden). +//////////////////////////////////////////////////////////////////// +int SequenceNode:: +get_num_frames() const { + return get_num_children(); } //////////////////////////////////////////////////////////////////// @@ -47,49 +64,6 @@ safe_to_combine() const { return false; } -//////////////////////////////////////////////////////////////////// -// Function: SequenceNode::CData::write_datagram -// Access: Public, Virtual -// Description: Writes the contents of this object to the datagram -// for shipping out to a Bam file. -//////////////////////////////////////////////////////////////////// -void SequenceNode::CData:: -write_datagram(BamWriter *manager, Datagram &dg) const { - dg.add_float32(_cycle_rate); - - float now = ClockObject::get_global_clock()->get_frame_time(); - float frame = (now - _start_time) * _cycle_rate + _frame_offset; - dg.add_float32(frame); -} - -//////////////////////////////////////////////////////////////////// -// Function: SequenceNode::CData::fillin -// Access: Public, Virtual -// Description: This internal function is called by make_from_bam to -// read in all of the relevant data from the BamFile for -// the new SequenceNode. -//////////////////////////////////////////////////////////////////// -void SequenceNode::CData:: -fillin(DatagramIterator &scan, BamReader *manager) { - _cycle_rate = scan.get_float32(); - _frame_offset = scan.get_float32(); - - float now = ClockObject::get_global_clock()->get_frame_time(); - _start_time = now; -} - -//////////////////////////////////////////////////////////////////// -// Function: SequenceNode::Copy Constructor -// Access: Protected -// Description: -//////////////////////////////////////////////////////////////////// -SequenceNode:: -SequenceNode(const SequenceNode ©) : - SelectiveChildNode(copy), - _cycler(copy._cycler) -{ -} - //////////////////////////////////////////////////////////////////// // Function: SequenceNode::make_copy // Access: Public, Virtual @@ -138,7 +112,7 @@ has_cull_callback() const { //////////////////////////////////////////////////////////////////// bool SequenceNode:: cull_callback(CullTraverser *, CullTraverserData &) { - select_child(get_visible_child()); + select_child(get_frame()); return true; } @@ -164,21 +138,14 @@ has_single_child_visibility() const { } //////////////////////////////////////////////////////////////////// -// Function: SequenceNode::get_visible_child +// Function: SequenceNode::output // Access: Published, Virtual -// Description: Returns the index of the child that should be visible -// for this particular frame, if there are any children. +// Description: //////////////////////////////////////////////////////////////////// -int SequenceNode:: -get_visible_child() const { - int num_children = get_num_children(); - if (num_children == 0) { - return 0; - } - - float frame = calc_frame(); - - return ((int)frame) % num_children; +void SequenceNode:: +output(ostream &out) const { + out << get_type() << " " << get_name() << ": "; + AnimInterface::output(out); } //////////////////////////////////////////////////////////////////// @@ -201,7 +168,7 @@ register_with_read_factory() { void SequenceNode:: write_datagram(BamWriter *manager, Datagram &dg) { SelectiveChildNode::write_datagram(manager, dg); - manager->write_cdata(dg, _cycler); + AnimInterface::write_datagram(manager, dg); } //////////////////////////////////////////////////////////////////// @@ -214,7 +181,7 @@ write_datagram(BamWriter *manager, Datagram &dg) { //////////////////////////////////////////////////////////////////// TypedWritable *SequenceNode:: make_from_bam(const FactoryParams ¶ms) { - SequenceNode *node = new SequenceNode(0.0f, ""); + SequenceNode *node = new SequenceNode(""); DatagramIterator scan; BamReader *manager; @@ -234,5 +201,12 @@ make_from_bam(const FactoryParams ¶ms) { void SequenceNode:: fillin(DatagramIterator &scan, BamReader *manager) { SelectiveChildNode::fillin(scan, manager); - manager->read_cdata(scan, _cycler); + if (manager->get_file_minor_ver() < 4) { + float cycle_rate = scan.get_float32(); + scan.get_float32(); + set_frame_rate(cycle_rate); + loop(true); + } else { + AnimInterface::fillin(scan, manager); + } } diff --git a/panda/src/pgraph/sequenceNode.h b/panda/src/pgraph/sequenceNode.h index 7bb0ae3518..696d2b2144 100644 --- a/panda/src/pgraph/sequenceNode.h +++ b/panda/src/pgraph/sequenceNode.h @@ -22,6 +22,7 @@ #include "pandabase.h" #include "selectiveChildNode.h" +#include "animInterface.h" #include "clockObject.h" //////////////////////////////////////////////////////////////////// @@ -29,13 +30,18 @@ // Description : A node that automatically cycles through rendering // each one of its children according to its frame rate. //////////////////////////////////////////////////////////////////// -class EXPCL_PANDA SequenceNode : public SelectiveChildNode { +class EXPCL_PANDA SequenceNode : public SelectiveChildNode, public AnimInterface { PUBLISHED: - INLINE SequenceNode(float cycle_rate, const string &name); + INLINE SequenceNode(const string &name); -public: +protected: SequenceNode(const SequenceNode ©); +PUBLISHED: + virtual int get_num_frames() const; + INLINE void set_frame_rate(double frame_rate); + +public: virtual PandaNode *make_copy() const; virtual bool safe_to_combine() const; @@ -43,33 +49,7 @@ public: virtual bool cull_callback(CullTraverser *trav, CullTraverserData &data); virtual bool has_single_child_visibility() const; -PUBLISHED: - INLINE void set_cycle_rate(float cycle_rate); - INLINE float get_cycle_rate() const; - - INLINE void set_visible_child(int index); - virtual int get_visible_child() const; - -private: - INLINE float calc_frame(float now) const; - INLINE float calc_frame() const; - - class EXPCL_PANDA CData : public CycleData { - public: - INLINE CData(); - INLINE CData(const CData ©); - virtual CycleData *make_copy() const; - virtual void write_datagram(BamWriter *manager, Datagram &dg) const; - virtual void fillin(DatagramIterator &scan, BamReader *manager); - - float _cycle_rate; - float _frame_offset; - float _start_time; - }; - - PipelineCycler _cycler; - typedef CycleDataReader CDReader; - typedef CycleDataWriter CDWriter; + virtual void output(ostream &out) const; public: static void register_with_read_factory(); @@ -85,8 +65,10 @@ public: } static void init_type() { SelectiveChildNode::init_type(); + AnimInterface::init_type(); register_type(_type_handle, "SequenceNode", - SelectiveChildNode::get_class_type()); + SelectiveChildNode::get_class_type(), + AnimInterface::get_class_type()); } virtual TypeHandle get_type() const { return get_class_type(); diff --git a/panda/src/putil/animInterface.I b/panda/src/putil/animInterface.I index 83097dcc4f..78f6b2b8f4 100644 --- a/panda/src/putil/animInterface.I +++ b/panda/src/putil/animInterface.I @@ -28,6 +28,26 @@ play() { play(0, get_num_frames() - 1); } +//////////////////////////////////////////////////////////////////// +// Function: AnimInterface::play +// Access: Published +// Description: Runs the animation from the frame "from" to and +// including the frame "to", at which point the +// animation is stopped. Both "from" and "to" frame +// numbers may be outside the range (0, +// get_num_frames()) and the animation will follow the +// range correctly, reporting numbers modulo +// get_num_frames(). For instance, play(0, +// get_num_frames() * 2) will play the animation twice +// and then stop. +//////////////////////////////////////////////////////////////////// +INLINE void AnimInterface:: +play(double from, double to) { + CDWriter cdata(_cycler); + cdata->play(from, to); + animation_activated(); +} + //////////////////////////////////////////////////////////////////// // Function: AnimInterface::loop // Access: Published @@ -40,6 +60,22 @@ loop(bool restart) { loop(restart, 0, get_num_frames() - 1); } +//////////////////////////////////////////////////////////////////// +// Function: AnimInterface::loop +// Access: Published +// Description: Loops the animation from the frame "from" to and +// including the frame "to", indefinitely. If restart +// is true, the animation is restarted from the +// beginning; otherwise, it continues from the current +// frame. +//////////////////////////////////////////////////////////////////// +INLINE void AnimInterface:: +loop(bool restart, double from, double to) { + CDWriter cdata(_cycler); + cdata->loop(restart, from, to); + animation_activated(); +} + //////////////////////////////////////////////////////////////////// // Function: AnimInterface::pingpong // Access: Published @@ -54,6 +90,20 @@ pingpong(bool restart) { pingpong(restart, 0, get_num_frames() - 1); } +//////////////////////////////////////////////////////////////////// +// Function: AnimInterface::pingpong +// Access: Published +// Description: Loops the animation from the frame "from" to and +// including the frame "to", and then back in the +// opposite direction, indefinitely. +//////////////////////////////////////////////////////////////////// +INLINE void AnimInterface:: +pingpong(bool restart, double from, double to) { + CDWriter cdata(_cycler); + cdata->pingpong(restart, from, to); + animation_activated(); +} + //////////////////////////////////////////////////////////////////// // Function: AnimInterface::stop // Access: Published @@ -66,6 +116,19 @@ stop() { pose(get_frame()); } +//////////////////////////////////////////////////////////////////// +// Function: AnimInterface::pose +// Access: Published +// Description: Sets the animation to the indicated frame and holds +// it there. +//////////////////////////////////////////////////////////////////// +INLINE void AnimInterface:: +pose(int frame) { + CDWriter cdata(_cycler); + cdata->pose(frame); + animation_activated(); +} + //////////////////////////////////////////////////////////////////// // Function: AnimInterface::set_play_rate // Access: Published @@ -77,7 +140,8 @@ stop() { //////////////////////////////////////////////////////////////////// INLINE void AnimInterface:: set_play_rate(double play_rate) { - internal_set_rate(_frame_rate, play_rate); + CDWriter cdata(_cycler); + cdata->internal_set_rate(cdata->_frame_rate, play_rate); } //////////////////////////////////////////////////////////////////// @@ -88,7 +152,8 @@ set_play_rate(double play_rate) { //////////////////////////////////////////////////////////////////// INLINE double AnimInterface:: get_play_rate() const { - return _play_rate; + CDReader cdata(_cycler); + return cdata->_play_rate; } //////////////////////////////////////////////////////////////////// @@ -102,19 +167,8 @@ get_play_rate() const { //////////////////////////////////////////////////////////////////// INLINE double AnimInterface:: get_frame_rate() const { - return _frame_rate; -} - -//////////////////////////////////////////////////////////////////// -// Function: AnimInterface::get_num_frames -// Access: Published -// Description: Returns the number of frames in the animation. This -// is a fixed property of the animation and may not be -// adjusted by the user. -//////////////////////////////////////////////////////////////////// -INLINE int AnimInterface:: -get_num_frames() const { - return _num_frames; + CDReader cdata(_cycler); + return cdata->_frame_rate; } //////////////////////////////////////////////////////////////////// @@ -126,10 +180,11 @@ get_num_frames() const { //////////////////////////////////////////////////////////////////// INLINE int AnimInterface:: get_frame() const { - if (get_num_frames() <= 0) { + int num_frames = get_num_frames(); + if (num_frames <= 0) { return 0; } - return cmod(get_full_frame(), get_num_frames()); + return cmod(get_full_frame(), num_frames); } //////////////////////////////////////////////////////////////////// @@ -145,7 +200,64 @@ get_frame() const { //////////////////////////////////////////////////////////////////// INLINE double AnimInterface:: get_frac() const { - return get_full_fframe() - (double)get_full_frame(); + CDReader cdata(_cycler); + return cdata->get_frac(); +} + +//////////////////////////////////////////////////////////////////// +// Function: AnimInterface::get_full_frame +// Access: Published +// Description: Returns the current integer frame number. +// +// Unlike the value returned by get_frame(), this frame +// number may extend beyond the range of +// get_num_frames() if the frame range passed to play(), +// loop(), etc. did. +// +// Unlike the value returned by get_full_fframe(), this +// return value will never exceed the value passed to +// to_frame in the play() method. +//////////////////////////////////////////////////////////////////// +INLINE int AnimInterface:: +get_full_frame() const { + CDReader cdata(_cycler); + return cdata->get_full_frame(); +} + +//////////////////////////////////////////////////////////////////// +// Function: AnimInterface::get_full_fframe +// Access: Published +// Description: Returns the current floating-point frame number. +// +// Unlike the value returned by get_frame(), this frame +// number may extend beyond the range of +// get_num_frames() if the frame range passed to play(), +// loop(), etc. did. +// +// Unlike the value returned by get_full_frame(), this +// return value may equal (to_frame + 1.0), when the +// animation has played to its natural end. However, in +// this case the return value of get_full_frame() will +// be to_frame, not (to_frame + 1). +//////////////////////////////////////////////////////////////////// +INLINE double AnimInterface:: +get_full_fframe() const { + CDReader cdata(_cycler); + return cdata->get_full_fframe(); +} + +//////////////////////////////////////////////////////////////////// +// Function: AnimInterface::is_playing +// Access: Published +// Description: Returns true if the animation is currently playing, +// false if it is stopped (e.g. because stop() or pose() +// was called, or because it reached the end of the +// animation after play() was called). +//////////////////////////////////////////////////////////////////// +INLINE bool AnimInterface:: +is_playing() const { + CDReader cdata(_cycler); + return cdata->is_playing(); } //////////////////////////////////////////////////////////////////// @@ -157,7 +269,8 @@ get_frac() const { //////////////////////////////////////////////////////////////////// INLINE void AnimInterface:: set_frame_rate(double frame_rate) { - internal_set_rate(frame_rate, _play_rate); + CDWriter cdata(_cycler); + cdata->internal_set_rate(frame_rate, cdata->_play_rate); } //////////////////////////////////////////////////////////////////// @@ -174,6 +287,22 @@ set_num_frames(int num_frames) { _num_frames = num_frames; } +//////////////////////////////////////////////////////////////////// +// Function: AnimInterface::CData::get_frac +// Access: Published +// Description: Returns the fractional part of the current frame. +// Normally, this is in the range 0.0 <= f < 1.0, but in +// the one special case of an animation playing to its +// end frame and stopping, it might exactly equal 1.0. +// +// It will always be true that get_full_frame() + +// get_frac() == get_full_fframe(). +//////////////////////////////////////////////////////////////////// +INLINE double AnimInterface::CData:: +get_frac() const { + return get_full_fframe() - (double)get_full_frame(); +} + INLINE ostream & operator << (ostream &out, const AnimInterface &ai) { ai.output(out); diff --git a/panda/src/putil/animInterface.cxx b/panda/src/putil/animInterface.cxx index 8d642e78cf..695eb84374 100644 --- a/panda/src/putil/animInterface.cxx +++ b/panda/src/putil/animInterface.cxx @@ -18,6 +18,10 @@ #include "animInterface.h" #include "clockObject.h" +#include "bamReader.h" +#include "bamWriter.h" +#include "datagram.h" +#include "datagramIterator.h" TypeHandle AnimInterface::_type_handle; @@ -28,8 +32,101 @@ TypeHandle AnimInterface::_type_handle; //////////////////////////////////////////////////////////////////// AnimInterface:: AnimInterface() : + _num_frames(0) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: AnimInterface::Copy Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +AnimInterface:: +AnimInterface(const AnimInterface ©) : + _num_frames(copy._num_frames), + _cycler(copy._cycler) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: AnimInterface::Destructor +// Access: Published, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +AnimInterface:: +~AnimInterface() { +} + +//////////////////////////////////////////////////////////////////// +// Function: AnimInterface::get_num_frames +// Access: Published, Virtual +// Description: Returns the number of frames in the animation. This +// is a property of the animation and may not be +// directly adjusted by the user (although it may change +// without warning with certain kinds of animations, +// since this is a virtual method that may be +// overridden). +//////////////////////////////////////////////////////////////////// +int AnimInterface:: +get_num_frames() const { + return _num_frames; +} + +//////////////////////////////////////////////////////////////////// +// Function: AnimInterface::output +// Access: Published, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void AnimInterface:: +output(ostream &out) const { + CDReader cdata(_cycler); + cdata->output(out); +} + +//////////////////////////////////////////////////////////////////// +// Function: AnimInterface::animation_activated +// Access: Protected, Virtual +// Description: This is provided as a callback method for when the +// user calls one of the play/loop/pose type methods to +// start the animation playing. +//////////////////////////////////////////////////////////////////// +void AnimInterface:: +animation_activated() { +} + +//////////////////////////////////////////////////////////////////// +// Function: AnimInterface::write_datagram +// Access: Public, Virtual +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void AnimInterface:: +write_datagram(BamWriter *manager, Datagram &dg) { + dg.add_int32(_num_frames); + manager->write_cdata(dg, _cycler); +} + +//////////////////////////////////////////////////////////////////// +// Function: AnimInterface::fillin +// Access: Protected +// Description: This internal function is called by make_from_bam to +// read in all of the relevant data from the BamFile for +// the new AnimInterface. +//////////////////////////////////////////////////////////////////// +void AnimInterface:: +fillin(DatagramIterator &scan, BamReader *manager) { + _num_frames = scan.get_int32(); + manager->read_cdata(scan, _cycler); +} + +//////////////////////////////////////////////////////////////////// +// Function: AnimInterface::CData::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +AnimInterface::CData:: +CData() : _frame_rate(0.0), - _num_frames(0), _play_mode(PM_pose), _start_time(0.0), _start_frame(0.0), @@ -44,14 +141,13 @@ AnimInterface() : } //////////////////////////////////////////////////////////////////// -// Function: AnimInterface::Copy Constructor +// Function: AnimInterface::CData::Copy Constructor // Access: Published // Description: //////////////////////////////////////////////////////////////////// -AnimInterface:: -AnimInterface(const AnimInterface ©) : +AnimInterface::CData:: +CData(const AnimInterface::CData ©) : _frame_rate(copy._frame_rate), - _num_frames(copy._num_frames), _play_mode(copy._play_mode), _start_time(copy._start_time), _start_frame(copy._start_frame), @@ -66,17 +162,60 @@ AnimInterface(const AnimInterface ©) : } //////////////////////////////////////////////////////////////////// -// Function: AnimInterface::Destructor -// Access: Published, Virtual +// Function: AnimInterface::CData::make_copy +// Access: Public, Virtual // Description: //////////////////////////////////////////////////////////////////// -AnimInterface:: -~AnimInterface() { +CycleData *AnimInterface::CData:: +make_copy() const { + return new CData(*this); } //////////////////////////////////////////////////////////////////// -// Function: AnimInterface::play -// Access: Published +// Function: AnimInterface::CData::write_datagram +// Access: Public, Virtual +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void AnimInterface::CData:: +write_datagram(BamWriter *, Datagram &dg) const { + dg.add_float32(_frame_rate); + dg.add_uint8(_play_mode); + dg.add_float32(_start_time); + dg.add_float32(_start_frame); + dg.add_float32(_play_frames); + dg.add_float32(_from_frame); + dg.add_float32(_to_frame); + dg.add_float32(_play_rate); + dg.add_bool(_paused); + dg.add_float32(_paused_f); +} + +//////////////////////////////////////////////////////////////////// +// Function: AnimInterface::CData::fillin +// Access: Public, Virtual +// Description: This internal function is called by make_from_bam to +// read in all of the relevant data from the BamFile for +// the new AnimInterface. +//////////////////////////////////////////////////////////////////// +void AnimInterface::CData:: +fillin(DatagramIterator &scan, BamReader *) { + _frame_rate = scan.get_float32(); + _play_mode = (PlayMode)scan.get_uint8(); + _start_time = scan.get_float32(); + _start_frame = scan.get_float32(); + _play_frames = scan.get_float32(); + _from_frame = scan.get_float32(); + _to_frame = scan.get_float32(); + _play_rate = scan.get_float32(); + _effective_frame_rate = _frame_rate * _play_rate; + _paused = scan.get_bool(); + _paused_f = scan.get_float32(); +} + +//////////////////////////////////////////////////////////////////// +// Function: AnimInterface::CData::play +// Access: Public // Description: Runs the animation from the frame "from" to and // including the frame "to", at which point the // animation is stopped. Both "from" and "to" frame @@ -87,7 +226,7 @@ AnimInterface:: // get_num_frames() * 2) will play the animation twice // and then stop. //////////////////////////////////////////////////////////////////// -void AnimInterface:: +void AnimInterface::CData:: play(double from, double to) { if (from >= to) { pose((int)from); @@ -106,20 +245,18 @@ play(double from, double to) { // If we'll be playing backward, start at the end. _start_time -= _play_frames / _effective_frame_rate; } - - animation_activated(); } //////////////////////////////////////////////////////////////////// -// Function: AnimInterface::loop -// Access: Published +// Function: AnimInterface::CData::loop +// Access: Public // Description: Loops the animation from the frame "from" to and // including the frame "to", indefinitely. If restart // is true, the animation is restarted from the // beginning; otherwise, it continues from the current // frame. //////////////////////////////////////////////////////////////////// -void AnimInterface:: +void AnimInterface::CData:: loop(bool restart, double from, double to) { if (from >= to) { pose((int)from); @@ -143,18 +280,16 @@ loop(bool restart, double from, double to) { _start_time -= fframe / _effective_frame_rate; } } - - animation_activated(); } //////////////////////////////////////////////////////////////////// -// Function: AnimInterface::pingpong -// Access: Published +// Function: AnimInterface::CData::pingpong +// Access: Public // Description: Loops the animation from the frame "from" to and // including the frame "to", and then back in the // opposite direction, indefinitely. //////////////////////////////////////////////////////////////////// -void AnimInterface:: +void AnimInterface::CData:: pingpong(bool restart, double from, double to) { if (from >= to) { pose((int)from); @@ -178,17 +313,15 @@ pingpong(bool restart, double from, double to) { _start_time -= fframe / _effective_frame_rate; } } - - animation_activated(); } //////////////////////////////////////////////////////////////////// -// Function: AnimInterface::pose -// Access: Published +// Function: AnimInterface::CData::pose +// Access: Public // Description: Sets the animation to the indicated frame and holds // it there. //////////////////////////////////////////////////////////////////// -void AnimInterface:: +void AnimInterface::CData:: pose(int frame) { _play_mode = PM_pose; _start_time = ClockObject::get_global_clock()->get_frame_time(); @@ -197,13 +330,11 @@ pose(int frame) { _from_frame = frame; _to_frame = frame; _paused_f = 0.0; - - animation_activated(); } //////////////////////////////////////////////////////////////////// -// Function: AnimInterface::get_full_frame -// Access: Published +// Function: AnimInterface::CData::get_full_frame +// Access: Public // Description: Returns the current integer frame number. // // Unlike the value returned by get_frame(), this frame @@ -215,7 +346,7 @@ pose(int frame) { // return value will never exceed the value passed to // to_frame in the play() method. //////////////////////////////////////////////////////////////////// -int AnimInterface:: +int AnimInterface::CData:: get_full_frame() const { int frame = (int)floor(get_full_fframe()); if (_play_mode == PM_play) { @@ -227,8 +358,8 @@ get_full_frame() const { } //////////////////////////////////////////////////////////////////// -// Function: AnimInterface::get_full_fframe -// Access: Published +// Function: AnimInterface::CData::get_full_fframe +// Access: Public // Description: Returns the current floating-point frame number. // // Unlike the value returned by get_frame(), this frame @@ -242,7 +373,7 @@ get_full_frame() const { // this case the return value of get_full_frame() will // be to_frame, not (to_frame + 1). //////////////////////////////////////////////////////////////////// -double AnimInterface:: +double AnimInterface::CData:: get_full_fframe() const { switch (_play_mode) { case PM_pose: @@ -271,14 +402,14 @@ get_full_fframe() const { } //////////////////////////////////////////////////////////////////// -// Function: AnimInterface::is_playing -// Access: Published +// Function: AnimInterface::CData::is_playing +// Access: Public // Description: Returns true if the animation is currently playing, // false if it is stopped (e.g. because stop() or pose() // was called, or because it reached the end of the // animation after play() was called). //////////////////////////////////////////////////////////////////// -bool AnimInterface:: +bool AnimInterface::CData:: is_playing() const { switch (_play_mode) { case PM_pose: @@ -296,69 +427,39 @@ is_playing() const { } //////////////////////////////////////////////////////////////////// -// Function: AnimInterface::output -// Access: Published, Virtual +// Function: AnimInterface::CData::output +// Access: Public // Description: //////////////////////////////////////////////////////////////////// -void AnimInterface:: +void AnimInterface::CData:: output(ostream &out) const { switch (_play_mode) { case PM_pose: - out << "pose, frame " << get_frame(); + out << "pose, frame " << get_full_frame(); return; case PM_play: - out << "play, frame " << get_frame(); + out << "play, frame " << get_full_frame(); return; case PM_loop: - out << "loop, frame " << get_frame(); + out << "loop, frame " << get_full_frame(); return; case PM_pingpong: - out << "pingpong, frame " << get_frame(); + out << "pingpong, frame " << get_full_frame(); return; } } //////////////////////////////////////////////////////////////////// -// Function: AnimInterface::animation_activated -// Access: Protected, Virtual -// Description: This is provided as a callback method for when the -// user calls one of the play/loop/pose type methods to -// start the animation playing. -//////////////////////////////////////////////////////////////////// -void AnimInterface:: -animation_activated() { -} - -//////////////////////////////////////////////////////////////////// -// Function: AnimInterface::get_f -// Access: Private -// Description: Returns the current floating-point frame number, -// elapsed since _start_frame. -//////////////////////////////////////////////////////////////////// -double AnimInterface:: -get_f() const { - if (_paused) { - return _paused_f; - - } else { - double now = ClockObject::get_global_clock()->get_frame_time(); - double elapsed = now - _start_time; - return (elapsed * _effective_frame_rate); - } -} - - -//////////////////////////////////////////////////////////////////// -// Function: AnimInterface::internal_set_rate -// Access: Private +// Function: AnimInterface::CData::internal_set_rate +// Access: Public // Description: Called internally to adjust either or both of the // frame_rate or play_rate without changing the current // frame number if the animation is already playing. //////////////////////////////////////////////////////////////////// -void AnimInterface:: +void AnimInterface::CData:: internal_set_rate(double frame_rate, double play_rate) { double f = get_f(); @@ -379,3 +480,21 @@ internal_set_rate(double frame_rate, double play_rate) { _paused = false; } } + +//////////////////////////////////////////////////////////////////// +// Function: AnimInterface::CData::get_f +// Access: Public +// Description: Returns the current floating-point frame number, +// elapsed since _start_frame. +//////////////////////////////////////////////////////////////////// +double AnimInterface::CData:: +get_f() const { + if (_paused) { + return _paused_f; + + } else { + double now = ClockObject::get_global_clock()->get_frame_time(); + double elapsed = now - _start_time; + return (elapsed * _effective_frame_rate); + } +} diff --git a/panda/src/putil/animInterface.h b/panda/src/putil/animInterface.h index 76c9477262..c4debed60c 100644 --- a/panda/src/putil/animInterface.h +++ b/panda/src/putil/animInterface.h @@ -22,6 +22,15 @@ #include "pandabase.h" #include "typeHandle.h" #include "register_type.h" +#include "cycleData.h" +#include "cycleDataReader.h" +#include "cycleDataWriter.h" +#include "pipelineCycler.h" + +class BamWriter; +class BamReader; +class Datagram; +class DatagramIterator; //////////////////////////////////////////////////////////////////// // Class : AnimInterface @@ -39,24 +48,24 @@ protected: PUBLISHED: virtual ~AnimInterface(); INLINE void play(); - void play(double from, double to); + INLINE void play(double from, double to); INLINE void loop(bool restart); - void loop(bool restart, double from, double to); + INLINE void loop(bool restart, double from, double to); INLINE void pingpong(bool restart); - void pingpong(bool restart, double from, double to); + INLINE void pingpong(bool restart, double from, double to); INLINE void stop(); - void pose(int frame); + INLINE void pose(int frame); INLINE void set_play_rate(double play_rate); INLINE double get_play_rate() const; INLINE double get_frame_rate() const; - INLINE int get_num_frames() const; + virtual int get_num_frames() const; INLINE int get_frame() const; INLINE double get_frac() const; - int get_full_frame() const; - double get_full_fframe() const; - bool is_playing() const; + INLINE int get_full_frame() const; + INLINE double get_full_fframe() const; + INLINE bool is_playing() const; virtual void output(ostream &out) const; @@ -65,10 +74,6 @@ protected: INLINE void set_num_frames(int num_frames); virtual void animation_activated(); -private: - double get_f() const; - void internal_set_rate(double frame_rate, double play_rate); - private: enum PlayMode { PM_pose, @@ -77,20 +82,57 @@ private: PM_pingpong, }; - double _frame_rate; + // This data is not cycled, because it is a semi-permanent part of + // the interface. Also, some derivatives of AnimInterface don't + // even use it. int _num_frames; - PlayMode _play_mode; - double _start_time; - double _start_frame; - double _play_frames; - int _from_frame; - int _to_frame; + // This is the data that must be cycled between pipeline stages. + class EXPCL_PANDA CData : public CycleData { + public: + CData(); + CData(const CData ©); + virtual CycleData *make_copy() const; + virtual void write_datagram(BamWriter *manager, Datagram &dg) const; + virtual void fillin(DatagramIterator &scan, BamReader *manager); - double _play_rate; - double _effective_frame_rate; - bool _paused; - double _paused_f; + void play(double from, double to); + void loop(bool restart, double from, double to); + void pingpong(bool restart, double from, double to); + void pose(int frame); + + INLINE double get_frac() const; + int get_full_frame() const; + double get_full_fframe() const; + bool is_playing() const; + + virtual void output(ostream &out) const; + + void internal_set_rate(double frame_rate, double play_rate); + double get_f() const; + + double _frame_rate; + + PlayMode _play_mode; + double _start_time; + double _start_frame; + double _play_frames; + int _from_frame; + int _to_frame; + + double _play_rate; + double _effective_frame_rate; + bool _paused; + double _paused_f; + }; + + PipelineCycler _cycler; + typedef CycleDataReader CDReader; + typedef CycleDataWriter CDWriter; + +protected: + virtual void write_datagram(BamWriter *manager, Datagram &dg); + void fillin(DatagramIterator &scan, BamReader *manager); public: static TypeHandle get_class_type() { diff --git a/panda/src/putil/bam.h b/panda/src/putil/bam.h index a4ff103621..426b886599 100644 --- a/panda/src/putil/bam.h +++ b/panda/src/putil/bam.h @@ -35,10 +35,11 @@ static const unsigned short _bam_major_ver = 5; // Bumped to major version 4 on 4/10/02 to store new scene graph. // Bumped to major version 5 on 5/6/05 for new Geom implementation. -static const unsigned short _bam_minor_ver = 3; +static const unsigned short _bam_minor_ver = 4; // Bumped to minor version 1 on 7/14/05 to add TextureStage::_saved_result. // Bumped to minor version 2 on 7/21/05 to add TransformState::is_2d. // Bumped to minor version 3 on 8/25/05 to add ModelNode::_preserve_attributes. +// Bumped to minor version 4 on 9/27/05 to make SequenceNode inherit from AnimInterface. #endif