GL Studio C++ Runtime API
util.h
Go to the documentation of this file.
1 /*! \file
2  \brief Generally useful defines, macros, enumerations and function
3  prototypes.
4 
5  \par Copyright Information
6 
7  Copyright (c) 2017 by The DiSTI Corporation.<br>
8  11301 Corporate Blvd; Suite 100<br>
9  Orlando, Florida 32817<br>
10  USA<br>
11  <br>
12  All rights reserved.<br>
13 
14  This Software contains proprietary trade secrets of DiSTI and may not be
15 reproduced, in whole or part, in any form, or by any means of electronic,
16 mechanical, or otherwise, without the written permission of DiSTI. Said
17 permission may be derived through the purchase of applicable DiSTI product
18 licenses which detail the distribution rights of this content and any
19 Derivative Works based on this or other copyrighted DiSTI Software.
20 
21  NO WARRANTY. THE SOFTWARE IS PROVIDED "AS-IS," WITHOUT WARRANTY OF ANY KIND,
22 AND ANY USE OF THIS SOFTWARE PRODUCT IS AT YOUR OWN RISK. TO THE MAXIMUM EXTENT
23 PERMITTED BY APPLICABLE LAW, DISTI AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES
24 AND CONDITIONS, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
25 IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY AND/OR FITNESS FOR A
26 PARTICULAR PURPOSE, TITLE, AND NON-INFRINGEMENT, WITH REGARD TO THE SOFTWARE.
27 
28  LIMITATION OF LIABILITY. TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW,
29 IN NO EVENT SHALL DISTI OR ITS SUPPLIERS BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
30 INDIRECT, OR CONSEQUENTIAL DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION,
31 DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS
32 INFORMATION, OR ANY OTHER PECUNIARY LOSS) ARISING OUT OF THE USE OF OR
33 INABILITY TO USE THE SOFTWARE, EVEN IF DISTI HAS BEEN ADVISED OF THE POSSIBILITY
34 OF SUCH DAMAGES. DISTI'S ENTIRE LIABILITY AND YOUR EXCLUSIVE REMEDY SHALL NOT
35 EXCEED FIVE DOLLARS (US$5.00).
36 
37  The aforementioned terms and restrictions are governed by the laws of the
38 State of Florida and the United States of America.
39 
40 */
41 
42 #ifndef INCLUDED_GLS_RUNTIME_UTIL_H
43 #define INCLUDED_GLS_RUNTIME_UTIL_H
44 
45 #include "disti_assert.h"
46 #include "dynamic_array.h"
47 #include "gls_cpp_lang_support.h"
48 #include "gls_include.h"
49 #include "gls_matrix_affine.h"
50 #include "scoped_ptr.h"
51 #include "unhide_globals.h"
52 #include "vertex.h"
53 
54 #include <algorithm>
55 #include <cmath>
56 #include <iostream>
57 #include <sstream>
58 #include <string>
59 #include <typeinfo>
60 #include <vector>
61 
62 #ifdef WIN32
63 # include <direct.h>
64 #else
65 # include <unistd.h>
66 #endif
67 
68 #if defined( QNX )
69 # include <stdio.h>
70 #else
71 # include <cstdio>
72 #endif
73 
74 #if defined( LINUX ) || defined( __VXWORKS__ ) || defined( __APPLE__ ) || defined( QNX )
75 # include <strings.h>
76 #endif
77 
78 #ifdef ANDROID
79 # include <android/asset_manager.h>
80 #endif
81 
82 const int DIALOG_MAX_DIRECTORY_LENGTH = 1024; // Limited by FLTK FileBrowser
83 
84 class Fl_Window;
85 
86 // Wrap code that should only be compiled in debug in GLS_DEBUG_CODE()
87 #if defined( GLS_DEBUG ) || !defined( NDEBUG )
88 # define GLS_DEBUG_CODE( x ) x
89 #else
90 # define GLS_DEBUG_CODE( x )
91 #endif
92 
93 namespace disti
94 {
95 class Vertex;
96 class DisplayObject;
97 class DisplayFrame;
98 
99 #ifndef TRUE
100 # define TRUE 1
101 #endif
102 
103 #ifndef FALSE
104 # define FALSE 0
105 #endif
106 
107 #ifdef WIN32
108 inline int strcasecmp( const char* const x, const char* const y )
109 {
110  return _stricmp( x, y );
111 }
112 #endif
113 
114 /** Used to generate inline textures. The writing and reading of the lines need to know the length. */
116 
117 /* Used for parsing lines of clear text */
118 const char PARSER_CLEARSTRING_DELIMETER_START[] = "#$STRING_START$#";
119 const char PARSER_CLEARSTRING_DELIMETER_END[] = "#$STRING_END$#";
120 
121 const double HIT_TOLERANCE = 5.0;
122 
123 /** Determines if x is included in the range x1 to x2 */
124 template<class X, class X1, class X2>
125 bool BETWEEN( const X& x, const X1& x1, const X2& x2 )
126 {
127  return ( x >= x1 && x <= x2 )
128  || ( x >= x2 && x <= x1 );
129 }
130 
131 /** Determines if the argument is negative */
132 template<class X>
133 bool IS_NEGATIVE( const X& x ) { return std::fabs( x ) > 0.0001 ? ( x < 0.0 ) : 0; }
134 
135 /** Determines if the argument is positive */
136 template<class X>
137 bool IS_POSITIVE( const X& x ) { return std::fabs( x ) > 0.0001 ? ( x > 0.0 ) : 0; }
138 
139 /** Determines if the argument is small (< 1e-1) */
140 template<class X>
141 bool CloseToZero( const X x, const X threshold = X( 1e-1 ) )
142 {
143  return std::fabs( x ) < threshold;
144 }
145 
146 /** Determines if the argument is extremely small (< 10E-4) */
147 template<class X>
148 bool VeryCloseToZero( X x ) { return CloseToZero( x, X( 0.0001 ) ); }
149 
150 /** Determines if the argument is very small (< 10E-3) */
151 template<class X>
152 bool IsNearZero( X x ) { return CloseToZero( x, X( 0.001 ) ); }
153 
154 /** \deprecated Renamed to IsNearZero(). */
155 template<class X>
156 bool IS_ZERO( X x ) { return IsNearZero( x ); }
157 
158 #ifndef MIN
159 /// Determines which argument is smaller
160 /// \deprecated Use disti::Min() instead.
161 # define MIN( A, B ) ( ( A ) < ( B ) ? ( A ) : ( B ) )
162 #endif
163 
164 #ifndef MAX
165 /// Determines which argument is larger
166 /// \deprecated Use disti::Min() instead.
167 # define MAX( A, B ) ( ( A ) > ( B ) ? ( A ) : ( B ) )
168 #endif
169 
170 /** Use for determining the current OpenGL version available in the current
171  * runtime environment.
172  * It may not be valid until called after a valid rendering context has been assigned.
173  */
174 GLS_EXPORT float OpenGLVersion();
175 
176 GLS_EXPORT bool gltIsExtSupported( const char* extension );
177 
178 // Additional #defines
179 //From glext.h Available at http://oss.sgi.com/projects/ogl-sample/registry/ */
180 #ifndef GLES
181 # define GLSTUDIO_CLAMP_TO_EDGE ( OpenGLVersion() >= 1.2f ? 0x812F : GL_CLAMP )
182 #else
183 # define GLSTUDIO_CLAMP_TO_EDGE GL_CLAMP_TO_EDGE
184 #endif
185 
186 /** GL Studio color defines */
187 // \enum color enumerations for use with GlsDefinedColor methods
189 {
190  GLS_COLOR_WHITE,
191  GLS_COLOR_CYAN,
192  GLS_COLOR_RED,
193  GLS_COLOR_AMBER,
194  GLS_COLOR_GREEN,
195  GLS_COLOR_YELLOW,
196  GLS_COLOR_MAGENTA,
197  GLS_COLOR_BLACK,
198  GLS_COLOR_BLUE,
199  GLS_COLOR_MAX
200 };
201 
202 /** Predefined colors (see \sa GlsDefinedColorEnum for the values). Use \sa GlsDefinedColor() for a range-checked version. */
203 GLS_EXPORT extern unsigned char glsDefinedColors[ GLS_COLOR_MAX ][ 4 ];
204 
205 /** Gets a predefined color in \sa GlsDefinedColorEnum.
206  * \param index of defined color
207  * \return an unsigned char array of the specified index
208  */
209 inline unsigned char* GlsDefinedColor( GlsDefinedColorEnum index )
210 {
211  if( ( index < 0 ) || ( index >= GLS_COLOR_MAX ) )
212  return glsDefinedColors[ 0 ];
213  else
214  return glsDefinedColors[ index ];
215 }
216 /** Allows the user to change the predefined colors */
218  GlsDefinedColorEnum index,
219  unsigned char red,
220  unsigned char green,
221  unsigned char blue,
222  unsigned char alpha )
223 {
224  if( ( index >= 0 ) && ( index < GLS_COLOR_MAX ) )
225  {
226  glsDefinedColors[ index ][ 0 ] = red;
227  glsDefinedColors[ index ][ 1 ] = green;
228  glsDefinedColors[ index ][ 2 ] = blue;
229  glsDefinedColors[ index ][ 3 ] = alpha;
230  }
231 }
232 
233 //---------------------------------------------------------------------------
234 /**
235  * Return whether two numbers are "equal" to eachother taking into account
236  * a certain precision. You can use this method on any numeric types and
237  * even mix types as the parameters. Eg. you can compare integers with
238  * floating point types or compare floats and doubles without casting.
239  *
240  * \param x first number to use in the comparison which determines the range
241  * \param y number to check if within the range determined by x and precision
242  * \param precision number that is added to and subtracted from x to
243  * determine the range to check y against.
244  */
245 template<class T1, class T2>
246 bool Equal( T1 x, T2 y, float precision = 0.001f )
247 {
248  return ( x - precision ) <= y && y <= ( x + precision );
249 }
250 
251 //---------------------------------------------------------------------------
252 /**
253  * Return the minimum of two objects. The class T must have the < operator
254  * defined.
255  */
256 template<class T>
257 const T& Min( const T& x, const T& y )
258 {
259  return x < y ? x : y;
260 }
261 
262 //---------------------------------------------------------------------------
263 /**
264  * Return the maximum of two objects. The class T must have the < operator
265  * defined.
266  */
267 template<class T>
268 const T& Max( const T& x, const T& y )
269 {
270  return x < y ? y : x;
271 }
272 
273 //---------------------------------------------------------------------------
274 /**
275  * Return the minimum of two objects determined by a predicate.
276  * If pr(x, y) is true, x is returned else y.
277  */
278 template<class T, class Pred>
279 const T& Min( const T& x, const T& y, Pred pr )
280 {
281  return pr( x, y ) ? x : y;
282 }
283 
284 //---------------------------------------------------------------------------
285 /**
286  * Return the maximum of two objects determined by a predicate.
287  * If pr(x, y) is true, y is returned else x.
288  */
289 template<class T, class Pred>
290 const T& Max( const T& x, const T& y, Pred pr )
291 {
292  return pr( x, y ) ? y : x;
293 }
294 
295 /** \brief Class to contain current OpenGL view, projection and draw matrices */
297 {
298 private:
299  bool _needsDelete;
300 
301 public:
302  int* viewMatrix;
303  GlsMatrixType* projMatrix;
304  GlsMatrixType* modelMatrix;
305 
306  /** Default constructor
307  * Keeps everything NULL */
308  GLS_EXPORT OpenGLMatrices();
309 
310  /** Copy constructor
311  * Pointers are copied as-is, copies of the
312  * data are NOT made. */
313  GLS_EXPORT OpenGLMatrices( const OpenGLMatrices& src );
314 
315  /** Another constructor.
316  * Pointers are copied as-is, copies of the
317  * data are NOT made. */
318  GLS_EXPORT OpenGLMatrices( int* view,
319  GlsMatrixType* proj,
320  GlsMatrixType* model );
321 
322  /** Destructor */
323  GLS_EXPORT ~OpenGLMatrices();
324 
325  /** Retrieves the current OpenGL Matrices from the
326  * OpenGL Subsystem */
327  GLS_EXPORT void GetCurrent();
328 };
329 
330 /** Find a transformation that will convert to a new coordinate
331  * system defined by the given origin and basis vectors (i,j,k).
332  * \note The new i,j,k vectors are in respect to the current origin.
333  * (i.e. for transformation that moves the origin
334  * along the x axis by 5 units you should pass in
335  * (Vector(5,0,0), Vector(1,0,0), Vector(0,1,0) , Vector(0,0,1))
336  * NOT (Vector(5,0,0), Vector(6,0,0), Vector(5,1,0) , Vector(5,0,1))
337  * Template argument is either double or float.
338  * \param new_origin Vector to the new coordinate system origin.
339  * \param new_i Vector parallel to the new x-axis with magnitude equal to one unit in the new coordinate system.
340  * \param new_j Vector parallel to the new y-axis with magnitude equal to one unit in the new coordinate system.
341  * \param new_k Vector parallel to the new z-axis with magnitude equal to one unit in the new coordinate system.
342  *
343  * \returns transformation matrix to the new coordinate system
344  */
345 template<class T>
346 GlsMatrixAffine<T> FindCoordinateTransformation( const Vector& new_origin, const Vector& new_i, const Vector& new_j, const Vector& new_k )
347 {
348  GlsMatrixAffine<T> transform;
349  GlsMatrixAffine<T> rotation_scaling;
350 
351  // First translate to the new origin
352 
353  transform.Translate( -new_origin );
354 
355  // Build a matrix taking the standard basis vectors to the new basis vectors
356 
357  rotation_scaling( 0, 0 ) = new_i.x;
358  rotation_scaling( 0, 1 ) = new_j.x;
359  rotation_scaling( 0, 2 ) = new_k.x;
360  rotation_scaling( 1, 0 ) = new_i.y;
361  rotation_scaling( 1, 1 ) = new_j.y;
362  rotation_scaling( 1, 2 ) = new_k.y;
363  rotation_scaling( 2, 0 ) = new_i.z;
364  rotation_scaling( 2, 1 ) = new_j.z;
365  rotation_scaling( 2, 2 ) = new_k.z;
366 
367  // Invert because we want the new basis vectors to become the standard basis vectors
368  rotation_scaling.Invert();
369 
370  // Combine the translation and rotation to produce the complete transformation
371  return rotation_scaling * transform;
372 }
373 
374 template<class T>
375 void FindCoordinateTransformation( const Vector& new_origin, const Vector& new_i, const Vector& new_j, const Vector& new_k, GlsMatrixAffine<T>& result )
376 {
377  GlsMatrixAffine<T> transform;
378  GlsMatrixAffine<T> rotation_scaling;
379 
380  // First translate to the new origin
381 
382  transform.Translate( -new_origin );
383 
384  // Build a matrix taking the standard basis vectors to the new basis vectors
385 
386  rotation_scaling( 0, 0 ) = new_i.x;
387  rotation_scaling( 0, 1 ) = new_j.x;
388  rotation_scaling( 0, 2 ) = new_k.x;
389  rotation_scaling( 1, 0 ) = new_i.y;
390  rotation_scaling( 1, 1 ) = new_j.y;
391  rotation_scaling( 1, 2 ) = new_k.y;
392  rotation_scaling( 2, 0 ) = new_i.z;
393  rotation_scaling( 2, 1 ) = new_j.z;
394  rotation_scaling( 2, 2 ) = new_k.z;
395 
396  // Invert because we want the new basis vectors to become the standard basis vectors
397  rotation_scaling.Invert();
398 
399  // Combine the translation and rotation to produce the complete transformation
400  result = rotation_scaling * transform;
401 }
402 
403 /** Gets the transformation from one DisplayObject's object coordinates to another's
404  * Note: This method uses a screen-space transformation (DisplayObject::ModelMatrix). This requires that the two objects have been PreDrawn with the same view, but they do not need to be part of the same object heirarchy.
405  * Use GetObjectCoordinatesTransform unless GetObjectCoordinatesTransformSameView is required.
406  *
407  * \sa GetObjectCoordinatesTransform
408  *
409  * \param from The DisplayObject to start at
410  * \param to The DisplayObject to end at
411  * \param outTransform Out parameter - If the function returns true, this will contain the resulting transformation.
412  * \returns true on success, false if there was an error
413  */
414 GLS_EXPORT bool GetObjectCoordinatesTransformSameView( DisplayObject* from, DisplayObject* to, GlsMatrixType* outTransform );
415 
416 /** Gets the Topmost Display Frame
417  *
418  * \param from The DisplayFrame to start at
419  * \returns the Topmost Display Frame
420  */
421 GLS_EXPORT DisplayFrame* GetTopLevelDisplayFrame( DisplayFrame* frame );
422 
423 /** Gets the transformation from one DisplayObject's object coordinates to another's (if possible)
424  * This is the preferred method for determining the coordinate space relationship between two objects that have DynamicTransforms applied.
425  * Note: This method requires that the two objects are part of the same object heirarchy.
426  * Consider using GetObjectCoordinatesTransformSameView if your situation does not meet this requirement.
427  *
428  * \code
429  * // Example: Move objB to be in the same location as objA (including all DynamicTransforms)
430  * // Change Location of objB so that it's RotationPoint aligns with the RotationPoint of objA
431  * GlsMatrixType transform;
432  * if( GetObjectCoordinatesTransform( objA, objB, &transform ) )
433  * {
434  * Vector objA_rotationPoint_transformed = transform * (objA->Location() + objA->RotationPoint());
435  * objB->Location( objA_rotationPoint_transformed - objB->RotationPoint() );
436  * }
437  * else
438  * {
439  * // Error: objects are not in the same heirarchy
440  * }
441  * \endcode
442  *
443  * \sa GetObjectCoordinatesTransform
444  *
445  * \param from The DisplayObject to start at
446  * \param to The DisplayObject to end at
447  * \param outTransform Out parameter - If the function returns true, this will contain the resulting transformation.
448  * \returns true on success, false if the objects are not in the same heirarchy.
449  */
450 GLS_EXPORT bool GetObjectCoordinatesTransform( DisplayObject* from, DisplayObject* to, GlsMatrixType* outTransform );
451 
452 /** Test if the given points are not colinear (they are not in a line)
453  * \return true if the points are not colinear
454  * \return false if the points are colinear
455  */
456 GLS_EXPORT bool NotColinear( const Vector& a, const Vector& b, const Vector& c );
457 
458 /** Search the given Vertex array for the first three non-colinear vertices.
459  * \param arraySize The size of vertex_array
460  * \param array The Vertex array
461  * \param index1 variable to receive 1st array index
462  * \param index2 variable to receive 2nd array index
463  * \param index3 variable to receive 3rd array index
464  * \param isVectorArray true if array points to a Vector array, false if it
465  * points to a Vertex array
466  *
467  * \return true If the vertices were found
468  * \returns false If there are not three non-colinear vertices in the array
469  * if this occurs, the index values are undefined
470  */
471 GLS_EXPORT bool FindNonColinearVertices( int arraySize, Vector array[],
472  int& index1, int& index2, int& index3,
473  bool isVectorArray = true );
474 
475 /** Vertex version of FindNonColinearVertices */
476 inline bool FindNonColinearVertices( int arraySize, Vertex array[], int& index1, int& index2, int& index3 )
477 {
478  return FindNonColinearVertices( arraySize, array, index1, index2, index3, false );
479 }
480 
481 /** Recalculate the texture points of a given DisplayObject
482  * based on its valid texture coordinates
483  *
484  * \return true On success
485  * \return false If the texture points could not be calculated.
486  * (The object doesn't have three non-colinear vertices or doesn't have texture coordinates.)
487  */
488 GLS_EXPORT bool CalculateTexPointsFromTexCoords( DisplayObject* object );
489 
490 /** Encodes a string such that if it contains newlines, it will be wrapped with the "#$STRING_START$#" and "#$STRING_END$#" delimiters.
491  * \param dest Destination string
492  * \param src Source string
493  * \param dest_str_length Size of the destination buffer
494  * \return The length of the encoded string.
495  */
496 GLS_EXPORT int EncodeString( char* dest, const char* src, const int dest_str_length );
497 
498 /** Encodes a std::string such that there are no whitespace characters in the string
499  * \param src Source string
500  * \return The encoded string
501  */
502 GLS_EXPORT std::string EncodeString( const std::string& src );
503 
504 /** Returns a minimum length for a call to EncodeString.
505  * This is based on the clear text delimeters
506  */
507 GLS_EXPORT int EncodedStringMinLength();
508 
509 /** Encodes a string using C language encoding
510  * \param dest Destination string
511  * \param src Source string
512  * \param dest_str_length Size of the destination buffer
513  * \return The length of the encoded string
514  */
515 GLS_EXPORT int C_EncodeString( char* dest, const char* src, const int dest_str_length );
516 
517 /** Returns and encoded std::string using C language encoding
518  * \param src Source string
519  * \return The encoded string
520  */
521 GLS_EXPORT std::string C_EncodeString( const std::string& src );
522 
523 /** Decodes a string that was encoded using EncodeString
524  * \param dest Destination string
525  * \param src Source string
526  * \param dest_str_length Size of the destination buffer
527  * \return The length of the encoded string
528  */
529 GLS_EXPORT int DecodeString( char* dest, const char* src, const int dest_str_length );
530 
531 /** Decodes a std::string that was encoded using EncodeString
532  * \param src Encoded Source string
533  * \return The decoded string
534  */
535 GLS_EXPORT std::string DecodeString( const std::string& src );
536 
537 /** The InlinePixmap structure */
538 typedef struct
539 {
540  int width;
541  int height;
542  int comprSize;
543  unsigned char* pixels;
544 } InlinePixmap;
545 
546 GLS_EXPORT char* MakeRelativePath( const char* originalPath, const char* relativePath );
547 GLS_EXPORT void ConvertBackslashToSlash( char* str );
548 GLS_EXPORT void ConvertBackslashToSlash( std::string& str );
549 
550 /** Determines if the given value falls in any of the ranges passed in.
551  * range_check(int number_of_ranges, double test_value,
552  * int index_0,double range_0_min,double range_0_max,
553  *
554  * ...
555  *
556  * int index_n,double range_n_min,double range_n_max);
557  *
558  * For example, to return 1 for values 0-10 and 2 for values 10-20:
559  *
560  * index = range_check(2,val,
561  * 1, 0.0, 10.0,
562  * 2, 10.0, 20.0);
563  */
564 
565 GLS_EXPORT int range_check( int num, double val, ... );
566 
567 /** Attempts to open the given file. Pops up an error message box if the
568  * attempt fails
569  * \param filename The name of the file to open
570  * \param flags fopen style file arguments (e.g. "r")
571  * \param f Contains file pointer on success
572  * \return True if the operation was successful
573  */
574 GLS_EXPORT int Safe_fopen( const char* filename, char* flags, FILE** f );
575 /** Stream version */
576 GLS_EXPORT int Safe_fopen( const char* filename, char* flags, std::fstream& outstr );
577 
578 #ifdef ANDROID
579 /** Sets if assets should be loaded directly from the apk (default true).
580  * This only affects Android builds.
581  * \param enableDirectAssetLoading true to allow assets to be loaded directly from the apk
582  * false to force assets to be read from the resource directory (\see SetResourcePath)
583  * \post HasAssetExtension returns false for all filetypes if direct asset loading was disabled
584  */
585 GLS_EXPORT void EnableDirectAssetLoading( bool enableDirectAssetLoading );
586 
587 /** Returns if the filetype is one that can be loaded directly from the apk assets.
588  * This only affects Android builds.
589  * \param filename The filename with extension to check
590  * \return True if the filetype can be loaded directly from the apk assets,
591  * False if the file is loaded from internal or external storage
592  */
593 GLS_EXPORT bool HasAssetExtension( const char* filename );
594 
595 /** Returns if the file exists in the apk assets.
596  * This only affects Android builds.
597  * \param filename The name of the file
598  * \return True if the file is an asset that can be opened.
599  * Returns false if no asset exists with filename or the pointer to the AAssetManager, set with SetAssetManager, is null.
600  */
601 GLS_EXPORT bool AssetExists( const char* filename );
602 
603 /** Sets the Android Asset Manager to use.
604  * When the assetManager is null, apk assets cannot be loaded.
605  * This only affects Android builds.
606  * \param assetManager The pointer to the AAssetManager
607  */
608 GLS_EXPORT void SetAssetManager( AAssetManager* assetManager );
609 #endif
610 
611 #if defined( ANDROID ) || defined( __APPLE__ ) || ( defined( LINUX ) && defined( GLES ) ) || defined( QNX ) || defined( INTEGRITY )
612 /** Prepends the resource path to a file name.
613  * \param[in] filename_ The name of the file
614  * \return string containing ResourcePath+filename_, with OS specific path.
615  * On Android, apk asset files are not prepended with a path.
616  */
617 GLS_EXPORT std::string ResolvePath( const char* filename_ );
618 
619 /** Sets the path for locating resource files.
620  * On Android, this is the location where resources outside of apk assets are found.
621  * \param resourcePath The path where application resources will be found
622  */
623 GLS_EXPORT void SetResourcePath( const char* resourcePath );
624 
625 /** Attempts to open the given file. Prepends the filename with the path from SetResourcePath
626  * for non-absolute paths.
627  * On Android, filenames that match an apk asset are opened. Opened assets should be closed
628  * with fclose to free resources, not with the Android Asset Manager close function (AAsset_close)
629  * \param filename The name of the file to open
630  * \param flags fopen style file arguments (e.g. "r")
631  * \pre On Android, Asset Manager != NULL, set with SetAssetManager, when opening an apk asset
632  * \return FILE pointer or NULL otherwise
633  */
634 GLS_EXPORT FILE* gls_fopen( const char* filename, const char* flags );
635 #else
636 /** Pushes a resource search path onto the stack. The CWD is always
637  * implicitly searched first. The resource search paths are local to
638  * the calling thread only. This function should be called from the same
639  * thread as the resources are loaded from.
640  * \param resourcePath The directory path to add to the search paths
641  */
642 GLS_EXPORT void PushResourcePath( const char* resourcePath );
643 
644 /** Remove the first search path from the stack. The resource search paths
645  * are local to the calling thread only. This function should be called from
646  * the same thread as the matching PushResourcePath.
647  */
648 GLS_EXPORT void PopResourcePath();
649 
650 /** Pushes a function that can locate resources. The Resources finders are applied after the resource paths are searched
651  * \param finder The function that can locate resources to add to the search paths
652  */
653 GLS_EXPORT void PushResourceFinder( std::string ( *finder )( const std::string& ) );
654 
655 /** Resolves the given path searching the resource path list. The
656  * CWD is always implicity searched first.
657  * \param path The relative path to resolve
658  */
659 GLS_EXPORT std::string ResolvePath( const char* path );
660 
661 // helper method taking a std::string
662 inline std::string ResolvePath( const std::string& path )
663 {
664  return ResolvePath( path.c_str() );
665 }
666 
667 /** Attempts to open the given file. Relative file paths
668  * are resolved using ResolvePath.
669  * \param filename The name of the file to open
670  * \param flags fopen style file arguments (e.g. "r")
671  * \return FILE pointer or NULL otherwise
672  */
673 GLS_EXPORT FILE* gls_fopen( const char* filename, const char* flags );
674 #endif
675 
676 #ifdef __APPLE__
677 /** \return a string indicating the location of a specific file in the default resource bundle.
678  * This method is designed for runtime platforms that have a pre-defined bundle
679  * location that is not immediately known to the application until runtime.
680  * in iOS, this returns the path to the main application bundle with the file name appended.
681  * \param fileName A string referring to the file without a path.
682  */
683 GLS_EXPORT std::string GetAbsolutePathAndFileNameInDefaultResourceBundle( const char* fileName );
684 #endif
685 
686 /** Prepends the resource path to a file name.
687  * \param[in] fileName The name of the file
688  * \return string containing ResourcePath + fileName, with OS specific path.
689  * On Android, apk asset files are not prepended with a path.
690  */
691 GLS_EXPORT std::string ResolveRuntimeResourcePath( const char* fileName );
692 
693 /** \return true if the file exists, false otherwise
694  * \param filename The filename to check
695  */
696 GLS_EXPORT bool FileExists( const char* filename );
697 GLS_EXPORT bool FileExists( const std::string& filename );
698 
699 /** \return true if the file exists and is a directory, false otherwise
700  * \param filename The filename to check
701  */
702 GLS_EXPORT bool IsDirectory( const char* filename );
703 GLS_EXPORT bool IsDirectory( const std::string& filename );
704 
705 /** \return The file extension for a filepath
706  * \param filepath Filepath to get extension from
707  */
708 GLS_EXPORT std::string FileExtension( const std::string& filepath );
709 
710 /** \return The filename from a file path by stripping off anything to the left of a slash
711  * \param filepath
712  */
713 GLS_EXPORT std::string FileName( const std::string& filepath );
714 
715 /** \return a string containing the path portion of a filename
716  * by stripping off everything to the right of the rightmost slash
717  * \param filepath A string containing a file with a path
718  */
719 GLS_EXPORT std::string FilePath( const std::string& filepath );
720 
721 /** \return a pointer to the string containing the path portion of a filename
722  * by stripping off everything to the right of the rightmost slash
723  * \param name A string containing a file with a path
724  * \warning If this function is called more than once all previous values WILL CHANGE to contain the newest value
725  * \deprecated Use FilePath instead
726  */
727 GLS_EXPORT const char* GetFilePath( const char* name );
728 
729 /** \return The filename from a file path by stripping off anything to the left of a slash
730  * \param name A string containing just the file name without a path
731  * \warning If this function is called more than once all previous values WILL CHANGE to contain the newest value
732  * \deprecated Use FileName instead
733  */
734 GLS_EXPORT char* GetFileName( const char* name );
735 
736 /** Appends a trailing slash to a path string, if one isn't there already
737  * \param s File path
738  */
739 GLS_EXPORT void AppendTrailingSlash( char* s );
740 
741 /** Appends a trailing slash to a path string, if one isn't there already
742  * \param s File path
743  */
744 GLS_EXPORT void AppendTrailingSlash( std::string& s );
745 
746 /** Convert a directory path to have the correct OS
747  * slashes /, or \. Also make sure that the path ends in a \, or /.
748  * So you always have the form <name 1>\\<name 2>...<name n>\\\, or <name 1>/<name 2>...<name n>/
749  * \param path A path to convert
750  * \return a "new-ed" string which may be longer than the original.
751  * It is the calling functions responsibility to free the memory.
752  */
753 GLS_EXPORT char* PathToOS( const char* path );
754 
755 /** \return The file extension for a filename
756  * \param filename Filename to get extension from
757  * No longer allocates memory, you can let the returned string
758  * be colected as it falls out of scope
759  */
760 GLS_EXPORT std::string GetExtension( const std::string& filename );
761 
762 /** Gets the file name from a filename with path
763  * It does not allocate new memory, but rather just returns
764  * a pointer inside the original string
765  */
766 GLS_EXPORT const char* GetBaseName( const char* path );
767 
768 /** \return Pointer to a position within the given \a path where the filename starts.
769  * \deprecated This function is not const-correct. Prefer the const-correct version.
770  * \sa GetBaseName( const char* )
771  */
772 GLS_EXPORT char* GetBaseName( char* path );
773 
774 /** Removes and double slashes from a path.
775  * It will look for the specified type of slash.
776  * It will modify path, but since it can only shrink,
777  * no allocation is done.
778  * \param path The path to operate on.
779  * \param slash The type of slash to search for.
780  */
781 GLS_EXPORT void RemoveDoubleSlashes( char* path, char slash = '/' );
782 
783 /** Remove possible extra spaces the user might enter in the server name input field.
784  * \param entry String to be manupulated.
785  */
786 GLS_EXPORT void RemoveSpaces( std::string& entry );
787 
788 /** \return The minimum angular distance between angle1 and angle2 in degrees
789  * \param angle1 First angle
790  * \param angle2 Second angle
791  */
792 GLS_EXPORT float AngularDistanceDeg( float angle1, float angle2 );
793 
794 /** \return The minimum angular distance between angle1 and angle2 in radians
795  * \param angle1 First angle
796  * \param angle2 Second angle
797  */
798 GLS_EXPORT float AngularDistanceRad( float angle1, float angle2 );
799 
800 GLS_EXPORT bool ContainsNonBlank( const std::string& val );
801 
802 GLS_EXPORT bool GetNoSpaces( FILE* f, char* result, int maxLen );
803 GLS_EXPORT bool GetToEnd( std::istream& instr, std::string& result, bool decode );
804 GLS_EXPORT bool GetVertex( std::istream& instr, Vertex* vert, bool getColor );
805 
806 /** Searches the specified binary file for the specified tag, and adds what immediatly follows the tag to the nameList.
807  * Returns true if at least one is found, false otherwise.
808  */
809 GLS_EXPORT bool GetComponentClassNames( const char* dllFileName, DynamicArray<std::string>& nameList, const char* createClassTag = "CreateComponent_" );
810 
811 /** Opens the DLL and attempts to run GlsDefaultClassName(), if found.
812  * Returns an empty string if not found. */
813 GLS_EXPORT std::string GetDefaultComponentClassName( const char* dllFileName );
814 
815 /** Returns the qualified instance name of an object that is
816  * contained within given DisplayFrame. (e.g "cockpit.altimeter.needle")
817  * Note that names are only added for each DisplayFrame (not every Group)
818  * and the name of the topFrame is not included in the qualified name.
819  * \param topFrame The frame in which the qualification will make sense.
820  * \param obj The object which is a direct child or located somewhere below topFrame.
821  * \returns The qualified instance name or an empty string if the qualified
822  * instance name could not be determined. */
823 GLS_EXPORT std::string GetQualifiedInstanceName( const DisplayFrame* topFrame, const DisplayObject* obj );
824 
825 #if !defined( GLES ) || defined( GLES_ANGLE )
826 GLS_EXPORT bool OpenFileDialog( Fl_Window* win, char* filePath, unsigned int filePathSize,
827  char* directory = NULL, const char* filterStr = NULL,
828  const char* defaultExt = NULL, const char* title = NULL,
829  bool multiSelect = false, bool createFile = false,
830  bool fileMustExist = false, bool pathMustExist = false,
831  bool noChangeDirectory = false );
832 
833 GLS_EXPORT bool SaveFileDialog( Fl_Window* win, char* filePath, unsigned int filePathSize,
834  char* directory = NULL, const char* filterStr = NULL,
835  const char* defaultExt = NULL, const char* title = NULL,
836  bool createFile = false,
837  bool fileMustExist = false, bool pathMustExist = false,
838  bool noChangeDirectory = false );
839 #endif
840 GLS_EXPORT void CheckGLError( void );
841 
842 //---------------------------------------------------------------------------
843 /**
844  * Returns a string which is the uppercase version of the passed parameter.
845  *
846  * \param str original string to convert to Uppercase
847  *
848  * \return a string copy of the original but in all caps.
849  */
850 GLS_EXPORT std::string Uppercase( const std::string& str );
851 
852 GLS_EXPORT std::string ReplaceEnvironmentVariables( const char* originalPath );
853 
854 /** A singleton used for accessing the command line arguments in generated code */
856 {
857 public:
858  GLS_EXPORT glsCommandLine();
859  GLS_EXPORT void ReadCommandLine( int argc, char** argv );
860  GLS_EXPORT void Usage();
861 
862  int _argc;
863  char** _argv;
864 
865  /** Whether or not the app should run in silent mode */
866  bool SilentMode() const { return _silentMode; }
867 
868  static GLS_EXPORT glsCommandLine* Instance();
869 
870 private:
871  bool _silentMode;
872  static ScopedPtr<glsCommandLine> _instance;
873 };
874 
875 /** Used to make interface information visible to the user at design time*/
876 class InterfaceDescriptionClass DISTI_FINAL
877 {
878  char* _code; // e.g. "DynamicRotate("
879  char* _usage; // e.g. "void DynamicRotate(float angle, int axis)"
880  char* _comment; // e.g. "Sets dynamic rotation in degrees for the specified axis"
881 
882 public:
883  GLS_EXPORT InterfaceDescriptionClass();
884  GLS_EXPORT InterfaceDescriptionClass( const char* code, const char* usage, const char* comment );
885 
886  GLS_EXPORT ~InterfaceDescriptionClass();
887  GLS_EXPORT InterfaceDescriptionClass( const InterfaceDescriptionClass& source );
888  GLS_EXPORT InterfaceDescriptionClass& operator=( const InterfaceDescriptionClass& source );
889 
890  GLS_EXPORT void Code( const char* );
891  GLS_EXPORT void Usage( const char* );
892  GLS_EXPORT void Comment( const char* );
893 
894  const char* Code() const { return _code; }
895  const char* Usage() const { return _usage; }
896  const char* Comment() const { return _comment; }
897 
898 #if defined( DISTI_HAS_RVAL_REFS )
899  InterfaceDescriptionClass( InterfaceDescriptionClass&& source )
900  : _code( NULL )
901  , _usage( NULL )
902  , _comment( NULL )
903  {
904  StealFrom( source );
905  }
906 
907  InterfaceDescriptionClass& operator=( InterfaceDescriptionClass&& source )
908  {
909  if( this != &source )
910  {
911  // Destroy current values
912  delete[] _code;
913  delete[] _usage;
914  delete[] _comment;
915 
916  StealFrom( source );
917  }
918  return *this;
919  }
920 
921 private:
922  void StealFrom( InterfaceDescriptionClass& source )
923  {
924  // Take ownership
925  _code = source._code;
926  _usage = source._usage;
927  _comment = source._comment;
928 
929  // Relieve of ownership
930  source._code = NULL;
931  source._usage = NULL;
932  source._comment = NULL;
933  }
934 #endif
935 };
936 
938 
939 /** Base class for GlsMultiVal template */
941 {
942 public:
943  virtual ~GlsMultiValBase() {}
944 
945  //These are used to avoid template problems with VC6.0
946  typedef std::ostream ostreamType;
947  typedef std::istream istreamType;
948 
949  virtual void StreamOut( ostreamType& outstr ) const = 0;
950  virtual void StreamIn( istreamType& instr ) = 0;
951 };
952 
953 /** GlsMultiVal is used to effectivly create a structure containing up
954  * to 10 values of varying types. An instance of the class is capable
955  * of streaming itself to and from a text stream. The individual values
956  * will be separated by spaces when written and read from the stream.
957  * The types have to follow some rules:
958  * - They must themselves have the << and >> stream operators defined.
959  * - operator>> must read all data written by operator<< and must not consume spaces or other characters that follow it
960  * - They must have a default constructor
961  * - They must have a copy constructor
962  * - They shall not be void* (it is used for determining the end of the desired types).
963  * - If a GlsPropString is used, there must be only one, and it *must* be the
964  * last entry in the GlsMultiVal instance.
965  * - A GlsPropStringQuoted will work in any position.
966  * This is intended primarily for the GL Studio end user to use as a Class Property type.
967  */
968 template<class T1,
969  class T2 = void*,
970  class T3 = void*,
971  class T4 = void*,
972  class T5 = void*,
973  class T6 = void*,
974  class T7 = void*,
975  class T8 = void*,
976  class T9 = void*,
977  class T10 = void*>
979 {
980  int _numVals;
981  void CalcNumVals()
982  {
983  _numVals = 1;
984  if( typeid( T2 ) != typeid( void* ) )
985  _numVals++;
986  else
987  return;
988  if( typeid( T3 ) != typeid( void* ) )
989  _numVals++;
990  else
991  return;
992  if( typeid( T4 ) != typeid( void* ) )
993  _numVals++;
994  else
995  return;
996  if( typeid( T5 ) != typeid( void* ) )
997  _numVals++;
998  else
999  return;
1000  if( typeid( T6 ) != typeid( void* ) )
1001  _numVals++;
1002  else
1003  return;
1004  if( typeid( T7 ) != typeid( void* ) )
1005  _numVals++;
1006  else
1007  return;
1008  if( typeid( T8 ) != typeid( void* ) )
1009  _numVals++;
1010  else
1011  return;
1012  if( typeid( T9 ) != typeid( void* ) )
1013  _numVals++;
1014  else
1015  return;
1016  if( typeid( T10 ) != typeid( void* ) )
1017  _numVals++;
1018  else
1019  return;
1020  }
1021 
1022 public:
1023  T1 _val1;
1024  T2 _val2;
1025  T3 _val3;
1026  T4 _val4;
1027  T5 _val5;
1028  T6 _val6;
1029  T7 _val7;
1030  T8 _val8;
1031  T9 _val9;
1032  T10 _val10;
1033 
1034  /** Default constructor.
1035  * The _val member types must have default constructors.
1036  */
1038  {
1039  CalcNumVals();
1040  }
1041 
1042  /** Copy constructor.
1043  * This GlsMultiVal will copy values from the src GlsMultiVal.
1044  * \param src GlsMultiVal object to use for initialization.
1045  * \return
1046  */
1047  GlsMultiVal( const GlsMultiVal& src )
1048  : _val1( src._val1 )
1049  , _val2( src._val2 )
1050  , _val3( src._val3 )
1051  , _val4( src._val4 )
1052  , _val5( src._val5 )
1053  , _val6( src._val6 )
1054  , _val7( src._val7 )
1055  , _val8( src._val8 )
1056  , _val9( src._val9 )
1057  , _val10( src._val10 )
1058  {
1059  CalcNumVals();
1060  }
1061  /** Full constructor. Creates a GlsMultiVal object with the provided data.
1062  * \param val1 First value to use for intialization of type T1.
1063  * \param val2 First value to use for intialization of type T2.
1064  * \param val3 First value to use for intialization of type T3.
1065  * \param val4 First value to use for intialization of type T4.
1066  * \param val5 First value to use for intialization of type T5.
1067  * \param val6 First value to use for intialization of type T6.
1068  * \param val7 First value to use for intialization of type T7.
1069  * \param val8 First value to use for intialization of type T8.
1070  * \param val9 First value to use for intialization of type T9.
1071  * \param val10 First value to use for intialization of type T10.
1072  * \return
1073  */
1075  const T1& val1,
1076  const T2& val2 = T2(),
1077  const T3& val3 = T3(),
1078  const T4& val4 = T4(),
1079  const T5& val5 = T5(),
1080  const T6& val6 = T6(),
1081  const T7& val7 = T7(),
1082  const T8& val8 = T8(),
1083  const T9& val9 = T9(),
1084  const T10& val10 = T10() )
1085  : _val1( val1 )
1086  , _val2( val2 )
1087  , _val3( val3 )
1088  , _val4( val4 )
1089  , _val5( val5 )
1090  , _val6( val6 )
1091  , _val7( val7 )
1092  , _val8( val8 )
1093  , _val9( val9 )
1094  , _val10( val10 )
1095  {
1096  CalcNumVals();
1097  }
1098 
1099  /** Compares two multival objects for equality */
1100  virtual bool operator==( const GlsMultiVal& val ) const
1101  {
1102  bool rval = true;
1103  // Only compare the number of used values.
1104  switch( _numVals )
1105  {
1106  // No breaks is intentional
1107  case 10: rval &= ( _val10 == val._val10 );
1108  case 9: rval &= ( _val9 == val._val9 );
1109  case 8: rval &= ( _val8 == val._val8 );
1110  case 7: rval &= ( _val7 == val._val7 );
1111  case 6: rval &= ( _val6 == val._val6 );
1112  case 5: rval &= ( _val5 == val._val5 );
1113  case 4: rval &= ( _val4 == val._val4 );
1114  case 3: rval &= ( _val3 == val._val3 );
1115  case 2: rval &= ( _val2 == val._val2 );
1116  case 1:
1117  rval &= ( _val1 == val._val1 );
1118  break;
1119  default:
1120  rval = false;
1121  }
1122  return rval;
1123  }
1124 
1125  /** Inverse of equality */
1126  virtual bool operator!=( const GlsMultiVal& val ) const
1127  {
1128  return !( *this == val );
1129  }
1130 
1131  /** StreamOut(). This function serializes itself into the provided stream object.
1132  * \param outstr This is the object used by the GlsMultiVal class to serialize itself onto.
1133  * \return
1134  */
1135  virtual void StreamOut( ostreamType& outstr ) const
1136  {
1137  outstr << _val1;
1138  if( _numVals >= 2 )
1139  outstr << " " << _val2;
1140  if( _numVals >= 3 )
1141  outstr << " " << _val3;
1142  if( _numVals >= 4 )
1143  outstr << " " << _val4;
1144  if( _numVals >= 5 )
1145  outstr << " " << _val5;
1146  if( _numVals >= 6 )
1147  outstr << " " << _val6;
1148  if( _numVals >= 7 )
1149  outstr << " " << _val7;
1150  if( _numVals >= 8 )
1151  outstr << " " << _val8;
1152  if( _numVals >= 9 )
1153  outstr << " " << _val9;
1154  if( _numVals >= 10 )
1155  outstr << " " << _val10;
1156  }
1157 
1158  /** StreamIn(). Uses the provided istream object to populate the current GlsMultiVal object
1159  * \param instr This is the stream object used by the GlsMultiVal instance to populate itself.
1160  * \return
1161  */
1162  virtual void StreamIn( istreamType& instr )
1163  {
1164  instr >> _val1;
1165  if( _numVals >= 2 )
1166  {
1167  instr.get(); // The separating space
1168  instr >> _val2;
1169  }
1170  if( _numVals >= 3 )
1171  {
1172  instr.get();
1173  instr >> _val3;
1174  }
1175  if( _numVals >= 4 )
1176  {
1177  instr.get();
1178  instr >> _val4;
1179  }
1180  if( _numVals >= 5 )
1181  {
1182  instr.get();
1183  instr >> _val5;
1184  }
1185  if( _numVals >= 6 )
1186  {
1187  instr.get();
1188  instr >> _val6;
1189  }
1190  if( _numVals >= 7 )
1191  {
1192  instr.get();
1193  instr >> _val7;
1194  }
1195  if( _numVals >= 8 )
1196  {
1197  instr.get();
1198  instr >> _val8;
1199  }
1200  if( _numVals >= 9 )
1201  {
1202  instr.get();
1203  instr >> _val9;
1204  }
1205  if( _numVals >= 10 )
1206  {
1207  instr.get();
1208  instr >> _val10;
1209  }
1210  }
1211 };
1212 
1213 GLS_EXPORT std::ostream& operator<<( std::ostream& outstr, const GlsMultiValBase& multiVal );
1214 GLS_EXPORT std::istream& operator>>( std::istream& instr, GlsMultiValBase& multiVal );
1215 
1216 /** GlsPropString is designed to be used as a string in GL Studio Class Properties.
1217  * It writes itself out as a single line, and will read in up to the next newline.
1218  * It will attempt to convert itself to and from std::strings.
1219  * If it is used in a GlsMultiVal, there must be only one, and it *must* be the
1220  * last entry in the GlsMultiVal instance.
1221  * See GlsPropStringQuoted for more usefulness in GlsMultiVal.
1222  */
1224 {
1225 public:
1226  std::string _string;
1227 
1228  /** Default constructor Creates an empty GlsPropString. */
1230  : _string( "" )
1231  {
1232  }
1233  /** Create a new GlsPropString using the provided std string.
1234  * \param str std::string to use to create the GlsPropString
1235  * \return
1236  */
1237  GlsPropString( const std::string& str )
1238  : _string( str )
1239  {
1240  }
1241 
1242  /** Create a new GlsPropString using the provided c-style string.
1243  * \param str c-style string to use to create the GlsPropString.
1244  * \return
1245  */
1246  GlsPropString( const char* str )
1247  : _string( str ? str : "" )
1248  {
1249  }
1250 
1251  operator std::string() const
1252  {
1253  return _string;
1254  }
1255 
1256  /** Get the string value for this object.
1257  * \return std::string containing the string value for this object.
1258  */
1259  std::string& String()
1260  {
1261  return _string;
1262  }
1263 
1264  /** Checks lexicographic equality of the two arguments */
1265  friend inline bool operator==( const GlsPropString& str1, const GlsPropString& str2 )
1266  {
1267  return str1._string == str2._string;
1268  }
1269 
1270  /** Checks lexicographic inequality of the two arguments */
1271  friend inline bool operator!=( const GlsPropString& str1, const GlsPropString& str2 )
1272  {
1273  return !( str1 == str2 );
1274  }
1275 };
1276 
1277 inline std::ostream& operator<<( std::ostream& outstr, const GlsPropString& str )
1278 {
1279  outstr << disti::C_EncodeString( str._string );
1280  return outstr;
1281 }
1282 inline std::istream& operator>>( std::istream& instr, GlsPropString& str )
1283 {
1284  std::string temp;
1285  disti::GetToEnd( instr, temp, false );
1286  str._string = disti::DecodeString( temp );
1287 
1288  return instr;
1289 }
1290 /** GlsPropStringQuoted is designed to be used as a string in GL Studio Class Properties.
1291  * It writes itself out as a single line surrounded with quotes (""), and will read in up to the next un-escaped quote.
1292  * It will attempt to convert itself to and from std::strings.
1293  * Use of GlsPropStringQuoted is preferred over GlsPropString for use in a GlsMultiVal.
1294  */
1296 {
1297 public:
1298  std::string _string;
1299 
1300  /** Default constructor, create an empty GlsPropStringQuoted object. */
1302  {
1303  }
1304  /** Constructor, create a new GlsPropStringQuoted object using the provided std::string object
1305  * \param str std::string object to use to create the GlsPropStringQuoted object
1306  * \return
1307  */
1308  GlsPropStringQuoted( const std::string& str )
1309  : _string( str )
1310  {
1311  }
1312  /** Constructor, create a new GlsPropStringQuoted object using the provided c-style string
1313  * \param str c-style string to use to create the GlsPropStringQuoted object
1314  * \return
1315  */
1316  GlsPropStringQuoted( const char* str )
1317  : _string( str )
1318  {
1319  }
1320 
1321  operator std::string() const
1322  {
1323  return _string;
1324  }
1325 
1326  std::string& String()
1327  {
1328  return _string;
1329  }
1330 
1331  bool operator==( const GlsPropStringQuoted& str ) const
1332  {
1333  return str._string == _string;
1334  }
1335 };
1336 
1337 inline std::ostream& operator<<( std::ostream& outstr, const GlsPropStringQuoted& str )
1338 {
1339  outstr << '\"' << disti::C_EncodeString( str._string ) << '\"';
1340  return outstr;
1341 }
1342 
1343 inline std::istream& operator>>( std::istream& instr, GlsPropStringQuoted& str )
1344 {
1345  std::string temp;
1346  str._string = "";
1347 
1348  // The next character should be a quote.
1349  // If it is not, we will attempt to do something useful anyway.
1350  if( instr.peek() != '\"' )
1351  {
1352  disti::GetToEnd( instr, temp, false );
1353  }
1354  else // Starts with quote
1355  {
1356  // Go ahead and consume the quote
1357  instr.get();
1358 
1359  int lastChar = 0;
1360  int currChar = 0;
1361  // Loop until we find an un-escaped quote or we run out of stream.
1362  while( instr.good() )
1363  {
1364  lastChar = currChar;
1365  currChar = instr.get();
1366  if( currChar != -1 )
1367  {
1368  if( currChar == '\"' && lastChar != '\\' )
1369  break; // We found the trailing quote
1370  temp += (char)currChar;
1371  }
1372  }
1373  }
1374 
1375  str._string = disti::DecodeString( temp );
1376 
1377  return instr;
1378 }
1379 
1380 #ifndef WIN32
1381 void SpawnBrowser( const char* url );
1382 #endif
1383 
1384 /** Call this to check for the availability of a DiSTI conrolled license.
1385  * It does not hold the license. It only checks it out and checks it back in.
1386  * \param licenseGroupName A name for what this license allows. i.e. "GL Studio Runtime".
1387  * \param feature The specific feature that will be checked out.
1388  * \param version The specific version that will be checked out.
1389  * \param quiet When true, no popup will occur upon missing license.
1390  */
1391 GLS_EXPORT bool CheckDistiLicense( const char* licenseGroupName, const char* feature, const char* version, bool quiet );
1392 
1393 /** This will set the m parameter to an orthographic projection.
1394  * The current value of m is ignored.
1395  * This does NOT make any OpenGL calls.
1396  */
1397 GLS_EXPORT void GlsGetOrtho( GlsMatrixType& m,
1398  double left,
1399  double right,
1400  double bottom,
1401  double top,
1402  double zNear,
1403  double zFar );
1404 
1405 /** This will set the m parameter to a perspective projection.
1406  * The current value of m is ignored
1407  * This does NOT make any OpenGL calls.
1408  */
1409 GLS_EXPORT void GlsGetPerspective( GlsMatrixType& m,
1410  double fovy,
1411  double aspect,
1412  double zNear,
1413  double zFar );
1414 
1415 // using a namespace to help avoid collisions with user code. Future functionality should prefer to go here
1416 namespace Util
1417 {
1418  ////////////////////////////////////////////////////////////////////////////////
1419  /// Clamps a value to the range [min, max]
1420  /// \param val The value to clamp
1421  /// \param min The minimum value in the range
1422  /// \param max The maximum value in the range
1423  ////////////////////////////////////////////////////////////////////////////////
1424  template<class T>
1425  T Clamp( const T& val, const T& min, const T& max )
1426  {
1427  return std::min( max, std::max( min, val ) );
1428  }
1429 
1430  ////////////////////////////////////////////////////////////////////////////////
1431  /// Split a string and add to existing vector of elements with delimeters removed.
1432  /// \param s The string to split
1433  /// \param delim The delimiter to split the string on.
1434  /// \param elems The vector of elements to append each split string to.
1435  /// \param maxElems The maximum number of elements to split. Remaining elements
1436  /// are appended unsplit as the last value. If 0, it does not
1437  /// have a maximum.
1438  /// \note Adapted from http://stackoverflow.com/questions/236129/split-a-string-in-c
1439  ////////////////////////////////////////////////////////////////////////////////
1440  inline void Split( const std::string& s, const char delim, std::vector<std::string>& elems, const std::size_t maxElems = 0 )
1441  {
1442  std::istringstream ss( s );
1443  std::string item;
1444  while( std::getline( ss, item, delim ) )
1445  {
1446  elems.push_back( DISTI_RVAL_MOVE( item ) );
1447  if( elems.size() == maxElems )
1448  {
1449  break;
1450  }
1451  }
1452  if( elems.size() == maxElems && ss.good() && maxElems > 0 )
1453  {
1454  std::string remainder;
1455  std::getline( ss, remainder, '\0' );
1456  elems.back() += delim + remainder;
1457  }
1458  }
1459 
1460  ////////////////////////////////////////////////////////////////////////////////
1461  /// Split a string return a vector of the elements with delimeters removed.
1462  /// \param s The string to split
1463  /// \param delim The delimiter to split the string on.
1464  /// \param maxElems The maximum number of elements to split. Remaining elements
1465  /// are appended unsplit as the last value. If 0, it does not
1466  /// have a maximum.
1467  /// \return The vector of split elements.
1468  /// \note Adapted from http://stackoverflow.com/questions/236129/split-a-string-in-c
1469  ////////////////////////////////////////////////////////////////////////////////
1470  inline std::vector<std::string> Split( const std::string& s, const char delim, const std::size_t maxElems = 0 )
1471  {
1472  std::vector<std::string> elems;
1473  Split( s, delim, elems, maxElems );
1474  return elems;
1475  }
1476 
1477  /// Passing null to std::string is not well-defined. Create a string safely.
1478  inline std::string MakeString( const char* const cStr )
1479  {
1480  return ( cStr ? cStr : "" );
1481  }
1482 } // namespace Util
1483 
1484 ///////////////////////////////////////////////////////////////////////////////////////////////////
1485 // Forward declarations for globals managed by GlsGlobals.
1486 class GlsFontMan;
1487 class IGlsStateManager;
1488 class List_c;
1489 class Mutex;
1490 class TextureLoaderList;
1491 
1492 /// Hold global objects so we can control order of destruction.
1494 {
1495 public:
1496  /// Singleton instance
1497  GLS_EXPORT static GlsGlobals& Instance();
1498 
1499  /// Gets the image list. \sa GetImageListMutex()
1500  GLS_EXPORT List_c& GetImageList();
1501 
1502  /// Gets the mutex for protecting the image list. \sa GetImageList()
1503  GLS_EXPORT Mutex& GetImageListMutex();
1504 
1505  /// Gets the global font manager.
1506  GLS_EXPORT GlsFontMan& GetFontMan();
1507 
1508  /// Gets the global state manager instance
1509  GLS_EXPORT IGlsStateManager& GetStateManager();
1510 
1511  /// Gets the global list of texture loaders
1512  GLS_EXPORT TextureLoaderList& GetTextureLoaders();
1513 
1514 private:
1515  // Order of objects is important here since they are destroyed in the reverse order listed
1516  ScopedPtr<List_c> _imageList;
1517  ScopedPtr<Mutex> _imageListMutex;
1518  ScopedPtr<GlsFontMan> _fontMan;
1519  ScopedPtr<IGlsStateManager> _stateManager;
1520  ScopedPtr<TextureLoaderList> _textureLoaders;
1521 
1522  GlsGlobals();
1523  GlsGlobals( const GlsGlobals& ) DISTI_SPECIAL_MEM_FUN_DELETE;
1524  void operator=( const GlsGlobals& ) DISTI_SPECIAL_MEM_FUN_DELETE;
1525 };
1526 
1527 // Check that bitness matches detected value
1528 namespace Detail
1529 {
1530  // We need this function because 'static_assert' replacements for pre-C++11 compilers cannot be at file scope.
1531  inline void _checkPointerSize()
1532  {
1533  // clang-format off
1534  DISTI_STATIC_ASSERT_STR( ( DISTI_IS_BITNESS( 64 ) && sizeof( void* ) == 8 )
1535  || ( DISTI_IS_BITNESS( 32 ) && sizeof( void* ) == 4 ),
1536  "Pointer size is unexpected for this bitness" );
1537  DISTI_STATIC_ASSERT_STR( DISTI_IS_BITNESS( 64 ) ^ DISTI_IS_BITNESS( 32 ), "Expected one bitness to be detected." );
1538  // clang-format on
1539  }
1540 } // namespace Detail
1541 } // namespace disti
1542 
1543 // Our own local versions of a few glu methods to avoid needing to include the GL Utility library
1544 GLS_EXPORT void glsPerspective( double fovy, double aspect, double zNear, double zFar );
1545 
1546 #ifdef MATRIX_TYPE_FLOAT
1547 GLS_EXPORT bool glsProject( double objx, double objy, double objz,
1548  const float modelMatrix[ 16 ],
1549  const float projMatrix[ 16 ],
1550  const int viewport[ 4 ],
1551  double* winx, double* winy, double* winz );
1552 
1553 GLS_EXPORT bool glsUnProject( double winx, double winy, double winz,
1554  const float modelMatrix[ 16 ],
1555  const float projMatrix[ 16 ],
1556  const int viewport[ 4 ],
1557  double* objx, double* objy, double* objz );
1558 #else
1559 GLS_EXPORT bool glsProject( double objx, double objy, double objz,
1560  const double modelMatrix[ 16 ],
1561  const double projMatrix[ 16 ],
1562  const int viewport[ 4 ],
1563  double* winx, double* winy, double* winz );
1564 
1565 GLS_EXPORT bool glsUnProject( double winx, double winy, double winz,
1566  const double modelMatrix[ 16 ],
1567  const double projMatrix[ 16 ],
1568  const int viewport[ 4 ],
1569  double* objx, double* objy, double* objz );
1570 #endif
1571 
1572 #endif
The DistiUnhideGlobalsDummyClass class.
const T & Min(const T &x, const T &y)
Definition: util.h:257
int EncodedStringMinLength()
GlsPropStringQuoted(const std::string &str)
Definition: util.h:1308
virtual void StreamOut(ostreamType &outstr) const
Definition: util.h:1135
#define DISTI_STATIC_ASSERT_STR(expr, msg)
Uses C++11's static_assert() because it is available on this platform.
Definition: gls_cpp_lang_support.h:384
std::string GetExtension(const std::string &filename)
Definition: vertex.h:409
GlsDefinedColorEnum
Definition: util.h:188
bool IS_NEGATIVE(const X &x)
Definition: util.h:133
const int INLINE_TEXTURE_LINE_LENGTH
Definition: util.h:115
Definition: util.h:1295
std::string & String()
Definition: util.h:1259
std::string FileExtension(const std::string &filepath)
void GlsGetPerspective(GlsMatrixType &m, double fovy, double aspect, double zNear, double zFar)
GlsPropString(const char *str)
Definition: util.h:1246
unsigned char glsDefinedColors[GLS_COLOR_MAX][4]
bool IsNearZero(X x)
Definition: util.h:152
virtual bool operator!=(const GlsMultiVal &val) const
Definition: util.h:1126
Definition: dynamic_array.h:66
The disti::DynamicArray class. A templated array of objects capable of dynamically growing...
Class to contain current OpenGL view, projection and draw matrices.
Definition: util.h:296
std::string FileName(const std::string &filepath)
const char * GetBaseName(const char *path)
bool VeryCloseToZero(X x)
Definition: util.h:148
int EncodeString(char *dest, const char *src, const int dest_str_length)
The GlsMatrixAffine class.
Definition: util.h:855
void AppendTrailingSlash(char *s)
Definition: util.h:978
GlsFontMan & GetFontMan()
Gets the global font manager.
void RemoveDoubleSlashes(char *path, char slash= '/')
Definition: texture_loader.h:55
bool CheckDistiLicense(const char *licenseGroupName, const char *feature, const char *version, bool quiet)
std::string GetQualifiedInstanceName(const DisplayFrame *topFrame, const DisplayObject *obj)
Hold global objects so we can control order of destruction.
Definition: util.h:1493
std::string GetDefaultComponentClassName(const char *dllFileName)
Definition: util.h:940
bool BETWEEN(const X &x, const X1 &x1, const X2 &x2)
Definition: util.h:125
GlsMultiVal()
Definition: util.h:1037
char * PathToOS(const char *path)
bool IS_ZERO(X x)
Definition: util.h:156
Definition: gls_state_manager_interface.h:67
void RemoveSpaces(std::string &entry)
float OpenGLVersion()
const T & Max(const T &x, const T &y)
Definition: util.h:268
virtual bool operator==(const GlsMultiVal &val) const
Definition: util.h:1100
GlsPropStringQuoted(const char *str)
Definition: util.h:1316
bool SilentMode() const
Definition: util.h:866
A file for all GL Studio files to include.
Mutex & GetImageListMutex()
Gets the mutex for protecting the image list.
int range_check(int num, double val,...)
std::ostream & operator<<(std::ostream &outstr, const AttributeName &name)
Defines the stream out operator.
bool GetObjectCoordinatesTransformSameView(DisplayObject *from, DisplayObject *to, GlsMatrixType *outTransform)
float AngularDistanceRad(float angle1, float angle2)
std::string Uppercase(const std::string &str)
void ChangeGlsDefinedColor(GlsDefinedColorEnum index, unsigned char red, unsigned char green, unsigned char blue, unsigned char alpha)
Definition: util.h:217
Definition: scoped_ptr.h:53
GlsPropString()
Definition: util.h:1229
void PopResourcePath()
bool GetComponentClassNames(const char *dllFileName, DynamicArray< std::string > &nameList, const char *createClassTag="CreateComponent_")
VertexNoColor Vector
Definition: gls_font_base.h:66
DisplayFrame * GetTopLevelDisplayFrame(DisplayFrame *frame)
GlsMatrixAffine< T > FindCoordinateTransformation(const Vector &new_origin, const Vector &new_i, const Vector &new_j, const Vector &new_k)
Definition: util.h:346
bool FindNonColinearVertices(int arraySize, Vector array[], int &index1, int &index2, int &index3, bool isVectorArray=true)
Definition: util.h:1223
bool GetObjectCoordinatesTransform(DisplayObject *from, DisplayObject *to, GlsMatrixType *outTransform)
int DecodeString(char *dest, const char *src, const int dest_str_length)
bool CalculateTexPointsFromTexCoords(DisplayObject *object)
TextureLoaderList & GetTextureLoaders()
Gets the global list of texture loaders.
Definition: gls_mutex.h:52
friend bool operator!=(const GlsPropString &str1, const GlsPropString &str2)
Definition: util.h:1271
Definition: util.h:538
The disti::Vertex class. A class for manipulating 3D vertices.
GlsMultiVal(const GlsMultiVal &src)
Definition: util.h:1047
void PushResourcePath(const char *resourcePath)
IGlsStateManager & GetStateManager()
Gets the global state manager instance.
void Translate(Type x, Type y, Type z)
Definition: gls_matrix_affine.h:198
bool FileExists(const char *filename)
int C_EncodeString(char *dest, const char *src, const int dest_str_length)
static GlsGlobals & Instance()
Singleton instance.
virtual void StreamIn(istreamType &instr)
Definition: util.h:1162
GlsMultiVal(const T1 &val1, const T2 &val2=T2(), const T3 &val3=T3(), const T4 &val4=T4(), const T5 &val5=T5(), const T6 &val6=T6(), const T7 &val7=T7(), const T8 &val8=T8(), const T9 &val9=T9(), const T10 &val10=T10())
Definition: util.h:1074
FILE * gls_fopen(const char *filename, const char *flags)
bool IsDirectory(const char *filename)
float AngularDistanceDeg(float angle1, float angle2)
std::string FilePath(const std::string &filepath)
Definition: gls_font_man.h:59
bool Equal(T1 x, T2 y, float precision=0.001f)
Definition: util.h:246
char * GetFileName(const char *name)
List_c & GetImageList()
Gets the image list.
bool NotColinear(const Vector &a, const Vector &b, const Vector &c)
const char * GetFilePath(const char *name)
Definition: vertex.h:84
std::string ResolveRuntimeResourcePath(const char *fileName)
void PushResourceFinder(std::string(*finder)(const std::string &))
A smart pointer with unique ownership – poor man's std::unique_ptr.
std::string ResolvePath(const char *path)
bool CloseToZero(const X x, const X threshold=X(1e-1))
Definition: util.h:141
friend bool operator==(const GlsPropString &str1, const GlsPropString &str2)
Definition: util.h:1265
Contains the DistiAssert macro.
Definition: util.h:876
Macros and helper code to determine what subset of C++11/14/17 is available.
void GlsGetOrtho(GlsMatrixType &m, double left, double right, double bottom, double top, double zNear, double zFar)
GlsPropString(const std::string &str)
Definition: util.h:1237
int Safe_fopen(const char *filename, char *flags, FILE **f)
unsigned char * GlsDefinedColor(GlsDefinedColorEnum index)
Definition: util.h:209
Definition: bmpimage.h:46
Definition: list.h:134
GlsPropStringQuoted()
Definition: util.h:1301
bool IS_POSITIVE(const X &x)
Definition: util.h:137