Panda3D
 All Classes Functions Variables Enumerations
occluderEffect.cxx
00001 // Filename: occluderEffect.cxx
00002 // Created by:  drose (17Mar11)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "occluderEffect.h"
00016 #include "pandaNode.h"
00017 #include "graphicsStateGuardianBase.h"
00018 #include "bamReader.h"
00019 #include "bamWriter.h"
00020 #include "datagram.h"
00021 #include "datagramIterator.h"
00022 #include "config_pgraph.h"
00023 #include "attribNodeRegistry.h"
00024 
00025 CPT(RenderEffect) OccluderEffect::_empty_effect;
00026 TypeHandle OccluderEffect::_type_handle;
00027 
00028 ////////////////////////////////////////////////////////////////////
00029 //     Function: OccluderEffect::make
00030 //       Access: Published, Static
00031 //  Description: Constructs a new OccluderEffect object that does
00032 //               nothing.
00033 ////////////////////////////////////////////////////////////////////
00034 CPT(RenderEffect) OccluderEffect::
00035 make() {
00036   // We make it a special case and store a pointer to the empty effect
00037   // forever once we find it the first time, as an optimization.
00038   if (_empty_effect == (RenderEffect *)NULL) {
00039     _empty_effect = return_new(new OccluderEffect);
00040   }
00041 
00042   return _empty_effect;
00043 }
00044 
00045 ////////////////////////////////////////////////////////////////////
00046 //     Function: OccluderEffect::add_on_occluder
00047 //       Access: Published
00048 //  Description: Returns a new OccluderEffect, just like this one, but
00049 //               with the indicated occluder added to the list of occluders
00050 //               enabled by this effect.
00051 ////////////////////////////////////////////////////////////////////
00052 CPT(RenderEffect) OccluderEffect::
00053 add_on_occluder(const NodePath &occluder) const {
00054   nassertr(!occluder.is_empty() && occluder.node()->is_of_type(OccluderNode::get_class_type()), this);
00055   OccluderEffect *effect = new OccluderEffect(*this);
00056   effect->_on_occluders.insert(occluder);
00057 
00058   pair<Occluders::iterator, bool> insert_result = 
00059     effect->_on_occluders.insert(Occluders::value_type(occluder));
00060 
00061   return return_new(effect);
00062 }
00063 
00064 ////////////////////////////////////////////////////////////////////
00065 //     Function: OccluderEffect::remove_on_occluder
00066 //       Access: Published
00067 //  Description: Returns a new OccluderEffect, just like this one, but
00068 //               with the indicated occluder removed from the list of
00069 //               occluders enabled by this effect.
00070 ////////////////////////////////////////////////////////////////////
00071 CPT(RenderEffect) OccluderEffect::
00072 remove_on_occluder(const NodePath &occluder) const {
00073   nassertr(!occluder.is_empty() && occluder.node()->is_of_type(OccluderNode::get_class_type()), this);
00074   OccluderEffect *effect = new OccluderEffect(*this);
00075   effect->_on_occluders.erase(occluder);
00076   return return_new(effect);
00077 }
00078 
00079 ////////////////////////////////////////////////////////////////////
00080 //     Function: OccluderEffect::output
00081 //       Access: Public, Virtual
00082 //  Description: 
00083 ////////////////////////////////////////////////////////////////////
00084 void OccluderEffect::
00085 output(ostream &out) const {
00086   out << get_type() << ":";
00087   if (_on_occluders.empty()) {
00088     out << "identity";
00089   } else {
00090     out << "on";
00091     
00092     Occluders::const_iterator li;
00093     for (li = _on_occluders.begin(); li != _on_occluders.end(); ++li) {
00094       NodePath occluder = (*li);
00095       out << " " << occluder;
00096     }
00097   }
00098 }
00099 
00100 ////////////////////////////////////////////////////////////////////
00101 //     Function: OccluderEffect::compare_to_impl
00102 //       Access: Protected, Virtual
00103 //  Description: Intended to be overridden by derived OccluderEffect
00104 //               types to return a unique number indicating whether
00105 //               this OccluderEffect is equivalent to the other one.
00106 //
00107 //               This should return 0 if the two OccluderEffect
00108 //               objects are equivalent, a number less than zero if
00109 //               this one should be sorted before the other one, and a
00110 //               number greater than zero otherwise.
00111 //
00112 //               This will only be called with two OccluderEffect
00113 //               objects whose get_type() functions return the same.
00114 ////////////////////////////////////////////////////////////////////
00115 int OccluderEffect::
00116 compare_to_impl(const RenderEffect *other) const {
00117   const OccluderEffect *ta;
00118   DCAST_INTO_R(ta, other, 0);
00119 
00120   Occluders::const_iterator li = _on_occluders.begin();
00121   Occluders::const_iterator oli = ta->_on_occluders.begin();
00122 
00123   while (li != _on_occluders.end() && oli != ta->_on_occluders.end()) {
00124     NodePath occluder = (*li);
00125     NodePath other_occluder = (*oli);
00126 
00127     int compare = occluder.compare_to(other_occluder);
00128     if (compare != 0) {
00129       return compare;
00130     }
00131 
00132     ++li;
00133     ++oli;
00134   }
00135 
00136   if (li != _on_occluders.end()) {
00137     return 1;
00138   }
00139   if (oli != ta->_on_occluders.end()) {
00140     return -1;
00141   }
00142   
00143   return 0;
00144 }
00145 
00146 ////////////////////////////////////////////////////////////////////
00147 //     Function: OccluderEffect::register_with_read_factory
00148 //       Access: Public, Static
00149 //  Description: Tells the BamReader how to create objects of type
00150 //               OccluderEffect.
00151 ////////////////////////////////////////////////////////////////////
00152 void OccluderEffect::
00153 register_with_read_factory() {
00154   BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
00155 }
00156 
00157 ////////////////////////////////////////////////////////////////////
00158 //     Function: OccluderEffect::write_datagram
00159 //       Access: Public, Virtual
00160 //  Description: Writes the contents of this object to the datagram
00161 //               for shipping out to a Bam file.
00162 ////////////////////////////////////////////////////////////////////
00163 void OccluderEffect::
00164 write_datagram(BamWriter *manager, Datagram &dg) {
00165   RenderEffect::write_datagram(manager, dg);
00166 
00167   // write the number of on occluders
00168   dg.add_uint16(get_num_on_occluders());
00169   // write the on occluders pointers if any
00170   Occluders::const_iterator nti;
00171   for (nti = _on_occluders.begin(); nti != _on_occluders.end(); ++nti) {
00172     NodePath occluder = (*nti);
00173     manager->write_pointer(dg, occluder.node());
00174   }
00175 }
00176 
00177 ////////////////////////////////////////////////////////////////////
00178 //     Function: OccluderEffect::complete_pointers
00179 //       Access: Public, Virtual
00180 //  Description: Receives an array of pointers, one for each time
00181 //               manager->read_pointer() was called in fillin().
00182 //               Returns the number of pointers processed.
00183 ////////////////////////////////////////////////////////////////////
00184 int OccluderEffect::
00185 complete_pointers(TypedWritable **p_list, BamReader *manager) {
00186   int pi = RenderEffect::complete_pointers(p_list, manager);
00187   AttribNodeRegistry *areg = AttribNodeRegistry::get_global_ptr();
00188 
00189   Occluders::iterator ci;
00190   ci = _on_occluders.begin();
00191   while (ci != _on_occluders.end()) {
00192     PandaNode *node;
00193     DCAST_INTO_R(node, p_list[pi++], pi);
00194 
00195     int ni = areg->find_node(node->get_type(), node->get_name());
00196     if (ni != -1) {
00197       (*ci) = areg->get_node(ni);
00198     } else {
00199       (*ci) = NodePath(node);
00200     }
00201     ++ci;
00202   }
00203   _on_occluders.sort();
00204 
00205   return pi;
00206 }
00207 
00208 ////////////////////////////////////////////////////////////////////
00209 //     Function: OccluderEffect::require_fully_complete
00210 //       Access: Public, Virtual
00211 //  Description: Some objects require all of their nested pointers to
00212 //               have been completed before the objects themselves can
00213 //               be completed.  If this is the case, override this
00214 //               method to return true, and be careful with circular
00215 //               references (which would make the object unreadable
00216 //               from a bam file).
00217 ////////////////////////////////////////////////////////////////////
00218 bool OccluderEffect::
00219 require_fully_complete() const {
00220   return true;
00221 }
00222 
00223 ////////////////////////////////////////////////////////////////////
00224 //     Function: OccluderEffect::make_from_bam
00225 //       Access: Protected, Static
00226 //  Description: This function is called by the BamReader's factory
00227 //               when a new object of type OccluderEffect is encountered
00228 //               in the Bam file.  It should create the OccluderEffect
00229 //               and extract its information from the file.
00230 ////////////////////////////////////////////////////////////////////
00231 TypedWritable *OccluderEffect::
00232 make_from_bam(const FactoryParams &params) {
00233   OccluderEffect *effect = new OccluderEffect;
00234   DatagramIterator scan;
00235   BamReader *manager;
00236 
00237   parse_params(params, scan, manager);
00238   effect->fillin(scan, manager);
00239 
00240   return effect;
00241 }
00242 
00243 ////////////////////////////////////////////////////////////////////
00244 //     Function: OccluderEffect::fillin
00245 //       Access: Protected
00246 //  Description: This internal function is called by make_from_bam to
00247 //               read in all of the relevant data from the BamFile for
00248 //               the new OccluderEffect.
00249 ////////////////////////////////////////////////////////////////////
00250 void OccluderEffect::
00251 fillin(DatagramIterator &scan, BamReader *manager) {
00252   RenderEffect::fillin(scan, manager);
00253     
00254   // Push back an empty NodePath for each Occluder for now, until we
00255   // get the actual list of pointers later in complete_pointers().
00256   int num_on_occluders = scan.get_uint16();
00257   _on_occluders.reserve(num_on_occluders);
00258   for (int i = 0; i < num_on_occluders; i++) {
00259     manager->read_pointer(scan);
00260     _on_occluders.push_back(NodePath());
00261   }
00262 }
 All Classes Functions Variables Enumerations