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