open_toontown_panda3d/panda/src/egg/eggTable.cxx

167 lines
5.3 KiB
C++

// Filename: eggTable.cxx
// Created by: drose (19Feb99)
//
////////////////////////////////////////////////////////////////////
//
// 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."
//
////////////////////////////////////////////////////////////////////
#include "eggTable.h"
#include "string_utils.h"
#include "indent.h"
TypeHandle EggTable::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: EggTable::has_transform
// Access: Public
// Description: Returns true if the table contains a transform
// description, false otherwise.
////////////////////////////////////////////////////////////////////
bool EggTable::
has_transform() const {
const_iterator ci;
for (ci = begin(); ci != end(); ++ci) {
EggNode *child = (*ci);
if (child->is_anim_matrix()) {
return true;
}
}
return false;
}
////////////////////////////////////////////////////////////////////
// Function: EggTable::write
// Access: Public, Virtual
// Description: Writes the table and all of its children to the
// indicated output stream in Egg format.
////////////////////////////////////////////////////////////////////
void EggTable::
write(ostream &out, int indent_level) const {
test_under_integrity();
switch (get_table_type()) {
case TT_table:
write_header(out, indent_level, "<Table>");
break;
case TT_bundle:
write_header(out, indent_level, "<Bundle>");
break;
default:
// invalid table type
nassertv(false);
}
EggGroupNode::write(out, indent_level + 2);
indent(out, indent_level) << "}\n";
}
////////////////////////////////////////////////////////////////////
// Function: EggTable::string_table_type
// Access: Public, Static
// Description: Returns the TableType value associated with the given
// string representation, or TT_invalid if the string
// does not match any known TableType value.
////////////////////////////////////////////////////////////////////
EggTable::TableType EggTable::
string_table_type(const string &string) {
if (cmp_nocase_uh(string, "table") == 0) {
return TT_table;
} else if (cmp_nocase_uh(string, "bundle") == 0) {
return TT_bundle;
} else {
return TT_invalid;
}
}
////////////////////////////////////////////////////////////////////
// Function: EggTable::r_transform
// Access: Protected, Virtual
// Description: This is called from within the egg code by
// transform(). It applies a transformation matrix
// to the current node in some sensible way, then
// continues down the tree.
//
// The first matrix is the transformation to apply; the
// second is its inverse. The third parameter is the
// coordinate system we are changing to, or CS_default
// if we are not changing coordinate systems.
////////////////////////////////////////////////////////////////////
void EggTable::
r_transform(const LMatrix4d &mat, const LMatrix4d &inv,
CoordinateSystem to_cs) {
// We need to duplicate the logic in EggGroup: if we have a matrix
// transform witin this table, apply the transformation to it, but
// then apply only the scale/rotational part of the transformation
// to any children.
// On the other hand, if we have no matrix transform within this
// table, pass the transformation through.
// This logic is complicated by the fact that matrix transforms with
// a <Table> group are not stored within the table itself, but
// rather within a child named "xform". Fortunately,
// has_transform() abstracts out this detail for us.
if (has_transform()) {
// At least one child of this table represents an animation matrix
// transform: that child gets the real matrix, while all other
// children get the truncated matrix.
LMatrix4d mat1 = mat;
LMatrix4d inv1 = inv;
// If we have a translation component, we should only apply
// it to the top matrix. All subsequent matrices get just the
// rotational component.
mat1.set_row(3, LVector3d(0.0, 0.0, 0.0));
inv1.set_row(3, LVector3d(0.0, 0.0, 0.0));
iterator ci;
for (ci = begin(); ci != end(); ++ci) {
EggNode *child = (*ci);
if (child->is_anim_matrix()) {
child->r_transform(mat, inv, to_cs);
} else {
child->r_transform(mat1, inv1, to_cs);
}
}
} else {
// No children of this table represent an animation matrix
// transform: all children get the real matrix.
EggGroupNode::r_transform(mat, inv, to_cs);
}
}
////////////////////////////////////////////////////////////////////
// Function: TableType output operator
// Description:
////////////////////////////////////////////////////////////////////
ostream &operator << (ostream &out, EggTable::TableType t) {
switch (t) {
case EggTable::TT_invalid:
return out << "invalid table";
case EggTable::TT_table:
return out << "table";
case EggTable::TT_bundle:
return out << "bundle";
}
nassertr(false, out);
return out << "(**invalid**)";
}