Panda3D
|
00001 // Filename: pgTop.cxx 00002 // Created by: drose (13Mar02) 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 "pgTop.h" 00016 #include "pgMouseWatcherGroup.h" 00017 #include "pgCullTraverser.h" 00018 #include "cullBinAttrib.h" 00019 00020 #include "omniBoundingVolume.h" 00021 00022 TypeHandle PGTop::_type_handle; 00023 00024 //////////////////////////////////////////////////////////////////// 00025 // Function: PGTop::Constructor 00026 // Access: Published 00027 // Description: 00028 //////////////////////////////////////////////////////////////////// 00029 PGTop:: 00030 PGTop(const string &name) : 00031 PandaNode(name) 00032 { 00033 set_cull_callback(); 00034 00035 _start_sort = 0; 00036 00037 // A PGTop node normally has an infinite bounding volume. Screw 00038 // culling. 00039 set_internal_bounds(new OmniBoundingVolume()); 00040 set_final(true); 00041 00042 // Also, screw state sorting. By default, everything under PGTop 00043 // will be unsorted: rendered in scene graph order. This is closer 00044 // to what the user wants anyway in a 2-d scene graph. 00045 00046 set_attrib(CullBinAttrib::make("unsorted", 0)); 00047 } 00048 00049 //////////////////////////////////////////////////////////////////// 00050 // Function: PGTop::Destructor 00051 // Access: Public, Virtual 00052 // Description: 00053 //////////////////////////////////////////////////////////////////// 00054 PGTop:: 00055 ~PGTop() { 00056 set_mouse_watcher((MouseWatcher *)NULL); 00057 } 00058 00059 //////////////////////////////////////////////////////////////////// 00060 // Function: PGTop::make_copy 00061 // Access: Protected, Virtual 00062 // Description: Returns a newly-allocated Node that is a shallow copy 00063 // of this one. It will be a different Node pointer, 00064 // but its internal data may or may not be shared with 00065 // that of the original Node. 00066 //////////////////////////////////////////////////////////////////// 00067 PandaNode *PGTop:: 00068 make_copy() const { 00069 return new PGTop(*this); 00070 } 00071 00072 //////////////////////////////////////////////////////////////////// 00073 // Function: PGTop::cull_callback 00074 // Access: Protected, Virtual 00075 // Description: This function will be called during the cull 00076 // traversal to perform any additional operations that 00077 // should be performed at cull time. This may include 00078 // additional manipulation of render state or additional 00079 // visible/invisible decisions, or any other arbitrary 00080 // operation. 00081 // 00082 // Note that this function will *not* be called unless 00083 // set_cull_callback() is called in the constructor of 00084 // the derived class. It is necessary to call 00085 // set_cull_callback() to indicated that we require 00086 // cull_callback() to be called. 00087 // 00088 // By the time this function is called, the node has 00089 // already passed the bounding-volume test for the 00090 // viewing frustum, and the node's transform and state 00091 // have already been applied to the indicated 00092 // CullTraverserData object. 00093 // 00094 // The return value is true if this node should be 00095 // visible, or false if it should be culled. 00096 //////////////////////////////////////////////////////////////////// 00097 bool PGTop:: 00098 cull_callback(CullTraverser *trav, CullTraverserData &data) { 00099 // We create a new MouseWatcherGroup for the purposes of collecting 00100 // a new set of regions visible onscreen. 00101 PT(PGMouseWatcherGroup) old_watcher_group; 00102 if (_watcher_group != (PGMouseWatcherGroup *)NULL) { 00103 _watcher_group->clear_top(this); 00104 old_watcher_group = _watcher_group; 00105 _watcher_group = new PGMouseWatcherGroup(this); 00106 } 00107 00108 // Now subsitute for the normal CullTraverser a special one of our 00109 // own choosing. This just carries around a pointer back to the 00110 // PGTop node, for the convenience of PGItems to register themselves 00111 // as they are drawn. 00112 PGCullTraverser pg_trav(this, trav); 00113 pg_trav.local_object(); 00114 pg_trav._sort_index = _start_sort; 00115 pg_trav.traverse_below(data); 00116 pg_trav.end_traverse(); 00117 00118 // Now tell the watcher about the new set of regions. Strictly 00119 // speaking, we shouldn't do this until the frame that we're about 00120 // to render has been presented; otherwise, we may make regions 00121 // active before they are actually visible. But no one has 00122 // complained about this so far. 00123 if (_watcher_group != (PGMouseWatcherGroup *)NULL) { 00124 nassertr(_watcher != (MouseWatcher *)NULL, false); 00125 _watcher->replace_group(old_watcher_group, _watcher_group); 00126 } 00127 00128 // We've taken care of the traversal, thank you. 00129 return false; 00130 } 00131 00132 //////////////////////////////////////////////////////////////////// 00133 // Function: PGTop::is_renderable 00134 // Access: Public, Virtual 00135 // Description: Returns true if there is some value to visiting this 00136 // particular node during the cull traversal for any 00137 // camera, false otherwise. This will be used to 00138 // optimize the result of get_net_draw_show_mask(), so 00139 // that any subtrees that contain only nodes for which 00140 // is_renderable() is false need not be visited. 00141 //////////////////////////////////////////////////////////////////// 00142 bool PGTop:: 00143 is_renderable() const { 00144 // We flag the PGTop as renderable, even though it technically 00145 // doesn't have anything to render, but we do need the traverser to 00146 // visit it every frame. 00147 return true; 00148 } 00149 00150 //////////////////////////////////////////////////////////////////// 00151 // Function: PGTop::set_mouse_watcher 00152 // Access: Published 00153 // Description: Sets the MouseWatcher pointer that the PGTop object 00154 // registers its PG items with. This must be set before 00155 // the PG items are active. 00156 //////////////////////////////////////////////////////////////////// 00157 void PGTop:: 00158 set_mouse_watcher(MouseWatcher *watcher) { 00159 if (_watcher_group != (PGMouseWatcherGroup *)NULL) { 00160 _watcher_group->clear_top(this); 00161 } 00162 if (_watcher != (MouseWatcher *)NULL) { 00163 _watcher->remove_group(_watcher_group); 00164 } 00165 00166 _watcher = watcher; 00167 _watcher_group = (PGMouseWatcherGroup *)NULL; 00168 00169 if (_watcher != (MouseWatcher *)NULL) { 00170 _watcher_group = new PGMouseWatcherGroup(this); 00171 _watcher->add_group(_watcher_group); 00172 } 00173 }