Panda3D
Loading...
Searching...
No Matches
mouseWatcherBase.cxx
Go to the documentation of this file.
1/**
2 * PANDA 3D SOFTWARE
3 * Copyright (c) Carnegie Mellon University. All rights reserved.
4 *
5 * All use of this software is subject to the terms of the revised BSD
6 * license. You should have received a copy of this license along
7 * with this source code in a file named "LICENSE."
8 *
9 * @file mouseWatcherBase.cxx
10 * @author rdb
11 * @date 2014-01-13
12 */
13
14#include "mouseWatcherBase.h"
15#include "lineSegs.h"
16#include "indent.h"
17#include "lightMutexHolder.h"
18
19TypeHandle MouseWatcherBase::_type_handle;
20
21/**
22 *
23 */
24MouseWatcherBase::
25MouseWatcherBase() :
26 _lock("MouseWatcherBase")
27{
28 _sorted = true;
29#ifndef NDEBUG
30 _show_regions = false;
31 _color.set(0.4, 0.6f, 1.0f, 1.0f);
32#endif // NDEBUG
33}
34
35/**
36 *
37 */
38MouseWatcherBase::
39~MouseWatcherBase() {
40}
41
42/**
43 * Adds the indicated region to the set of regions in the group. It is no
44 * longer an error to call this for the same region more than once.
45 */
48 LightMutexHolder holder(_lock);
49
50#ifndef NDEBUG
51 // Also add it to the vizzes if we have them.
52 if (UNLIKELY(_show_regions)) {
53 // We need to check whether it is already in the set, so that we don't
54 // create a duplicate viz.
55 Regions::const_iterator ri =
56 std::find(_regions.begin(), _regions.end(), region);
57
58 if (ri == _regions.end()) {
59 nassertv(_vizzes.size() == _regions.size());
60 _vizzes.push_back(make_viz_region(region));
61 } else {
62 return;
63 }
64 }
65#endif // NDEBUG
66
67 _regions.push_back(std::move(region));
68 _sorted = false;
69}
70
71/**
72 * Returns true if the indicated region has already been added to the
73 * MouseWatcherBase, false otherwise.
74 */
76has_region(MouseWatcherRegion *region) const {
77 LightMutexHolder holder(_lock);
78
79 PT(MouseWatcherRegion) ptr = region;
80
81 if (_sorted) {
82 // If the vector is already sorted, we can do this the quick way.
83 Regions::const_iterator ri = lower_bound(_regions.begin(), _regions.end(), ptr);
84 return (ri != _regions.end() && (*ri) == ptr);
85 }
86
87 // If the vector isn't sorted, do a linear scan.
88 Regions::const_iterator ri = find(_regions.begin(), _regions.end(), ptr);
89 return (ri != _regions.end());
90}
91
92/**
93 * Removes the indicated region from the group. Returns true if it was
94 * successfully removed, or false if it wasn't there in the first place.
95 */
98 LightMutexHolder holder(_lock);
99 return do_remove_region(region);
100}
101
102/**
103 * Returns a pointer to the first region found with the indicated name. If
104 * multiple regions share the same name, the one that is returned is
105 * indeterminate.
106 */
108find_region(const std::string &name) const {
109 LightMutexHolder holder(_lock);
110
111 for (MouseWatcherRegion *region : _regions) {
112 if (region->get_name() == name) {
113 return region;
114 }
115 }
116
117 return nullptr;
118}
119
120/**
121 * Removes all the regions from the group.
122 */
125 LightMutexHolder holder(_lock);
126
127 _regions.clear();
128 _sorted = true;
129
130#ifndef NDEBUG
131 if (_show_regions) {
132 _show_regions_root.node()->remove_all_children();
133 _vizzes.clear();
134 }
135#endif // NDEBUG
136}
137
138/**
139 * Returns the number of regions in the group.
140 */
142get_num_regions() const {
143 LightMutexHolder holder(_lock);
144 if (!_sorted) {
145 // Remove potential duplicates to get an accurate count.
146 ((MouseWatcherBase *)this)->do_sort_regions();
147 }
148 return _regions.size();
149}
150
151/**
152 * Returns the nth region of the group; returns NULL if there is no nth
153 * region. Note that this is not thread-safe; another thread might have
154 * removed the nth region before you called this method.
155 */
157get_region(size_t n) const {
158 LightMutexHolder holder(_lock);
159 if (!_sorted) {
160 ((MouseWatcherBase *)this)->do_sort_regions();
161 }
162 if (n < _regions.size()) {
163 return _regions[n];
164 }
165 return nullptr;
166}
167
168/**
169 *
170 */
171void MouseWatcherBase::
172output(std::ostream &out) const {
173 out << "MouseWatcherGroup (" << _regions.size() << " regions)";
174}
175
176/**
177 *
178 */
179void MouseWatcherBase::
180write(std::ostream &out, int indent_level) const {
181 LightMutexHolder holder(_lock);
182
183 for (MouseWatcherRegion *region : _regions) {
184 region->write(out, indent_level);
185 }
186}
187
188#if !defined(NDEBUG) || !defined(CPPPARSER)
189/**
190 * Enables the visualization of all of the regions handled by this
191 * MouseWatcherBase. The supplied NodePath should be the root of the 2-d
192 * scene graph for the window.
193 */
195show_regions(const NodePath &render2d, const std::string &bin_name, int draw_order) {
196#ifndef NDEBUG
197 LightMutexHolder holder(_lock);
198 do_show_regions(render2d, bin_name, draw_order);
199#endif
200}
201#endif // NDEBUG
202
203#if !defined(NDEBUG) || !defined(CPPPARSER)
204/**
205 * Specifies the color used to draw the region rectangles for the regions
206 * visualized by show_regions().
207 */
209set_color(const LColor &color) {
210#ifndef NDEBUG
211 LightMutexHolder holder(_lock);
212
213 _color = color;
214 do_update_regions();
215#endif
216}
217#endif // NDEBUG
218
219#if !defined(NDEBUG) || !defined(CPPPARSER)
220/**
221 * Stops the visualization created by a previous call to show_regions().
222 */
224hide_regions() {
225#ifndef NDEBUG
226 LightMutexHolder holder(_lock);
227 do_hide_regions();
228#endif
229}
230#endif // NDEBUG
231
232#if !defined(NDEBUG) || !defined(CPPPARSER)
233/**
234 * Refreshes the visualization created by show_regions().
235 */
238#ifndef NDEBUG
239 LightMutexHolder holder(_lock);
240 do_update_regions();
241#endif
242}
243#endif // NDEBUG
244
245
246/**
247 * Sorts all the regions in this group into pointer order. Assumes the lock
248 * is already held.
249 */
250void MouseWatcherBase::
251do_sort_regions() {
252 if (!_sorted) {
253 _regions.sort_unique();
254 _sorted = true;
255 }
256}
257
258/**
259 * The internal implementation of remove_region(); assumes the lock is already
260 * held.
261 */
262bool MouseWatcherBase::
263do_remove_region(MouseWatcherRegion *region) {
264 // See if the region is in the vector.
265 PT(MouseWatcherRegion) ptr = region;
266 Regions::iterator ri;
267
268 if (_sorted) {
269 // Faster, binary search
270 ri = lower_bound(_regions.begin(), _regions.end(), ptr);
271 } else {
272 // Unsorted, so use slower linear scan
273 ri = find(_regions.begin(), _regions.end(), ptr);
274 }
275
276 if (ri != _regions.end() && (*ri) == ptr) {
277 // Found it, now erase it
278#ifndef NDEBUG
279 // Also remove it from the vizzes.
280 if (_show_regions) {
281 nassertr(_vizzes.size() == _regions.size(), false);
282 size_t index = ri - _regions.begin();
283 Vizzes::iterator vi = _vizzes.begin() + index;
284 _show_regions_root.node()->remove_child(*vi);
285 _vizzes.erase(vi);
286 }
287#endif // NDEBUG
288
289 _regions.erase(ri);
290 return true;
291 }
292
293 // Did not find the region to erase
294 return false;
295}
296
297#ifndef NDEBUG
298/**
299 * The protected implementation of show_regions(). This assumes the lock is
300 * already held.
301 */
302void MouseWatcherBase::
303do_show_regions(const NodePath &render2d, const std::string &bin_name,
304 int draw_order) {
305 do_hide_regions();
306 _show_regions = true;
307 _show_regions_root = render2d.attach_new_node("show_regions");
308 _show_regions_root.set_bin(bin_name, draw_order);
309 do_update_regions();
310}
311#endif // NDEBUG
312
313#ifndef NDEBUG
314/**
315 * The protected implementation of hide_regions(). This assumes the lock is
316 * already held.
317 */
318void MouseWatcherBase::
319do_hide_regions() {
320 _show_regions_root.remove_node();
321 _show_regions = false;
322 _vizzes.clear();
323}
324#endif // NDEBUG
325
326#ifndef NDEBUG
327/**
328 * Internally regenerates the show_regions() visualization. Assumes the lock
329 * is already held.
330 */
331void MouseWatcherBase::
332do_update_regions() {
333 nassertv(_lock.debug_is_locked());
334
335 if (_show_regions) {
336 // Make sure we have no duplicates.
337 do_sort_regions();
338
339 _show_regions_root.node()->remove_all_children();
340 _vizzes.clear();
341 _vizzes.reserve(_regions.size());
342
343 for (MouseWatcherRegion *region : _regions) {
344 _vizzes.push_back(make_viz_region(region));
345 }
346 }
347}
348#endif // NDEBUG
349
350
351#ifndef NDEBUG
352/**
353 * Creates a node to represent the indicated region, and attaches it to the
354 * _show_regions_root. Does not add it to _vizzes. Assumes the lock is
355 * already held.
356 */
357PandaNode *MouseWatcherBase::
358make_viz_region(MouseWatcherRegion *region) {
359 nassertr(_lock.debug_is_locked(), nullptr);
360
361 LineSegs ls("show_regions");
362 ls.set_color(_color);
363
364 const LVecBase4 &f = region->get_frame();
365
366 ls.move_to(LVector3::rfu(f[0], 0.0f, f[2]));
367 ls.draw_to(LVector3::rfu(f[1], 0.0f, f[2]));
368 ls.draw_to(LVector3::rfu(f[1], 0.0f, f[3]));
369 ls.draw_to(LVector3::rfu(f[0], 0.0f, f[3]));
370 ls.draw_to(LVector3::rfu(f[0], 0.0f, f[2]));
371
372 PT(PandaNode) node = ls.create();
373 _show_regions_root.attach_new_node(node);
374
375 return node;
376}
377#endif // NDEBUG
bool debug_is_locked() const
Returns true if the current thread has locked the LightMutex, false otherwise.
Similar to MutexHolder, but for a light mutex.
Encapsulates creation of a series of connected or disconnected line segments or points,...
Definition lineSegs.h:33
This represents a collection of MouseWatcherRegions that may be managed as a group.
bool remove_region(MouseWatcherRegion *region)
Removes the indicated region from the group.
get_num_regions
Returns the number of regions in the group.
void clear_regions()
Removes all the regions from the group.
void add_region(PT(MouseWatcherRegion) region)
Adds the indicated region to the set of regions in the group.
void show_regions(const NodePath &render2d, const std::string &bin_name, int draw_order)
Enables the visualization of all of the regions handled by this MouseWatcherBase.
MouseWatcherRegion * find_region(const std::string &name) const
Returns a pointer to the first region found with the indicated name.
get_region
Returns the nth region of the group; returns NULL if there is no nth region.
void set_color(const LColor &color)
Specifies the color used to draw the region rectangles for the regions visualized by show_regions().
void update_regions()
Refreshes the visualization created by show_regions().
void hide_regions()
Stops the visualization created by a previous call to show_regions().
bool has_region(MouseWatcherRegion *region) const
Returns true if the indicated region has already been added to the MouseWatcherBase,...
This is the class that defines a rectangular region on the screen for the MouseWatcher.
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition nodePath.h:159
void remove_node(Thread *current_thread=Thread::get_current_thread())
Disconnects the referenced node from the scene graph.
Definition nodePath.cxx:627
PandaNode * node() const
Returns the referenced node of the path.
Definition nodePath.I:227
NodePath attach_new_node(PandaNode *node, int sort=0, Thread *current_thread=Thread::get_current_thread()) const
Attaches a new node, with or without existing parents, to the scene graph below the referenced node o...
Definition nodePath.cxx:599
void set_bin(const std::string &bin_name, int draw_order, int priority=0)
Assigns the geometry at this level and below to the named rendering bin.
A basic node of the scene graph or data graph.
Definition pandaNode.h:65
void remove_all_children(Thread *current_thread=Thread::get_current_thread())
Removes all the children from the node at once, including stashed children.
void remove_child(int child_index, Thread *current_thread=Thread::get_current_thread())
Removes the nth child from the node.
TypeHandle is the identifier used to differentiate C++ class types.
Definition typeHandle.h:81
void sort_unique()
Ensures that the vector is properly sorted after a potentially damaging operation.
iterator_0 begin()
Returns the iterator that marks the first element in the ordered vector.
void push_back(const value_type_0 &key)
Adds the new element to the end of the vector without regard for proper sorting.
size_type_0 size() const
Returns the number of elements in the ordered vector.
iterator_0 end()
Returns the iterator that marks the end of the ordered vector.
void clear()
Removes all elements from the ordered vector.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.