text:
#ifndef PHX_ArrayList
#define PHX_ArrayList
#define __FFI_IGNORE__

#include "PhxMemory.h"

/* --- ArrayList ---------------------------------------------------------------
 *
 *   A dynamic linear array with geometric allocation, yielding O(1) amortized
 *   append and O(1) random access (like std::vector).
 *
 *   Example idiomatic usage:
 *
 *     struct MyStruct {
 *       ArrayList(int, nums);
 *       ArrayList(double, roots);
 *       ...
 *     };
 *
 *     MyStruct* MyStruct_Create(...) {
 *       MyStruct* self = MemNew(MyStruct);
 *       ArrayList_Init(self->nums);
 *       ArrayList_Init(self->roots);
 *
 *       for (int i = 0; i < 100; ++i)
 *         ArrayList_Append(self->nums, i);
 *
 *       for (int i = 0; i < ArrayList_GetSize(self->nums); ++i) {
 *         int elem = ArrayList_Get(self->nums, i);
 *         ArrayList_Append(self->roots, Sqrt((double)elem));
 *       }
 *       ...
 *       return self;
 *    }
 *
 *    void MyStruct_Free(MyStruct* self) {
 *      ArrayList_Free(self->nums);
 *      ArrayList_Free(self->roots);
 *    }
 *
 * -------------------------------------------------------------------------- */

#define ArrayList(T, name)                                                     \
  int32 name##_size;                                                           \
  int32 name##_capacity;                                                       \
  T* name##_data

