| GL Studio C++ Runtime API

traverser.h
Go to the documentation of this file.
1/*! \file
2 \brief The disti::TraverseGroup class and corresponding Traverse namespace.
3
4 \par Copyright Information
5
6 Copyright (c) 2017 by The DiSTI Corporation.<br>
7 11301 Corporate Blvd; Suite 100<br>
8 Orlando, Florida 32817<br>
9 USA<br>
10 <br>
11 All rights reserved.<br>
12
13 This Software contains proprietary trade secrets of DiSTI and may not be
14 reproduced, in whole or part, in any form, or by any means of electronic,
15 mechanical, or otherwise, without the written permission of DiSTI. Said
16 permission may be derived through the purchase of applicable DiSTI product
17 licenses which detail the distribution rights of this content and any
18 Derivative Works based on this or other copyrighted DiSTI Software.
19
20 NO WARRANTY. THE SOFTWARE IS PROVIDED "AS-IS," WITHOUT WARRANTY OF ANY KIND,
21 AND ANY USE OF THIS SOFTWARE PRODUCT IS AT YOUR OWN RISK. TO THE MAXIMUM EXTENT
22 PERMITTED BY APPLICABLE LAW, DISTI AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES
23 AND CONDITIONS, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
24 IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY AND/OR FITNESS FOR A
25 PARTICULAR PURPOSE, TITLE, AND NON-INFRINGEMENT, WITH REGARD TO THE SOFTWARE.
26
27 LIMITATION OF LIABILITY. TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW,
28 IN NO EVENT SHALL DISTI OR ITS SUPPLIERS BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
29 INDIRECT, OR CONSEQUENTIAL DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION,
30 DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS
31 INFORMATION, OR ANY OTHER PECUNIARY LOSS) ARISING OUT OF THE USE OF OR
32 INABILITY TO USE THE SOFTWARE, EVEN IF DISTI HAS BEEN ADVISED OF THE POSSIBILITY
33 OF SUCH DAMAGES. DISTI'S ENTIRE LIABILITY AND YOUR EXCLUSIVE REMEDY SHALL NOT
34 EXCEED FIVE DOLLARS (US$5.00).
35
36 The aforementioned terms and restrictions are governed by the laws of the
37 State of Florida and the United States of America.
38
39*/
40#ifndef _TRAVERSER_H
41#define _TRAVERSER_H
42
43#include "display.h"
44#include "disti_metadata.h"
45#include "gls_color.h"
46#include "group.h"
47
48 namespace disti
49{
50 namespace Traverse
51{
52 /// \details The ResultEnum enumeration. Describes the state of a located object.
53 /// </summary>
54 typedef enum
55 {
56 NOT_FOUND = 0,
57 FOUND_EQUAL = 1,
58 FOUND_NOT_EQUAL = 2
59 } ResultEnum;
60} // namespace Traverse
61
62/** The TraverseGroup class
63 */
64 template<class T, class argType = int, class arg2Type = int>
65 class TraverseGroup
66{
67 public:
68 /// Just to see if the object contains one of T.
69 /// \param obj The object to check within.
70 /// \param findThis An optional specific object to check for.
71 /// \return If findThis is NULL, will return true if any one is found.
72 /// If findThis has a value, will return true only if findThis is found.
73 static bool Contained( DisplayObject* obj, DisplayObject* findThis = nullptr )
74 {
75 if( dynamic_cast<T*>( obj ) )
76 {
77 if( findThis == nullptr )
78 return true;
79 else if( findThis == obj )
80 return true;
81 }
82
83 if( dynamic_cast<Group*>( obj ) )
84 {
85 // Call for groups children
86 auto* grp = dynamic_cast<Group*>( obj );
87 for( unsigned int i = 0; i < grp->Count(); i++ )
88 {
89 if( Contained( ( *grp )[ i ], findThis ) )
90 return true;
91 }
92 }
93 return false;
94 }
95
96 /// Like Contained(), but looks only one level deep.
97 /// \param grp The object to check within.
98 /// \param findThis An optional specific object to check for.
99 /// \return If findThis is NULL, will return true if any one is found.
100 /// If findThis has a value, will return true only if findThis is found.
101 static bool ContainedNoChildren( Group* grp, DisplayObject* findThis = nullptr )
102 {
103 if( grp )
104 {
105 // Call for groups children
106 for( unsigned int i = 0; i < grp->Count(); i++ )
107 {
108 T* specific = dynamic_cast<T*>( ( *grp )[ i ] );
109 if( specific )
110 {
111 if( findThis == nullptr )
112 return true;
113 else if( findThis == specific )
114 return true;
115 }
116 }
117 }
118 return false;
119 }
120
121 /// \return A group containing all of the matching children that are of the specified class.
122 /// \note Does not traverse sub groups.
123 /// \param grp The object to check within.
124 static Group* AllMatchingNoChildren( Group* grp )
125 {
126 Group* newGrp = nullptr;
127 if( grp )
128 {
129 for( unsigned int i = 0; i < grp->Count(); i++ )
130 {
131 T* specific = dynamic_cast<T*>( ( *grp )[ i ] );
132 if( specific )
133 {
134 if( !newGrp )
135 newGrp = new Group();
136
137 newGrp->InsertObject( specific, false, false, -1 );
138 }
139 }
140 }
141 return newGrp;
142 }
143
144 /// \returns The nth object (1 is the first) of the template type in the specified selections.
145 /// The value of n will be decremented to zero if found.
146 /// return Value will be NULL if not found.
147 /// \param obj The object to check within.
148 /// \param n The index to retrieve.
149 static T* GetNth( DisplayObject* obj, const int n )
150 {
151 int temp = n;
152 return GetNthRecurse( obj, temp );
153 }
154
155 /// Helper function for use with GetNth().
156 /// \param obj The object to check within.
157 /// \param n The index to retrieve.
158 /// \return The pointer to the object found, or NULL.
159 static T* GetNthRecurse( DisplayObject* obj, int& n )
160 {
161 if( dynamic_cast<T*>( obj ) && n > 0 )
162 {
163 T* specific = dynamic_cast<T*>( obj );
164 n--;
165 return specific;
166 }
167 else if( dynamic_cast<Group*>( obj ) )
168 {
169 // Call for groups children
170 auto* grp = dynamic_cast<Group*>( obj );
171 for( unsigned int i = 0; i < grp->Count(); i++ )
172 {
173 T* specific = GetNthRecurse( ( *grp )[ i ], n );
174 if( n == 0 )
175 return specific;
176 }
177 }
178 return NULL;
179 }
180
181 /// T::variable
182 /// \param obj The object to locate, or group to search through.
183 /// \param variablePtr The returned underlying storage of argType.
184 /// \param foundValue The returned value of the underlying storage of argType.
185 /// \return The ResultEnum found state for the object.
186 static Traverse::ResultEnum GetValue( DisplayObject* obj, argType T::*variablePtr, argType& foundValue )
187 {
188 Traverse::ResultEnum foundOne = Traverse::NOT_FOUND;
189
190 if( dynamic_cast<T*>( obj ) )
191 {
192 T* specific = dynamic_cast<T*>( obj );
193 foundValue = specific->*variablePtr;
194 foundOne = Traverse::FOUND_EQUAL;
195 }
196
197 if( dynamic_cast<Group*>( obj ) )
198 {
199 // Call for groups children
200 auto* grp = dynamic_cast<Group*>( obj );
201 argType tempVal;
202 for( unsigned int i = 0; i < grp->Count(); i++ )
203 {
204 Traverse::ResultEnum result = GetValue( ( *grp )[ i ], variablePtr, tempVal );
205 if( result != Traverse::NOT_FOUND )
206 {
207 if( result == Traverse::FOUND_EQUAL )
208 {
209 if( tempVal == foundValue )
210 {
211 foundOne = Traverse::FOUND_EQUAL;
212 }
213 else
214 {
215 foundOne = Traverse::FOUND_NOT_EQUAL;
216 }
217 }
218 else
219 foundOne = Traverse::FOUND_NOT_EQUAL;
220
221 // Save the value either way.
222 foundValue = tempVal;
223 }
224 }
225 }
226 return foundOne;
227 }
228
229 typedef void ( T::*void_CallMethod_void )(); ///< Typedef for a function pointer with no arguments or return value.
230
231 /// void Method()
232 /// \param obj The object to locate, or group to search through.
233 /// \param method The function pointer to call on said object.
234 /// \return True if one is found.
235 static bool Call( DisplayObject* obj, void_CallMethod_void method )
236 {
237 bool foundOne = false;
238
239 if( dynamic_cast<T*>( obj ) )
240 {
241 T* specific = dynamic_cast<T*>( obj );
242 ( specific->*method )();
243 foundOne = true;
244 }
245
246 if( dynamic_cast<Group*>( obj ) )
247 {
248 // Call for groups children
249 auto* grp = dynamic_cast<Group*>( obj );
250 for( unsigned int i = 0; i < grp->Count(); i++ )
251 {
252 if( Call( ( *grp )[ i ], method ) )
253 foundOne = true;
254 }
255 }
256 return foundOne;
257 }
258
259 typedef void ( T::*void_CallMethod_argType )( argType ); ///< Typedef for a function pointer taking one argument and no return value.
260
261 /// void Method(int)
262 /// \param obj The object to locate, or group to search through.
263 /// \param method The function pointer to call on said object.
264 /// \param arg1 The argument to pass through the function pointer.
265 /// \returns true If one is found.
266 static bool Call( DisplayObject* obj, void_CallMethod_argType method, const argType arg1 )
267 {
268 bool foundOne = false;
269
270 if( dynamic_cast<T*>( obj ) )
271 {
272 T* specific = dynamic_cast<T*>( obj );
273 ( specific->*method )( arg1 );
274 foundOne = true;
275 }
276
277 if( dynamic_cast<Group*>( obj ) )
278 {
279 // Call for groups children
280 auto* grp = dynamic_cast<Group*>( obj );
281 for( unsigned int i = 0; i < grp->Count(); i++ )
282 {
283 if( Call( ( *grp )[ i ], method, arg1 ) )
284 foundOne = true;
285 }
286 }
287 return foundOne;
288 }
289
290 typedef void ( T::*void_CallMethod_argType_arg2Type )( argType, arg2Type ); ///< Typedef for a function pointer taking two arguments and no return value.
291
292 /// void Method(type,type)
293 /// \param obj The object to locate, or group to search through.
294 /// \param method The function pointer to call on said object.
295 /// \param arg1 The first argument to pass through the function pointer.
296 /// \param arg2 The second argument to pass through the function pointer.
297 /// \return True if one is found.
298 static bool Call( DisplayObject* obj, void_CallMethod_argType_arg2Type method, argType arg1, arg2Type arg2 )
299 {
300 bool foundOne = false;
301
302 if( dynamic_cast<T*>( obj ) )
303 {
304 T* specific = dynamic_cast<T*>( obj );
305 ( specific->*method )( arg1, arg2 );
306 foundOne = true;
307 }
308
309 if( dynamic_cast<Group*>( obj ) )
310 {
311 // Call for groups children
312 auto* grp = dynamic_cast<Group*>( obj );
313 for( unsigned int i = 0; i < grp->Count(); i++ )
314 {
315 if( Call( ( *grp )[ i ], method, arg1, arg2 ) )
316 foundOne = true;
317 }
318 }
319 return foundOne;
320 }
321
322 typedef void ( T::*void_CallMethod_argTypeRef )( argType& ); ///< Typedef for a function pointer taking one argument as a reference, no return value.
323
324 /// void Method(int&)
325 /// \param obj The object to locate, or group to search through.
326 /// \param method The function pointer to call on said object.
327 /// \param arg1 The argument to pass through the function pointer.
328 /// \return True if one is found.
329 static bool Call( DisplayObject* obj, void_CallMethod_argTypeRef method, argType& arg1 )
330 {
331 bool foundOne = false;
332
333 if( dynamic_cast<T*>( obj ) )
334 {
335 T* specific = dynamic_cast<T*>( obj );
336 ( specific->*method )( arg1 );
337 foundOne = true;
338 }
339
340 if( dynamic_cast<Group*>( obj ) )
341 {
342 // Call for groups children
343 auto* grp = dynamic_cast<Group*>( obj );
344 for( unsigned int i = 0; i < grp->Count(); i++ )
345 {
346 if( Call( ( *grp )[ i ], method, arg1 ) )
347 foundOne = true;
348 }
349 }
350 return foundOne;
351 }
352
353 typedef argType ( T::*argType_CallMethod_void )(); ///< Typedef for a function pointer with no arguments, and has a return value.
354
355 /// int Method(void)
356 /// \param obj The object to locate, or group to search through.
357 /// \param method The function pointer to call on said object.
358 /// \param notFoundValue The value to set if not found.
359 /// \param multipleValue The value to set if multiple values are found.
360 /// \param rvalFoundOne Used for recursion.
361 /// \note This will not get the values from groups themselves, just their children.
362 /// \return notFoundValue If not found.
363 /// returns multipleValue If multiple values are found.
364 static argType ReturnCall( DisplayObject* obj, argType_CallMethod_void method, const argType notFoundValue = argType( 0 ), const argType multipleValue = argType( -1 ), bool* rvalFoundOne = nullptr )
365 {
366 argType rval = notFoundValue;
367 bool weFoundOne = false;
368
369 // Check this object first
370 if( dynamic_cast<T*>( obj ) )
371 {
372 T* specific = dynamic_cast<T*>( obj );
373
374 rval = ( specific->*method )();
375 weFoundOne = true;
376 }
377
378 if( dynamic_cast<Group*>( obj ) )
379 {
380 // Check each of the children
381 argType temp;
382 auto* grp = dynamic_cast<Group*>( obj );
383 for( unsigned int i = 0; i < grp->Count(); i++ )
384 {
385 bool foundOneThisIndex;
386 temp = ReturnCall( ( *grp )[ i ], method, notFoundValue, multipleValue, &foundOneThisIndex );
387
388 if( foundOneThisIndex )
389 {
390 if( weFoundOne )
391 {
392 // We already found one
393 if( temp != rval )
394 {
395 // Different values: no need to continue
396 rval = multipleValue;
397 break;
398 }
399 }
400 else
401 {
402 // This is the first one
403 weFoundOne = true;
404 rval = temp;
405 }
406 }
407 }
408 }
409
410 if( rvalFoundOne )
411 {
412 *rvalFoundOne = weFoundOne;
413 }
414 return rval;
415 }
416
417 typedef GlsColor ( T::*GlsColor_CallMethod_void )(); ///< Typedef for a function pointer that has no arguments, and returns a GlsColor.
418
419 /// GlsColor Method(void)
420 /// \note This will not get the values from groups themselves, just their children.
421 /// \param obj The object to locate, or group to search through.
422 /// \param method The function pointer to call on said object.
423 /// \param foundColor The returned located color.
424 /// \return 0 if not found.
425 /// Returns -1 if multiple values are found.
426 /// Returns 1 if a single value is found.
427 static int Call( DisplayObject* obj, GlsColor_CallMethod_void method, GlsColor& foundColor )
428 {
429 int rval = 0;
430
431 if( dynamic_cast<Group*>( obj ) )
432 {
433 // Call for group's children
434 GlsColor tempColor;
435 int temp;
436 auto* grp = dynamic_cast<Group*>( obj );
437 for( unsigned int i = 0; i < grp->Count(); i++ )
438 {
439 temp = Call( ( *grp )[ i ], method, tempColor );
440
441 // If found duplicate, were done.
442 if( temp == -1 )
443 return temp;
444
445 // If we haven't found one yet
446 if( rval == 0 )
447 {
448 if( temp == 1 )
449 {
450 foundColor = tempColor;
451 rval = 1;
452 }
453 }
454 else // We need to compare with what we have
455 {
456 if( foundColor != tempColor )
457 {
458 // Colors don't match, so we are finished.
459 return -1;
460 }
461 }
462 }
463 }
464 else if( dynamic_cast<T*>( obj ) )
465 {
466 T* specific = dynamic_cast<T*>( obj );
467 foundColor = ( specific->*method )();
468 rval = 1; // Since we found one
469 }
470
471 return rval;
472 }
473};
474
475} // namespace disti
476
477#endif
disti::DisplayObject
Definition: display.h:96
disti::GlsColor
Definition: gls_color.h:54
disti::Group
Definition: group.h:53
disti::Group::Count
unsigned int Count() const
Definition: group.h:173
disti::Group::InsertObject
virtual void InsertObject(DisplayObject *obj, bool reparent=true, bool recalculateBoundingbox=true, int loc=-1)
disti::TraverseGroup
Definition: traverser.h:66
disti::TraverseGroup::GetNth
static T * GetNth(DisplayObject *obj, const int n)
Definition: traverser.h:149
disti::TraverseGroup::void_CallMethod_void
void(T::* void_CallMethod_void)()
Typedef for a function pointer with no arguments or return value.
Definition: traverser.h:229
disti::TraverseGroup::Call
static bool Call(DisplayObject *obj, void_CallMethod_argType method, const argType arg1)
Definition: traverser.h:266
disti::TraverseGroup::AllMatchingNoChildren
static Group * AllMatchingNoChildren(Group *grp)
Definition: traverser.h:124
disti::TraverseGroup::Call
static int Call(DisplayObject *obj, GlsColor_CallMethod_void method, GlsColor &foundColor)
Definition: traverser.h:427
disti::TraverseGroup::Call
static bool Call(DisplayObject *obj, void_CallMethod_argTypeRef method, argType &arg1)
Definition: traverser.h:329
disti::TraverseGroup::GetNthRecurse
static T * GetNthRecurse(DisplayObject *obj, int &n)
Definition: traverser.h:159
disti::TraverseGroup::Call
static bool Call(DisplayObject *obj, void_CallMethod_argType_arg2Type method, argType arg1, arg2Type arg2)
Definition: traverser.h:298
disti::TraverseGroup::argType_CallMethod_void
argType(T::* argType_CallMethod_void)()
Typedef for a function pointer with no arguments, and has a return value.
Definition: traverser.h:353
disti::TraverseGroup::GlsColor_CallMethod_void
GlsColor(T::* GlsColor_CallMethod_void)()
Typedef for a function pointer that has no arguments, and returns a GlsColor.
Definition: traverser.h:417
disti::TraverseGroup::Contained
static bool Contained(DisplayObject *obj, DisplayObject *findThis=nullptr)
Definition: traverser.h:73
disti::TraverseGroup::ReturnCall
static argType ReturnCall(DisplayObject *obj, argType_CallMethod_void method, const argType notFoundValue=argType(0), const argType multipleValue=argType(-1), bool *rvalFoundOne=nullptr)
Definition: traverser.h:364
disti::TraverseGroup::void_CallMethod_argType
void(T::* void_CallMethod_argType)(argType)
Typedef for a function pointer taking one argument and no return value.
Definition: traverser.h:259
disti::TraverseGroup::Call
static bool Call(DisplayObject *obj, void_CallMethod_void method)
Definition: traverser.h:235
disti::TraverseGroup::void_CallMethod_argType_arg2Type
void(T::* void_CallMethod_argType_arg2Type)(argType, arg2Type)
Typedef for a function pointer taking two arguments and no return value.
Definition: traverser.h:290
disti::TraverseGroup::void_CallMethod_argTypeRef
void(T::* void_CallMethod_argTypeRef)(argType &)
Typedef for a function pointer taking one argument as a reference, no return value.
Definition: traverser.h:322
disti::TraverseGroup::ContainedNoChildren
static bool ContainedNoChildren(Group *grp, DisplayObject *findThis=nullptr)
Definition: traverser.h:101
disti::TraverseGroup::GetValue
static Traverse::ResultEnum GetValue(DisplayObject *obj, argType T::*variablePtr, argType &foundValue)
Definition: traverser.h:186
display.h
The disti::DisplayObject class and global enumerations.
disti_metadata.h
The disti metadata.
gls_color.h
The Color class: Implements a 4 component RGBA color.
group.h
The disti::Group class. Implements groups of objects.
disti
Definition: bmpimage.h:47
disti::Traverse::ResultEnum
ResultEnum
Definition: traverser.h:55