263 lines
9.4 KiB
C++
Executable File
263 lines
9.4 KiB
C++
Executable File
// Filename: occluderEffect.cxx
|
|
// Created by: drose (17Mar11)
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// 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 "occluderEffect.h"
|
|
#include "pandaNode.h"
|
|
#include "graphicsStateGuardianBase.h"
|
|
#include "bamReader.h"
|
|
#include "bamWriter.h"
|
|
#include "datagram.h"
|
|
#include "datagramIterator.h"
|
|
#include "config_pgraph.h"
|
|
#include "attribNodeRegistry.h"
|
|
|
|
CPT(RenderEffect) OccluderEffect::_empty_effect;
|
|
TypeHandle OccluderEffect::_type_handle;
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: OccluderEffect::make
|
|
// Access: Published, Static
|
|
// Description: Constructs a new OccluderEffect object that does
|
|
// nothing.
|
|
////////////////////////////////////////////////////////////////////
|
|
CPT(RenderEffect) OccluderEffect::
|
|
make() {
|
|
// We make it a special case and store a pointer to the empty effect
|
|
// forever once we find it the first time, as an optimization.
|
|
if (_empty_effect == (RenderEffect *)NULL) {
|
|
_empty_effect = return_new(new OccluderEffect);
|
|
}
|
|
|
|
return _empty_effect;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: OccluderEffect::add_on_occluder
|
|
// Access: Published
|
|
// Description: Returns a new OccluderEffect, just like this one, but
|
|
// with the indicated occluder added to the list of occluders
|
|
// enabled by this effect.
|
|
////////////////////////////////////////////////////////////////////
|
|
CPT(RenderEffect) OccluderEffect::
|
|
add_on_occluder(const NodePath &occluder) const {
|
|
nassertr(!occluder.is_empty() && occluder.node()->is_of_type(OccluderNode::get_class_type()), this);
|
|
OccluderEffect *effect = new OccluderEffect(*this);
|
|
effect->_on_occluders.insert(occluder);
|
|
|
|
pair<Occluders::iterator, bool> insert_result =
|
|
effect->_on_occluders.insert(Occluders::value_type(occluder));
|
|
|
|
return return_new(effect);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: OccluderEffect::remove_on_occluder
|
|
// Access: Published
|
|
// Description: Returns a new OccluderEffect, just like this one, but
|
|
// with the indicated occluder removed from the list of
|
|
// occluders enabled by this effect.
|
|
////////////////////////////////////////////////////////////////////
|
|
CPT(RenderEffect) OccluderEffect::
|
|
remove_on_occluder(const NodePath &occluder) const {
|
|
nassertr(!occluder.is_empty() && occluder.node()->is_of_type(OccluderNode::get_class_type()), this);
|
|
OccluderEffect *effect = new OccluderEffect(*this);
|
|
effect->_on_occluders.erase(occluder);
|
|
return return_new(effect);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: OccluderEffect::output
|
|
// Access: Public, Virtual
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
void OccluderEffect::
|
|
output(ostream &out) const {
|
|
out << get_type() << ":";
|
|
if (_on_occluders.empty()) {
|
|
out << "identity";
|
|
} else {
|
|
out << "on";
|
|
|
|
Occluders::const_iterator li;
|
|
for (li = _on_occluders.begin(); li != _on_occluders.end(); ++li) {
|
|
NodePath occluder = (*li);
|
|
out << " " << occluder;
|
|
}
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: OccluderEffect::compare_to_impl
|
|
// Access: Protected, Virtual
|
|
// Description: Intended to be overridden by derived OccluderEffect
|
|
// types to return a unique number indicating whether
|
|
// this OccluderEffect is equivalent to the other one.
|
|
//
|
|
// This should return 0 if the two OccluderEffect
|
|
// objects are equivalent, a number less than zero if
|
|
// this one should be sorted before the other one, and a
|
|
// number greater than zero otherwise.
|
|
//
|
|
// This will only be called with two OccluderEffect
|
|
// objects whose get_type() functions return the same.
|
|
////////////////////////////////////////////////////////////////////
|
|
int OccluderEffect::
|
|
compare_to_impl(const RenderEffect *other) const {
|
|
const OccluderEffect *ta;
|
|
DCAST_INTO_R(ta, other, 0);
|
|
|
|
Occluders::const_iterator li = _on_occluders.begin();
|
|
Occluders::const_iterator oli = ta->_on_occluders.begin();
|
|
|
|
while (li != _on_occluders.end() && oli != ta->_on_occluders.end()) {
|
|
NodePath occluder = (*li);
|
|
NodePath other_occluder = (*oli);
|
|
|
|
int compare = occluder.compare_to(other_occluder);
|
|
if (compare != 0) {
|
|
return compare;
|
|
}
|
|
|
|
++li;
|
|
++oli;
|
|
}
|
|
|
|
if (li != _on_occluders.end()) {
|
|
return 1;
|
|
}
|
|
if (oli != ta->_on_occluders.end()) {
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: OccluderEffect::register_with_read_factory
|
|
// Access: Public, Static
|
|
// Description: Tells the BamReader how to create objects of type
|
|
// OccluderEffect.
|
|
////////////////////////////////////////////////////////////////////
|
|
void OccluderEffect::
|
|
register_with_read_factory() {
|
|
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: OccluderEffect::write_datagram
|
|
// Access: Public, Virtual
|
|
// Description: Writes the contents of this object to the datagram
|
|
// for shipping out to a Bam file.
|
|
////////////////////////////////////////////////////////////////////
|
|
void OccluderEffect::
|
|
write_datagram(BamWriter *manager, Datagram &dg) {
|
|
RenderEffect::write_datagram(manager, dg);
|
|
|
|
// write the number of on occluders
|
|
dg.add_uint16(get_num_on_occluders());
|
|
// write the on occluders pointers if any
|
|
Occluders::const_iterator nti;
|
|
for (nti = _on_occluders.begin(); nti != _on_occluders.end(); ++nti) {
|
|
NodePath occluder = (*nti);
|
|
manager->write_pointer(dg, occluder.node());
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: OccluderEffect::complete_pointers
|
|
// Access: Public, Virtual
|
|
// Description: Receives an array of pointers, one for each time
|
|
// manager->read_pointer() was called in fillin().
|
|
// Returns the number of pointers processed.
|
|
////////////////////////////////////////////////////////////////////
|
|
int OccluderEffect::
|
|
complete_pointers(TypedWritable **p_list, BamReader *manager) {
|
|
int pi = RenderEffect::complete_pointers(p_list, manager);
|
|
AttribNodeRegistry *areg = AttribNodeRegistry::get_global_ptr();
|
|
|
|
Occluders::iterator ci;
|
|
ci = _on_occluders.begin();
|
|
while (ci != _on_occluders.end()) {
|
|
PandaNode *node;
|
|
DCAST_INTO_R(node, p_list[pi++], pi);
|
|
|
|
int ni = areg->find_node(node->get_type(), node->get_name());
|
|
if (ni != -1) {
|
|
(*ci) = areg->get_node(ni);
|
|
} else {
|
|
(*ci) = NodePath(node);
|
|
}
|
|
++ci;
|
|
}
|
|
_on_occluders.sort();
|
|
|
|
return pi;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: OccluderEffect::require_fully_complete
|
|
// Access: Public, Virtual
|
|
// Description: Some objects require all of their nested pointers to
|
|
// have been completed before the objects themselves can
|
|
// be completed. If this is the case, override this
|
|
// method to return true, and be careful with circular
|
|
// references (which would make the object unreadable
|
|
// from a bam file).
|
|
////////////////////////////////////////////////////////////////////
|
|
bool OccluderEffect::
|
|
require_fully_complete() const {
|
|
return true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: OccluderEffect::make_from_bam
|
|
// Access: Protected, Static
|
|
// Description: This function is called by the BamReader's factory
|
|
// when a new object of type OccluderEffect is encountered
|
|
// in the Bam file. It should create the OccluderEffect
|
|
// and extract its information from the file.
|
|
////////////////////////////////////////////////////////////////////
|
|
TypedWritable *OccluderEffect::
|
|
make_from_bam(const FactoryParams ¶ms) {
|
|
OccluderEffect *effect = new OccluderEffect;
|
|
DatagramIterator scan;
|
|
BamReader *manager;
|
|
|
|
parse_params(params, scan, manager);
|
|
effect->fillin(scan, manager);
|
|
|
|
return effect;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: OccluderEffect::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 OccluderEffect.
|
|
////////////////////////////////////////////////////////////////////
|
|
void OccluderEffect::
|
|
fillin(DatagramIterator &scan, BamReader *manager) {
|
|
RenderEffect::fillin(scan, manager);
|
|
|
|
// Push back an empty NodePath for each Occluder for now, until we
|
|
// get the actual list of pointers later in complete_pointers().
|
|
int num_on_occluders = scan.get_uint16();
|
|
_on_occluders.reserve(num_on_occluders);
|
|
for (int i = 0; i < num_on_occluders; i++) {
|
|
manager->read_pointer(scan);
|
|
_on_occluders.push_back(NodePath());
|
|
}
|
|
}
|