SequenceNode inherits from AnimInterface

This commit is contained in:
David Rose 2005-09-27 17:52:39 +00:00
parent 0e236030be
commit 5465571963
9 changed files with 499 additions and 317 deletions

View File

@ -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());

View File

@ -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<PandaNode *> Decals;
Decals _decals;
typedef pset<PandaNode *> ExtraNodes;
ExtraNodes _decals;
ExtraNodes _sequences;
class VertexPoolTransform {
public:

View File

@ -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 &copy) :
_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);
}

View File

@ -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 &copy) :
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 &copy) :
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 &params) {
SequenceNode *node = new SequenceNode(0.0f, "");
SequenceNode *node = new SequenceNode("");
DatagramIterator scan;
BamReader *manager;
@ -234,5 +201,12 @@ make_from_bam(const FactoryParams &params) {
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);
}
}

View File

@ -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 &copy);
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 &copy);
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<CData> _cycler;
typedef CycleDataReader<CData> CDReader;
typedef CycleDataWriter<CData> 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();

View File

@ -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);

View File

@ -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 &copy) :
_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 &copy) :
AnimInterface::CData::
CData(const AnimInterface::CData &copy) :
_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 &copy) :
}
////////////////////////////////////////////////////////////////////
// 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);
}
}

View File

@ -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 &copy);
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<CData> _cycler;
typedef CycleDataReader<CData> CDReader;
typedef CycleDataWriter<CData> CDWriter;
protected:
virtual void write_datagram(BamWriter *manager, Datagram &dg);
void fillin(DatagramIterator &scan, BamReader *manager);
public:
static TypeHandle get_class_type() {

View File

@ -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