open_toontown_panda3d/pandatool/src/xfileegg/xFileAnimationSet.cxx

154 lines
4.5 KiB
C++

/**
* PANDA 3D SOFTWARE
* Copyright (c) Carnegie Mellon University. All rights reserved.
*
* All use of this software is subject to the terms of the revised BSD
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file xFileAnimationSet.cxx
* @author drose
* @date 2004-10-02
*/
#include "xFileAnimationSet.h"
#include "xFileToEggConverter.h"
#include "config_xfile.h"
#include "eggGroup.h"
#include "eggTable.h"
#include "eggData.h"
#include "eggXfmSAnim.h"
#include "dcast.h"
/**
*
*/
XFileAnimationSet::
XFileAnimationSet() {
_frame_rate = 0.0;
}
/**
*
*/
XFileAnimationSet::
~XFileAnimationSet() {
}
/**
* Sets up the hierarchy of EggTables corresponding to this AnimationSet.
*/
bool XFileAnimationSet::
create_hierarchy(XFileToEggConverter *converter) {
// Egg animation tables start off with one Table entry, enclosing a Bundle
// entry.
EggTable *table = new EggTable(get_name());
converter->get_egg_data()->add_child(table);
EggTable *bundle = new EggTable(converter->_char_name);
table->add_child(bundle);
bundle->set_table_type(EggTable::TT_bundle);
// Then the Bundle contains a "<skeleton>" entry, which begins the animation
// table hierarchy.
EggTable *skeleton = new EggTable("<skeleton>");
bundle->add_child(skeleton);
// Fill in the rest of the hierarchy with empty tables.
mirror_table(converter, converter->get_dart_node(), skeleton);
// Now populate those empty tables with the frame data.
JointData::const_iterator ji;
for (ji = _joint_data.begin(); ji != _joint_data.end(); ++ji) {
const string &joint_name = (*ji).first;
const FrameData &table = (*ji).second;
EggXfmSAnim *anim_table = get_table(joint_name);
if (anim_table == (EggXfmSAnim *)NULL) {
xfile_cat.warning()
<< "Frame " << joint_name << ", named by animation data, not defined.\n";
} else {
// If we have animation data, apply it.
FrameEntries::const_iterator fi;
for (fi = table._entries.begin(); fi != table._entries.end(); ++fi) {
anim_table->add_data((*fi).get_mat(table._flags));
}
anim_table->optimize();
}
}
// Put some data in the empty tables also.
Tables::iterator ti;
for (ti = _tables.begin(); ti != _tables.end(); ++ti) {
EggXfmSAnim *anim_table = (*ti).second._table;
EggGroup *joint = (*ti).second._joint;
if (anim_table->empty() && joint != (EggGroup *)NULL) {
// If there's no animation data, assign the rest transform.
anim_table->add_data(joint->get_transform3d());
}
anim_table->optimize();
if (_frame_rate != 0.0) {
anim_table->set_fps(_frame_rate);
}
}
return true;
}
/**
* Returns the table associated with the indicated joint name.
*/
EggXfmSAnim *XFileAnimationSet::
get_table(const string &joint_name) const {
Tables::const_iterator ti;
ti = _tables.find(joint_name);
if (ti != _tables.end()) {
return (*ti).second._table;
}
return NULL;
}
/**
* Returns a reference to a new FrameData table corresponding to the indicated
* joint.
*/
XFileAnimationSet::FrameData &XFileAnimationSet::
create_frame_data(const string &joint_name) {
return _joint_data[joint_name];
}
/**
* Builds up a new set of EggTable nodes, as a mirror of the existing set of
* EggGroup (joint) nodes, and saves each new table in the _tables record.
*/
void XFileAnimationSet::
mirror_table(XFileToEggConverter *converter,
EggGroup *model_node, EggTable *anim_node) {
EggGroupNode::iterator gi;
for (gi = model_node->begin(); gi != model_node->end(); ++gi) {
EggNode *child = (*gi);
if (child->is_of_type(EggGroup::get_class_type())) {
EggGroup *group = DCAST(EggGroup, child);
if (group->get_group_type() == EggGroup::GT_joint) {
// When we come to a <Joint>, create a new Table for it.
EggTable *new_table = new EggTable(group->get_name());
anim_node->add_child(new_table);
CoordinateSystem cs =
converter->get_egg_data()->get_coordinate_system();
EggXfmSAnim *xform = new EggXfmSAnim("xform", cs);
new_table->add_child(xform);
xform->set_fps(converter->_frame_rate);
TablePair &table_pair = _tables[group->get_name()];
table_pair._table = xform;
table_pair._joint = group;
// Now recurse.
mirror_table(converter, group, new_table);
} else {
// If we come to an ordinary <Group>, skip past it.
mirror_table(converter, group, anim_node);
}
}
}
}