#define ArrayList_Init(name)                                                   \
  { name##_capacity = 0;                                                       \
    name##_size = 0;                                                           \
    name##_data = 0; }

#define ArrayList_Free(name)                                                   \
  MemFree(name##_data);

#define ArrayList_FreeEx(name, freeFn)                                         \
  { for (int i = 0; i < name##_size; ++i)                                      \
      freeFn(name##_data[i]);                                                  \
    MemFree(name##_data); }

#define ArrayList_FreeExPtr(name, freeFn)                                      \
  { for (int i = 0; i < name##_size; ++i)                                      \
      freeFn(name##_data + i);                                                 \
    MemFree(name##_data); }

#define ArrayList_Append(name, value)                                          \
  { ArrayList_Grow(name);                                                      \
    name##_data[name##_size++] = (value); }

#define ArrayList_ForEach(name, T, iter)                                       \
  for (T *iter = name##_data, *__iterend = name##_data + name##_size;          \
       iter < __iterend; ++iter)

#define ArrayList_ForEachI(name, index)                                        \
  for (int index = 0; index < name##_size; ++index)

#define ArrayList_ForEachReverse(name, T, iter)                                \
  for (T *iter = name##_data + name##_size - 1, *__iterbegin = name##_data;    \
       iter >= __iterbegin; --iter)

#define ArrayList_ForEachIReverse(name, index)                                 \
  for (int index = name##_size - 1; index >= 0; --index)

#define ArrayList_Grow(name)                                                   \
  IF_UNLIKELY (name##_capacity == name##_size) {                               \
    name##_capacity = name##_capacity ? name##_capacity * 2 : 1;               \
    size_t elemSize = sizeof(name##_data[0]);                                  \
    void** pData    = ((void**) &name##_data);                                 \
    *pData = MemRealloc(name##_data, name##_capacity * elemSize);              \
  }

#define ArrayList_Insert(name, value, index)                                   \
  { ArrayList_Grow(name);                                                      \
    if (i != name##_size - 1) {                                                \
      void*  curr     = name##_data + i + 0;                                   \
      void*  next     = name##_data + i + 1;                                   \
      size_t elemSize = sizeof(name##_data[0]);                                \
      MemMove(next, curr, (name##_size - 1 - i) * elemSize);                   \
    }                                                                          \
    name##_data[index] = (value);                                              \
    name##_size++; }

#define ArrayList_Pop(name)                                                    \
  --name##_size

#define ArrayList_PopRet(name)                                                 \
  name##_data[--name##_size]

#define ArrayList_RemoveAt(name, i)                                            \
  { if (i != name##_size - 1) {                                                \
      void*  curr     = name##_data + i + 0;                                   \
      void*  next     = name##_data + i + 1;                                   \
      size_t elemSize = sizeof(name##_data[0]);                                \
      MemMove(curr, next, (name##_size - 1 - i) * elemSize);                   \
    }                                                                          \
    name##_size--; }

#define ArrayList_RemoveAtFast(name, i)                                        \
  { name##_data[i] = name##_data[--name##_size]; }

#define ArrayList_Remove(name, elem)                                           \
  { for (int32 _i = 0; _i < name##_size; ++_i) {                               \
      IF_UNLIKELY (name##_data[_i] == elem) {                                  \
        if (_i != name##_size - 1) {                                           \
          void*  curr     = name##_data + _i + 0;                              \
          void*  next     = name##_data + _i + 1;                              \
          size_t elemSize = sizeof(name##_data[0]);                            \
          MemMove(curr, next, (name##_size - 1 - _i) * elemSize);              \
        }                                                                      \
        name##_size--;                                                         \
        break;                                                                 \
      }                                                                        \
  }}

#define ArrayList_RemoveWhere(name, T, predicate)                              \
  { for (int32 _i = 0; _i < name##_size; ++_i) {                               \
      T* x = &name##_data[_i];                                                 \
      IF_UNLIKELY (predicate) {                                                \
        for (int32 _j = _i; _j < name##_size - 1; ++_j)                        \
          name##_data[_j] = name##_data[_j + 1];                               \
        --name##_size;                                                         \
        break;                                                                 \
      }                                                                        \
  }}

#define ArrayList_RemoveFast(name, elem)                                       \
  { for (int32 _i = 0; _i < name##_size; ++_i) {                               \
      IF_UNLIKELY (name##_data[_i] == elem) {                                  \
        name##_data[_i] = name##_data[--name##_size];                          \
        break;                                                                 \
      }                                                                        \
  }}

#define ArrayList_RemoveLast(name)                                             \
  { IF_LIKELY (name##_size > 0)                                                \
    name##_size--; }

#define ArrayList_Reserve(name, n)                                             \
  { IF_LIKELY (name##_capacity < n) {                                          \
    name##_capacity = n;                                                       \
    size_t elemSize = sizeof(name##_data[0]);                                  \
    void** pData    = ((void**) &name##_data);                                 \
    *pData = MemRealloc(name##_data, name##_capacity * elemSize);              \
  }}

#define ArrayList_ZeroFill(name)                                               \
  size_t elemSize = sizeof(name##_data[0]);                                    \
  MemZero(name##_data, name##_capacity * elemSize);

#define ArrayList_Clear(name)          name##_size = 0
#define ArrayList_Get(name, index)     (name##_data[(index)])
#define ArrayList_GetData(name)        (name##_data)
#define ArrayList_GetPtr(name, index)  (name##_data + (index))
#define ArrayList_GetLast(name)        (name##_data[name##_size - 1])
#define ArrayList_GetLastPtr(name)     (name##_data + name##_size - 1)
#define ArrayList_GetCapacity(name)    (name##_capacity)
#define ArrayList_GetSize(name)        (name##_size)

#define ArrayList_Args(name)           name##_capacity, name##_size, name##_data
#define ArrayList_ArgsDef(name, T)     int32 name##_capacity, int32 name##_size, T* name##_data

#endif


text:
#ifndef PHX_WindowMode
#define PHX_WindowMode

#include "Common.h"

PHX_API const WindowMode WindowMode_AlwaysOnTop;
PHX_API const WindowMode WindowMode_Borderless;
PHX_API const WindowMode WindowMode_Fullscreen;
PHX_API const WindowMode WindowMode_Hidden;
PHX_API const WindowMode WindowMode_Maximized;
PHX_API const WindowMode WindowMode_Minimized;
PHX_API const WindowMode WindowMode_Resizable;
PHX_API const WindowMode WindowMode_Shown;

#endif

repo_name: JoshParnell/libphx

repo_language: C

mime_type: text/x-c++


text:
#ifndef PHX_HatDir
#define PHX_HatDir

/* TODO DEPRECATED : Remove this API */
#define __FFI_IGNORE__

#include "Common.h"

PHX_API const HatDir HatDir_Centered;
PHX_API const HatDir HatDir_Up;
PHX_API const HatDir HatDir_Right;
PHX_API const HatDir HatDir_Down;
PHX_API const HatDir HatDir_Left;
PHX_API const HatDir HatDir_RightUp;
PHX_API const HatDir HatDir_RightDown;
PHX_API const HatDir HatDir_LeftUp;
PHX_API const HatDir HatDir_LeftDown;

#endif


text:
#ifndef PHX_Physics
#define PHX_Physics

#include "Common.h"
#include "ArrayList.h"
#include "Vec3.h"

/* --- Physics -----------------------------------------------------------------
 *
 *   Ray/shape casts/overlaps will return RigidBodys but not Triggers.
 *
 *     Physics_Free             : Removes RigidBodys but does not free them.
 *     Physics_AddRigidBody     : Automatically adds all attached Triggers.
 *                                Automatically adds all attached children and
 *                                their Triggers.
 *     Physics_RemoveRigidBody  : Automatically removes all attached Triggers.
 *                                Automatically removes all attached children
 *                                and their Triggers.
 *     Physics_GetNextCollision : Will include results for both child and parent
 *                                RigidBodys that are colliding. Will not
 *                                include Triggers.
 *     Physics_SphereCast       : Results are unsorted and will include child
 *                                objects.
 *     Physics_BoxCast          : Results are unsorted and will include child
 *                                objects.
 *
 * -------------------------------------------------------------------------- */

struct Collision {
  int        index;
  int        count;
  RigidBody* body0;
  RigidBody* body1;
};

struct RayCastResult {
  RigidBody* body;
  Vec3f      norm;
  Vec3f      pos;
  float      t;
};

struct ShapeCastResult {
  ArrayList(RigidBody*, hits);
};

PHX_API Physics*  Physics_Create                  ();
PHX_API void      Physics_Free                    (Physics*);

PHX_API void      Physics_AddRigidBody            (Physics*, RigidBody*);
PHX_API void      Physics_RemoveRigidBody         (Physics*, RigidBody*);
PHX_API void      Physics_AddTrigger              (Physics*, Trigger*);
PHX_API void      Physics_RemoveTrigger           (Physics*, Trigger*);

PHX_API bool      Physics_GetNextCollision        (Physics*, Collision*);
PHX_API void      Physics_Update                  (Physics*, float dt);

PHX_API void      Physics_RayCast                 (Physics*, Ray*, RayCastResult*);
PHX_API void      Physics_SphereCast              (Physics*, Sphere*, ShapeCastResult*);
PHX_API void      Physics_BoxCast                 (Physics*, Vec3f* pos, Quat* rot, Vec3f* halfExtents, ShapeCastResult*);
PHX_API bool      Physics_SphereOverlap           (Physics*, Sphere*);
PHX_API bool      Physics_BoxOverlap              (Physics*, Vec3f* pos, Quat* rot, Vec3f* halfExtents);

PHX_API void      Physics_PrintProfiling          (Physics*);
PHX_API void      Physics_DrawBoundingBoxesLocal  (Physics*);
PHX_API void      Physics_DrawBoundingBoxesWorld  (Physics*);
PHX_API void      Physics_DrawTriggers            (Physics*);
PHX_API void      Physics_DrawWireframes          (Physics*);

PRIVATE void  Physics_FlushCachedRigidBodyData  (Physics*, RigidBody*);

#endif


text:
#ifndef PHX_Time
#define PHX_Time

#include "Common.h"

struct Time {
  int second;
  int minute;
  int hour;
  int dayOfWeek;
  int dayOfMonth;
  int dayOfYear;
  int month;
  int year;
};

PHX_API Time  Time_GetLocal  ();
PHX_API Time  Time_GetUTC    ();
PHX_API uint  Time_GetRaw    ();

#endif


text:
#ifndef PHX_WindowPos
#define PHX_WindowPos

#include "Common.h"

PHX_API const WindowPos WindowPos_Centered;
PHX_API const WindowPos WindowPos_Default;

#endif


text:
#ifndef PHX_Directory
#define PHX_Directory

#include "Common.h"

/* --- Directory ---------------------------------------------------------------
 *
 *   An iterator over the contents of the directory.
 *
 *   Directory_Open    : Returns 0 if opening dir fails
 *   Directory_GetNext : Returns 0 once the iterator has traversed all files
 *                     : Automatically skips . and ..
 *
 * -------------------------------------------------------------------------- */

PHX_API Directory*  Directory_Open        (cstr path);
PHX_API void        Directory_Close       (Directory*);
PHX_API cstr        Directory_GetNext     (Directory*);

PHX_API bool        Directory_Change      (cstr cwd);
PHX_API bool        Directory_Create      (cstr path);
PHX_API cstr        Directory_GetCurrent  ();
PHX_API bool        Directory_Remove      (cstr path);

#endif


text:
#ifndef PHX_GLMatrix
#define PHX_GLMatrix

#include "Common.h"
#include "Vec3.h"

PHX_API void     GLMatrix_Clear        ();
PHX_API void     GLMatrix_LookAt       (Vec3d const* eye, Vec3d const* at, Vec3d const* up);
PHX_API void     GLMatrix_Load         (Matrix* matrix);
PHX_API void     GLMatrix_ModeP        ();
PHX_API void     GLMatrix_ModeWV       ();
PHX_API Matrix*  GLMatrix_Get          ();
PHX_API void     GLMatrix_Mult         (Matrix* matrix);
PHX_API void     GLMatrix_Perspective  (double degreesFovY, double aspect, double zNear, double zFar);
PHX_API void     GLMatrix_Pop          ();
PHX_API void     GLMatrix_Push         ();
PHX_API void     GLMatrix_PushClear    ();
PHX_API void     GLMatrix_RotateX      (double rads);
PHX_API void     GLMatrix_RotateY      (double rads);
PHX_API void     GLMatrix_RotateZ      (double rads);
PHX_API void     GLMatrix_Scale        (double x, double y, double z);
PHX_API void     GLMatrix_Translate    (double x, double y, double z);

#endif


text:
#ifndef PHX_Math
#define PHX_Math

#include "Common.h"

#include <math.h>
#include <stdlib.h>

/* -- Float/Double ---------------------------------------------------------- */

const float  Tau         = 6.28318531f;
const float  Pi          = 3.14159265f;
const float  Pi2         = 1.57079633f;
const float  Pi4         = 0.785398163f;
const float  Pi6         = 0.523598776f;
const float  F32_EPSILON = 1.19209290e-07f;
const double F64_EPSILON = 2.2204460492503131e-16;

inline bool   Approx     (float a, float b);
inline float  Acos       (float t);
inline float  Asin       (float t);
inline float  Atan       (float t);
inline float  Atan       (float y, float x);
inline float  Ceil       (float t);
inline float  Cos        (float t);
inline float  Degrees    (float radians);
inline float  Exp        (float t);
inline float  Floor      (float t);
inline float  Fract      (float t);
inline float  Lerp       (float a, float b, float t);
inline float  Log        (float t);
inline float  Log        (float t, float b);
inline bool   NonZero    (float t);
inline float  Pow        (float t, float p);
inline float  Pow2       (float t);
inline float  Pow4       (float t);
inline float  Pow8       (float t);
inline float  Radians    (float degrees);
inline float  Round      (float t);
inline float  Round      (float t, int places);
inline float  Saturate   (float t);
inline float  SignPow    (float t, float p);
inline float  Sin        (float t);
inline float  Sqrt       (float t);
inline float  Step       (float t, float edge);
inline float  Tan        (float t);

/* -- Int/Float/Double  ----------------------------------------------------- */

inline int    Abs        (int t);
inline int    Clamp      (int t, int lower, int upper);
inline int    Clamp01    (int t);
inline int    ClampUnit  (int t);
inline int    Max        (int a, int b);
inline int    Min        (int a, int b);
inline int    Mod        (int i, int m);
inline int    Sign       (int t);

/*
 *   Functions suffixed with 'Signed' are signed:
 *     FnSigned (x, ...)              Sign(x) * Fn(Abs(x), ...)
 *
 *   Functions marked with ! are specialized variants of another function.
 *   Specializations are provided only when doing so affords a significant
 *   performance benefit. Thus, functions marked with ! should be preferred
 *   over their generic variants when applicable:
 *
 *       Fn
 *     ! FnBlah  <-- Strictly more efficient than Fn
 *
 *     ExpMap (x, p)                  1.0 - Exp(-Pow(Abs(x), p))
 *   ! ExpMap1 (x)                    ExpMap(x, 1)
 *   ! ExpMap2 (x)                    ExpMap(x, 2)
 *
 *     PowSigned (x, p)               Sign(x) * Pow(Abs(x), p)
 *
 *     Sign(x)                        |  1  x > 0
 *                                    |  0  x = 0
 *                                    | -1  x < 0
 *
 */

PHX_API double  Math_Bezier3        (double x, double, double, double);
PHX_API double  Math_Bezier4        (double x, double, double, double, double);
PHX_API double  Math_Clamp          (double x, double a, double b);
PHX_API double  Math_Clamp01        (double x);
PHX_API double  Math_ClampSafe      (double x, double a, double b);
PHX_API double  Math_ClampUnit      (double x);
PHX_API double  Math_ExpMap         (double x, double p);
PHX_API double  Math_ExpMapSigned   (double x, double p);
PHX_API double  Math_ExpMap1        (double x);
PHX_API double  Math_ExpMap1Signed  (double x);
PHX_API double  Math_ExpMap2        (double x);
PHX_API double  Math_ExpMap2Signed  (double x);
PHX_API double  Math_PowSigned      (double x, double p);
PHX_API double  Math_Round          (double x);
PHX_API double  Math_Sign           (double x);

/* -------------------------------------------------------------------------- */

/* Units. */
inline float Degrees (float radians) {
  return (180.0f / Pi) * radians;
}

inline double Degrees (double radians) {
  return (180.0 / Pi) * radians;
}

inline float Radians (float degrees) {
  return (Pi / 180.0f) * degrees;
}

inline double Radians (double degrees) {
  return (Pi / 180.0) * degrees;
}

/* General. */
inline int Abs (int t) {
  return t < 0 ? -t : t;
}

inline float Abs (float t) {
  return (float)fabs((double)t);
}

inline double Abs (double t) {
  return fabs(t);
}

inline bool Approx (float a, float b) {
  return fabs(a - b) < 1e-4;
}

inline bool Approx (double a, double b) {
  return fabs(a - b) < 1e-4;
}

inline float Ceil (float t) {
  return (float)ceil((double)t);
}

inline double Ceil (double t) {
  return ceil(t);
}

inline int Clamp (int t, int lower, int upper) {
  t = t > upper ? upper : t;
  t = t < lower ? lower : t;
  return t;
}

inline float Clamp (float t, float lower, float upper) {
  t = t > upper ? upper : t;
  t = t < lower ? lower : t;
  return t;
}

inline double Clamp (double t, double lower, double upper) {
  t = t > upper ? upper : t;
  t = t < lower ? lower : t;
  return t;
}

inline int Clamp01 (int t) {
  t = t > 1 ? 1 : t;
  t = t < 0 ? 0 : t;
  return t;
}

inline float Clamp01 (float t) {
  t = t > 1.0f ? 1.0f : t;
  t = t < 0.0f ? 0.0f : t;
  return t;
}

inline double Clamp01 (double t) {
  t = t > 1.0 ? 1.0 : t;
  t = t < 0.0 ? 0.0 : t;
  return t;
}

inline int ClampUnit (int t) {
  t = t >  1 ?  1 : t;
  t = t < -1 ? -1 : t;
  return t;
}

inline float ClampUnit (float t) {
  t = t >  1.0f ?  1.0f : t;
  t = t < -1.0f ? -1.0f : t;
  return t;
}

inline double ClampUnit (double t) {
  t = t >  1.0 ?  1.0 : t;
  t = t < -1.0 ? -1.0 : t;
  return t;
}

inline float Exp (float t) {
  return (float)exp((double)t);
}

inline double Exp (double t) {
  return exp(t);
}

inline float Floor (float t) {
  return (float)floor((double)t);
}

inline double Floor (double t) {
  return floor(t);
}

inline float Fract (float t) {
  return t - Floor(t);
}

inline double Fract (double t) {
  return t - Floor(t);
}

inline float Lerp (float a, float b, float t) {
  return a + t * (b - a);
}

inline double Lerp (double a, double b, double t) {
  return a + t * (b - a);
}

inline float Log (float t) {
  return (float)log((double)t);
}

inline double Log (double t) {
  return log(t);
}

inline float Log (float t, float b) {
  return Log(t) / Log(b);
}

inline double Log (double t, double b) {
  return Log(t) / Log(b);
}

inline uint32 Max (uint32 a, uint32 b) {
  return a > b ? a : b;
}

inline int Max (int a, int b) {
  return a > b ? a : b;
}

inline float Max (float a, float b) {
  return a > b ? a : b;
}

inline double Max (double a, double b) {
  return a > b ? a : b;
}

inline int Min (int a, int b) {
  return a < b ? a : b;
}

inline float Min (float a, float b) {
  return a < b ? a : b;
}

inline double Min (double a, double b) {
  return a < b ? a : b;
}

inline int Mod (int i, int m) {
  return i % m;
}

inline float Mod (float t, float m) {
  return (float)fmod((double)t, (double)m);
}

inline double Mod (double t, double m) {
  return fmod(t, m);
}

inline bool NonZero (float t) {
  return Abs(t) > F32_EPSILON;
}

inline bool NonZero (double t) {
  return Abs(t) > F64_EPSILON;
}

inline float Pow (float t, float p) {
  return (float)pow((double)t, (double)p);
}

inline double Pow (double t, double p) {
  return pow(t, p);
}

inline float Pow2 (float t) {
  return t * t;
}

inline double Pow2 (double t) {
  return t * t;
}

inline float Pow4 (float t) {
  float t2 = t * t;
  return t2 * t2;
}

inline double Pow4 (double t) {
  double t2 = t * t;
  return t2 * t2;
}

inline float Pow8 (float t) {
  float t2 = t * t;
  float t4 = t2 * t2;
  return t4 * t4;
}

inline double Pow8 (double t) {
  double t2 = t * t;
  double t4 = t2 * t2;
  return t4 * t4;
}

inline float Round (float t) {
  return Floor(t + 0.5f);
}

inline double Round (double t) {
  return Floor(t + 0.5);
}

inline float Round (float t, int places) {
  double factor = 10.0;
  for (int i = 0; i < places; ++i)
    factor *= 10.0;
  return (float)(Floor(factor * t + 0.5) / factor);
}

inline double Round (double t, int places) {
  double factor = 10.0;
  for (int i = 0; i < places; ++i)
    factor *= 10.0;
  return Floor(factor * t + 0.5) / factor;
}

inline float Saturate (float t) {
  return t < 0.0f ? 0.0f :
         t > 1.0f ? 1.0f :
         t;
}

inline double Saturate (double t) {
  return t < 0.0 ? 0.0 :
         t > 1.0 ? 1.0 :
         t;
}

inline int Sign (int t) {
  return t  > 0 ? 1 :
         t == 0 ? 0 : -1;
}

inline float Sign (float t) {
  return t  > 0.0f ? 1.0f :
         t == 0.0f ? 0.0f : -1.0f;
}

inline double Sign (double t) {
  return t  > 0.0 ? 1.0 :
         t == 0.0 ? 0.0 : -1.0;
}

inline float SignPow (float t, float p) {
  return Sign(t) * Pow(Abs(t), p);
}

inline double SignPow (double t, double p) {
  return Sign(t) * Pow(Abs(t), p);
}

inline float Step (float t, float edge) {
  return t < edge ? 0.0f : 1.0f;
}

inline double Step (double t, double edge) {
  return t < edge ? 0.0 : 1.0;
}

inline float Sqrt (float t) {
  return (float)sqrt((double)t);
}

inline double Sqrt (double t) {
  return sqrt(t);
}

/* Trig. */
inline float Acos (float t) {
  return (float)acos((double)t);
}

inline double Acos (double t) {
  return acos(t);
}

inline float Asin (float t) {
  return (float)asin((double)t);
}

inline double Asin (double t) {
  return asin(t);
}

inline float Atan (float t) {
  return (float)atan((double)t);
}

inline double Atan (double t) {
  return atan(t);
}

inline float Atan (float y, float x) {
  return (float)atan2((double)y, (double)x);
}

inline double Atan (double y, double x) {
  return atan2(y, x);
}

inline float Cos (float t) {
  return (float)cos((double)t);
}

inline double Cos (double t) {
  return cos(t);
}

inline float Sin (float t) {
  return (float)sin((double)t);
}

inline double Sin (double t) {
  return sin(t);
}

inline float Tan (float t) {
  return (float)tan((double)t);
}

inline double Tan (double t) {
  return tan(t);
}

#endif


text:
#define __FFI_IGNORE__
#if 0
#ifndef PHX_VR
#define PHX_VR

#include "Common.h"
#include "Vec2.h"

PHX_API const VRDeviceType VRDeviceType_Invalid;
PHX_API const VRDeviceType VRDeviceType_HMD;
PHX_API const VRDeviceType VRDeviceType_Controller;
PHX_API const VRDeviceType VRDeviceType_Tracker;
PHX_API const VRDeviceType VRDeviceType_Other;

PHX_API bool           VR_Exists              ();

PHX_API bool           VR_Init                ();
PHX_API void           VR_Free                ();

PHX_API Vec2i          VR_GetResolution       ();
PHX_API Matrix         VR_GetProjection       (int eye, double z0, double z1);
PHX_API Matrix         VR_GetEyeTransform     (int eye);

PHX_API int            VR_GetMaxAxis          ();
PHX_API int            VR_GetMaxButton        ();
PHX_API int            VR_GetMaxDevice        ();

PHX_API cstr           VR_GetDeviceName       (int index);
PHX_API Matrix         VR_GetDeviceTransform  (int index);
PHX_API VRDeviceType   VR_GetDeviceType       (int index);
PHX_API bool           VR_IsDeviceConnected   (int index);

PHX_API VRController*  VR_OpenController      (int index);
PHX_API void           VR_CloseController     (VRController*);

PHX_API Vec2d          VR_GetAxis             (VRController*, int button);
PHX_API bool           VR_GetButton           (VRController*, int button);
PHX_API void           VR_Vibrate             (VRController*, int axis, int microseconds);

PHX_API void           VR_GetTransforms       ();
PHX_API void           VR_Render              (int eye, Tex2D* texture);
#endif

#endif


text:
#ifndef PHX_PhysicsDefs
#define PHX_PhysicsDefs

#include "Bullet.h"
#include "Common.h"

typedef uint8 PhysicsType;
const PhysicsType PhysicsType_Null      = 0;
const PhysicsType PhysicsType_RigidBody = 1;
const PhysicsType PhysicsType_Trigger   = 2;

struct RigidBody {
  PhysicsType  type;
  btRigidBody* handle;         // Always references *this* object, even when part of a compound
  int          iShape;         // Always references *this* object, even when part of a compound
  int          collisionGroup; // Which group this object is part of
  int          collisionMask;  // Which other groups this object collides with
  float        mass;           // For GetMass and calculating inertia (mass is not stored in btRigidBody)

  int          iCompound;      // The index within the compound (-1 when not a compound)
  int          iCompoundShape; // The compound shape (-1 when not a compound)
  RigidBody*   parent;         // The parent object in the compound (null when not a compound)
  RigidBody*   next;           // The next object in the compound (null when this is the last child or not a compound)

  Physics*     physics;
  Trigger*     triggers;
  Matrix       mat;
};

struct Trigger {
  PhysicsType  type;
  GhostObject* handle;
  int          iShape;
  int          collisionGroup;
  int          collisionMask;

  RigidBody*   parent;
  Trigger*     next;
  btTransform  transformLocal;

  Physics*     physics;
};

#endif

/* NOTE : We have to store mass for GetMass and recalculating inertia. */
/* NOTE : We need access to all children to free when freeing a parent. */
/* NOTE : We need access to the parent to detch when freeing a child. */

/* NOTE : For 2 objects to collide the layer of each object must be present in
          the collidesWithLayers of the other object (i.e. it's symmetric). */


text:
#ifndef PHX_PhxConfig
#define PHX_PhxConfig

/* GLCHECK inserts a GL driver error query after every OpenGL call that can
 * set an error. Extremely slow but extremely effective at verifying correctness
 * of GL API usage. */
#define ENABLE_GLCHECK 0

/* The internal profiler has near-zero overhead, but turning it off can still
 * be useful to periodically ensure that frames are not causing overhead. */
#define ENABLE_PROFILER 1

/* Causes the internal profiler to produce a detailed event trace that can be
 * inspected by chrome://tracing. Producing trace output adds significant
 * overhead to each profiled frame, so trace output should be turned on only
 * when the output is actually needed. */
#define ENABLE_PROFILER_TRACE 0

/* TODO AB : Brief summary of this flag (hoisted from BSP.cpp) */
#define ENABLE_BSP_PROFILING 0

#endif


text:
#ifndef PHX_InputEvent
#define PHX_InputEvent

#include "Common.h"
#include "Device.h"

struct InputEvent {
  uint32 timestamp;
  Device device;
  Button button;
  float  value;
  State  state;
};

PHX_API cstr  InputEvent_ToString  (InputEvent*);

#endif


text:
#ifndef PHX_DataFormat
#define PHX_DataFormat

#include "Common.h"

/* --- DataFormat --------------------------------------------------------------
 *
 *   DataFormat_GetSize : Size in bytes of single element
 *
 * -------------------------------------------------------------------------- */

PHX_API const DataFormat DataFormat_U8;
PHX_API const DataFormat DataFormat_I8;
PHX_API const DataFormat DataFormat_U16;
PHX_API const DataFormat DataFormat_I16;
PHX_API const DataFormat DataFormat_U32;
PHX_API const DataFormat DataFormat_I32;
PHX_API const DataFormat DataFormat_Float;

PHX_API int  DataFormat_GetSize  (DataFormat);

#endif


text:
#ifndef PHX_MemStack
#define PHX_MemStack

#include "Common.h"

/* --- MemStack ----------------------------------------------------------------
 *
 *    Provides a fixed-size, stack-based allocator, allowing for nearly-instant
 *    alloc, dealloc, and clear. This is the fastest allocator, but has the
 *    strictest allocation pattern requirements.
 *
 *    Allocations MUST be properly paired, otherwise memory corruption will
 *    ensue. The last allocation must always be the first free, etc.
 *
 *    Note that freeing is not necessary if using clear, making this a good
 *    choice for intra-frame allocations, or any allocations with a bounded
 *    lifetime.
 *
 *    For a dynamically-sized version, use MemStackDynamic, which leverages
 *    multiple MemStacks to provide the same interface without requiring a
 *    pre-determined capacity.
 *
 * -------------------------------------------------------------------------- */

PHX_API MemStack* MemStack_Create  (uint32 capacity);
PHX_API void      MemStack_Free    (MemStack*);

PHX_API void*     MemStack_Alloc   (MemStack*, uint32 size);
PHX_API void      MemStack_Clear   (MemStack*);
PHX_API void      MemStack_Dealloc (MemStack*, uint32 size);

PHX_API bool      MemStack_CanAlloc     (MemStack*, uint32 size);
PHX_API uint32    MemStack_GetSize      (MemStack*);
PHX_API uint32    MemStack_GetCapacity  (MemStack*);
PHX_API uint32    MemStack_GetRemaining (MemStack*);

#endif


text:
#ifndef PHX_Tex1D
#define PHX_Tex1D

#include "Common.h"

/* --- API NOTES ---------------------------------------------------------------
 *
 *   This type is REFERENCE-COUNTED. See ../doc/RefCounted.txt for details.
 *
 * -------------------------------------------------------------------------- */

PHX_API Tex1D*     Tex1D_Create        (int size, TexFormat);
PHX_API void       Tex1D_Acquire       (Tex1D*);
PHX_API void       Tex1D_Free          (Tex1D*);

PHX_API void       Tex1D_Draw          (Tex1D*, float x, float y, float xs, float ys);
PHX_API void       Tex1D_GenMipmap     (Tex1D*);
PHX_API void       Tex1D_GetData       (Tex1D*, void*, PixelFormat, DataFormat);
PHX_API Bytes*     Tex1D_GetDataBytes  (Tex1D*, PixelFormat, DataFormat);
PHX_API TexFormat  Tex1D_GetFormat     (Tex1D*);
PHX_API uint       Tex1D_GetHandle     (Tex1D*);
PHX_API uint       Tex1D_GetSize       (Tex1D*);
PHX_API void       Tex1D_SetData       (Tex1D*, void const*, PixelFormat, DataFormat);
PHX_API void       Tex1D_SetDataBytes  (Tex1D*, Bytes*, PixelFormat, DataFormat);
PHX_API void       Tex1D_SetMagFilter  (Tex1D*, TexFilter);
PHX_API void       Tex1D_SetMinFilter  (Tex1D*, TexFilter);
PHX_API void       Tex1D_SetTexel      (Tex1D*, int x, float r, float g, float b, float a);
PHX_API void       Tex1D_SetWrapMode   (Tex1D*, TexWrapMode);

#endif


text:
#ifndef PHX_Ray
#define PHX_Ray

#include "Common.h"
#include "Vec3.h"

struct Ray {
  Vec3f p;
  Vec3f dir;
  float tMin;
  float tMax;
};

PHX_API void  Ray_GetPoint                       (Ray const*, float t, Vec3f* out);
PHX_API bool  Ray_IntersectPlane                 (Ray const*, Plane const*, Vec3f* pHit);
PHX_API bool  Ray_IntersectTriangle_Barycentric  (Ray const*, Triangle const*, float tEpsilon, float* tHit);
PHX_API bool  Ray_IntersectTriangle_Moller1      (Ray const*, Triangle const*, float* tHit);
PHX_API bool  Ray_IntersectTriangle_Moller2      (Ray const*, Triangle const*, float* tHit);

PHX_API void  Ray_ToLineSegment                  (Ray const*, LineSegment*);
PHX_API void  Ray_FromLineSegment                (LineSegment const*, Ray*);

#endif


text:
#ifndef PHX_Vertex
#define PHX_Vertex

#include "Common.h"
#include "Vec2.h"
#include "Vec3.h"

struct Vertex {
  Vec3f p;
  Vec3f n;
  Vec2f uv;
};

#endif


text:
#ifndef PHX_TexCube
#define PHX_TexCube

#include "Common.h"

/* --- API NOTES ---------------------------------------------------------------
 *
 *   This type is REFERENCE-COUNTED. See ../doc/RefCounted.txt for details.
 *
 * -------------------------------------------------------------------------- */

PHX_API TexCube*   TexCube_Create        (int size, TexFormat);
PHX_API TexCube*   TexCube_Load          (cstr path);
PHX_API void       TexCube_Acquire       (TexCube*);
PHX_API void       TexCube_Free          (TexCube*);

PHX_API void       TexCube_Clear         (TexCube*, float r, float g, float b, float a);
PHX_API void       TexCube_Generate      (TexCube*, ShaderState*);
PHX_API TexCube*   TexCube_GenIRMap      (TexCube*, int samples);
PHX_API void       TexCube_GenMipmap     (TexCube*);
PHX_API void       TexCube_GetData       (TexCube*, void*, CubeFace, int level, PixelFormat, DataFormat);
PHX_API Bytes*     TexCube_GetDataBytes  (TexCube*, CubeFace, int level, PixelFormat, DataFormat);
PHX_API TexFormat  TexCube_GetFormat     (TexCube*);
PHX_API uint       TexCube_GetHandle     (TexCube*);
PHX_API int        TexCube_GetSize       (TexCube*);
PHX_API void       TexCube_SetData       (TexCube*, void const*, CubeFace, int level, PixelFormat, DataFormat);
PHX_API void       TexCube_SetDataBytes  (TexCube*, Bytes*, CubeFace, int level, PixelFormat, DataFormat);
PHX_API void       TexCube_SetMagFilter  (TexCube*, TexFilter);
PHX_API void       TexCube_SetMinFilter  (TexCube*, TexFilter);

PHX_API void       TexCube_Save          (TexCube*, cstr path);
PHX_API void       TexCube_SaveLevel     (TexCube*, cstr path, int level);

#endif


text:
#ifndef PHX_Audio
#define PHX_Audio

#include "Common.h"

PHX_API void        Audio_Init               ();
PHX_API void        Audio_Free               ();

PHX_API void        Audio_AttachListenerPos  (Vec3f const* pos, Vec3f const* vel, Vec3f const* fwd, Vec3f const* up);
PHX_API void        Audio_Set3DSettings      (float doppler, float scale, float rolloff);
PHX_API void        Audio_SetListenerPos     (Vec3f const* pos, Vec3f const* vel, Vec3f const* fwd, Vec3f const* up);
PHX_API void        Audio_Update             ();

/* --- Debug API ------------------------------------------------------------ */

PHX_API int32       Audio_GetLoadedCount     ();
PHX_API int32       Audio_GetPlayingCount    ();
PHX_API int32       Audio_GetTotalCount      ();

/* --- Private API ---------------------------------------------------------- */

PRIVATE void*       Audio_GetHandle          ();
PRIVATE SoundDesc*  Audio_AllocSoundDesc     (cstr name);
PRIVATE void        Audio_DeallocSoundDesc   (SoundDesc*);
PRIVATE Sound*      Audio_AllocSound         ();
PRIVATE void        Audio_DeallocSound       (Sound*);
PRIVATE void        Audio_SoundStateChanged  (Sound*);

#endif

/* NOTE : Primary */
/* TODO : Implement the FMOD Studio API and test with an FMOD project */
/* TODO : Investigate Oculus' HRTF */

/* NOTE : Secondary */
/* TODO : What happens when there is no audio device or the audio device is disconnected? */
/* TODO : Finish Sound_ToFile */
/* TODO : Where is CoInitialize being called? I don't see a warning from FMOD */
/* TODO : Respect the default device if it changes at runtime. This can't be done
 *        with FMOD alone. We'll need to detect default device changes some other way.
 *        http://www.fmod.org/questions/question/detecting-playback-device-change-in-windows/ */

/* NOTE : If we ever decide to use streams or internet sounds all sound APIs
 *        must be carefully updated to support it. In those cases channels have
 *        additional open states that we don't currently handle. */


text:
#ifndef PHX_Shader
#define PHX_Shader

#include "Common.h"

/* --- API NOTES ---------------------------------------------------------------
 *
 *   This type is REFERENCE-COUNTED. See ../doc/RefCounted.txt for details.
 *
 * -------------------------------------------------------------------------- */

PHX_API Shader*       Shader_Create         (cstr vertCode, cstr fragCode);
PHX_API Shader*       Shader_Load           (cstr vertName, cstr fragName);
PHX_API void          Shader_Acquire        (Shader*);
PHX_API void          Shader_Free           (Shader*);
PHX_API ShaderState*  Shader_ToShaderState  (Shader*);

PHX_API void          Shader_Start          (Shader*);
PHX_API void          Shader_Stop           (Shader*);

PHX_API uint          Shader_GetHandle      (Shader*);
PHX_API int           Shader_GetVariable    (Shader*, cstr);
PHX_API bool          Shader_HasVariable    (Shader*, cstr);

PHX_API void          Shader_ClearCache     ();
PHX_API void          Shader_SetFloat       (cstr, float);
PHX_API void          Shader_SetFloat2      (cstr, float, float);
PHX_API void          Shader_SetFloat3      (cstr, float, float, float);
PHX_API void          Shader_SetFloat4      (cstr, float, float, float, float);
PHX_API void          Shader_SetInt         (cstr, int);
PHX_API void          Shader_SetMatrix      (cstr, Matrix*);
PHX_API void          Shader_SetMatrixT     (cstr, Matrix*);
PHX_API void          Shader_SetTex1D       (cstr, Tex1D*);
PHX_API void          Shader_SetTex2D       (cstr, Tex2D*);
PHX_API void          Shader_SetTex3D       (cstr, Tex3D*);
PHX_API void          Shader_SetTexCube     (cstr, TexCube*);

PHX_API void          Shader_ISetFloat      (int, float);
PHX_API void          Shader_ISetFloat2     (int, float, float);
PHX_API void          Shader_ISetFloat3     (int, float, float, float);
PHX_API void          Shader_ISetFloat4     (int, float, float, float, float);
PHX_API void          Shader_ISetInt        (int, int);
PHX_API void          Shader_ISetMatrix     (int, Matrix*);
PHX_API void          Shader_ISetMatrixT    (int, Matrix*);
PHX_API void          Shader_ISetTex1D      (int, Tex1D*);
PHX_API void          Shader_ISetTex2D      (int, Tex2D*);
PHX_API void          Shader_ISetTex3D      (int, Tex3D*);
PHX_API void          Shader_ISetTexCube    (int, TexCube*);
#endif


text:
#ifndef PHX_Metric
#define PHX_Metric

#include "Common.h"

/* --- API NOTES ---------------------------------------------------------------
 *
 *   The Metric API is a simple set of accumulators that engine functions may
 *   call to provide information relevent to performance profiling and
 *   debugging. Metrics are reset each frame in Engine_Update, hence provide
 *   only instantaneous information.
 *
 *   Metrics are quantities that only code internal to the engine can change
 *   (e.g., a Lua script cannot draw a polygon without passing through
 *   Draw_*, Mesh_Draw*, etc). Hence, all functions that modify metrics are
 *   private.
 *
 *   Metric_Reset is called automatically in Engine_Update, so that metrics
 *   are per-frame.
 *
 *     DrawCalls  : # gl_Draw* calls. glBegin/glEnd does not count.
 *     Immediate  : # glBegin/glEnd pairs.
 *     PolysDrawn : # polys drawn. gl_Begin(GL_QUADS) et al. should report the
 *                  number of *polygons*, not triangles!
 *
 *     TrisDrawn  : # tris drawn. Non-tri draw calls should report
 *                  #verts - 2, e.g. number of tris required for convex
 *                  decomposition.
 *
 *     VertsDrawn : # verts *referenced* in draw calls. Buffered draws could
 *                  report only the size of the vertex buffer! Immediate
 *                  mode should report # calls to glVertex*.
 *
 *     Flush      : An *upper bound* on pipeline flushes. Each call that can
 *                  cause a flush should increment this metric.
 *
 *     FBOSwap    : # glBindFramebuffer calls. Each call should be reported.
 *                  In the future, we will introduce a new metric to report #
 *                  of validation-inducing bind calls, but this will only be
 *                  relevant once fbo caching is implemented.
 *
 * -------------------------------------------------------------------------- */

const Metric Metric_None       = 0x0;
const Metric Metric_DrawCalls  = 0x1;
const Metric Metric_Immediate  = 0x2;
const Metric Metric_PolysDrawn = 0x3;
const Metric Metric_TrisDrawn  = 0x4;
const Metric Metric_VertsDrawn = 0x5;
const Metric Metric_Flush      = 0x6;
const Metric Metric_FBOSwap    = 0x7;
const Metric Metric_SIZE       = 0x7;

PHX_API int32  Metric_Get         (Metric);
PHX_API cstr   Metric_GetName     (Metric);

/* --- Private API ---------------------------------------------------------- */

PRIVATE void   Metric_Inc         (Metric);
PRIVATE void   Metric_Mod         (Metric, int32);
PRIVATE void   Metric_Reset       ();

PRIVATE void   Metric_AddDraw     (int32 polys, int32 tris, int32 verts);
PRIVATE void   Metric_AddDrawImm  (int32 polys, int32 tris, int32 verts);

#endif


text:
#ifndef PHX_Mesh
#define PHX_Mesh

#include "Common.h"

/* --- Mesh --------------------------------------------------------------------
 *
 *   This type is REFERENCE-COUNTED. See ../doc/RefCounted.txt for details.
 *   This type is VERSIONED. See ../doc/Versioned.txt for details.
 *
 *   The draw functions allow explicit binding and unbinding of a mesh's
 *   internal buffers. Explicit binding should be used when the same mesh must
 *   be drawn many times. It is unnecessary when a mesh will be drawn only once.
 *
 *     Mesh_DrawBind   : Binds internal buffers
 *     Mesh_DrawBound  : Assumes buffers have already been bound with DrawBind
 *     Mesh_DrawUnbind : Unbinds internal buffers; must be paired with DrawBind
 *                       call after draw operations are finished
 *     Mesh_Draw       : Equivalent to DrawBind -> DrawBound -> DrawUnbind
 *
 *   The following informational functions are computed lazily and cached
 *   according to the mesh version. Keeping an external cache is therefore
 *   redundant.
 *
 *     Mesh_GetBound  : Returns local AABB.
 *     Mesh_GetCenter : Returns the center of the mesh's AABB.
 *                      NOTE : In general, NOT equivalent to the centroid of
 *                      vertex positions! Equivalent to getting the center of
 *                      Mesh_GetBound.
 *     Mesh_GetRadius : Returns the radius of the minimal bounding sphere
 *                      with origin at the center of the local AABB.
 *                      NOTE : In general, NOT equivalent to minimal bounding
 *                             sphere radius; although usually a very good
 *                             approximation.
 *
 * -------------------------------------------------------------------------- */

PHX_API Mesh*    Mesh_Create             ();
PHX_API void     Mesh_Acquire            (Mesh*);
PHX_API void     Mesh_Free               (Mesh*);

PHX_API Mesh*    Mesh_Load               (cstr name);
PHX_API Mesh*    Mesh_Clone              (Mesh*);
PHX_API Bytes*   Mesh_ToBytes            (Mesh*);
PHX_API Mesh*    Mesh_FromBytes          (Bytes*);
PHX_API Mesh*    Mesh_FromObj            (cstr);
PHX_API Mesh*    Mesh_FromSDF            (SDF*);

PHX_API void     Mesh_AddIndex           (Mesh*, int);
PHX_API void     Mesh_AddMesh            (Mesh*, Mesh*);
PHX_API void     Mesh_AddQuad            (Mesh*, int, int, int, int);
PHX_API void     Mesh_AddTri             (Mesh*, int, int, int);
PHX_API void     Mesh_AddVertex          (Mesh*, float px, float py, float pz,
                                                 float nx, float ny, float nz,
                                                 float u, float v);
PHX_API void     Mesh_AddVertexRaw       (Mesh*, Vertex const*);

PHX_API uint64   Mesh_GetVersion         (Mesh*);
PHX_API void     Mesh_IncVersion         (Mesh*);

PHX_API void     Mesh_GetBound           (Mesh*, Box3f* out);
PHX_API void     Mesh_GetCenter          (Mesh*, Vec3f* out);
PHX_API int      Mesh_GetIndexCount      (Mesh*);
PHX_API int*     Mesh_GetIndexData       (Mesh*);
PHX_API float    Mesh_GetRadius          (Mesh*);
PHX_API Vertex*  Mesh_GetVertex          (Mesh*, int);
PHX_API int      Mesh_GetVertexCount     (Mesh*);
PHX_API Vertex*  Mesh_GetVertexData      (Mesh*);
PHX_API void     Mesh_ReserveIndexData   (Mesh*, int capacity);
PHX_API void     Mesh_ReserveVertexData  (Mesh*, int capacity);
PHX_API Error    Mesh_Validate           (Mesh*);

PHX_API void     Mesh_Draw               (Mesh*);
PHX_API void     Mesh_DrawBind           (Mesh*);
PHX_API void     Mesh_DrawBound          (Mesh*);
PHX_API void     Mesh_DrawUnbind         (Mesh*);
PHX_API void     Mesh_DrawNormals        (Mesh*, float scale);

PHX_API Mesh*    Mesh_Center             (Mesh*);
PHX_API Mesh*    Mesh_Invert             (Mesh*);
PHX_API Mesh*    Mesh_RotateX            (Mesh*, float rads);
PHX_API Mesh*    Mesh_RotateY            (Mesh*, float rads);
PHX_API Mesh*    Mesh_RotateZ            (Mesh*, float rads);
PHX_API Mesh*    Mesh_RotateYPR          (Mesh*, float yaw, float pitch, float roll);
PHX_API Mesh*    Mesh_Scale              (Mesh*, float x, float y, float z);
PHX_API Mesh*    Mesh_ScaleUniform       (Mesh*, float);
PHX_API Mesh*    Mesh_Transform          (Mesh*, Matrix*);
PHX_API Mesh*    Mesh_Translate          (Mesh*, float x, float y, float z);

PHX_API void     Mesh_ComputeAO          (Mesh*, float radius);
PHX_API void     Mesh_ComputeOcclusion   (Mesh*, Tex3D* sdf, float radius);
PHX_API void     Mesh_ComputeNormals     (Mesh*);
PHX_API void     Mesh_SplitNormals       (Mesh*, float minDot);

#endif

/* TODO : Mesh_LoadObj */


text:
#ifndef PHX_GUID
#define PHX_GUID

#include "Common.h"

PHX_API uint64  GUID_Create  ();
PHX_API bool    GUID_Exists  (uint64);
PHX_API void    GUID_Reset   ();

#endif


text:
#ifndef PHX_TexFilter
#define PHX_TexFilter

#include "Common.h"

PHX_API const TexFilter TexFilter_Point;
PHX_API const TexFilter TexFilter_PointMipPoint;
PHX_API const TexFilter TexFilter_PointMipLinear;
PHX_API const TexFilter TexFilter_Linear;
PHX_API const TexFilter TexFilter_LinearMipPoint;
PHX_API const TexFilter TexFilter_LinearMipLinear;

#endif


text:
#ifndef PHX_Timer
#define PHX_Timer

#include "Common.h"

PHX_API Timer*  Timer_Create();
PHX_API void    Timer_Free         (Timer*);

PHX_API double  Timer_GetAndReset  (Timer*);
PHX_API double  Timer_GetElapsed   (Timer*);
PHX_API void    Timer_Reset        (Timer*);

#endif


text:
#ifndef PHX_UIRenderer
#define PHX_UIRenderer

#include "Common.h"

PHX_API void UIRenderer_Begin ();
PHX_API void UIRenderer_End   ();
PHX_API void UIRenderer_Draw  ();

PHX_API void UIRenderer_BeginLayer (float x, float y, float sx, float sy, bool clip);
PHX_API void UIRenderer_EndLayer   ();

PHX_API void UIRenderer_Image (Tex2D*, float x, float y, float sx, float sy);

PHX_API void UIRenderer_Panel (float x, float y, float sx, float sy,
                               float r, float g, float b, float a,
                               float bevel, float innerAlpha);

PHX_API void UIRenderer_Rect  (float x, float y, float sx, float sy,
                               float r, float g, float b, float a,
                               bool outline);

PHX_API void UIRenderer_Text  (Font* font, cstr text, float x, float y,
                               float r, float g, float b, float a);

#endif


text:
#ifndef PHX_Vec4
#define PHX_Vec4

#include "Common.h"
#include "Error.h"
#include "PhxFloat.h"
#include "Vec2.h"
#include "Vec3.h"

/* TODO : Replace as macro-free C using codegen. */

#define UNPACK4(v) (v).x, (v).y, (v).z, (v).w
#define REPEAT4(v) (v), (v), (v), (v)

struct Vec4i { int x, y, z, w; };
struct Vec4f { float x, y, z, w; };
struct Vec4d { double x, y, z, w; };

#define Vec4_Create(T, sub) inline T T##_Create(sub x, sub y, sub z, sub w) { \
  T self = { x, y, z, w }; return self; }

Vec4_Create(Vec4i, int)
Vec4_Create(Vec4d, double)
Vec4_Create(Vec4f, float)

#define Vec4_Abs(T) inline T T##_Abs(T v) { \
  T self = { Abs(v.x), Abs(v.y), Abs(v.z), Abs(v.w) }; return self; }

Vec4_Abs(Vec4i)
Vec4_Abs(Vec4f)
Vec4_Abs(Vec4d)

#define Vec4_IAbs(T) inline void T##_Abs(T* v) { \
  v->x = Abs(v->x); v->y = Abs(v->y); v->z = Abs(v->z); v->w = Abs(v->w); }

Vec4_IAbs(Vec4i)
Vec4_IAbs(Vec4f)
Vec4_IAbs(Vec4d)

#define Vec4_Equal(T) inline bool T##_Equal(T a, T b) { \
  return a.x == b.x && a.y == b.y && a.z == b.z && a.w == b.w; }

Vec4_Equal(Vec4i) Vec4_Equal(Vec4f) Vec4_Equal(Vec4d)

#define Vec4_Sub(T) inline T T##_Sub(T a, T b) { \
  T self = { a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w }; return self; }

Vec4_Sub(Vec4i) Vec4_Sub(Vec4d) Vec4_Sub(Vec4f)

#define Vec4_To3(T, TSub, CSub) inline TSub T##_To##TSub(T a) { \
  TSub self = { (CSub) a.x, (CSub) a.y, (CSub) a.z, }; return self; }

Vec4_To3(Vec4i, Vec3f, float)
Vec4_To3(Vec4i, Vec3d, double)
Vec4_To3(Vec4d, Vec3i, int)
Vec4_To3(Vec4d, Vec3f, float)
Vec4_To3(Vec4f, Vec3i, int)
Vec4_To3(Vec4f, Vec3d, double)

#define Vec4_XYZ(T, U) inline U T##_XYZ(T a) { \
  U self = { a.x, a.y, a.z }; return self; }

Vec4_XYZ(Vec4i, Vec3i)
Vec4_XYZ(Vec4d, Vec3d)
Vec4_XYZ(Vec4f, Vec3f)

#define Vec4_XY(T, U) inline U T##_XY(T a) { U self = { a.x, a.y }; return self; }
#define Vec4_ZW(T, U) inline U T##_ZW(T a) { U self = { a.z, a.w }; return self; }

Vec4_XY(Vec4i, Vec2i)
Vec4_ZW(Vec4i, Vec2i)
Vec4_XY(Vec4d, Vec2d)
Vec4_ZW(Vec4d, Vec2d)
Vec4_XY(Vec4f, Vec2f)
Vec4_ZW(Vec4f, Vec2f)

#define Vec4_Validate(T, sub) inline Error T##_Validate(T v) { \
  Error e = Error_None; \
  e |= Float_Validate(v.x); \
  e |= Float_Validate(v.y); \
  e |= Float_Validate(v.z); \
  e |= Float_Validate(v.w); \
  return e; }

Vec4_Validate(Vec4f, float)
Vec4_Validate(Vec4d, double)

#define Vec4_ToString(T, sub, fmt) inline cstr T##_ToString(T* v) { \
  static char buffer[512]; \
  snprintf(buffer, (size_t) Array_GetSize(buffer), \
    "(" fmt ", " fmt ", " fmt ", " fmt ")", v->x, v->y, v->z, v->w); \
  return buffer; }

Vec4_ToString(Vec4i, int,    "%i")
Vec4_ToString(Vec4f, float,  "%.4f")
Vec4_ToString(Vec4d, double, "%.4f")

#endif


text:
#ifndef PHX_Draw
#define PHX_Draw

#include "Common.h"
#include "Box3.h"
#include "Vec2.h"

/* TODO : This API is a bit hapazard with respect to using floats or vectors. */

/* --- Shared API ----------------------------------------------------------- */

PHX_API void  Draw_Clear         (float r, float g, float b, float a);
PHX_API void  Draw_ClearDepth    (float d);
PHX_API void  Draw_Color         (float r, float g, float b, float a);
PHX_API void  Draw_Flush         ();
PHX_API void  Draw_LineWidth     (float width);
PHX_API void  Draw_PointSize     (float size);
PHX_API void  Draw_PushAlpha     (float a);
PHX_API void  Draw_PopAlpha      ();
PHX_API void  Draw_SmoothLines   (bool);
PHX_API void  Draw_SmoothPoints  (bool);

/* --- 2D API --------------------------------------------------------------- */

PHX_API void  Draw_Border        (float s, float x, float y, float w, float h);
PHX_API void  Draw_Line          (float x1, float y1, float x2, float y2);
PHX_API void  Draw_Point         (float x, float y);
PHX_API void  Draw_Poly          (Vec2f const* points, int count);
PHX_API void  Draw_Quad          (Vec2f const* p1, Vec2f const* p2, Vec2f const* p3, Vec2f const* p4);
PHX_API void  Draw_Rect          (float x, float y, float sx, float sy);
PHX_API void  Draw_Tri           (Vec2f const* p1, Vec2f const* p2, Vec2f const* p3);

/* --- 3D API --------------------------------------------------------------- */

PHX_API void  Draw_Axes          (Vec3f const* pos,
                                  Vec3f const* x,
                                  Vec3f const* y,
                                  Vec3f const* z,
                                  float scale,
                                  float alpha);
PHX_API void  Draw_Box3          (Box3f const* box);
PHX_API void  Draw_Line3         (Vec3f const* p1, Vec3f const* p2);
PHX_API void  Draw_Plane         (Vec3f const* p, Vec3f const* n, float scale);
PHX_API void  Draw_Point3        (float x, float y, float z);
PHX_API void  Draw_Poly3         (Vec3f const* points, int count);
PHX_API void  Draw_Quad3         (Vec3f const* p1, Vec3f const* p2, Vec3f const* p3, Vec3f const* p4);
PHX_API void  Draw_Sphere        (Vec3f const* p, float r);
PHX_API void  Draw_Tri3          (Vec3f const* p1, Vec3f const* p2, Vec3f const* p3);

#endif


text:
#ifndef PHX_LodMesh
#define PHX_LodMesh

#include "Common.h"

/* --- LodMesh -----------------------------------------------------------------
 *
 *   A basic container for abstracting LOD rendering behavior. LodMesh consists
 *   of any number of (Mesh, distMin, distMax) tuples. Drawing a requires
 *   passing a *distance squared* argument that is used to determine which
 *   component(s) of the LodMesh to draw.
 *
 *   This type is REFERENCE-COUNTED. See ../doc/RefCounted.txt for details.
 *
 * -------------------------------------------------------------------------- */

PHX_API LodMesh*  LodMesh_Create   ();
PHX_API void      LodMesh_Acquire  (LodMesh*);
PHX_API void      LodMesh_Free     (LodMesh*);

PHX_API void      LodMesh_Add      (LodMesh*, Mesh*, float distMin, float distMax);
PHX_API void      LodMesh_Draw     (LodMesh*, float distanceSquared);
PHX_API Mesh*     LodMesh_Get      (LodMesh*, float distanceSquared);

#endif


text:
#ifndef PHX_KDTree
#define PHX_KDTree

#include "Common.h"
#include "Box3.h"

PHX_API KDTree*  KDTree_FromMesh      (Mesh*);
PHX_API void     KDTree_Free          (KDTree*);

PHX_API void     KDTree_Draw          (KDTree*, int maxDepth);
PHX_API int      KDTree_GetMemory     (KDTree*);
PHX_API bool     KDTree_IntersectRay  (KDTree*, Matrix*, Vec3f const* ro, Vec3f const* rd);

#endif


text:
#ifndef PHX_ShaderVar
#define PHX_ShaderVar

#include "Common.h"

PHX_API void* ShaderVar_Get         (cstr, ShaderVarType);
PHX_API void  ShaderVar_PushFloat   (cstr, float);
PHX_API void  ShaderVar_PushFloat2  (cstr, float, float);
PHX_API void  ShaderVar_PushFloat3  (cstr, float, float, float);
PHX_API void  ShaderVar_PushFloat4  (cstr, float, float, float, float);
PHX_API void  ShaderVar_PushInt     (cstr, int);
PHX_API void  ShaderVar_PushMatrix  (cstr, Matrix*);
PHX_API void  ShaderVar_PushTex1D   (cstr, Tex1D*);
PHX_API void  ShaderVar_PushTex2D   (cstr, Tex2D*);
PHX_API void  ShaderVar_PushTex3D   (cstr, Tex3D*);
PHX_API void  ShaderVar_PushTexCube (cstr, TexCube*);
PHX_API void  ShaderVar_Pop         (cstr);

PRIVATE void ShaderVar_Init ();
PRIVATE void ShaderVar_Free ();

#endif


text:
#ifndef PHX_Font
#define PHX_Font

#include "Common.h"
#include "Vec4.h"

/* --- Font --------------------------------------------------------------------
 *
 *   This type is REFERENCE-COUNTED. See ../doc/RefCounted.txt for details.
 *
 *   Font_DrawShaded : In addition to drawing glyphs as textured quads,
 *                     DrawShaded binds the texture for the current glyph to
 *                     the uniform sampler2D "glyph" of the currently-active
 *                     shader. This allows for text to be rendered through
 *                     the shader pipeline and, for example, output HDR values
 *                     for glyph colors.
 *
 * -------------------------------------------------------------------------- */

PHX_API Font*  Font_Load          (cstr name, int size);
PHX_API void   Font_Acquire       (Font*);
PHX_API void   Font_Free          (Font*);

PHX_API void   Font_Draw          (Font*, cstr text, float x, float y,
                                   float r, float g, float b, float a);
PHX_API void   Font_DrawShaded    (Font*, cstr text, float x, float y);

PHX_API int    Font_GetLineHeight (Font*);

PHX_API void   Font_GetSize       (Font*, Vec4i* out, cstr text);
PHX_API void   Font_GetSize2      (Font*, Vec2i* out, cstr text);

#endif


text:
#ifndef PHX_CubeFace
#define PHX_CubeFace

#include "Common.h"

PHX_API const CubeFace CubeFace_PX;
PHX_API const CubeFace CubeFace_NX;
PHX_API const CubeFace CubeFace_PY;
PHX_API const CubeFace CubeFace_NY;
PHX_API const CubeFace CubeFace_PZ;
PHX_API const CubeFace CubeFace_NZ;

PHX_API CubeFace  CubeFace_Get  (int index);

#endif


text:
#ifndef PHX_Device
#define PHX_Device

#include "Common.h"

struct Device {
  DeviceType type;
  uint32     id;
};

PHX_API bool  Device_Equal     (Device*, Device*);
PHX_API cstr  Device_ToString  (Device*);

#endif


text:
#ifndef PHX_LinkedList
#define PHX_LinkedList

#define LinkedListCell(name, T)                                                \
  T** name##_prev;                                                             \
  T*  name##_next

#define LinkedListCell_Init(name)                                              \
  { name##_prev = 0; name##_next = 0; }

#define LinkedList(name, T)                                                    \
  T* name

#define LinkedList_Insert(name, elem)                                          \
  { elem->name##_prev = &name;                                                 \
    elem->name##_next =  name;                                                 \
    if (name) name->name##_prev = &elem->name##_next;                          \
    name = elem; }

#define LinkedList_Remove(name, elem)                                          \
  { *(elem->name##_prev) = elem->name##_next;                                  \
    if (elem->name##_next)                                                     \
      { (elem->name##_next)->name##_prev = elem->name##_prev; }                \
  }

#define LinkedList_ForEach(name, T, iter)                                      \
    for (T* iter = name; iter; iter = iter->name##_next)

#endif


text:
#ifndef PHX_Triangle
#define PHX_Triangle

#include "Common.h"
#include "Vec3.h"

struct Triangle {
  Vec3f vertices[3];
};

PHX_API void   Triangle_ToPlane      (Triangle const*, Plane*);
PHX_API void   Triangle_ToPlaneFast  (Triangle const*, Plane*);
PHX_API float  Triangle_GetArea      (Triangle const*);
PHX_API Error  Triangle_Validate     (Triangle const*);

#endif


text:
#ifndef PHX_GamepadAxis
#define PHX_GamepadAxis

/* TODO DEPRECATED : Remove this API */
#define __FFI_IGNORE__

#include "Common.h"

PHX_API const GamepadAxis GamepadAxis_BEGIN;
PHX_API const GamepadAxis GamepadAxis_LeftX;
PHX_API const GamepadAxis GamepadAxis_LeftY;
PHX_API const GamepadAxis GamepadAxis_RightX;
PHX_API const GamepadAxis GamepadAxis_RightY;
PHX_API const GamepadAxis GamepadAxis_LTrigger;
PHX_API const GamepadAxis GamepadAxis_RTrigger;
PHX_API const GamepadAxis GamepadAxis_END;
const GamepadAxis GamepadAxis_SIZE = 6;

#endif


text:
#ifndef PHX_Memory
#define PHX_Memory

#include "Common.h"

#include <stdlib.h>
#include <string.h>

inline void*  MemAlloc      (size_t size);
inline void*  MemAllocZero  (size_t size);
inline void   MemCpy        (void* dst, void const* src, size_t size);
inline void   MemMove       (void* dst, void const* src, size_t size);
inline void   MemFree       (void const* ptr);
inline void*  MemRealloc    (void* ptr, size_t newSize);
inline void   MemSet        (void* dst, int value, size_t size);
inline void   MemZero       (void* dst, size_t size);

#define MemNew(x)             ((x*)MemAlloc(sizeof(x)))
#define MemNewZero(x)         ((x*)MemAllocZero(sizeof(x)))
#define MemNewArray(x, s)     ((x*)MemAlloc(sizeof(x) * (s)))
#define MemNewArrayZero(x, s) ((x*)MemAllocZero(sizeof(x) * (s)))

/* Exported versions for applications that need to ensure usage of the same
 * memory allocator as libphx. */
PHX_API void*  Memory_Alloc    (size_t);
PHX_API void*  Memory_Calloc   (size_t n, size_t size);
PHX_API void   Memory_Free     (void* ptr);
PHX_API void   Memory_MemCopy  (void* dst, void const* src, size_t size);
PHX_API void   Memory_MemMove  (void* dst, void const* src, size_t size);
PHX_API void*  Memory_Realloc  (void* ptr, size_t newSize);

/* -------------------------------------------------------------------------- */

inline void* MemAlloc (size_t size) {
  return malloc(size);
}

inline void* MemAllocZero (size_t size) {
  return calloc(1, size);
}

inline void MemCpy (void* dst, void const* src, size_t size) {
  memcpy(dst, src, size);
}

inline void MemMove (void* dst, void const* src, size_t size) {
  memmove(dst, src, size);
}

inline void MemFree (void const* ptr) {
  free((void*)ptr);
}

inline void* MemRealloc (void* ptr, size_t newSize) {
  return realloc(ptr, newSize);
}

inline void MemSet (void* dst, int value, size_t size) {
  memset(dst, value, size);
}

inline void MemZero (void* dst, size_t size) {
  memset(dst, 0, size);
}

#endif


text:
#ifndef PHX_Common
#define PHX_Common

#include "PhxConfig.h"
#include "PhxInt.h"

#ifdef _WIN32
  #ifndef WINDOWS
    #define WINDOWS 1
  #endif
#elif __APPLE__
  #ifndef APPLE
    #define APPLE 1
    #define POSIX 1
  #endif
#elif __linux__
  #ifndef LINUX
    #define LINUX 1
    #define POSIX 1
  #endif
#endif

#if WINDOWS
  #if LIBPHX_BUILDING
    #define PHX_API           extern "C" __declspec(dllexport)
  #else
    #define PHX_API           extern "C" __declspec(dllimport)
  #endif

  #define DEBUG_BREAK         __debugbreak()
  #define PRIVATE
  #define ALIGN_OF(x)         __alignof(x)
  #define FORCE_INLINE        static __forceinline
  #define NO_ALIAS            __restrict
  #define IF_LIKELY(x)        if (x)
  #define IF_UNLIKELY(x)      if (x)

#else

  #define DEBUG_BREAK         __builtin_trap()
  #define PHX_API             extern "C" __attribute__((visibility("default")))
  #define PRIVATE             __attribute__((visibility("hidden")))
  #define ALIGN_OF(x)         __alignof__(x)
  #define FORCE_INLINE        inline static __attribute__((always_inline))
  #define NO_ALIAS            __restrict__
  #define IF_LIKELY(x)        if (__builtin_expect(!!(x), 1))
  #define IF_UNLIKELY(x)      if (__builtin_expect(!!(x), 0))

#endif

#define OPAQUE_T              struct
#define STRUCT_T              struct
#define ENUM_T
#define OFFSET_OF(st, m)      ((size_t)&(((st*)0)->m))
#define HAS_FLAG(x, flag)     ((x & flag) == flag)
#define UNUSED(x)             (void)x

/* --- Standard Aliases ----------------------------------------------------- */

  typedef unsigned long  ulong;
  typedef unsigned int   uint;
  typedef unsigned short ushort;
  typedef unsigned char  uchar;
  typedef char const*    cstr;

  typedef int8_t         int8;
  typedef int16_t        int16;
  typedef int32_t        int32;
  typedef int64_t        int64;

  typedef uint8_t        uint8;
  typedef uint16_t       uint16;
  typedef uint32_t       uint32;
  typedef uint64_t       uint64;

/* --- Opaque Types ------------------------------------------------------------
 *
 *   Note: The 'OPAQUE_T' and 'STRUCT_T' macros are used instead of struct as
 *         annotations for external tools to differentiate between struct
 *         forward declarations and opaque types.
 *
 * -------------------------------------------------------------------------- */

  OPAQUE_T BoxMesh;
  OPAQUE_T BoxTree;
  OPAQUE_T BSP;
  OPAQUE_T Bytes;
  OPAQUE_T Directory;
  OPAQUE_T File;
  OPAQUE_T Font;
  OPAQUE_T HashGrid;
  OPAQUE_T HashGridElem;
  OPAQUE_T HashMap;
  OPAQUE_T InputBinding;
  OPAQUE_T KDTree;
  OPAQUE_T LodMesh;
  OPAQUE_T MemPool;
  OPAQUE_T MemStack;
  OPAQUE_T Mesh;
  OPAQUE_T MidiDevice;
  OPAQUE_T Octree;
  OPAQUE_T Physics;
  OPAQUE_T RigidBody;
  OPAQUE_T RmGui;
  OPAQUE_T RNG;
  OPAQUE_T SDF;
  OPAQUE_T Shader;
  OPAQUE_T ShaderState;
  OPAQUE_T Socket;
  OPAQUE_T Sound;
  OPAQUE_T SoundDesc;
  OPAQUE_T StrBuffer;
  OPAQUE_T StrMap;
  OPAQUE_T StrMapIter;
  OPAQUE_T Tex1D;
  OPAQUE_T Tex2D;
  OPAQUE_T Tex3D;
  OPAQUE_T TexCube;
  OPAQUE_T Thread;
  OPAQUE_T ThreadPool;
  OPAQUE_T Timer;
  OPAQUE_T Trigger;
  OPAQUE_T Window;

/* --- Transparent Structs -------------------------------------------------- */

  STRUCT_T Box3i;
  STRUCT_T Box3d;
  STRUCT_T Box3f;
  STRUCT_T BSPNodeRef;
  STRUCT_T Collision;
  STRUCT_T Device;
  STRUCT_T IntersectSphereProfiling;
  STRUCT_T InputEvent;
  STRUCT_T LineSegment;
  STRUCT_T Matrix;
  STRUCT_T Plane;
  STRUCT_T Polygon;
  STRUCT_T Quat;
  STRUCT_T Ray;
  STRUCT_T RayCastResult;
  STRUCT_T ShapeCastResult;
  STRUCT_T Sphere;
  STRUCT_T Time;
  STRUCT_T Triangle;
  STRUCT_T TriangleTest;
  STRUCT_T Vec2i;
  STRUCT_T Vec2d;
  STRUCT_T Vec2f;
  STRUCT_T Vec3i;
  STRUCT_T Vec3d;
  STRUCT_T Vec3f;
  STRUCT_T Vec4i;
  STRUCT_T Vec4d;
  STRUCT_T Vec4f;
  STRUCT_T Vertex;

/* --- Enums ---------------------------------------------------------------- */

  ENUM_T typedef int32  BlendMode;
  ENUM_T typedef uint8  BSPNodeRel;
  ENUM_T typedef int32  Button;
  ENUM_T typedef int32  CollisionGroup;
  ENUM_T typedef int32  CollisionMask;
  ENUM_T typedef int32  CubeFace;
  ENUM_T typedef int32  CullFace;
  ENUM_T typedef int32  DataFormat;
  ENUM_T typedef int32  DeviceType;
  ENUM_T typedef uint32 Error;
  ENUM_T typedef int32  Metric;
  ENUM_T typedef int32  Modifier;
  ENUM_T typedef int32  PixelFormat;
  ENUM_T typedef uint8  PointClassification;
  ENUM_T typedef uint8  PolygonClassification;
  ENUM_T typedef int32  ResourceType;
  ENUM_T typedef int32  ShaderVarType;
  ENUM_T typedef int32  SocketType;
  ENUM_T typedef int32  State;
  ENUM_T typedef int32  TexFilter;
  ENUM_T typedef int32  TexFormat;
  ENUM_T typedef int32  TexWrapMode;
  ENUM_T typedef uint64 TimeStamp;
  ENUM_T typedef uint32 WindowMode;
  ENUM_T typedef int    WindowPos;

/* --- Deprecated ----------------------------------------------------------- */

  struct Gamepad;
  struct Joystick;
  typedef int32 GamepadAxis;
  typedef int32 GamepadButton;
  typedef int32 HatDir;
  typedef uchar Key;
  typedef int32 MouseButton;

/* --- Debugging ------------------------------------------------------------ */

/*  CHECK_LEVEL
 *    Determines the rigor with which internal engine code will check
 *    assertions and validate state. The granularity of CHECK_LEVEL allows for
 *    progressive debugging without having to immediately kill performance.
 *    Higher CHECK_LEVELs incurs higher performance penalties. The levels are
 *    defined qualitatively as follows:
 *
 *      0 : No checking. This is 'release'.
 *      1 : Light sanity checks that don't significantly affect performance.
 *          Assert et al. are defined. This is the recommended default for
 *          development.
 *      2 : Moderately-intrusive checks. Good for periodic internal validation.
 *      3 : Maximal rigor in checks, including those that incur heavy perf
 *          overheads. Intended only for debugging difficult bugs and for
 *          pre-release quality checks. */

#ifndef CHECK_LEVEL
  #define CHECK_LEVEL 0
#endif

#if CHECK_LEVEL == 0
  #define NCHECK(x) x
#else
  #define NCHECK(x)
#endif

#if CHECK_LEVEL >= 1
  #define  CHECK1(x) x
  #define  CHECK1PARAM(x) x,
  #define NCHECK1(x)
  #define Assert(x) _Assert((x) != 0, #x)
  #define Expect(x) _Expect((x) != 0, #x)
#else
  #define  CHECK1(x)
  #define  CHECK1PARAM(x)
  #define NCHECK1(x) x
  #define Expect(x)
  #define Assert(x)
#endif

#if CHECK_LEVEL >= 2
  #define  CHECK2(x) x
  #define  CHECK2PARAM(x) x,
  #define NCHECK2(x)
#else
  #define  CHECK2(x)
  #define  CHECK2PARAM(x)
  #define NCHECK2(x) x
#endif

#if CHECK_LEVEL >= 3
  #define  CHECK3(x) x
  #define  CHECK3PARAM(x) x,
  #define NCHECK3(x)
#else
  #define  CHECK3(x)
  #define  CHECK3PARAM(x)
  #define NCHECK3(x) x
#endif

/* Indicate fatal error and abort program. */
PHX_API void Fatal (cstr, ...);
inline void _Assert(bool condition, cstr expression) {
  if (!condition)
    Fatal("Assertion Failed!\n%s", expression);
}

/* Indicate non-fatal error and continue execution. */
PHX_API void Warn (cstr, ...);
inline void _Expect(bool condition, cstr expression) {
  if (!condition)
    Warn("Expect Failed!\n%s", expression);
}

#define NYI Fatal("NYI @ %s: %d", __FILE__, __LINE__);

template <class T>
inline static void Swap(T& a, T& b) {
  T temp = a;
  a = b;
  b = temp;
}

#endif

/* TODO : Export Assert and Expect for use in Lua */


text:
#ifndef PHX_Hash
#define PHX_Hash

#include "Common.h"

/* --- API NOTES ---------------------------------------------------------------
 *
 *   Hash_FNV*     : Uses the FNV-1a variant, not the strictly-inferior FNV1
 *   Hash_FNVStr*  : FNV can operate on a null-terminated buffer without knowing
 *                   the length in advance; useful for eliminating strlen calls
 *
 *   Hash_Murmur   : In general superior to FNV in both quality and perf
 *
 *   Hash_XX64     : The best of them all. Quality similar to Murmur with perf
 *                   similar to memcpy. Why walk when you can ride? We make
 *                   a special trip, just for you.
 *
 * -------------------------------------------------------------------------- */

PHX_API uint32  Hash_FNV32     (void const* buf, int len);
PHX_API uint64  Hash_FNV64     (void const* buf, int len);
PHX_API uint32  Hash_FNVStr32  (cstr);
PHX_API uint64  Hash_FNVStr64  (cstr);

PHX_API uint64  Hash_FNV64_Init        ();
PHX_API uint64  Hash_FNV64_Incremental (uint64, void const* buf, int len);

PHX_API uint32  Hash_Murmur3   (void const* buf, int len);

PHX_API uint64  Hash_XX64      (void const* buf, int len, uint64 seed);

#endif


text:
#ifndef PHX_StrMap
#define PHX_StrMap

#include "Common.h"

PHX_API StrMap*  StrMap_Create   (uint32 initCapacity);
PHX_API void     StrMap_Free     (StrMap*);
PHX_API void     StrMap_FreeEx   (StrMap*, void (*freeFn)(cstr key, void* value));

PHX_API void*    StrMap_Get      (StrMap*, cstr key);
PHX_API uint32   StrMap_GetSize  (StrMap*);
PHX_API void     StrMap_Remove   (StrMap*, cstr key);
PHX_API void     StrMap_Set      (StrMap*, cstr key, void* val);

PHX_API void     StrMap_Dump     (StrMap*);

PHX_API StrMapIter* StrMap_Iterate      (StrMap*);
PHX_API void        StrMapIter_Advance  (StrMapIter*);
PHX_API void        StrMapIter_Free     (StrMapIter*);
PHX_API bool        StrMapIter_HasMore  (StrMapIter*);
PHX_API cstr        StrMapIter_GetKey   (StrMapIter*);
PHX_API void*       StrMapIter_GetValue (StrMapIter*);

#endif


text:
#ifndef PHX_Vec2
#define PHX_Vec2

#include "Common.h"
#include "Array.h"
#include "Error.h"
#include "PhxMath.h"
#include "PhxFloat.h"

#include <stdio.h>

/* TODO : Replace as macro-free C using codegen. */

#define UNPACK2(v) (v).x, (v).y
#define REPEAT2(v) (v), (v)

struct Vec2i { int x, y; };
struct Vec2d { double x, y; };
struct Vec2f { float x, y; };

#define Vec2_Create(T, sub) inline T T##_Create(sub x, sub y) { \
  T self = { x, y }; return self; }

#define Vec2_Add(T) inline T T##_Add(T a, T b) { \
  T self = { a.x + b.x, a.y + b.y }; return self; }
#define Vec2_Div(T) inline T T##_Div(T a, T b) { \
  T self = { a.x / b.x, a.y / b.y }; return self; }
#define Vec2_Mul(T) inline T T##_Mul(T a, T b) { \
  T self = { a.x * b.x, a.y * b.y }; return self; }
#define Vec2_Sub(T) inline T T##_Sub(T a, T b) { \
  T self = { a.x - b.x, a.y - b.y }; return self; }

#define Vec2_IAdd(T) inline void T##_IAdd(T* a, T b) { \
  a->x += b.x; a->y += b.y; }
#define Vec2_IDiv(T) inline void T##_IDiv(T* a, T b) { \
  a->x /= b.x; a->y /= b.y; }
#define Vec2_IMul(T) inline void T##_IMul(T* a, T b) { \
  a->x *= b.x; a->y *= b.y; }
#define Vec2_ISub(T) inline void T##_ISub(T* a, T b) { \
  a->x -= b.x; a->y -= b.y; }

#define Vec2_Adds(T, sub) inline T T##_Adds(T a, sub b) { \
  T self = { a.x + b, a.y + b }; return self; }
#define Vec2_Divs(T, sub) inline T T##_Divs(T a, sub b) { \
  T self = { a.x / b, a.y / b }; return self; }
#define Vec2_Muls(T, sub) inline T T##_Muls(T a, sub b) { \
  T self = { a.x * b, a.y * b }; return self; }
#define Vec2_Subs(T, sub) inline T T##_Subs(T a, sub b) { \
  T self = { a.x - b, a.y - b }; return self; }

#define Vec2_IAdds(T, sub) inline void T##_IAdds(T* a, sub b) { \
  a->x += b; a->y += b; }
#define Vec2_IDivs(T, sub) inline void T##_IDivs(T* a, sub b) { \
  a->x /= b; a->y /= b; }
#define Vec2_IMuls(T, sub) inline void T##_IMuls(T* a, sub b) { \
  a->x *= b; a->y *= b; }
#define Vec2_ISubs(T, sub) inline void T##_ISubs(T* a, sub b) { \
  a->x -= b; a->y -= b; }

Vec2_Create(Vec2i, int)
Vec2_Create(Vec2d, double)
Vec2_Create(Vec2f, float)

Vec2_Add(Vec2i) Vec2_Add(Vec2d) Vec2_Add(Vec2f)
Vec2_Div(Vec2i) Vec2_Div(Vec2d) Vec2_Div(Vec2f)
Vec2_Mul(Vec2i) Vec2_Mul(Vec2d) Vec2_Mul(Vec2f)
Vec2_Sub(Vec2i) Vec2_Sub(Vec2d) Vec2_Sub(Vec2f)

Vec2_IAdd(Vec2i) Vec2_IAdd(Vec2d) Vec2_IAdd(Vec2f)
Vec2_IDiv(Vec2i) Vec2_IDiv(Vec2d) Vec2_IDiv(Vec2f)
Vec2_IMul(Vec2i) Vec2_IMul(Vec2d) Vec2_IMul(Vec2f)
Vec2_ISub(Vec2i) Vec2_ISub(Vec2d) Vec2_ISub(Vec2f)

Vec2_Adds(Vec2i, int) Vec2_Adds(Vec2d, double) Vec2_Adds(Vec2f, float)
Vec2_Divs(Vec2i, int) Vec2_Divs(Vec2d, double) Vec2_Divs(Vec2f, float)
Vec2_Muls(Vec2i, int) Vec2_Muls(Vec2d, double) Vec2_Muls(Vec2f, float)
Vec2_Subs(Vec2i, int) Vec2_Subs(Vec2d, double) Vec2_Subs(Vec2f, float)

Vec2_IAdds(Vec2i, int) Vec2_IAdds(Vec2d, double) Vec2_IAdds(Vec2f, float)
Vec2_IDivs(Vec2i, int) Vec2_IDivs(Vec2d, double) Vec2_IDivs(Vec2f, float)
Vec2_IMuls(Vec2i, int) Vec2_IMuls(Vec2d, double) Vec2_IMuls(Vec2f, float)
Vec2_ISubs(Vec2i, int) Vec2_ISubs(Vec2d, double) Vec2_ISubs(Vec2f, float)

#define Vec2_Abs(T) inline T T##_Abs(T v) { \
  T self = { Abs(v.x), Abs(v.y) }; return self; }

Vec2_Abs(Vec2i)
Vec2_Abs(Vec2f)
Vec2_Abs(Vec2d)

#define Vec2_IAbs(T) inline void T##_Abs(T* v) { \
  v->x = Abs(v->x); v->y = Abs(v->y); }

Vec2_IAbs(Vec2i)
Vec2_IAbs(Vec2f)
Vec2_IAbs(Vec2d)

#define Vec2_Equal(T) inline bool T##_Equal(T a, T b) { \
  bool self = a.x == b.x && a.y == b.y; \
  return self; }

Vec2_Equal(Vec2i)
Vec2_Equal(Vec2f)
Vec2_Equal(Vec2d)

#define Vec2_Length(T, sub) inline sub T##_Length(T v) { \
  return Sqrt(v.x * v.x + v.y * v.y); }

Vec2_Length(Vec2f, float)
Vec2_Length(Vec2d, double)

#define Vec2_LengthSquared(T, sub) inline sub T##_LengthSquared(T v) { \
  return v.x * v.x + v.y * v.y; }

Vec2_LengthSquared(Vec2f, float)
Vec2_LengthSquared(Vec2d, double)

#define Vec2_Normalize(T, sub) inline T T##_Normalize(T v) { \
  sub l = T##_Length(v); \
  T self = { v.x / l, v.y / l }; return self; }

Vec2_Normalize(Vec2f, float)
Vec2_Normalize(Vec2d, double)

#define Vec2_Dot(T, sub) inline sub T##_Dot(T a, T b) { \
  return a.x * b.x + a.y * b.y; }

Vec2_Dot(Vec2i, int)
Vec2_Dot(Vec2f, float)
Vec2_Dot(Vec2d, double)

#define Vec2_Validate(T, sub) inline Error T##_Validate(T v) { \
  Error e = Error_None; \
  e |= Float_Validate(v.x); \
  e |= Float_Validate(v.y); \
  return e; }

Vec2_Validate(Vec2f, float)
Vec2_Validate(Vec2d, double)

#define Vec2_ToString(T, sub, fmt) inline cstr T##_ToString(T* v) { \
  static char buffer[512]; \
  snprintf(buffer, (size_t) Array_GetSize(buffer), \
    "(" fmt ", " fmt ")", v->x, v->y); \
  return buffer; }

Vec2_ToString(Vec2i, int,    "%i")
Vec2_ToString(Vec2f, float,  "%.4f")
Vec2_ToString(Vec2d, double, "%.4f")

#endif


text:
#ifndef PHX_Matrix
#define PHX_Matrix

#include "Common.h"

/* --- API NOTES ---------------------------------------------------------------
 *
 *   Matrices are stored with ROW-MAJOR memory layout:
 *
 *                                 float mat[] = {
 *     |  m0  m1  m2  m3 |           m0,  m1,  m2,  m3,          | Xx Yx Zx Tx |
 *     |  m4  m5  m6  m7 |  /---\    m4,  m5,  m6,  m7,   /---\  | Xy Yy Zy Ty |
 *     |  m8  m9 m10 m11 |  \---/    m8,  m9, m10, m11,   \---/  | Xz Yz Zz Tz |
 *     | m12 m13 m14 m15 |          m12, m13, m14, m15 };        |  0  0  0  1 |
 *
 *   We use POST-multiplication for matrices:
 *     Matrix_Product(A, B) = AB
 *
 *   And POST-multiplication for vectors (i.e., vectors are COLUMN vectors):
 *     Matrix_MulVec(A, v) = Av
 *
 *     |  A0   A1   A2   A3 |    | x |       |  A0*x +  A1*y +  A2*z +  A3*w |
 *     |  A4   A5   A6   A7 | \/ | y |  --\  |  A4*x +  A5*y +  A6*z +  A7*w |
 *     |  A8   A9  A10  A11 | /\ | z |  --/  |  A8*x +  A9*y + A10*z + A11*w |
 *     | A12  A13  A14  A15 |    | w |       | A12*x + A13*y + A14*z + A15*w |
 *
 *   Hence, Matrix_Product(A, Matrix_Product(B, C)) creates a matrix that
 *   applies transforms C, then B, then A, respectively, to incoming vectors.
 *
 *   Note that our storage order is transposed from OpenGL. In OpenGL bases are
 *   contiguous and translation is stored in 12, 13, 14.
 *
 * -------------------------------------------------------------------------- */

PHX_API Matrix*  Matrix_Clone               (Matrix const*);
PHX_API void     Matrix_Free                (Matrix*);

PHX_API bool     Matrix_Equal               (Matrix const*, Matrix const*);
PHX_API bool     Matrix_ApproximatelyEqual  (Matrix const*, Matrix const*);
PHX_API Matrix*  Matrix_Inverse             (Matrix const*);
PHX_API Matrix*  Matrix_InverseTranspose    (Matrix const*);
PHX_API Matrix*  Matrix_Product             (Matrix const*, Matrix const*);
PHX_API Matrix*  Matrix_Sum                 (Matrix const*, Matrix const*);
PHX_API Matrix*  Matrix_Transpose           (Matrix const*);

PHX_API void     Matrix_IInverse            (Matrix*);
PHX_API void     Matrix_IScale              (Matrix*, float);
PHX_API void     Matrix_ITranspose          (Matrix*);

PHX_API Matrix*  Matrix_Identity            ();
PHX_API Matrix*  Matrix_LookAt              (Vec3f const* pos, Vec3f const* at, Vec3f const* up);
PHX_API Matrix*  Matrix_LookUp              (Vec3f const* pos, Vec3f const* look, Vec3f const* up);
PHX_API Matrix*  Matrix_Perspective         (float degreesFovY, float aspect, float zNear, float zFar);
PHX_API Matrix*  Matrix_RotationX           (float rads);
PHX_API Matrix*  Matrix_RotationY           (float rads);
PHX_API Matrix*  Matrix_RotationZ           (float rads);
PHX_API Matrix*  Matrix_Scaling             (float sx, float sy, float sz);
PHX_API Matrix*  Matrix_SRT                 (float sx, float sy, float sz,
                                             float ry, float rp, float rr,
                                             float tx, float ty, float tz);
PHX_API Matrix*  Matrix_Translation         (float tx, float ty, float tz);
PHX_API Matrix*  Matrix_YawPitchRoll        (float yaw, float pitch, float roll);

PHX_API void     Matrix_MulBox              (Matrix const*, Box3f* out, Box3f const* in);
PHX_API void     Matrix_MulDir              (Matrix const*, Vec3f* out, float x, float y, float z);
PHX_API void     Matrix_MulPoint            (Matrix const*, Vec3f* out, float x, float y, float z);
PHX_API void     Matrix_MulVec              (Matrix const*, Vec4f* out, float x, float y, float z, float w);

PHX_API void     Matrix_GetForward          (Matrix const*, Vec3f* out);
PHX_API void     Matrix_GetRight            (Matrix const*, Vec3f* out);
PHX_API void     Matrix_GetUp               (Matrix const*, Vec3f* out);
PHX_API void     Matrix_GetPos              (Matrix const*, Vec3f* out);
PHX_API void     Matrix_GetRow              (Matrix const*, Vec4f* out, int row);

PHX_API Matrix*  Matrix_FromBasis           (Vec3f const* x, Vec3f const* y, Vec3f const* z);
PHX_API Matrix*  Matrix_FromPosRot          (Vec3f const*, Quat const*);
PHX_API Matrix*  Matrix_FromPosRotScale     (Vec3f const*, Quat const*, float);
PHX_API Matrix*  Matrix_FromPosBasis        (Vec3f const* pos, Vec3f const* x, Vec3f const* y, Vec3f const* z);
PHX_API Matrix*  Matrix_FromQuat            (Quat const*);
PHX_API void     Matrix_ToQuat              (Matrix const*, Quat* out);

PHX_API void     Matrix_Print               (Matrix const*);
PHX_API cstr     Matrix_ToString            (Matrix const*);

#endif

/* TODO : Is there any real reason for having scalar functions anymore? */


text:
#ifndef PHX_Random
#define PHX_Random

#include "Common.h"
#include "Bit.h"

inline uint64 rotl (uint64 const x, int k) {
	return (x << k) | (x >> (64 - k));
}

inline uint64 Random_SplitMix64 (uint64& state) {
	uint64 z = (state += UINT64_C(0x9E3779B97F4A7C15));
	z = (z ^ (z >> 30)) * UINT64_C(0xBF58476D1CE4E5B9);
	z = (z ^ (z >> 27)) * UINT64_C(0x94D049BB133111EB);
	return z ^ (z >> 31);
}

inline uint64 Random_Xoroshiro128 (uint64& state0, uint64& state1) {
	uint64 const s0 = state0;
	uint64 s1 = state1;
	uint64 const result = s0 + s1;
	s1 ^= s0;
	state0 = rotl(s0, 55) ^ s1 ^ (s1 << 14);
	state1 = rotl(s1, 36);
	return result;
}

#endif


text:
#ifndef PHX_HashGrid
#define PHX_HashGrid

#include "Common.h"

/* --- HashGrid ----------------------------------------------------------------
 *
 *   A flat, uniform-grid-backed spatial partitioning structure. Much like a
 *   HashMap, the HashGrid has no hierarchy, and instead uses hashing to
 *   achieve (amortized) O(1) lookups. Since chunks of space are mapped via a
 *   hash function to their corresponding bucket, HashGrids have the nice
 *   property of easily supporting unbounded, highly-sparse spaces without
 *   requiring any cleverness.
 *
 *   The primary drawback of the HashGrid is in the lack of hierarchy. Large
 *   objects will take up asymptotically more grid cells. Large, moving objects
 *   are pathological for grids, since a cubic amount of space must be cleared
 *   and then re-inserted when an object moves. Hence, this structure is most
 *   appropriate for uniformly or nearly-uniformly-sized objects, and performs
 *   very well with large numbers of such objects.
 *
 * -------------------------------------------------------------------------- */

PHX_API HashGrid*      HashGrid_Create      (float cellSize, uint32 cellCount);
PHX_API void           HashGrid_Free        (HashGrid*);

PHX_API HashGridElem*  HashGrid_Add         (HashGrid*, void* object, Box3f const*);
PHX_API void           HashGrid_Clear       (HashGrid*);
PHX_API void           HashGrid_Remove      (HashGrid*, HashGridElem*);
PHX_API void           HashGrid_Update      (HashGrid*, HashGridElem*, Box3f const*);

PHX_API void**         HashGrid_GetResults  (HashGrid*);
PHX_API int            HashGrid_QueryBox    (HashGrid*, Box3f const*);
PHX_API int            HashGrid_QueryPoint  (HashGrid*, Vec3f const*);

#endif


text:
#ifndef PHX_MouseButton
#define PHX_MouseButton

/* TODO DEPRECATED : Remove this API */
#define __FFI_IGNORE__

#include "Common.h"

PHX_API const MouseButton MouseButton_Left;
PHX_API const MouseButton MouseButton_Middle;
PHX_API const MouseButton MouseButton_Right;
PHX_API const MouseButton MouseButton_X1;
PHX_API const MouseButton MouseButton_X2;

#endif


text:
#ifndef PHX_RefCounted
#define PHX_RefCounted

#define RefCounted               mutable uint32 _refCount
#define RefCounted_Init(self)    (self)->_refCount = 1
#define RefCounted_Free(self)    if (self && (--((self)->_refCount) <= 0))
#define RefCounted_Acquire(self) (self)->_refCount++

#endif


text:
#ifndef PHX_Float
#define PHX_Float

#include "Common.h"
#include "Error.h"
#include "PhxMath.h"

#include <float.h>
#include <math.h>

inline Error  Float_Validate            (float x);
inline Error  Float_Validate            (double x);
inline bool   Float_ApproximatelyEqual  (float x, float y);
inline bool   Float_ApproximatelyEqual  (double x, double y);

/* -------------------------------------------------------------------------- */

inline Error Float_Validate (float x) {
  int classification = fpclassify(x);
  switch (classification) {
    case FP_INFINITE:  return Error_Overflow;
    /* NOTE : Denormals are allowed until they become a perf issue. */
    //case FP_SUBNORMAL: return Error_Underflow;
    case FP_SUBNORMAL: break;
    case FP_NAN:       return Error_NaN;

    case FP_ZERO:
    case FP_NORMAL:   return Error_None;

    default:
      Fatal("Float_Validate: Unhandled case: %i", classification);
  }
  return Error_None;
}

inline Error Float_Validate (double x) {
  int classification = fpclassify(x);
  switch (classification) {
    case FP_INFINITE:  return Error_Overflow;
    case FP_SUBNORMAL: return Error_Underflow;
    case FP_NAN:       return Error_NaN;

    case FP_ZERO:
    case FP_NORMAL:    return Error_None;

    default:
      Fatal("Float_Validate: Unhandled case: %i", classification);
  }
  return Error_None;
}

inline bool Float_ApproximatelyEqual (float x, float y) {
  return Abs(x - y) < 1e-3f;
}

inline bool Float_ApproximatelyEqual (double x, double y) {
  return Abs(x - y) < 1e-3;
}

#endif


text:
/***************************************************************************/
/*                                                                         */
/*  ft2build.h                                                             */
/*                                                                         */
/*    FreeType 2 build and setup macros.                                   */
/*                                                                         */
/*  Copyright 1996-2017 by                                                 */
/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
/*                                                                         */
/*  This file is part of the FreeType project, and may only be used,       */
/*  modified, and distributed under the terms of the FreeType project      */
/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
/*  this file you indicate that you have read the license and              */
/*  understand and accept it fully.                                        */
/*                                                                         */
/***************************************************************************/

  /*************************************************************************/
  /*                                                                       */
  /* This is the `entry point' for FreeType header file inclusions.  It is */
  /* the only header file which should be included directly; all other     */
  /* FreeType header files should be accessed with macro names (after      */
  /* including `ft2build.h').                                              */
  /*                                                                       */
  /* A typical example is                                                  */
  /*                                                                       */
  /*   #include <ft2build.h>                                               */
  /*   #include FT_FREETYPE_H                                              */
  /*                                                                       */
  /*************************************************************************/

#ifndef FT2BUILD_H_
#define FT2BUILD_H_

#include <freetype/config/ftheader.h>

#endif /* FT2BUILD_H_ */

/* END */