362 lines
13 KiB
C++
362 lines
13 KiB
C++
// Filename: dataNode.cxx
|
|
// Created by: drose (11Mar02)
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// 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 "dataNode.h"
|
|
#include "dataNodeTransmit.h"
|
|
#include "config_dgraph.h"
|
|
#include "dcast.h"
|
|
|
|
TypeHandle DataNode::_type_handle;
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DataNode::make_copy
|
|
// Access: Public, Virtual
|
|
// Description: Returns a newly-allocated Node that is a shallow copy
|
|
// of this one. It will be a different Node pointer,
|
|
// but its internal data may or may not be shared with
|
|
// that of the original Node.
|
|
////////////////////////////////////////////////////////////////////
|
|
PandaNode *DataNode::
|
|
make_copy() const {
|
|
return new DataNode(*this);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DataNode::transmit_data
|
|
// Access: Public
|
|
// Description: Collects the data from all of the parent nodes and
|
|
// puts it into one DataNodeTransmit object, for
|
|
// processing; calls do_transmit_data() to read all the
|
|
// inputs and put the result into the indicated output.
|
|
////////////////////////////////////////////////////////////////////
|
|
void DataNode::
|
|
transmit_data(DataGraphTraverser *trav,
|
|
const DataNodeTransmit inputs[],
|
|
DataNodeTransmit &output) {
|
|
DataNodeTransmit new_input;
|
|
new_input.reserve(get_num_inputs());
|
|
|
|
DataConnections::const_iterator ci;
|
|
for (ci = _data_connections.begin(); ci != _data_connections.end(); ++ci) {
|
|
const DataConnection &connect = (*ci);
|
|
const EventParameter &data =
|
|
inputs[connect._parent_index].get_data(connect._output_index);
|
|
if (!data.is_empty()) {
|
|
new_input.set_data(connect._input_index, data);
|
|
}
|
|
}
|
|
|
|
#ifndef NDEBUG
|
|
if (dgraph_cat.is_spam()) {
|
|
bool any_data = false;
|
|
Wires::const_iterator wi;
|
|
for (wi = _input_wires.begin(); wi != _input_wires.end(); ++wi) {
|
|
const string &name = (*wi).first;
|
|
const WireDef &def = (*wi).second;
|
|
if (new_input.has_data(def._index)) {
|
|
if (!any_data) {
|
|
dgraph_cat.spam()
|
|
<< *this << " receives:\n";
|
|
any_data = true;
|
|
}
|
|
dgraph_cat.spam(false)
|
|
<< " " << name << " = " << new_input.get_data(def._index)
|
|
<< "\n";
|
|
}
|
|
}
|
|
}
|
|
#endif // NDEBUG
|
|
|
|
do_transmit_data(trav, new_input, output);
|
|
|
|
#ifndef NDEBUG
|
|
if (dgraph_cat.is_spam()) {
|
|
bool any_data = false;
|
|
Wires::const_iterator wi;
|
|
for (wi = _output_wires.begin(); wi != _output_wires.end(); ++wi) {
|
|
const string &name = (*wi).first;
|
|
const WireDef &def = (*wi).second;
|
|
if (output.has_data(def._index)) {
|
|
if (!any_data) {
|
|
dgraph_cat.spam()
|
|
<< *this << " transmits:\n";
|
|
any_data = true;
|
|
}
|
|
dgraph_cat.spam(false)
|
|
<< " " << name << " = " << output.get_data(def._index)
|
|
<< "\n";
|
|
}
|
|
}
|
|
}
|
|
#endif // NDEBUG
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DataNode::write_inputs
|
|
// Access: Published
|
|
// Description: Writes to the indicated ostream a list of all the
|
|
// inputs this DataNode might expect to receive.
|
|
////////////////////////////////////////////////////////////////////
|
|
void DataNode::
|
|
write_inputs(ostream &out) const {
|
|
Wires::const_iterator wi;
|
|
for (wi = _input_wires.begin(); wi != _input_wires.end(); ++wi) {
|
|
const string &name = (*wi).first;
|
|
const WireDef &def = (*wi).second;
|
|
out << name << " " << def._data_type << "\n";
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DataNode::write_outputs
|
|
// Access: Published
|
|
// Description: Writes to the indicated ostream a list of all the
|
|
// outputs this DataNode might generate.
|
|
////////////////////////////////////////////////////////////////////
|
|
void DataNode::
|
|
write_outputs(ostream &out) const {
|
|
Wires::const_iterator wi;
|
|
for (wi = _output_wires.begin(); wi != _output_wires.end(); ++wi) {
|
|
const string &name = (*wi).first;
|
|
const WireDef &def = (*wi).second;
|
|
out << name << " " << def._data_type << "\n";
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DataNode::write_connections
|
|
// Access: Published
|
|
// Description: Writes to the indicated ostream a list of all the
|
|
// connections currently showing between this DataNode
|
|
// and its parent(s).
|
|
////////////////////////////////////////////////////////////////////
|
|
void DataNode::
|
|
write_connections(ostream &out) const {
|
|
DataConnections::const_iterator ci;
|
|
for (ci = _data_connections.begin(); ci != _data_connections.end(); ++ci) {
|
|
const DataConnection &connect = (*ci);
|
|
nassertv(connect._parent_index >= 0 && connect._parent_index < get_num_parents());
|
|
|
|
// Now we have to search exhaustively for the input with the
|
|
// matching index number.
|
|
Wires::const_iterator wi;
|
|
bool found = false;
|
|
for (wi = _input_wires.begin(); wi != _input_wires.end() && !found; ++wi) {
|
|
const string &name = (*wi).first;
|
|
const WireDef &def = (*wi).second;
|
|
if (def._index == connect._input_index) {
|
|
out << name << " " << def._data_type << " from "
|
|
<< *get_parent(connect._parent_index) << "\n";
|
|
found = true;
|
|
}
|
|
}
|
|
nassertv(found);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DataNode::define_input
|
|
// Access: Protected
|
|
// Description: Adds a new input wire with the given name and the
|
|
// indicated data type. The data type should be the
|
|
// TypeHandle for some type that derives from
|
|
// TypedReferenceCount, e.g. EventStoreInt,
|
|
// EventStoreDouble, or some fancier data type like
|
|
// Texture.
|
|
//
|
|
// If there is already an input wire defined with the
|
|
// indicated name, its type is changed.
|
|
//
|
|
// The return value is the index into the "input"
|
|
// parameter to do_transmit_data() that can be used to
|
|
// access the input data.
|
|
////////////////////////////////////////////////////////////////////
|
|
int DataNode::
|
|
define_input(const string &name, TypeHandle data_type) {
|
|
// We shouldn't already be connected.
|
|
nassertr(_data_connections.empty(), 0);
|
|
|
|
Wires::iterator wi;
|
|
wi = _input_wires.find(name);
|
|
if (wi != _input_wires.end()) {
|
|
// This wire already existed; modify it and return the original
|
|
// index.
|
|
WireDef &def = (*wi).second;
|
|
def._data_type = data_type;
|
|
return def._index;
|
|
}
|
|
|
|
// This wire did not already exist; add it.
|
|
WireDef &def = _input_wires[name];
|
|
def._data_type = data_type;
|
|
def._index = _input_wires.size() - 1;
|
|
return def._index;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DataNode::define_output
|
|
// Access: Protected
|
|
// Description: Adds a new output wire with the given name and the
|
|
// indicated data type. The data type should be the
|
|
// TypeHandle for some type that derives from
|
|
// TypedReferenceCount, e.g. EventStoreInt,
|
|
// EventStoreDouble, or some fancier data type like
|
|
// Texture.
|
|
//
|
|
// If there is already an output wire defined with the
|
|
// indicated name, its type is changed.
|
|
//
|
|
// The return value is the index into the "output"
|
|
// parameter to do_transmit_data() where the output data
|
|
// should be stored.
|
|
////////////////////////////////////////////////////////////////////
|
|
int DataNode::
|
|
define_output(const string &name, TypeHandle data_type) {
|
|
// We shouldn't already be connected.
|
|
nassertr(_data_connections.empty(), 0);
|
|
|
|
Wires::iterator wi;
|
|
wi = _output_wires.find(name);
|
|
if (wi != _output_wires.end()) {
|
|
// This wire already existed; modify it and return the original
|
|
// index.
|
|
WireDef &def = (*wi).second;
|
|
def._data_type = data_type;
|
|
return def._index;
|
|
}
|
|
|
|
// This wire did not already exist; add it.
|
|
WireDef &def = _output_wires[name];
|
|
def._data_type = data_type;
|
|
def._index = _output_wires.size() - 1;
|
|
return def._index;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DataNode::parents_changed
|
|
// Access: Protected, Virtual
|
|
// Description: Called after a scene graph update that either adds or
|
|
// remove parents from this node, this just provides a
|
|
// hook for derived PandaNode objects that need to
|
|
// update themselves based on the set of parents the
|
|
// node has.
|
|
////////////////////////////////////////////////////////////////////
|
|
void DataNode::
|
|
parents_changed() {
|
|
PandaNode::parents_changed();
|
|
reconnect();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DataNode::do_transmit_data
|
|
// Access: Protected, Virtual
|
|
// Description: The virtual implementation of transmit_data(). This
|
|
// function receives an array of input parameters and
|
|
// should generate an array of output parameters. The
|
|
// input parameters may be accessed with the index
|
|
// numbers returned by the define_input() calls that
|
|
// were made earlier (presumably in the constructor);
|
|
// likewise, the output parameters should be set with
|
|
// the index numbers returned by the define_output()
|
|
// calls.
|
|
////////////////////////////////////////////////////////////////////
|
|
void DataNode::
|
|
do_transmit_data(DataGraphTraverser *, const DataNodeTransmit &,
|
|
DataNodeTransmit &) {
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DataNode::reconnect
|
|
// Access: Private
|
|
// Description: Establishes the input(s) that this DataNode has in
|
|
// common with its parents' output(s). Builds up the
|
|
// _data_connections list correspondingly.
|
|
////////////////////////////////////////////////////////////////////
|
|
void DataNode::
|
|
reconnect() {
|
|
int num_parents = get_num_parents();
|
|
_data_connections.clear();
|
|
// Look for each input among one of the parents.
|
|
int num_datanode_parents = 0;
|
|
|
|
Wires::const_iterator wi;
|
|
for (wi = _input_wires.begin(); wi != _input_wires.end(); ++wi) {
|
|
const string &name = (*wi).first;
|
|
const WireDef &input_def = (*wi).second;
|
|
|
|
int num_found = 0;
|
|
for (int i = 0; i < num_parents; i++) {
|
|
PandaNode *parent_node = get_parent(i);
|
|
if (parent_node->is_of_type(DataNode::get_class_type())) {
|
|
DataNode *data_node = DCAST(DataNode, parent_node);
|
|
num_datanode_parents++;
|
|
Wires::const_iterator pi;
|
|
pi = data_node->_output_wires.find(name);
|
|
if (pi != data_node->_output_wires.end()) {
|
|
const WireDef &output_def = (*pi).second;
|
|
num_found++;
|
|
if (output_def._data_type != input_def._data_type) {
|
|
dgraph_cat.warning()
|
|
<< "Ignoring mismatched type for connection " << name
|
|
<< " between " << *data_node << " and " << *this << "\n";
|
|
} else {
|
|
DataConnection dc;
|
|
dc._parent_index = i;
|
|
dc._output_index = output_def._index;
|
|
dc._input_index = input_def._index;
|
|
_data_connections.push_back(dc);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (num_found > 1) {
|
|
if (dgraph_cat.is_debug()) {
|
|
dgraph_cat.debug()
|
|
<< "Multiple connections found for " << name << " into " << *this
|
|
<< "\n";
|
|
}
|
|
}
|
|
}
|
|
|
|
if (_data_connections.empty() && get_num_inputs() != 0 &&
|
|
num_datanode_parents != 0) {
|
|
dgraph_cat.warning()
|
|
<< "No data connected to " << *this << "\n";
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DataNode::write_datagram
|
|
// Access: Public, Virtual
|
|
// Description: Writes the contents of this object to the datagram
|
|
// for shipping out to a Bam file.
|
|
////////////////////////////////////////////////////////////////////
|
|
void DataNode::
|
|
write_datagram(BamWriter *manager, Datagram &dg) {
|
|
PandaNode::write_datagram(manager, dg);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DataNode::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 Lens.
|
|
////////////////////////////////////////////////////////////////////
|
|
void DataNode::
|
|
fillin(DatagramIterator &scan, BamReader *manager) {
|
|
PandaNode::fillin(scan, manager);
|
|
}
|