00001 // Filename: graphicsLayer.cxx 00002 // Created by: drose (18Apr00) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved 00008 // 00009 // All use of this software is subject to the terms of the Panda 3d 00010 // Software license. You should have received a copy of this license 00011 // along with this source code; you will also find a current copy of 00012 // the license at http://www.panda3d.org/license.txt . 00013 // 00014 // To contact the maintainers of this program write to 00015 // panda3d@yahoogroups.com . 00016 // 00017 //////////////////////////////////////////////////////////////////// 00018 00019 #include "graphicsLayer.h" 00020 #include "graphicsChannel.h" 00021 #include "graphicsWindow.h" 00022 #include "config_display.h" 00023 #include "notify.h" 00024 #include "mutexHolder.h" 00025 00026 #include <algorithm> 00027 00028 00029 TypeHandle GraphicsLayer::_type_handle; 00030 00031 //////////////////////////////////////////////////////////////////// 00032 // Function: GraphicsLayer::Constructor 00033 // Access: Private 00034 // Description: Use GraphicsChannel::make_layer() to make a new 00035 // layer. 00036 //////////////////////////////////////////////////////////////////// 00037 GraphicsLayer:: 00038 GraphicsLayer() { 00039 _channel = NULL; 00040 _is_active = true; 00041 } 00042 00043 //////////////////////////////////////////////////////////////////// 00044 // Function: GraphicsLayer::Constructor 00045 // Access: Public 00046 // Description: Use GraphicsChannel::make_layer() to make a new 00047 // layer. 00048 //////////////////////////////////////////////////////////////////// 00049 GraphicsLayer:: 00050 GraphicsLayer(GraphicsChannel *channel) 00051 : _channel(channel) 00052 { 00053 _is_active = true; 00054 } 00055 00056 //////////////////////////////////////////////////////////////////// 00057 // Function: GraphicsLayer::Copy Constructor 00058 // Access: Private 00059 // Description: 00060 //////////////////////////////////////////////////////////////////// 00061 GraphicsLayer:: 00062 GraphicsLayer(const GraphicsLayer &) { 00063 nassertv(false); 00064 } 00065 00066 //////////////////////////////////////////////////////////////////// 00067 // Function: GraphicsLayer::Copy Assignment Operator 00068 // Access: Private 00069 // Description: 00070 //////////////////////////////////////////////////////////////////// 00071 void GraphicsLayer:: 00072 operator = (const GraphicsLayer &) { 00073 nassertv(false); 00074 } 00075 00076 //////////////////////////////////////////////////////////////////// 00077 // Function: GraphicsLayer::Destructor 00078 // Access: Published 00079 // Description: 00080 //////////////////////////////////////////////////////////////////// 00081 GraphicsLayer:: 00082 ~GraphicsLayer() { 00083 // We don't have to destruct our child display regions explicitly, 00084 // since they are all reference-counted and will go away when their 00085 // pointers do. However, we do need to zero out their pointers to 00086 // us. 00087 DisplayRegions::iterator dri; 00088 for (dri = _display_regions.begin(); 00089 dri != _display_regions.end(); 00090 ++dri) { 00091 DisplayRegion *dr = (*dri); 00092 MutexHolder holder(dr->_lock); 00093 dr->_layer = NULL; 00094 } 00095 win_display_regions_changed(); 00096 00097 // We don't need to remove ourself from the channel's list of 00098 // layers. We must have already been removed, or we wouldn't be 00099 // destructing! 00100 } 00101 00102 //////////////////////////////////////////////////////////////////// 00103 // Function: GraphicsLayer::make_display_region 00104 // Access: Published 00105 // Description: Creates a new DisplayRegion that covers the entire 00106 // layer. 00107 //////////////////////////////////////////////////////////////////// 00108 DisplayRegion *GraphicsLayer:: 00109 make_display_region() { 00110 PT(DisplayRegion) dr = new DisplayRegion(this); 00111 00112 MutexHolder holder(_lock); 00113 _display_regions.push_back(dr); 00114 win_display_regions_changed(); 00115 return dr; 00116 } 00117 00118 //////////////////////////////////////////////////////////////////// 00119 // Function: GraphicsLayer::make_display_region 00120 // Access: Published 00121 // Description: Creates a new DisplayRegion that covers the indicated 00122 // sub-rectangle within the layer. 00123 //////////////////////////////////////////////////////////////////// 00124 DisplayRegion *GraphicsLayer:: 00125 make_display_region(float l, float r, float b, float t) { 00126 nassertr(this != (GraphicsLayer *)NULL, NULL); 00127 PT(DisplayRegion) dr = new DisplayRegion(this, l, r, b, t); 00128 00129 MutexHolder holder(_lock); 00130 _display_regions.push_back(dr); 00131 win_display_regions_changed(); 00132 return dr; 00133 } 00134 00135 //////////////////////////////////////////////////////////////////// 00136 // Function: GraphicsLayer::get_num_drs 00137 // Access: Published 00138 // Description: Returns the number of DisplayRegions associated with 00139 // the layer. 00140 //////////////////////////////////////////////////////////////////// 00141 int GraphicsLayer:: 00142 get_num_drs() const { 00143 MutexHolder holder(_lock); 00144 return _display_regions.size(); 00145 } 00146 00147 //////////////////////////////////////////////////////////////////// 00148 // Function: GraphicsLayer::get_dr 00149 // Access: Published 00150 // Description: Returns the nth DisplayRegion associated with the 00151 // layer. This might return NULL if another thread has 00152 // recently removed a DisplayRegion. 00153 //////////////////////////////////////////////////////////////////// 00154 DisplayRegion *GraphicsLayer:: 00155 get_dr(int index) const { 00156 MutexHolder holder(_lock); 00157 if (index >= 0 && index < (int)_display_regions.size()) { 00158 return _display_regions[index]; 00159 } else { 00160 return NULL; 00161 } 00162 } 00163 00164 //////////////////////////////////////////////////////////////////// 00165 // Function: GraphicsLayer::remove_dr 00166 // Access: Published 00167 // Description: Removes (and possibly deletes) the nth DisplayRegion 00168 // associated with the layer. All subsequent index 00169 // numbers will shift down one. 00170 //////////////////////////////////////////////////////////////////// 00171 void GraphicsLayer:: 00172 remove_dr(int index) { 00173 MutexHolder holder(_lock); 00174 nassertv(index >= 0 && index < (int)_display_regions.size()); 00175 _display_regions[index]->_layer = NULL; 00176 _display_regions.erase(_display_regions.begin() + index); 00177 win_display_regions_changed(); 00178 } 00179 00180 //////////////////////////////////////////////////////////////////// 00181 // Function: GraphicsLayer::remove_dr 00182 // Access: Published 00183 // Description: Removes (and possibly deletes) the indicated 00184 // DisplayRegion associated with the layer. All 00185 // subsequent index numbers will shift down one. 00186 // Returns true if the DisplayRegion was removed, false 00187 // if it was not a member of the layer. 00188 //////////////////////////////////////////////////////////////////// 00189 bool GraphicsLayer:: 00190 remove_dr(DisplayRegion *display_region) { 00191 MutexHolder holder(_lock); 00192 PT(DisplayRegion) ptdr = display_region; 00193 DisplayRegions::iterator dri = 00194 find(_display_regions.begin(), _display_regions.end(), ptdr); 00195 if (dri != _display_regions.end()) { 00196 display_region->_layer = NULL; 00197 _display_regions.erase(dri); 00198 win_display_regions_changed(); 00199 return true; 00200 } 00201 return false; 00202 } 00203 00204 //////////////////////////////////////////////////////////////////// 00205 // Function: GraphicsLayer::get_channel 00206 // Access: Published 00207 // Description: Returns the GraphicsChannel that this layer is 00208 // associated with. It is possible that the 00209 // GraphicsChannel might have been deleted while an 00210 // outstanding PT(GraphicsLayer) prevented all of its 00211 // children layers from also being deleted; in this 00212 // unlikely case, get_channel() may return NULL. 00213 //////////////////////////////////////////////////////////////////// 00214 GraphicsChannel *GraphicsLayer:: 00215 get_channel() const { 00216 MutexHolder holder(_lock); 00217 return _channel; 00218 } 00219 00220 //////////////////////////////////////////////////////////////////// 00221 // Function: GraphicsLayer::get_window 00222 // Access: Published 00223 // Description: Returns the GraphicsWindow that this layer is 00224 // ultimately associated with, or NULL if no window is 00225 // associated. 00226 //////////////////////////////////////////////////////////////////// 00227 GraphicsWindow *GraphicsLayer:: 00228 get_window() const { 00229 MutexHolder holder(_lock); 00230 return (_channel != (GraphicsChannel *)NULL) ? _channel->get_window() : NULL; 00231 } 00232 00233 //////////////////////////////////////////////////////////////////// 00234 // Function: GraphicsLayer::get_pipe 00235 // Access: Published 00236 // Description: Returns the GraphicsPipe that this layer is 00237 // ultimately associated with, or NULL if no pipe is 00238 // associated. 00239 //////////////////////////////////////////////////////////////////// 00240 GraphicsPipe *GraphicsLayer:: 00241 get_pipe() const { 00242 MutexHolder holder(_lock); 00243 return (_channel != (GraphicsChannel *)NULL) ? _channel->get_pipe() : NULL; 00244 } 00245 00246 //////////////////////////////////////////////////////////////////// 00247 // Function: GraphicsLayer::set_active 00248 // Access: Published 00249 // Description: Sets the active flag on the layer. If the layer 00250 // is marked as inactive, nothing will be rendered. 00251 //////////////////////////////////////////////////////////////////// 00252 void GraphicsLayer:: 00253 set_active(bool active) { 00254 MutexHolder holder(_lock); 00255 if (active != _is_active) { 00256 _is_active = active; 00257 win_display_regions_changed(); 00258 } 00259 } 00260 00261 //////////////////////////////////////////////////////////////////// 00262 // Function: GraphicsLayer::channel_resized 00263 // Access: Public 00264 // Description: This is called whenever the parent channel has been 00265 // resized; it should do whatever needs to be done to 00266 // adjust the layer to account for it. 00267 //////////////////////////////////////////////////////////////////// 00268 void GraphicsLayer:: 00269 channel_resized(int x, int y) { 00270 MutexHolder holder(_lock); 00271 // Since a layer always fills the whole channel, when the channel 00272 // resizes so does the layer, by the same amount. 00273 DisplayRegions::iterator dri; 00274 for (dri = _display_regions.begin(); 00275 dri != _display_regions.end(); 00276 ++dri) { 00277 (*dri)->compute_pixels(x, y); 00278 } 00279 } 00280 00281 //////////////////////////////////////////////////////////////////// 00282 // Function: GraphicsLayer::win_display_regions_changed 00283 // Access: Private 00284 // Description: Intended to be called when the active state on a 00285 // nested channel or layer or display region changes, 00286 // forcing the window to recompute its list of active 00287 // display regions. It is assumed the lock is already 00288 // held. 00289 //////////////////////////////////////////////////////////////////// 00290 void GraphicsLayer:: 00291 win_display_regions_changed() { 00292 if (_channel != (GraphicsChannel *)NULL) { 00293 _channel->win_display_regions_changed(); 00294 } 00295 }