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