text:
#ifndef PHX_Button
#define PHX_Button

#include "Common.h"
#include "SDL.h"

PHX_API const Button Button_Null;
PHX_API const Button Button_First;

PHX_API const Button Button_Keyboard_First;
PHX_API const Button Button_Keyboard_A;
PHX_API const Button Button_Keyboard_B;
PHX_API const Button Button_Keyboard_C;
PHX_API const Button Button_Keyboard_D;
PHX_API const Button Button_Keyboard_E;
PHX_API const Button Button_Keyboard_F;
PHX_API const Button Button_Keyboard_G;
PHX_API const Button Button_Keyboard_H;
PHX_API const Button Button_Keyboard_I;
PHX_API const Button Button_Keyboard_J;
PHX_API const Button Button_Keyboard_K;
PHX_API const Button Button_Keyboard_L;
PHX_API const Button Button_Keyboard_M;
PHX_API const Button Button_Keyboard_N;
PHX_API const Button Button_Keyboard_O;
PHX_API const Button Button_Keyboard_P;
PHX_API const Button Button_Keyboard_Q;
PHX_API const Button Button_Keyboard_R;
PHX_API const Button Button_Keyboard_S;
PHX_API const Button Button_Keyboard_T;
PHX_API const Button Button_Keyboard_U;
PHX_API const Button Button_Keyboard_V;
PHX_API const Button Button_Keyboard_W;
PHX_API const Button Button_Keyboard_X;
PHX_API const Button Button_Keyboard_Y;
PHX_API const Button Button_Keyboard_Z;
PHX_API const Button Button_Keyboard_N0;
PHX_API const Button Button_Keyboard_N1;
PHX_API const Button Button_Keyboard_N2;
PHX_API const Button Button_Keyboard_N3;
PHX_API const Button Button_Keyboard_N4;
PHX_API const Button Button_Keyboard_N5;
PHX_API const Button Button_Keyboard_N6;
PHX_API const Button Button_Keyboard_N7;
PHX_API const Button Button_Keyboard_N8;
PHX_API const Button Button_Keyboard_N9;
PHX_API const Button Button_Keyboard_F1;
PHX_API const Button Button_Keyboard_F2;
PHX_API const Button Button_Keyboard_F3;
PHX_API const Button Button_Keyboard_F4;
PHX_API const Button Button_Keyboard_F5;
PHX_API const Button Button_Keyboard_F6;
PHX_API const Button Button_Keyboard_F7;
PHX_API const Button Button_Keyboard_F8;
PHX_API const Button Button_Keyboard_F9;
PHX_API const Button Button_Keyboard_F10;
PHX_API const Button Button_Keyboard_F11;
PHX_API const Button Button_Keyboard_F12;
PHX_API const Button Button_Keyboard_F13;
PHX_API const Button Button_Keyboard_F14;
PHX_API const Button Button_Keyboard_F15;
PHX_API const Button Button_Keyboard_F16;
PHX_API const Button Button_Keyboard_F17;
PHX_API const Button Button_Keyboard_F18;
PHX_API const Button Button_Keyboard_F19;
PHX_API const Button Button_Keyboard_F20;
PHX_API const Button Button_Keyboard_F21;
PHX_API const Button Button_Keyboard_F22;
PHX_API const Button Button_Keyboard_F23;
PHX_API const Button Button_Keyboard_F24;
PHX_API const Button Button_Keyboard_KP0;
PHX_API const Button Button_Keyboard_KP1;
PHX_API const Button Button_Keyboard_KP2;
PHX_API const Button Button_Keyboard_KP3;
PHX_API const Button Button_Keyboard_KP4;
PHX_API const Button Button_Keyboard_KP5;
PHX_API const Button Button_Keyboard_KP6;
PHX_API const Button Button_Keyboard_KP7;
PHX_API const Button Button_Keyboard_KP8;
PHX_API const Button Button_Keyboard_KP9;
PHX_API const Button Button_Keyboard_KPNumLock;
PHX_API const Button Button_Keyboard_KPDivide;
PHX_API const Button Button_Keyboard_KPMultiply;
PHX_API const Button Button_Keyboard_KPSubtract;
PHX_API const Button Button_Keyboard_KPAdd;
PHX_API const Button Button_Keyboard_KPEnter;
PHX_API const Button Button_Keyboard_KPDecimal;
PHX_API const Button Button_Keyboard_Backspace;
PHX_API const Button Button_Keyboard_Escape;
PHX_API const Button Button_Keyboard_Return;
PHX_API const Button Button_Keyboard_Space;
PHX_API const Button Button_Keyboard_Tab;
PHX_API const Button Button_Keyboard_Backtick;
PHX_API const Button Button_Keyboard_CapsLock;
PHX_API const Button Button_Keyboard_Minus;
PHX_API const Button Button_Keyboard_Equals;
PHX_API const Button Button_Keyboard_LBracket;
PHX_API const Button Button_Keyboard_RBracket;
PHX_API const Button Button_Keyboard_Backslash;
PHX_API const Button Button_Keyboard_Semicolon;
PHX_API const Button Button_Keyboard_Apostrophe;
PHX_API const Button Button_Keyboard_Comma;
PHX_API const Button Button_Keyboard_Period;
PHX_API const Button Button_Keyboard_Slash;
PHX_API const Button Button_Keyboard_PrintScreen;
PHX_API const Button Button_Keyboard_ScrollLock;
PHX_API const Button Button_Keyboard_Pause;
PHX_API const Button Button_Keyboard_Insert;
PHX_API const Button Button_Keyboard_Delete;
PHX_API const Button Button_Keyboard_Home;
PHX_API const Button Button_Keyboard_End;
PHX_API const Button Button_Keyboard_PageUp;
PHX_API const Button Button_Keyboard_PageDown;
PHX_API const Button Button_Keyboard_Right;
PHX_API const Button Button_Keyboard_Left;
PHX_API const Button Button_Keyboard_Down;
PHX_API const Button Button_Keyboard_Up;
PHX_API const Button Button_Keyboard_LCtrl;
PHX_API const Button Button_Keyboard_LShift;
PHX_API const Button Button_Keyboard_LAlt;
PHX_API const Button Button_Keyboard_LMeta;
PHX_API const Button Button_Keyboard_RCtrl;
PHX_API const Button Button_Keyboard_RShift;
PHX_API const Button Button_Keyboard_RAlt;
PHX_API const Button Button_Keyboard_RMeta;
PHX_API const Button Button_Keyboard_Last;

PHX_API const Button Button_Mouse_First;
PHX_API const Button Button_Mouse_Left;
PHX_API const Button Button_Mouse_Middle;
PHX_API const Button Button_Mouse_Right;
PHX_API const Button Button_Mouse_X1;
PHX_API const Button Button_Mouse_X2;
PHX_API const Button Button_Mouse_X;
PHX_API const Button Button_Mouse_Y;
PHX_API const Button Button_Mouse_ScrollX;
PHX_API const Button Button_Mouse_ScrollY;
PHX_API const Button Button_Mouse_Last;

PHX_API const Button Button_Gamepad_First;
PHX_API const Button Button_Gamepad_Button_First;
PHX_API const Button Button_Gamepad_A;
PHX_API const Button Button_Gamepad_B;
PHX_API const Button Button_Gamepad_X;
PHX_API const Button Button_Gamepad_Y;
PHX_API const Button Button_Gamepad_Back;
PHX_API const Button Button_Gamepad_Guide;
PHX_API const Button Button_Gamepad_Start;
PHX_API const Button Button_Gamepad_LStick;
PHX_API const Button Button_Gamepad_RStick;
PHX_API const Button Button_Gamepad_LBumper;
PHX_API const Button Button_Gamepad_RBumper;
PHX_API const Button Button_Gamepad_Up;
PHX_API const Button Button_Gamepad_Down;
PHX_API const Button Button_Gamepad_Left;
PHX_API const Button Button_Gamepad_Right;
PHX_API const Button Button_Gamepad_Button_Last;
PHX_API const Button Button_Gamepad_Axis_First;
PHX_API const Button Button_Gamepad_LTrigger;
PHX_API const Button Button_Gamepad_RTrigger;
PHX_API const Button Button_Gamepad_LStickX;
PHX_API const Button Button_Gamepad_LStickY;
PHX_API const Button Button_Gamepad_RStickX;
PHX_API const Button Button_Gamepad_RStickY;
PHX_API const Button Button_Gamepad_Axis_Last;
PHX_API const Button Button_Gamepad_Last;

PHX_API const Button Button_System_First;
PHX_API const Button Button_System_Exit;
PHX_API const Button Button_System_Last;

PHX_API const Button Button_Last;

PHX_API DeviceType                Button_ToDeviceType             (Button);
PHX_API cstr                      Button_ToString                 (Button);

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

PRIVATE bool                      Button_IsAutoRelease            (Button);
PRIVATE Button                    Button_FromSDLScancode          (SDL_Scancode);
PRIVATE SDL_Scancode              Button_ToSDLScancode            (Button);
PRIVATE Button                    Button_FromSDLMouseButton       (uint8);
PRIVATE uint8                     Button_ToSDLMouseButton         (Button);
PRIVATE Button                    Button_FromSDLControllerAxis    (SDL_GameControllerAxis);
PRIVATE SDL_GameControllerAxis    Button_ToSDLControllerAxis      (Button);
PRIVATE Button                    Button_FromSDLControllerButton  (SDL_GameControllerButton);
PRIVATE SDL_GameControllerButton  Button_ToSDLControllerButton    (Button);

#endif


text:
#ifndef PHX_ImGui
#define PHX_ImGui

#include "Common.h"

PHX_API void ImGui_Begin (float sx, float sy);
PHX_API void ImGui_End   ();
PHX_API void ImGui_Draw  ();

PHX_API void  ImGui_AlignCursor (float sx, float sy, float alignX, float alignY);
PHX_API float ImGui_GetCursorX  ();
PHX_API float ImGui_GetCursorY  ();
PHX_API void  ImGui_PushCursor  ();
PHX_API void  ImGui_PopCursor   ();
PHX_API void  ImGui_SetCursor   (float x, float y);
PHX_API void  ImGui_SetCursorX  (float x);
PHX_API void  ImGui_SetCursorY  (float y);
PHX_API void  ImGui_Indent      ();
PHX_API void  ImGui_Undent      ();

PHX_API bool ImGui_Button      (cstr label);
PHX_API bool ImGui_ButtonEx    (cstr label, float sx, float sy);
PHX_API bool ImGui_Checkbox    (bool value);
PHX_API void ImGui_Divider     ();
PHX_API bool ImGui_Selectable  (cstr label);
PHX_API void ImGui_Tex2D       (Tex2D*);
PHX_API void ImGui_Text        (cstr text);
PHX_API void ImGui_TextColored (cstr text, float r, float g, float b, float a);
PHX_API void ImGui_TextEx      (Font* font, cstr text, float r, float g, float b, float a);

PHX_API void ImGui_BeginGroupX (float sy);
PHX_API void ImGui_BeginGroupY (float sx);
PHX_API void ImGui_EndGroup    ();

PHX_API void ImGui_BeginPanel  (float sx, float sy);
PHX_API void ImGui_EndPanel    ();

PHX_API void ImGui_BeginWindow (cstr title, float sx, float sy);
PHX_API void ImGui_EndWindow   ();

PHX_API void ImGui_BeginScrollFrame (float sx, float sy);
PHX_API void ImGui_EndScrollFrame   ();

PHX_API void ImGui_PushStyle          ();
PHX_API void ImGui_PushStyleFont      (Font*);
PHX_API void ImGui_PushStylePadding   (float px, float py);
PHX_API void ImGui_PushStyleSpacing   (float sx, float sy);
PHX_API void ImGui_PushStyleTextColor (float r, float g, float b, float a);
PHX_API void ImGui_PopStyle           ();

PHX_API void ImGui_SetFont            (Font*);
PHX_API void ImGui_SetSpacing         (float sx, float sy);

PHX_API void ImGui_SetNextWidth  (float sx);
PHX_API void ImGui_SetNextHeight (float sy);

#endif

repo_name: JoshParnell/libphx

repo_language: C

mime_type: text/x-c++


text:
#ifndef PHX_SocketType
#define PHX_SocketType

#include "Common.h"

const SocketType SocketType_None = 0x0;
const SocketType SocketType_UDP  = 0x1;
const SocketType SocketType_TCP  = 0x2;

#endif


text:
#ifndef PHX_Resource
#define PHX_Resource

#include "Common.h"
#include "ResourceType.h"

PHX_API void    Resource_AddPath    (ResourceType, cstr format);

PHX_API bool    Resource_Exists     (ResourceType, cstr name);
PHX_API cstr    Resource_GetPath    (ResourceType, cstr name);
PHX_API Bytes*  Resource_LoadBytes  (ResourceType, cstr name);
PHX_API cstr    Resource_LoadCstr   (ResourceType, cstr name);

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

PRIVATE void    Resource_Init       ();

#endif

/* TODO : Passing a null name may fail in obscure ways. Determine where we
 *        should check for this to give an appropriate error. (Namely, is it
 *        handled in Resource or File?) */


text:
#ifndef PHX_DepthTesh
#define PHX_DepthTesh

#include "Common.h"

PHX_API void  DepthTest_Pop           ();
PHX_API void  DepthTest_Push          (bool);
PHX_API void  DepthTest_PushDisabled  ();
PHX_API void  DepthTest_PushEnabled   ();

#endif


text:
#ifndef PHX_Bullet
#define PHX_Bullet
#define __FFI_IGNORE__

#include "ArrayList.h"
#include "Common.h"
#include "Draw.h"
#include "Matrix.h"
#include "MatrixDef.h"
#include "Physics.h"
#include "Quat.h"
#include "Ray.h"
#include "RigidBody.h"
#include "Trigger.h"
#include "Vec3.h"
#include "Vec4.h"

#pragma warning(push)
#pragma warning(disable : 4127) // conditional is constant
#pragma warning(disable : 4577) // noexcept with no mode specified
#pragma warning(disable : 4625) // deleted copy constructor
#pragma warning(disable : 4626) // deleted assignemnt operator
#pragma warning(disable : 5027) // deleted move operator
#include "bullet/btBulletDynamicsCommon.h"
#include "bullet/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h"
#include <bullet/BulletCollision/CollisionDispatch/btGhostObject.h>
#pragma warning(pop)

inline static Vec3f Vec3f_FromBullet (btVector3 const& v) {
  return Vec3f_Create(v.getX(), v.getY(), v.getZ());
}

inline static btVector3 Vec3f_ToBullet (Vec3f const* v) {
  return btVector3(UNPACK3(*v));
}

inline static Quat Quat_FromBullet (btQuaternion const& q) {
  return Quat_Create(q.getX(), q.getY(), q.getZ(), q.getW());
}

inline static btQuaternion Quat_ToBullet (Quat const* q) {
  return btQuaternion(UNPACK4(*q));
}

inline static void Matrix_FromTransform (btTransform* transform, Matrix* mat, float scale) {
  float* m = mat->m;
  transform->getOpenGLMatrix(m);

  /* NOTE : Inject scale. */
  m[0] *= scale; m[1] *= scale; m[ 2] *= scale;
  m[4] *= scale; m[5] *= scale; m[ 6] *= scale;
  m[8] *= scale; m[9] *= scale; m[10] *= scale;

  /* NOTE : Fix storage order. */
  Matrix_ITranspose(mat);
}

struct DebugDrawer : btIDebugDraw {
  int debugMode;
  virtual void setDebugMode(int _debugMode) { debugMode = _debugMode; }
  virtual int  getDebugMode() const { return debugMode; }

  virtual void reportErrorWarning(const char* warningString) {
    Warn(warningString);
  }

  virtual void drawLine(const btVector3& _from, const btVector3& _to, const btVector3&) {
    Vec3f from = Vec3f_FromBullet(_from);
    Vec3f to   = Vec3f_FromBullet(_to);
    Draw_Line3(&from, &to);
  }

  virtual void drawLine(const btVector3& from, const btVector3& to, const btVector3& fromColor, const btVector3&) {
    drawLine(from, to, fromColor);
  }

  virtual void drawContactPoint(const btVector3&, const btVector3&, btScalar, int, const btVector3&) { NYI; }
  virtual void draw3dText(const btVector3&, const char*) { NYI; }
};

struct RayCastCallback : public btCollisionWorld::RayResultCallback {
  btBroadphaseProxy* selfProxy;
  Ray*               ray;
  RayCastResult*     result;

  virtual bool needsCollision(btBroadphaseProxy* proxy0) const {
    bool collides = true;
    collides = collides && (proxy0->m_collisionFilterGroup & m_collisionFilterMask) != 0;
    collides = collides && (m_collisionFilterGroup & proxy0->m_collisionFilterMask) != 0;
    collides = collides && (!selfProxy || proxy0 != selfProxy);
    return collides;
  }

  virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult, bool normalInWorldSpace) {
    /* OPTIMIZE : If performance becomes an issue, most of this can be deferred. */

    m_closestHitFraction = rayResult.m_hitFraction;
    m_collisionObject    = rayResult.m_collisionObject;

    RigidBody* body = (RigidBody*) rayResult.m_collisionObject->getUserPointer();
    if (rayResult.m_localShapeInfo) {
      int iCompound = rayResult.m_localShapeInfo->m_triangleIndex;
      body = RigidBody_GetPart(body, iCompound);
    }
    result->body = body;

    btVector3 normal = rayResult.m_hitNormalLocal;
    if (!normalInWorldSpace)
      normal = m_collisionObject->getWorldTransform().getBasis() * normal;
    result->norm = Vec3f_FromBullet(normal);

    result->t = Lerp(ray->tMin, ray->tMax, rayResult.m_hitFraction);
    Ray_GetPoint(ray, result->t, &result->pos);

    return m_closestHitFraction;
  }
};

struct ShapeCastCallback : public btCollisionWorld::ContactResultCallback {
  btCollisionObject* castShape;
  btBroadphaseProxy* selfProxy;
  ShapeCastResult*   result;

  virtual bool needsCollision(btBroadphaseProxy* proxy0) const {
    bool collides = true;
    collides = collides && (proxy0->m_collisionFilterGroup & m_collisionFilterMask) != 0;
    collides = collides && (m_collisionFilterGroup & proxy0->m_collisionFilterMask) != 0;
    collides = collides && (!selfProxy || proxy0 != selfProxy);
    return collides;
  }

  virtual btScalar addSingleResult(
    btManifoldPoint&                cp,
    const btCollisionObjectWrapper* colObj0Wrap,
    int                             partId0,
    int                             index0,
    const btCollisionObjectWrapper* colObj1Wrap,
    int                             partId1,
    int                             index1) {
    /* OPTIMIZE : Assuming multiple contacts for the same object will be
                  sequential, we can remember the last object and short circuit
                  rather than searching the result list for duplicates. */

    /* WARNING : partId# and index# are uninitialized when the object is not a compound! */

    UNUSED(cp); UNUSED(partId0); UNUSED(index0); UNUSED(partId1); UNUSED(index1);
    Assert(colObj0Wrap->m_collisionObject == castShape
        || colObj1Wrap->m_collisionObject == castShape);

    colObj0Wrap = colObj0Wrap->m_collisionObject == castShape ? colObj1Wrap : colObj0Wrap;

    RigidBody* body = (RigidBody*) colObj0Wrap->m_collisionObject->getUserPointer();
    if (colObj0Wrap->m_index != -1)
      body = RigidBody_GetPart(body, colObj0Wrap->m_index);

    bool duplicate = false;
    for (int i = 0; i < ArrayList_GetSize(result->hits); i++) {
      duplicate |= ArrayList_Get(result->hits, i) == body;
    }

    if (!duplicate)
      ArrayList_Append(result->hits, body);

     /* NOTE : Unused by Bullet. */
     return 1;
  }
};

struct ShapeOverlapCallback : public btCollisionWorld::ContactResultCallback {
  btCollisionObject* castShape;
  btBroadphaseProxy* selfProxy;
  bool               foundHit;

  virtual bool needsCollision(btBroadphaseProxy* proxy0) const {
    bool collides = true;
    collides = collides && (proxy0->m_collisionFilterGroup & m_collisionFilterMask) != 0;
    collides = collides && (m_collisionFilterGroup & proxy0->m_collisionFilterMask) != 0;
    collides = collides && (!selfProxy || proxy0 != selfProxy);
    collides = collides && !foundHit;
    return collides;
  }

  virtual btScalar addSingleResult(
    btManifoldPoint&                cp,
    const btCollisionObjectWrapper* colObj0Wrap,
    int                             partId0,
    int                             index0,
    const btCollisionObjectWrapper* colObj1Wrap,
    int                             partId1,
    int                             index1) {
    UNUSED(cp);
    UNUSED(colObj0Wrap); UNUSED(partId0); UNUSED(index0);
    UNUSED(colObj1Wrap); UNUSED(partId1); UNUSED(index1);
    Assert(colObj0Wrap->m_collisionObject == castShape
        || colObj1Wrap->m_collisionObject == castShape);

    foundHit = true;

     /* NOTE : Unused by Bullet. */
     return 1;
  }
};

struct GhostObject : public btGhostObject {
  /* HACK : Ensure checkCollideWithOverride will get called. */
  GhostObject() {
    setIgnoreCollisionCheck(0, true);
  }

  /* NOTE: This prevents Triggers from tracking other triggers and the RigidBody
           they are attached to. Anything that gets past this filter will be in
           Trigger_GetContents. */
  bool needBroadphaseCollision(const btCollisionObject* co) const {
    typedef btCollisionObject::CollisionObjectTypes Type;
    bool collide = true;
    collide = collide && co->getInternalType() != Type::CO_GHOST_OBJECT;
    collide = collide && co->getUserPointer() != Trigger_GetParent((Trigger*) getUserPointer());
    return collide;
  }

  /* NOTE: Triggers *never* want narrowphase collision. This prevents wasted
           work calculating contact points between triggers and the objects
           within them. Since tracking happens in broadphase we've already add
           the object to our list. */
  virtual bool checkCollideWithOverride(const btCollisionObject*) const {
     return false;
  }
};

struct BroadphaseFilterCallback : public btOverlapFilterCallback {
  virtual bool needBroadphaseCollision(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) const {
    btCollisionObject* colObj0 = (btCollisionObject*) proxy0->m_clientObject;
    btCollisionObject* colObj1 = (btCollisionObject*) proxy1->m_clientObject;

    typedef btCollisionObject::CollisionObjectTypes Type;
    bool collide = true;
    if (colObj0->getInternalType() == Type::CO_GHOST_OBJECT)
      collide = collide && ((GhostObject*) colObj0)->needBroadphaseCollision(colObj1);
    if (colObj1->getInternalType() == Type::CO_GHOST_OBJECT)
      collide = collide && ((GhostObject*) colObj1)->needBroadphaseCollision(colObj0);
    return collide;
  }
};

#endif


text:
#ifndef PHX_ShaderState
#define PHX_ShaderState

#include "Common.h"

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

PHX_API ShaderState*  ShaderState_Create          (Shader*);
PHX_API void          ShaderState_Acquire         (ShaderState*);
PHX_API void          ShaderState_Free            (ShaderState*);
PHX_API ShaderState*  ShaderState_FromShaderLoad  (cstr vertName, cstr fragName);

PHX_API void          ShaderState_SetFloat        (ShaderState*, cstr, float);
PHX_API void          ShaderState_SetFloat2       (ShaderState*, cstr, float, float);
PHX_API void          ShaderState_SetFloat3       (ShaderState*, cstr, float, float, float);
PHX_API void          ShaderState_SetFloat4       (ShaderState*, cstr, float, float, float, float);
PHX_API void          ShaderState_SetInt          (ShaderState*, cstr, int);
PHX_API void          ShaderState_SetMatrix       (ShaderState*, cstr, Matrix*);
PHX_API void          ShaderState_SetTex1D        (ShaderState*, cstr, Tex1D*);
PHX_API void          ShaderState_SetTex2D        (ShaderState*, cstr, Tex2D*);
PHX_API void          ShaderState_SetTex3D        (ShaderState*, cstr, Tex3D*);
PHX_API void          ShaderState_SetTexCube      (ShaderState*, cstr, TexCube*);

PHX_API void          ShaderState_Start           (ShaderState*);
PHX_API void          ShaderState_Stop            (ShaderState*);

#endif


text:
#ifndef PHX_FMODError
#define PHX_FMODError

#include "Common.h"
#include "fmod/fmod.h"
#include "fmod/fmod_errors.h"

#define FMODERROR_X                                                            \
  X(FMOD_OK)                                                                   \
  X(FMOD_ERR_BADCOMMAND)                                                       \
  X(FMOD_ERR_CHANNEL_ALLOC)                                                    \
  X(FMOD_ERR_CHANNEL_STOLEN)                                                   \
  X(FMOD_ERR_DMA)                                                              \
  X(FMOD_ERR_DSP_CONNECTION)                                                   \
  X(FMOD_ERR_DSP_DONTPROCESS)                                                  \
  X(FMOD_ERR_DSP_FORMAT)                                                       \
  X(FMOD_ERR_DSP_INUSE)                                                        \
  X(FMOD_ERR_DSP_NOTFOUND)                                                     \
  X(FMOD_ERR_DSP_RESERVED)                                                     \
  X(FMOD_ERR_DSP_SILENCE)                                                      \
  X(FMOD_ERR_DSP_TYPE)                                                         \
  X(FMOD_ERR_FILE_BAD)                                                         \
  X(FMOD_ERR_FILE_COULDNOTSEEK)                                                \
  X(FMOD_ERR_FILE_DISKEJECTED)                                                 \
  X(FMOD_ERR_FILE_EOF)                                                         \
  X(FMOD_ERR_FILE_ENDOFDATA)                                                   \
  X(FMOD_ERR_FILE_NOTFOUND)                                                    \
  X(FMOD_ERR_FORMAT)                                                           \
  X(FMOD_ERR_HEADER_MISMATCH)                                                  \
  X(FMOD_ERR_HTTP)                                                             \
  X(FMOD_ERR_HTTP_ACCESS)                                                      \
  X(FMOD_ERR_HTTP_PROXY_AUTH)                                                  \
  X(FMOD_ERR_HTTP_SERVER_ERROR)                                                \
  X(FMOD_ERR_HTTP_TIMEOUT)                                                     \
  X(FMOD_ERR_INITIALIZATION)                                                   \
  X(FMOD_ERR_INITIALIZED)                                                      \
  X(FMOD_ERR_INTERNAL)                                                         \
  X(FMOD_ERR_INVALID_FLOAT)                                                    \
  X(FMOD_ERR_INVALID_HANDLE)                                                   \
  X(FMOD_ERR_INVALID_PARAM)                                                    \
  X(FMOD_ERR_INVALID_POSITION)                                                 \
  X(FMOD_ERR_INVALID_SPEAKER)                                                  \
  X(FMOD_ERR_INVALID_SYNCPOINT)                                                \
  X(FMOD_ERR_INVALID_THREAD)                                                   \
  X(FMOD_ERR_INVALID_VECTOR)                                                   \
  X(FMOD_ERR_MAXAUDIBLE)                                                       \
  X(FMOD_ERR_MEMORY)                                                           \
  X(FMOD_ERR_MEMORY_CANTPOINT)                                                 \
  X(FMOD_ERR_NEEDS3D)                                                          \
  X(FMOD_ERR_NEEDSHARDWARE)                                                    \
  X(FMOD_ERR_NET_CONNECT)                                                      \
  X(FMOD_ERR_NET_SOCKET_ERROR)                                                 \
  X(FMOD_ERR_NET_URL)                                                          \
  X(FMOD_ERR_NET_WOULD_BLOCK)                                                  \
  X(FMOD_ERR_NOTREADY)                                                         \
  X(FMOD_ERR_OUTPUT_ALLOCATED)                                                 \
  X(FMOD_ERR_OUTPUT_CREATEBUFFER)                                              \
  X(FMOD_ERR_OUTPUT_DRIVERCALL)                                                \
  X(FMOD_ERR_OUTPUT_FORMAT)                                                    \
  X(FMOD_ERR_OUTPUT_INIT)                                                      \
  X(FMOD_ERR_OUTPUT_NODRIVERS)                                                 \
  X(FMOD_ERR_PLUGIN)                                                           \
  X(FMOD_ERR_PLUGIN_MISSING)                                                   \
  X(FMOD_ERR_PLUGIN_RESOURCE)                                                  \
  X(FMOD_ERR_PLUGIN_VERSION)                                                   \
  X(FMOD_ERR_RECORD)                                                           \
  X(FMOD_ERR_REVERB_CHANNELGROUP)                                              \
  X(FMOD_ERR_REVERB_INSTANCE)                                                  \
  X(FMOD_ERR_SUBSOUNDS)                                                        \
  X(FMOD_ERR_SUBSOUND_ALLOCATED)                                               \
  X(FMOD_ERR_SUBSOUND_CANTMOVE)                                                \
  X(FMOD_ERR_TAGNOTFOUND)                                                      \
  X(FMOD_ERR_TOOMANYCHANNELS)                                                  \
  X(FMOD_ERR_TRUNCATED)                                                        \
  X(FMOD_ERR_UNIMPLEMENTED)                                                    \
  X(FMOD_ERR_UNINITIALIZED)                                                    \
  X(FMOD_ERR_UNSUPPORTED)                                                      \
  X(FMOD_ERR_VERSION)                                                          \
  X(FMOD_ERR_EVENT_ALREADY_LOADED)                                             \
  X(FMOD_ERR_EVENT_LIVEUPDATE_BUSY)                                            \
  X(FMOD_ERR_EVENT_LIVEUPDATE_MISMATCH)                                        \
  X(FMOD_ERR_EVENT_LIVEUPDATE_TIMEOUT)                                         \
  X(FMOD_ERR_EVENT_NOTFOUND)                                                   \
  X(FMOD_ERR_STUDIO_UNINITIALIZED)                                             \
  X(FMOD_ERR_STUDIO_NOT_LOADED)                                                \
  X(FMOD_ERR_INVALID_STRING)                                                   \
  X(FMOD_ERR_ALREADY_LOCKED)                                                   \
  X(FMOD_ERR_NOT_LOCKED)                                                       \
  X(FMOD_ERR_RECORD_DISCONNECTED)                                              \
  X(FMOD_ERR_TOOMANYSAMPLES)                                                   \
  X(FMOD_RESULT_FORCEINT)

inline cstr FMODError_ToString (FMOD_RESULT self) {
  switch (self) {
#define X(x) case x: return #x;
    FMODERROR_X
#undef X
  };
  return "Unknown Error";
}

inline void FMOD_CheckError (FMOD_RESULT result, cstr file, int line, cstr func) {
  if (result != FMOD_OK) {
    Fatal("%s: %s\n%s\n  [%s @ Line %d]",
      func, FMODError_ToString(result), FMOD_ErrorString(result), file, line
    );
  }
}
#define FMODCALL(r) FMOD_CheckError(r, __FILE__, __LINE__, __func__)

#endif


text:
#ifndef PHX_Gamepad
#define PHX_Gamepad

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

#include "Common.h"

PHX_API  bool      Gamepad_CanOpen            (int index);
PHX_API  Gamepad*  Gamepad_Open               (int index);
PHX_API  void      Gamepad_Close              (Gamepad*);

PHX_API  int       Gamepad_AddMappings        (cstr file);

PHX_API  double    Gamepad_GetAxis            (Gamepad*, GamepadAxis);
PHX_API  double    Gamepad_GetAxisDelta       (Gamepad*, GamepadAxis);
PHX_API  bool      Gamepad_GetButton          (Gamepad*, GamepadButton);
PHX_API  double    Gamepad_GetButtonPressed   (Gamepad*, GamepadButton);
PHX_API  double    Gamepad_GetButtonReleased  (Gamepad*, GamepadButton);
PHX_API  double    Gamepad_GetIdleTime        (Gamepad*);
PHX_API  int       Gamepad_GetID              (Gamepad*);
PHX_API  cstr      Gamepad_GetName            (Gamepad*);
PHX_API  bool      Gamepad_IsConnected        (Gamepad*);
PHX_API  void      Gamepad_SetDeadzone        (Gamepad*, GamepadAxis, double);

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

PRIVATE void       Gamepad_Update             ();

#endif


text:
#ifndef PHX_Quat
#define PHX_Quat

#include "Common.h"

/* --- API NOTES ---------------------------------------------------------------
 *
 *   Unlike matrices, Quats are PRE-multiplicative with respect to vectors.
 *   Hence, Quat_Mul(A, B) procudes a quaternion that rotates first by A, THEN
 *   by B.
 *
 * -------------------------------------------------------------------------- */

struct Quat {
  float x;
  float y;
  float z;
  float w;
};

PHX_API Quat   Quat_Create              (float x, float y, float z, float w);

PHX_API void   Quat_GetAxisX            (Quat const*, Vec3f*);
PHX_API void   Quat_GetAxisY            (Quat const*, Vec3f*);
PHX_API void   Quat_GetAxisZ            (Quat const*, Vec3f*);
PHX_API void   Quat_GetForward          (Quat const*, Vec3f*);
PHX_API void   Quat_GetRight            (Quat const*, Vec3f*);
PHX_API void   Quat_GetUp               (Quat const*, Vec3f*);

PHX_API void   Quat_Identity            (Quat*);

PHX_API void   Quat_Canonicalize        (Quat const*, Quat* out);
PHX_API void   Quat_ICanonicalize       (Quat*);
PHX_API float  Quat_Dot                 (Quat const*, Quat const*);
PHX_API bool   Quat_Equal               (Quat const*, Quat const*);
PHX_API bool   Quat_ApproximatelyEqual  (Quat const*, Quat const*);
PHX_API void   Quat_Inverse             (Quat const*, Quat* out);
PHX_API void   Quat_IInverse            (Quat*);
PHX_API void   Quat_Lerp                (Quat const*, Quat const*, float t, Quat* out);
PHX_API void   Quat_ILerp               (Quat*, Quat const*, float t);
PHX_API void   Quat_Mul                 (Quat const*, Quat const*, Quat* out);
PHX_API void   Quat_IMul                (Quat*, Quat const*);
PHX_API void   Quat_MulV                (Quat const*, Vec3f const*, Vec3f* out);
PHX_API void   Quat_Normalize           (Quat const*, Quat* out);
PHX_API void   Quat_INormalize          (Quat*);
PHX_API void   Quat_Scale               (Quat const*, float, Quat* out);
PHX_API void   Quat_IScale              (Quat*, float);
PHX_API void   Quat_Slerp               (Quat const*, Quat const*, float, Quat* out);
PHX_API void   Quat_ISlerp              (Quat*, Quat const*, float);

PHX_API cstr   Quat_ToString            (Quat const*);
PHX_API Error  Quat_Validate            (Quat const*);

PHX_API void   Quat_FromAxisAngle       (Vec3f const* axis, float radians, Quat*);
PHX_API void   Quat_FromBasis           (Vec3f const* x, Vec3f const* y, Vec3f const* z, Quat*);
PHX_API void   Quat_FromLookUp          (Vec3f const* look, Vec3f const* up, Quat*);
//PHX_API void   Quat_FromMatrix          ();
//PHX_API void   Quat_ToMatrix            ();
PHX_API void   Quat_FromRotateTo        (Vec3f const* from, Vec3f const* to, Quat*);

#endif

/* TODO : Quat_FromAxisAngle takes radians. Ensure this matches the rest of the engine API */


text:
#ifndef PHX_RenderTarget
#define PHX_RenderTarget

#include "Common.h"

/* --- RenderTarget ------------------------------------------------------------
 *
 *   The RenderTarget_*Level variants bind a specific mip level of the given
 *   texture. Level 0 is the primary texture and the default for the non-level
 *   variants; level 1 is the first mip level, level log2(res) is the final
 *   (single-texel) mip level.
 *
 *   The RenderTarget_PushTex* functions are convenience wrappers for binding
 *   a single texture as the sole framebuffer target. The Push/Pop and Bind
 *   functions must be used if a more advanced framebuffer configuration is
 *   needed (e.g. multiple output surfaces, depth attachments, etc.)
 *
 * -------------------------------------------------------------------------- */

PHX_API void  RenderTarget_Push              (int sx, int sy);
PHX_API void  RenderTarget_Pop               ();

PHX_API void  RenderTarget_BindTex2D         (Tex2D*);
PHX_API void  RenderTarget_BindTex2DLevel    (Tex2D*, int level);
PHX_API void  RenderTarget_BindTex3D         (Tex3D*, int layer);
PHX_API void  RenderTarget_BindTex3DLevel    (Tex3D*, int layer, int level);
PHX_API void  RenderTarget_BindTexCube       (TexCube*, CubeFace);
PHX_API void  RenderTarget_BindTexCubeLevel  (TexCube*, CubeFace, int level);

PHX_API void  RenderTarget_PushTex2D         (Tex2D*);
PHX_API void  RenderTarget_PushTex2DLevel    (Tex2D*, int level);
PHX_API void  RenderTarget_PushTex3D         (Tex3D*, int layer);
PHX_API void  RenderTarget_PushTex3DLevel    (Tex3D*, int layer, int level);

#endif


text:
#ifndef PHX_Bit
#define PHX_Bit

#include "Common.h"

inline uint32 Bit_RotL32(uint32 x, int n) { return (x << n) | (x >> (32 - n)); }
inline uint32 Bit_RotR32(uint32 x, int n) { return (x << (32 - n) | (x >> n)); }

inline uint64 Bit_RotL64(uint64 x, int n) { return (x << n) | (x >> (64 - n)); }
inline uint64 Bit_RotR64(uint64 x, int n) { return (x << (64 - n) | (x >> n)); }

PHX_API uint32  Bit_And32  (uint32 x, uint32 y);
PHX_API uint32  Bit_Or32   (uint32 x, uint32 y);
PHX_API uint32  Bit_Xor32  (uint32 x, uint32 y);
PHX_API bool    Bit_Has32  (uint32 x, uint32 y);

PHX_API uint64  Bit_And64  (uint64 x, uint64 y);
PHX_API uint64  Bit_Or64   (uint64 x, uint64 y);
PHX_API uint64  Bit_Xor64  (uint64 x, uint64 y);
PHX_API bool    Bit_Has64  (uint64 x, uint64 y);

#endif


text:
#ifndef PHX_BSP
#define PHX_BSP

#include "ArrayList.h"
#include "Intersect.h"
#include "Mesh.h"
#include "Vec3.h"

PHX_API BSP*  BSP_Create                (Mesh*);
PHX_API void  BSP_Free                  (BSP*);

PHX_API bool  BSP_IntersectRay          (BSP*, Ray const*, float* tHit);
PHX_API bool  BSP_IntersectLineSegment  (BSP*, LineSegment const*, Vec3f* pHit);
PHX_API bool  BSP_IntersectSphere       (BSP*, Sphere const*, Vec3f* pHit);

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

PHX_API const BSPNodeRel BSPNodeRel_Parent;
PHX_API const BSPNodeRel BSPNodeRel_Back;
PHX_API const BSPNodeRel BSPNodeRel_Front;

struct BSPNodeRef {
  int32 index;
  uint8 triangleCount;
};

struct TriangleTest {
  Triangle* triangle;
  bool      hit;
};

struct IntersectSphereProfiling {
  int32                   nodes;
  int32                   leaves;
  int32                   triangles;
  ArrayList(TriangleTest, triangleTests);
};

PHX_API BSPNodeRef  BSPDebug_GetNode                      (BSP*, BSPNodeRef, BSPNodeRel);
PHX_API void        BSPDebug_DrawNode                     (BSP*, BSPNodeRef);
PHX_API void        BSPDebug_DrawNodeSplit                (BSP*, BSPNodeRef);
PHX_API void        BSPDebug_DrawLineSegment              (BSP*, LineSegment*);
PHX_API void        BSPDebug_DrawSphere                   (BSP*, Sphere*);
PHX_API void        BSPDebug_PrintRayProfilingData        (BSP*, double totalTime);
PHX_API void        BSPDebug_PrintSphereProfilingData     (BSP*, double totalTime);

PHX_API bool        BSPDebug_GetIntersectSphereTriangles  (BSP*, Sphere*, IntersectSphereProfiling* sphereProf);
PHX_API BSPNodeRef  BSPDebug_GetLeaf                      (BSP*, int32 leafIndex);

#endif


text:
#ifndef PHX_Viewport
#define PHX_Viewport

#include "Common.h"

PHX_API void   Viewport_Pop        ();
PHX_API void   Viewport_Push       (int x, int y, int sx, int sy, bool isWindow);
PHX_API float  Viewport_GetAspect  ();
PHX_API void   Viewport_GetSize    (Vec2i* out);

#endif


text:
#ifndef PHX_RNG
#define PHX_RNG

#include "Common.h"

/* --- RNG ---------------------------------------------------------------------
 *
 *   A 64-bit random number generator with convenience methods for generating
 *   a wide variety of random objects and distributions.
 *
 *   RNGs are lightweight, using the Xoroshiro128 algorithm for high-quality
 *   random numbers with high performance and a small internal state. As such,
 *   they can be created and destroyed fairly liberally.
 *
 *   Distribution functions:
 *
 *     RNG_Chance          : True with the given probability (in [0, 1])
 *     RNG_Get31           : Uniform non-negative 32-bit signed integer
 *     RNG_GetAngle        : Uniform angle in [0, 2Pi]
 *     RNG_GetErlang       : Sum of k exponentially-distributed variables
 *     RNG_GetExp          : Exponentially-distributed random variable
 *     RNG_GetGaussian     : Gaussian-distributed random variable with mean 0,
 *                           variance 1
 *     RNG_GetRNG          : Equivalent to RNG_Create(RNG_Get64(self))
 *     RNG_GetUniform      : Uniform double in [0, 1] (inclusive!)
 *     RNG_GetUniformRange : Uniform double in [lower, upper]
 *     RNG_GetAxis2        : {(+-1, 0), (0, +-1)}
 *     RNG_GetAxis3        : {(+-1, 0, 0), (0, +-1, 0), (0, 0, +-1)}
 *     RNG_GetDir2         : Uniform Vec2 with unit length
 *     RNG_GetDir3         : Uniform Vec3 with unit length
 *     RNG_GetDisc         : Uniform Vec2 inside the unit disc
 *     RNG_GetSign         : {-1, 1} with equal probability
 *     RNG_GetSphere       : Uniform Vec3 inside the unit sphere
 *     RNG_GetQuat         : Uniform orientation in 3D space
 *
 * -------------------------------------------------------------------------- */

PHX_API RNG*    RNG_Create           (uint64 seed);
PHX_API RNG*    RNG_FromStr          (cstr);
PHX_API RNG*    RNG_FromTime         ();
PHX_API void    RNG_Free             (RNG*);
PHX_API void    RNG_Rewind           (RNG*);

PHX_API bool    RNG_Chance           (RNG*, double probability);
PHX_API  int32  RNG_Get31            (RNG*);
PHX_API uint32  RNG_Get32            (RNG*);
PHX_API uint64  RNG_Get64            (RNG*);
PHX_API double  RNG_GetAngle         (RNG*);
PHX_API double  RNG_GetErlang        (RNG*, int k);
PHX_API double  RNG_GetExp           (RNG*);
PHX_API double  RNG_GetGaussian      (RNG*);
PHX_API int     RNG_GetInt           (RNG*, int lower, int upper);
PHX_API RNG*    RNG_GetRNG           (RNG*);
PHX_API double  RNG_GetSign          (RNG*);
PHX_API double  RNG_GetUniform       (RNG*);
PHX_API double  RNG_GetUniformRange  (RNG*, double lower, double upper);

PHX_API void    RNG_GetAxis2         (RNG*, Vec2f* out);
PHX_API void    RNG_GetAxis3         (RNG*, Vec3f* out);

PHX_API void    RNG_GetDir2          (RNG*, Vec2f* out);
PHX_API void    RNG_GetDir3          (RNG*, Vec3f* out);
PHX_API void    RNG_GetDisc          (RNG*, Vec2f* out);
PHX_API void    RNG_GetSphere        (RNG*, Vec3f* out);

PHX_API void    RNG_GetVec2          (RNG*, Vec2f* out, double lower, double upper);
PHX_API void    RNG_GetVec3          (RNG*, Vec3f* out, double lower, double upper);
PHX_API void    RNG_GetVec4          (RNG*, Vec4f* out, double lower, double upper);

PHX_API void    RNG_GetQuat          (RNG*, Quat* out);

#endif


text:
#ifndef PHX_StrBuffer
#define PHX_StrBuffer

#include "Common.h"

PHX_API StrBuffer*  StrBuffer_Create     (uint32 capacity);
PHX_API StrBuffer*  StrBuffer_FromStr    (cstr);
PHX_API void        StrBuffer_Free       (StrBuffer*);

PHX_API void        StrBuffer_Append     (StrBuffer*, StrBuffer*);
PHX_API void        StrBuffer_AppendStr  (StrBuffer*, cstr);
PHX_API void        StrBuffer_Set        (StrBuffer*, cstr format, ...);
PHX_API StrBuffer*  StrBuffer_Clone      (StrBuffer*);
PHX_API cstr        StrBuffer_GetData    (StrBuffer*);

#endif


text:
#ifndef PHX_Modifier
#define PHX_Modifier

#include "Common.h"

PHX_API const Modifier Modifier_Null;
PHX_API const Modifier Modifier_Alt;
PHX_API const Modifier Modifier_Ctrl;
PHX_API const Modifier Modifier_Shift;

PHX_API cstr  Modifier_ToString  (Modifier);

#endif


text:
#ifndef PHX_Thread
#define PHX_Thread

#include "Common.h"

/* --- API NOTES ---------------------------------------------------------------
 *
 *  One must choose carefully whether to detach a thread or not. When threads
 *  need to be tightly-synced with the main thread, it is generally more
 *  convenient to keep them attached (as they are by default), and call
 *  Thread_Wait when the main thread needs to ensure that the threaded function
 *  has completed (and to obtain the return code). Threads are not explicitly
 *  freed, since either Thread_Detach or Thread_Wait will end up consuming any
 *  given thread's handle.
 *
 *   Thread_Detach : A detached thread runs its ThreadFn until completion,
 *                   then returns and is automatically destroyed.
 *                 : Consumes the Thread*. A detached thread can no longer be
 *                   accessed by Thread handle. This means it can NOT be waited
 *                   on.
 *                 : Typically used for processes that implement their own loop
 *                   and run independently of the main thread, or asynchronous
 *                   jobs that do not need to be polled for completion.
 *
 *                   Note that it is not possible to obtain the return code
 *                   from a detached thread.
 *
 *   Thread_Wait   : For non-detached threads, wait on the thread to complete
 *                   and then return the corresponding ThreadFn return code.
 *                 : Consumes the Thread*.
 *
 * -------------------------------------------------------------------------- */

typedef int (*ThreadFn)(void* data);

PHX_API Thread*  Thread_Create  (cstr name, ThreadFn, void* data);
PHX_API void     Thread_Detach  (Thread*);
PHX_API void     Thread_Sleep   (uint ms);
PHX_API int      Thread_Wait    (Thread*);

#endif


text:
#ifndef PHX_Vec3
#define PHX_Vec3

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

#include <stdio.h>

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

#define UNPACK3(v) (v).x, (v).y, (v).z
#define REPEAT3(v) (v), (v), (v)

struct Vec3i { int x, y, z; };
struct Vec3d { double x, y, z; };
struct Vec3f { float x, y, z; };

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

#define Vec3_Rep(T, sub) inline T T##_Rep(sub r) { \
  T self = { r, r, r }; return self; }

#define Vec3_Add(T) inline T T##_Add(T a, T b) { \
  T self = { a.x + b.x, a.y + b.y, a.z + b.z }; return self; }
#define Vec3_Div(T) inline T T##_Div(T a, T b) { \
  T self = { a.x / b.x, a.y / b.y, a.z / b.z }; return self; }
#define Vec3_Mul(T) inline T T##_Mul(T a, T b) { \
  T self = { a.x * b.x, a.y * b.y, a.z * b.z }; return self; }
#define Vec3_Sub(T) inline T T##_Sub(T a, T b) { \
  T self = { a.x - b.x, a.y - b.y, a.z - b.z }; return self; }

#define Vec3_IAdd(T) inline void T##_IAdd(T* a, T b) { \
  a->x += b.x; a->y += b.y; a->z += b.z; }
#define Vec3_IDiv(T) inline void T##_IDiv(T* a, T b) { \
  a->x /= b.x; a->y /= b.y; a->z /= b.z; }
#define Vec3_IMul(T) inline void T##_IMul(T* a, T b) { \
  a->x *= b.x; a->y *= b.y; a->z *= b.z; }
#define Vec3_ISub(T) inline void T##_ISub(T* a, T b) { \
  a->x -= b.x; a->y -= b.y; a->z -= b.z; }

#define Vec3_Adds(T, sub) inline T T##_Adds(T a, sub b) { \
  T self = { a.x + b, a.y + b, a.z + b }; return self; }
#define Vec3_Divs(T, sub) inline T T##_Divs(T a, sub b) { \
  T self = { a.x / b, a.y / b, a.z / b }; return self; }
#define Vec3_Muls(T, sub) inline T T##_Muls(T a, sub b) { \
  T self = { a.x * b, a.y * b, a.z * b }; return self; }
#define Vec3_Subs(T, sub) inline T T##_Subs(T a, sub b) { \
  T self = { a.x - b, a.y - b, a.z - b }; return self; }

#define Vec3_IAdds(T, sub) inline void T##_IAdds(T* a, sub b) { \
  a->x += b; a->y += b; a->z += b; }
#define Vec3_IDivs(T, sub) inline void T##_IDivs(T* a, sub b) { \
  a->x /= b; a->y /= b; a->z /= b; }
#define Vec3_IMuls(T, sub) inline void T##_IMuls(T* a, sub b) { \
  a->x *= b; a->y *= b; a->z *= b; }
#define Vec3_ISubs(T, sub) inline void T##_ISubs(T* a, sub b) { \
  a->x -= b; a->y -= b; a->z -= b; }

Vec3_Create(Vec3i, int)
Vec3_Create(Vec3d, double)
Vec3_Create(Vec3f, float)

Vec3_Rep(Vec3i, int)
Vec3_Rep(Vec3d, double)
Vec3_Rep(Vec3f, float)

Vec3_Add(Vec3i) Vec3_Add(Vec3d) Vec3_Add(Vec3f)
Vec3_Div(Vec3i) Vec3_Div(Vec3d) Vec3_Div(Vec3f)
Vec3_Mul(Vec3i) Vec3_Mul(Vec3d) Vec3_Mul(Vec3f)
Vec3_Sub(Vec3i) Vec3_Sub(Vec3d) Vec3_Sub(Vec3f)

Vec3_IAdd(Vec3i) Vec3_IAdd(Vec3d) Vec3_IAdd(Vec3f)
Vec3_IDiv(Vec3i) Vec3_IDiv(Vec3d) Vec3_IDiv(Vec3f)
Vec3_IMul(Vec3i) Vec3_IMul(Vec3d) Vec3_IMul(Vec3f)
Vec3_ISub(Vec3i) Vec3_ISub(Vec3d) Vec3_ISub(Vec3f)

Vec3_Adds(Vec3i, int) Vec3_Adds(Vec3d, double) Vec3_Adds(Vec3f, float)
Vec3_Divs(Vec3i, int) Vec3_Divs(Vec3d, double) Vec3_Divs(Vec3f, float)
Vec3_Muls(Vec3i, int) Vec3_Muls(Vec3d, double) Vec3_Muls(Vec3f, float)
Vec3_Subs(Vec3i, int) Vec3_Subs(Vec3d, double) Vec3_Subs(Vec3f, float)

Vec3_IAdds(Vec3i, int) Vec3_IAdds(Vec3d, double) Vec3_IAdds(Vec3f, float)
Vec3_IDivs(Vec3i, int) Vec3_IDivs(Vec3d, double) Vec3_IDivs(Vec3f, float)
Vec3_IMuls(Vec3i, int) Vec3_IMuls(Vec3d, double) Vec3_IMuls(Vec3f, float)
Vec3_ISubs(Vec3i, int) Vec3_ISubs(Vec3d, double) Vec3_ISubs(Vec3f, float)

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

Vec3_Abs(Vec3i)
Vec3_Abs(Vec3f)
Vec3_Abs(Vec3d)

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

Vec3_IAbs(Vec3i)
Vec3_IAbs(Vec3f)
Vec3_IAbs(Vec3d)

#define Vec3_Clamp(T) inline T T##_Clamp(T v, T lower, T upper) { \
  T self = { \
    Clamp(v.x, lower.x, upper.x), \
    Clamp(v.y, lower.y, upper.y), \
    Clamp(v.z, lower.z, upper.z), \
  }; \
  return self; }

Vec3_Clamp(Vec3i)
Vec3_Clamp(Vec3f)
Vec3_Clamp(Vec3d)

#define Vec3_Cross(T) inline T T##_Cross(T a, T b) { \
  T self = { \
    b.z * a.y - b.y * a.z, \
    b.x * a.z - b.z * a.x, \
    b.y * a.x - b.x * a.y, \
  }; \
  return self; }

Vec3_Cross(Vec3i)
Vec3_Cross(Vec3f)
Vec3_Cross(Vec3d)

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

Vec3_Equal(Vec3i)
Vec3_Equal(Vec3f)
Vec3_Equal(Vec3d)

#define Vec3_Distance(T, sub) inline sub T##_Distance(T a, T b) { \
  sub dx = a.x - b.x, dy = a.y - b.y, dz = a.z - b.z; \
  return Sqrt(dx * dx + dy * dy + dz * dz); }

Vec3_Distance(Vec3f, float)
Vec3_Distance(Vec3d, double)

#define Vec3_DistanceSquared(T, sub) inline sub T##_DistanceSquared(T a, T b) { \
  sub dx = a.x - b.x, dy = a.y - b.y, dz = a.z - b.z; \
  return dx * dx + dy * dy + dz * dz; }

Vec3_DistanceSquared(Vec3i, int)
Vec3_DistanceSquared(Vec3f, float)
Vec3_DistanceSquared(Vec3d, double)

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

Vec3_Dot(Vec3i, int)
Vec3_Dot(Vec3f, float)
Vec3_Dot(Vec3d, double)

Vec3_Dots(Vec3i, int)
Vec3_Dots(Vec3f, float)
Vec3_Dots(Vec3d, double)

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

Vec3_Length(Vec3f, float)
Vec3_Length(Vec3d, double)

inline float Vec3i_Length(Vec3i v) {
  return Sqrt(
      (float)v.x * (float)v.x
    + (float)v.y * (float)v.y
    + (float)v.z * (float)v.z);
}

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

Vec3_LengthSquared(Vec3i, int)
Vec3_LengthSquared(Vec3f, float)
Vec3_LengthSquared(Vec3d, double)

#define Vec3_Lerp(T, sub) inline T T##_Lerp(T a, T b, sub t) { \
  T self = { \
    a.x + (b.x - a.x) * t, \
    a.y + (b.y - a.y) * t, \
    a.z + (b.z - a.z) * t, \
  }; \
  return self; }

Vec3_Lerp(Vec3f, float)
Vec3_Lerp(Vec3d, double)

#define Vec3_Max(T) inline T T##_Max(T a, T b) { \
  T self = { Max(a.x, b.x), Max(a.y, b.y), Max(a.z, b.z) }; return self; }

#define Vec3_Min(T) inline T T##_Min(T a, T b) { \
  T self = { Min(a.x, b.x), Min(a.y, b.y), Min(a.z, b.z) }; return self; }

Vec3_Max(Vec3i)
Vec3_Max(Vec3f)
Vec3_Max(Vec3d)
Vec3_Min(Vec3i)
Vec3_Min(Vec3f)
Vec3_Min(Vec3d)

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

#define Vec3_SNormalize(T, sub) inline T T##_SNormalize(T v) { \
  sub l = T##_Length(v); \
  if (l > 0) { T self = { v.x / l, v.y / l, v.z / l }; return self; } \
  return v; }

Vec3_Normalize(Vec3f, float)
Vec3_Normalize(Vec3d, double)
Vec3_SNormalize(Vec3f, float)
Vec3_SNormalize(Vec3d, double)

#define Vec3_Pow(T) inline T T##_Pow(T a, T b) { \
  T self = { Pow(a.x, b.x), Pow(a.y, b.y), Pow(a.z, b.z) }; return self; }
#define Vec3_Pows(T, sub) inline T T##_Pows(T a, sub b) { \
  T self = { Pow(a.x, b), Pow(a.y, b), Pow(a.z, b) }; return self; }

Vec3_Pow(Vec3d)
Vec3_Pow(Vec3f)
Vec3_Pows(Vec3d, double)
Vec3_Pows(Vec3f, float)

#define Vec3_Project(T, sub) inline T T##_Project(T a, T b) { \
  sub d = T##_Dot(a, b); \
  T self = { d * b.x, d * b.y, d * b.z }; return self; }

Vec3_Project(Vec3i, int)
Vec3_Project(Vec3f, float)
Vec3_Project(Vec3d, double)

#define Vec3_Rcp(T, sub) inline T T##_Rcp(T a) { \
  T self = { \
    (sub)(1.0 / a.x), \
    (sub)(1.0 / a.y), \
    (sub)(1.0 / a.z), \
  }; \
  return self; }

Vec3_Rcp(Vec3i, int)
Vec3_Rcp(Vec3d, double)
Vec3_Rcp(Vec3f, float)

#define Vec3_Reject(T, sub) inline T T##_Reject(T a, T b) { \
  sub d = T##_Dot(a, b); \
  T self = { a.x - d * b.x, a.y - d * b.y, a.z - d * b.z }; return self; }

Vec3_Reject(Vec3i, int)
Vec3_Reject(Vec3f, float)
Vec3_Reject(Vec3d, double)

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

Vec3_To(Vec3i, Vec3f, float)
Vec3_To(Vec3i, Vec3d, double)
Vec3_To(Vec3f, Vec3i, int)
Vec3_To(Vec3f, Vec3d, double)
Vec3_To(Vec3d, Vec3i, int)
Vec3_To(Vec3d, Vec3f, float)

#define Vec3_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); \
  return e; }

Vec3_Validate(Vec3f, float)
Vec3_Validate(Vec3d, double)

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

Vec3_ToString(Vec3i, int,    "%i")
Vec3_ToString(Vec3f, float,  "%.4f")
Vec3_ToString(Vec3d, double, "%.4f")

#endif


text:
#ifndef PHX_Intersect
#define PHX_Intersect

#include "Common.h"
#include "LineSegment.h"

/* --- Intersect ---------------------------------------------------------------
 *
 *   Intersect_RectRect     : Rect format is {x, y, sx, sy}
 *   Intersect_RectRectFast : Only works with non-inverted rects (sx, sy > 0)
 *
 * -------------------------------------------------------------------------- */

/* NOTE : See Intersect.cpp for information on choosing these epsilons. */
const float PLANE_THICKNESS_EPSILON     = 1e-4;
const float POINT_INTERSECTION_EPSILON  = (2.0f*PLANE_THICKNESS_EPSILON);
const float RAY_INTERSECTION_EPSILON    = (8.0f*PLANE_THICKNESS_EPSILON);
const float SPHERE_INTERSECTION_EPSILON = (2.0f*PLANE_THICKNESS_EPSILON);

PHX_API bool  Intersect_PointBox                   (Matrix* t1, Matrix* t2);
PHX_API bool  Intersect_PointTriangle_Barycentric  (Vec3f const*, Triangle const*);
PHX_API bool  Intersect_RayPlane                   (Ray const*, Plane const*, Vec3f* pHit);
PHX_API bool  Intersect_RayTriangle_Barycentric    (Ray const*, Triangle const*, float tEpsilon, float* tHit);
PHX_API bool  Intersect_RayTriangle_Moller1        (Ray const*, Triangle const*, float* tHit);
PHX_API bool  Intersect_RayTriangle_Moller2        (Ray const*, Triangle const*, float* tHit);
PHX_API bool  Intersect_LineSegmentPlane           (LineSegment const*, Plane const*, Vec3f* pHit);
PHX_API bool  Intersect_RectRect                   (Vec4f const*, Vec4f const*);
PHX_API bool  Intersect_RectRectFast               (Vec4f const*, Vec4f const*);
PHX_API bool  Intersect_SphereTriangle             (Sphere const*, Triangle const*, Vec3f* pHit);

#endif


text:
#ifndef PHX_Tex2D
#define PHX_Tex2D

#include "Common.h"

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

PHX_API Tex2D*     Tex2D_Create         (int sx, int sy, TexFormat);
PHX_API Tex2D*     Tex2D_Load           (cstr name);
PHX_API Tex2D*     Tex2D_ScreenCapture  ();
PHX_API void       Tex2D_Acquire        (Tex2D*);
PHX_API void       Tex2D_Free           (Tex2D*);

PHX_API void       Tex2D_Pop            (Tex2D*);
PHX_API void       Tex2D_Push           (Tex2D*);
PHX_API void       Tex2D_PushLevel      (Tex2D*, int level);

PHX_API void       Tex2D_Clear          (Tex2D*, float r, float g, float b, float a);
PHX_API Tex2D*     Tex2D_Clone          (Tex2D*);
PHX_API void       Tex2D_Draw           (Tex2D*, float x, float y, float sx, float sy);
PHX_API void       Tex2D_DrawEx         (Tex2D*, float x0, float y0, float x1, float y1,
                                                 float u0, float v0, float u1, float v1);
PHX_API void       Tex2D_GenMipmap      (Tex2D*);
PHX_API void       Tex2D_GetData        (Tex2D*, void*, PixelFormat, DataFormat);
PHX_API Bytes*     Tex2D_GetDataBytes   (Tex2D*, PixelFormat, DataFormat);
PHX_API TexFormat  Tex2D_GetFormat      (Tex2D*);
PHX_API uint       Tex2D_GetHandle      (Tex2D*);
PHX_API void       Tex2D_GetSize        (Tex2D*, Vec2i* out);
PHX_API void       Tex2D_GetSizeLevel   (Tex2D*, Vec2i* out, int level);
PHX_API void       Tex2D_SetAnisotropy  (Tex2D*, float);
PHX_API void       Tex2D_SetData        (Tex2D*, void const*, PixelFormat, DataFormat);
PHX_API void       Tex2D_SetDataBytes   (Tex2D*, Bytes*, PixelFormat, DataFormat);
PHX_API void       Tex2D_SetMagFilter   (Tex2D*, TexFilter);
PHX_API void       Tex2D_SetMinFilter   (Tex2D*, TexFilter);
PHX_API void       Tex2D_SetMipRange    (Tex2D*, int minLevel, int maxLevel);
PHX_API void       Tex2D_SetTexel       (Tex2D*, int x, int y, float r, float g, float b, float a);
PHX_API void       Tex2D_SetWrapMode    (Tex2D*, TexWrapMode);

PHX_API void       Tex2D_Save           (Tex2D*, cstr path);

#endif


text:
#ifndef PHX_Plane
#define PHX_Plane

#include "Vec3.h"

struct Plane {
  Vec3f n;
  float d;
};

const PointClassification PointClassification_InFront  = 1;
const PointClassification PointClassification_Behind   = 2;
const PointClassification PointClassification_Coplanar = 3;

const PolygonClassification PolygonClassification_InFront    = 1;
const PolygonClassification PolygonClassification_Behind     = 2;
const PolygonClassification PolygonClassification_Coplanar   = 3;
const PolygonClassification PolygonClassification_Straddling = 4;

PHX_API PointClassification    Plane_ClassifyPoint    (Plane*, Vec3f*);
PHX_API PolygonClassification  Plane_ClassifyPolygon  (Plane*, Polygon*);
PHX_API Error                  Plane_Validate         (Plane*);

PHX_API void                   Plane_FromPolygon      (Polygon*, Plane*);
PHX_API void                   Plane_FromPolygonFast  (Polygon*, Plane*);

#endif


text:
#ifndef PHX_Mouse
#define PHX_Mouse

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

#include "Common.h"

PHX_API void   Mouse_GetDelta          (Vec2i* out);
PHX_API double Mouse_GetIdleTime       ();
PHX_API void   Mouse_GetPosition       (Vec2i* out);
PHX_API void   Mouse_GetPositionGlobal (Vec2i* out);
PHX_API int    Mouse_GetScroll         ();
PHX_API void   Mouse_SetPosition       (int, int);
PHX_API void   Mouse_SetVisible        (bool);

PHX_API bool   Mouse_Down              (MouseButton);
PHX_API bool   Mouse_Pressed           (MouseButton);
PHX_API bool   Mouse_Released          (MouseButton);

PRIVATE void Mouse_Init      ();
PRIVATE void Mouse_Free      ();
PRIVATE void Mouse_SetScroll (int amount);
PRIVATE void Mouse_Update    ();

#endif


text:
#ifndef PHX_Window
#define PHX_Window

#include "Common.h"

PHX_API Window*  Window_Create            (cstr title, WindowPos x, WindowPos y, int sx, int sy, WindowMode mode);
PHX_API void     Window_Free              (Window*);

PHX_API void     Window_BeginDraw         (Window*);
PHX_API void     Window_EndDraw           (Window*);

PHX_API void     Window_GetPosition       (Window*, Vec2i* out);
PHX_API void     Window_GetSize           (Window*, Vec2i* out);
PHX_API cstr     Window_GetTitle          (Window*);

PHX_API void     Window_SetFullscreen     (Window*, bool);
PHX_API void     Window_SetPosition       (Window*, WindowPos, WindowPos);
PHX_API void     Window_SetSize           (Window*, int, int);
PHX_API void     Window_SetTitle          (Window*, cstr);
PHX_API void     Window_SetVsync          (Window*, bool);

PHX_API void     Window_ToggleFullscreen  (Window*);

PHX_API void     Window_Hide              (Window*);
PHX_API void     Window_Show              (Window*);

#endif


text:
#ifndef PHX_Engine
#define PHX_Engine

#include "Common.h"

/* --- Engine ------------------------------------------------------------------
 *
 *    Engine_Abort      : Calls abort() (immediate/non-graceful termination)
 *    Engine_GetBits    : Returns 32 for x86-32, 64 for x86-64
 *    Engine_GetTime    : Returns time in seconds since Engine_Init
 *    Engine_GetVersion : Returns pseudo-version string with the date & time of
 *                        the library's compilation
 *    Engine_Terminate  : Calls exit(0)  (graceful termination)
 *
 * -------------------------------------------------------------------------- */

PHX_API void   Engine_Init          (int glVersionMajor, int glVersionMinor);
PHX_API void   Engine_Free          ();

PHX_API void   Engine_Abort         ();
PHX_API int    Engine_GetBits       ();
PHX_API double Engine_GetTime       ();
PHX_API cstr   Engine_GetVersion    ();
PHX_API bool   Engine_IsInitialized ();
PHX_API void   Engine_Terminate     ();
PHX_API void   Engine_Update        ();

#endif


text:
#ifndef PHX_Int
#define PHX_Int

#include <stdint.h>

#ifndef INT8_MIN
  #define INT8_MIN    (-0x7f - 1)
  #define INT16_MIN   (-0x7fff - 1)
  #define INT32_MIN   (-0x7fffffff - 1)
  #define INT64_MIN   (-0x7fffffffffffffff - 1)
#endif

#ifndef INT8_MAX
  #define INT8_MAX    0x7f
  #define INT16_MAX   0x7fff
  #define INT32_MAX   0x7fffffff
  #define INT64_MAX   0x7fffffffffffffff
#endif

#ifndef UINT8_MAX
  #define UINT8_MAX   0xff
  #define UINT16_MAX  0xffff
  #define UINT32_MAX  0xffffffff
  #define UINT64_MAX  0xffffffffffffffff
#endif

#ifndef INT8_C
  #define INT8_C(x)    (x)
  #define INT16_C(x)   (x)
  #define INT32_C(x)   (x ## L)
  #define INT64_C(x)   (x ## LL)
#endif

#ifndef UINT8_C
  #define UINT8_C(x)   (x)
  #define UINT16_C(x)  (x)
  #define UINT32_C(x)  (x ## UL)
  #define UINT64_C(x)  (x ## ULL)
#endif

#endif


text:
#ifndef PHX_CullFace
#define PHX_CullFace

#include "Common.h"

const CullFace CullFace_None  = 0;
const CullFace CullFace_Back  = 1;
const CullFace CullFace_Front = 2;

PHX_API void  CullFace_Pop        ();
PHX_API void  CullFace_Push       (CullFace);
PHX_API void  CullFace_PushNone   ();
PHX_API void  CullFace_PushBack   ();
PHX_API void  CullFace_PushFront  ();

#endif


text:
#ifndef PHX_LineSegment
#define PHX_LineSegment

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

struct LineSegment {
  Vec3f p0;
  Vec3f p1;
};

PHX_API void  LineSegment_ToRay     (LineSegment const*, Ray*);
PHX_API void  LineSegment_FromRay   (Ray const*, LineSegment*);
PHX_API cstr  LineSegment_ToString  (LineSegment*);

#endif


text:
#ifndef PHX_GamepadButton
#define PHX_GamepadButton

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

#include "Common.h"

PHX_API const GamepadButton GamepadButton_BEGIN;
PHX_API const GamepadButton GamepadButton_A;
PHX_API const GamepadButton GamepadButton_B;
PHX_API const GamepadButton GamepadButton_X;
PHX_API const GamepadButton GamepadButton_Y;
PHX_API const GamepadButton GamepadButton_Back;
PHX_API const GamepadButton GamepadButton_Guide;
PHX_API const GamepadButton GamepadButton_Start;
PHX_API const GamepadButton GamepadButton_LStick;
PHX_API const GamepadButton GamepadButton_RStick;
PHX_API const GamepadButton GamepadButton_LBumper;
PHX_API const GamepadButton GamepadButton_RBumper;
PHX_API const GamepadButton GamepadButton_Up;
PHX_API const GamepadButton GamepadButton_Down;
PHX_API const GamepadButton GamepadButton_Left;
PHX_API const GamepadButton GamepadButton_Right;
PHX_API const GamepadButton GamepadButton_END;
const GamepadButton GamepadButton_SIZE = 15;

#endif


text:
#ifndef PHX_Profiler
#define PHX_Profiler

#include "Common.h"

#define ENABLE_PROFILER 1

PHX_API void  Profiler_Enable      ();
PHX_API void  Profiler_Disable     ();

PHX_API void  Profiler_Begin       (cstr);
PHX_API void  Profiler_End         ();
PHX_API void  Profiler_SetValue    (cstr, int);

PHX_API void  Profiler_LoopMarker  ();

PHX_API void  Profiler_Backtrace   ();

#if ENABLE_PROFILER
  #define FRAME_BEGIN Profiler_Begin(__func__)
  #define FRAME_END Profiler_End()
#else
  #define FRAME_BEGIN
  #define FRAME_END
#endif

#endif


text:
#ifndef PHX_Lua
#define PHX_Lua
#define __FFI_IGNORE__

#include "Common.h"
#include "luajit/lua.hpp"

typedef lua_State Lua;
typedef int (*LuaFn)(Lua*);
typedef lua_Integer LuaRef;

PHX_API Lua*    Lua_Create             ();
PHX_API Lua*    Lua_CreateThread       (Lua*);
PHX_API void    Lua_Free               (Lua*);
PHX_API Lua*    Lua_GetActive          ();

PHX_API void    Lua_DoFile             (Lua*, cstr name);
PHX_API void    Lua_DoString           (Lua*, cstr code);

PHX_API void    Lua_LoadFile           (Lua*, cstr name);
PHX_API void    Lua_LoadString         (Lua*, cstr code);

PHX_API void    Lua_Call               (Lua*, int args, int rets, int errorHandler);
PHX_API void    Lua_PushGlobal         (Lua*, cstr name);
PHX_API void    Lua_PushNumber         (Lua*, double);
PHX_API void    Lua_PushPtr            (Lua*, void*);
PHX_API void    Lua_PushStr            (Lua*, cstr);
PHX_API void    Lua_PushThread         (Lua*, Lua* thread);
PHX_API void    Lua_SetBool            (Lua*, cstr name, bool);
PHX_API void    Lua_SetFn              (Lua*, cstr name, LuaFn);
PHX_API void    Lua_SetNumber          (Lua*, cstr name, double);
PHX_API void    Lua_SetPtr             (Lua*, cstr name, void*);
PHX_API void    Lua_SetStr             (Lua*, cstr name, cstr);
PHX_API void    Lua_TransferStack      (Lua* src, Lua* dst, int count);

PHX_API LuaRef  Lua_GetRef             (Lua*);
PHX_API void    Lua_ReleaseRef         (Lua*, LuaRef);
PHX_API void    Lua_PushRef            (Lua*, LuaRef);

PHX_API void    Lua_GCFull             (Lua*);
PHX_API void    Lua_GCSetActive        (Lua*, bool active);
PHX_API void    Lua_GCStep             (Lua*);

PHX_API void    Lua_Backtrace          ();
PHX_API int     Lua_GetMemory          (Lua*);

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

PRIVATE void    LuaScheduler_Init      (Lua*);
PRIVATE void    LuaScheduler_Register  (Lua*);

#endif


text:
#ifndef PHX_Input
#define PHX_Input

#include "Common.h"

/* --- Input -------------------------------------------------------------------
 *
 *   The low level engine API for reading input from the system. Input can be
 *   read using two paradigms: direct queries or through an event loop that is
 *   pumped by the application.
 *   (There is also a high level API, InputBindings)
 *
 *   The Button enum defines every possible input the engine supports. Notice
 *   that both button (e.g. Button_Keyboard_Space) and axis
 *   (Button_Gamepad_LTrigger) inputs are present in the enum. This is because
 *   every input, no matter it's 'type' or source can be read as a button with
 *   pressed/down/released state and as a axis with a [-1, 1] value.
 *
 *   This API will *always* provide button pressed and released states/events in
 *   perfect pairs. It is not possible to see 2 presses in a row, 2 released
 *   events in a row, a press without a release, or a release without a press.
 *
 *   Note that mouse movement is not translated to button presses/releases.
 *
 *   When a device is disconnected (currently only gamepads) all input will be
 *   set to zero (and yield the appropriate release states/events). Remapping a
 *   gamepad will yield the appropriate pressed and released states/events.
 *
 *
 *   Direct Queries
 *   --------------
 *   Input_GetPressed       : Return information about the button on the
 *   Input_GetDown            matching device with id 0.
 *   Input_GetReleased
 *   Input_GetValue
 *
 *   Input_GetChanged       : Check if a value has changed
 *   Input_GetDelta         : Returns the change in value since the last frame.
 *
 *   Input_GetIdleTime      : Returns time since the last input of any sort.
 *
 *   Input_GetActiveDevice* : Return information about a specific Device. These
 *   Input_Device*            also provide additional functionality for specific
 *   Input_Mouse*             DeviceTypes.
 *   Input_Keyboard*
 *   Input_Gamepad*
 *
 *
 *   Event Loop
 *   ----------
 *   Input_GetEventCount    : Unread events will be thrown away at the beginning
 *   Input_GetNextEvent       of the next update so they don't pile up when the
 *                            event loop isn't being utilized.
 *
 * -------------------------------------------------------------------------- */

PHX_API void        Input_LoadGamepadDatabase      (cstr filepath);

/* --- Direct Query API ----------------------------------------------------- */

PHX_API bool        Input_GetPressed               (Button);
PHX_API bool        Input_GetDown                  (Button);
PHX_API bool        Input_GetReleased              (Button);
PHX_API float       Input_GetValue                 (Button);
//PHX_API bool        Input_GetChanged               (Button);
//PHX_API float       Input_GetDelta                 (Button);
PHX_API float       Input_GetIdleTime              ();

PHX_API void        Input_GetActiveDevice          (Device*);
PHX_API DeviceType  Input_GetActiveDeviceType      ();
PHX_API uint32      Input_GetActiveDeviceID        ();
PHX_API float       Input_GetActiveDeviceIdleTime  ();

PHX_API bool        Input_GetDevicePressed         (Device*, Button);
PHX_API bool        Input_GetDeviceDown            (Device*, Button);
PHX_API bool        Input_GetDeviceReleased        (Device*, Button);
PHX_API float       Input_GetDeviceValue           (Device*, Button);
PHX_API float       Input_GetDeviceIdleTime        (Device*);

PHX_API void        Input_GetMouseDelta            (Vec2i*);
PHX_API float       Input_GetMouseIdleTime         ();
PHX_API void        Input_GetMousePosition         (Vec2i*);
PHX_API void        Input_GetMouseScroll           (Vec2i*);
PHX_API void        Input_SetMousePosition         (Vec2i*);
PHX_API void        Input_SetMouseScroll           (Vec2i*);
PHX_API void        Input_SetMouseVisible          (bool);
PHX_API void        Input_SetMouseVisibleAuto      ();

PHX_API float       Input_GetKeyboardIdleTime      ();
PHX_API bool        Input_GetKeyboardMod           (Modifier);
PHX_API bool        Input_GetKeyboardAlt           ();
PHX_API bool        Input_GetKeyboardCtrl          ();
PHX_API bool        Input_GetKeyboardShift         ();

PHX_API float       Input_GetGamepadIdleTime       (uint32 id);
PHX_API bool        Input_GetGamepadPressed        (uint32 id, Button);
PHX_API bool        Input_GetGamepadDown           (uint32 id, Button);
PHX_API bool        Input_GetGamepadReleased       (uint32 id, Button);
PHX_API float       Input_GetGamepadValue          (uint32 id, Button);
//PHX_API cstr        Input_GetGamepadName           (uint32 id);
//PHX_API bool        Input_IsGamepadConnected       (uint32 id);

/* --- Event Loop API ------------------------------------------------------- */

PHX_API int32       Input_GetEventCount            ();
PHX_API bool        Input_GetNextEvent             (InputEvent*);

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

PRIVATE void        Input_Init                     ();
PRIVATE void        Input_Free                     ();
PRIVATE void        Input_Update                   ();

#endif


text:
#ifndef PHX_PixelFormat
#define PHX_PixelFormat

#include "Common.h"

PHX_API const PixelFormat PixelFormat_Red;
PHX_API const PixelFormat PixelFormat_RG;
PHX_API const PixelFormat PixelFormat_RGB;
PHX_API const PixelFormat PixelFormat_BGR;
PHX_API const PixelFormat PixelFormat_RGBA;
PHX_API const PixelFormat PixelFormat_BGRA;
PHX_API const PixelFormat PixelFormat_Depth_Component;

PHX_API int  PixelFormat_Components  (PixelFormat);

#endif


text:
#ifndef PHX_ClipRect
#define PHX_ClipRect

#include "Common.h"

/* --- ClipRect ----------------------------------------------------------------
 *
 *   Uses OpenGL's scissoring functionality to prevent drawing outside a
 *   certain rectangular region of the current viewport.
 *
 *     ClipRect_[Push/Pop]Transform : Specify a transform for the ClipRect stack.
 *                                    Used to allow rects to remain relative to
 *                                    a local viewport or base resolution.
 *
 * -------------------------------------------------------------------------- */

PHX_API void  ClipRect_Push           (float x, float y, float sx, float sy);
PHX_API void  ClipRect_PushCombined   (float x, float y, float sx, float sy);
PHX_API void  ClipRect_PushDisabled   ();
PHX_API void  ClipRect_PushTransform  (float tx, float ty, float sx, float sy);
PHX_API void  ClipRect_Pop            ();
PHX_API void  ClipRect_PopTransform   ();

#endif


text:
#ifndef PHX_Sound
#define PHX_Sound

#include "Common.h"

/* --- Sound -------------------------------------------------------------------
 *
 *   A simple API for playing sounds.
 *
 *   Any operations on an asynchronously loaded sound will block until loading
 *   has finished if necessary.
 *
 *   Sound assets will automatically be unloaded once all sounds are freed.
 *
 *   This type is REFERENCE-COUNTED. See ../doc/RefCounted.txt for details.
 *
 * -------------------------------------------------------------------------- */

PHX_API void    Sound_Acquire                (Sound*);
PHX_API void    Sound_Free                   (Sound*);

PHX_API Sound*  Sound_Load                   (cstr name, bool isLooped, bool is3D);
PHX_API Sound*  Sound_LoadAsync              (cstr name, bool isLooped, bool is3D);
PHX_API Sound*  Sound_Clone                  (Sound*);
PHX_API void    Sound_ToFile                 (Sound*, cstr);

PHX_API void    Sound_Pause                  (Sound*);
PHX_API void    Sound_Play                   (Sound*);
PHX_API void    Sound_Rewind                 (Sound*);

PHX_API bool    Sound_Get3D                  (Sound*);
PHX_API float   Sound_GetDuration            (Sound*);
PHX_API bool    Sound_GetLooped              (Sound*);
PHX_API cstr    Sound_GetName                (Sound*);
PHX_API cstr    Sound_GetPath                (Sound*);
PHX_API bool    Sound_IsFinished             (Sound*);
PHX_API bool    Sound_IsPlaying              (Sound*);

PHX_API void    Sound_Attach3DPos            (Sound*, Vec3f const* pos, Vec3f const* vel);
PHX_API void    Sound_Set3DLevel             (Sound*, float);
PHX_API void    Sound_Set3DPos               (Sound*, Vec3f const* pos, Vec3f const* vel);
PHX_API void    Sound_SetFreeOnFinish        (Sound*, bool);
PHX_API void    Sound_SetPan                 (Sound*, float);
PHX_API void    Sound_SetPitch               (Sound*, float);
PHX_API void    Sound_SetPlayPos             (Sound*, float);
PHX_API void    Sound_SetVolume              (Sound*, float);

/* --- Convenience API ------------------------------------------------------ */

PHX_API Sound*  Sound_LoadPlay               (cstr name, bool isLooped, bool is3D);
PHX_API Sound*  Sound_LoadPlayAttached       (cstr name, bool isLooped, bool is3D, Vec3f const* pos, Vec3f const* vel);
PHX_API void    Sound_LoadPlayFree           (cstr name, bool isLooped, bool is3D);
PHX_API void    Sound_LoadPlayFreeAttached   (cstr name, bool isLooped, bool is3D, Vec3f const* pos, Vec3f const* vel);
PHX_API Sound*  Sound_ClonePlay              (Sound*);
PHX_API Sound*  Sound_ClonePlayAttached      (Sound*, Vec3f const* pos, Vec3f const* vel);
PHX_API void    Sound_ClonePlayFree          (Sound*);
PHX_API void    Sound_ClonePlayFreeAttached  (Sound*, Vec3f const* pos, Vec3f const* vel);

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

PRIVATE void    Sound_Update                 (Sound*);
PRIVATE bool    Sound_IsFreed                (Sound*);

#endif

/* TODO : Will the sound re-load if reused? */


text:
#ifndef PHX_SoundDef
#define PHX_SoundDef

#include "Common.h"
#include "RefCounted.h"
#include "fmod/fmod.h"

struct SoundDesc {
  RefCounted;
  FMOD_SOUND* handle;
  cstr        name;
  cstr        path;
};

typedef uint8 SoundState;
const SoundState SoundState_Null     = 0;
const SoundState SoundState_Loading  = 1;
const SoundState SoundState_Paused   = 2;
const SoundState SoundState_Playing  = 3;
const SoundState SoundState_Finished = 4;
const SoundState SoundState_Freed    = 5;

struct Sound {
  SoundDesc*    desc;
  FMOD_CHANNEL* handle;
  SoundState    state;
  Vec3f const*  autoPos;
  Vec3f const*  autoVel;
  bool          freeOnFinish;
};

#endif


text:
#ifndef PHX_Array
#define PHX_Array

#define Array_Arg(x)      (x), ((int) (sizeof(x) / sizeof(*(x))))
#define Array_GetSize(x)  ((int) (sizeof(x) / sizeof(*(x))))
#define Array_Param(T)    T* arr, int len

#endif


text:
#ifndef PHX_SDL
#define PHX_SDL

#include "sdl/SDL.h"
#ifdef main
#  undef main
#endif

#endif


text:
#ifndef PHX_Octree
#define PHX_Octree

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

PHX_API Octree*  Octree_Create        (Box3f bound);
PHX_API Octree*  Octree_FromMesh      (Mesh*);
PHX_API void     Octree_Free          (Octree*);

PHX_API void     Octree_Add           (Octree*, Box3f bound, uint32 id);
PHX_API void     Octree_Draw          (Octree*);
PHX_API double   Octree_GetAvgLoad    (Octree*);
PHX_API int      Octree_GetMaxLoad    (Octree*);
PHX_API int      Octree_GetMemory     (Octree*);
PHX_API bool     Octree_IntersectRay  (Octree*, Matrix*, Vec3f const* ro, Vec3f const* rd);

#endif


text:
#ifndef PHX_CollisionShape
#define PHX_CollisionShape
#define __FFI_IGNORE__

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

/* --- CollisionShape ----------------------------------------------------------
 *
 *   This was split out of RigidBody to support Triggers of different shapes.
 *   However, since Triggers are currently AABB tests only this isn't really
 *   used by Trigger. But that may change in the future and splitting up shape
 *   and rigidbodies is a good idea anyway.
 *
 * -------------------------------------------------------------------------- */

typedef uint8 CollisionShapeType;
const CollisionShapeType CollisionShapeType_Null     = 0;
const CollisionShapeType CollisionShapeType_Box      = 1;
const CollisionShapeType CollisionShapeType_Sphere   = 2;
const CollisionShapeType CollisionShapeType_Hull     = 3;
const CollisionShapeType CollisionShapeType_Compound = 4;

const CollisionGroup CollisionGroup_Null    = 0 << 0;
const CollisionGroup CollisionGroup_Default = 1 << 0;
const CollisionGroup CollisionGroup_Trigger = 1 << 1;

const CollisionMask CollisionMask_Null       = 0 << 0;
const CollisionMask CollisionMask_All        = ~CollisionGroup_Null;
const CollisionMask CollisionMask_NoTriggers = ~CollisionGroup_Trigger;

struct CollisionShape {
  int                iShape;
  float              scale;
  CollisionShapeType type;

  union {
    struct {
      btCollisionShape* handle;
    } base;

    struct {
      btBoxShape* handle;
      Vec3f       halfExtents;
    } box;

    struct {
      btSphereShape* handle;
      float          radius;
    } sphere;

    struct {
      btUniformScalingShape* handle;
      btConvexHullShape*     hullHandle;
      /* TODO : Ref-count the mesh. */
      Mesh*                  mesh;
    } hull;

    struct {
      btCompoundShape*  handle;
      /* TODO : Use for ref-counting/freeing. */
      //ArrayList(int,    subShapes);
    } compound;
  };
};

PHX_API CollisionShape*  CollisionShape_Create                (CollisionShape);
PHX_API void             CollisionShape_Free                  (CollisionShape*);

PHX_API CollisionShape*  CollisionShape_CreateBox             (Vec3f* halfExtents);
PHX_API CollisionShape*  CollisionShape_CreateBoxFromMesh     (Mesh*);
PHX_API CollisionShape*  CollisionShape_CreateSphere          (float);
PHX_API CollisionShape*  CollisionShape_CreateSphereFromMesh  (Mesh*);
PHX_API CollisionShape*  CollisionShape_CreateHullFromMesh    (Mesh*);
PHX_API CollisionShape*  CollisionShape_GetCached             (int);

#endif


text:
#ifndef PHX_Joystick
#define PHX_Joystick

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

#include "Common.h"

PHX_API  int        Joystick_GetCount        ();
PHX_API  Joystick*  Joystick_Open            (int index);
PHX_API  void       Joystick_Close           (Joystick*);

PHX_API  cstr       Joystick_GetGUID         (Joystick*);
PHX_API  cstr       Joystick_GetGUIDByIndex  (int index);
PHX_API  cstr       Joystick_GetName         (Joystick*);
PHX_API  cstr       Joystick_GetNameByIndex  (int index);
PHX_API  int        Joystick_GetAxisCount    (Joystick*);
PHX_API  int        Joystick_GetBallCount    (Joystick*);
PHX_API  int        Joystick_GetButtonCount  (Joystick*);
PHX_API  int        Joystick_GetHatCount     (Joystick*);
PHX_API  double     Joystick_GetIdleTime     (Joystick*);

PHX_API  double     Joystick_GetAxis         (Joystick*, int index);
PHX_API  bool       Joystick_GetAxisAlive    (Joystick*, int index);
PHX_API  double     Joystick_GetAxisDelta    (Joystick*, int index);
PHX_API  HatDir     Joystick_GetHat          (Joystick*, int index);

PHX_API  bool       Joystick_ButtonDown      (Joystick*, int index);
PHX_API  bool       Joystick_ButtonPressed   (Joystick*, int index);
PHX_API  bool       Joystick_ButtonReleased  (Joystick*, int index);

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

PRIVATE void        Joystick_Update          ();

#endif


text:
#ifndef PHX_TexWrapMode
#define PHX_TexWrapMode

#include "Common.h"

PHX_API const TexWrapMode TexWrapMode_Clamp;
PHX_API const TexWrapMode TexWrapMode_MirrorClamp;
PHX_API const TexWrapMode TexWrapMode_MirrorRepeat;
PHX_API const TexWrapMode TexWrapMode_Repeat;

#endif


text:
#ifndef PHX_RigidBody
#define PHX_RigidBody

#include "Common.h"

/* --- RigidBody ---------------------------------------------------------------
 *
 *   The following API functions are disabled for parent objects:
 *   RigidBody_GetPosLocal, RigidBody_SetPosLocal, RigidBody_GetRotLocal, and
 *   RigidBody_SetRotLocal.
 *
 *   The following API functions are disabled for child objects:
 *   RigidBody_Free, RigidBody_ApplyForce, RigidBody_ApplyTorque,
 *   RigidBody_GetSpeed, RigidBody_GetVelocity, RigidBody_GetVelocityA,
 *   RigidBody_SetPos, and RigidBody_SetRot.
 *
 *   The following API functions only have an effect once the child is removed
 *   from its parent: RigidBody_SetCollidable, RigidBody_SetCollisionGroup,
 *   RigidBody_SetCollisionMask, RigidBody_SetDrag, RigidBody_SetFriction,
 *   RigidBody_SetKinematic, RigidBody_SetRestitution, and
 *   RigidBody_SetSleepThreshold.
 *
 *   The following API functions return information only about the current part
 *   when the object is part of a compound: RigidBody_GetBoundingBoxLocal,
 *   RigidBody_GetBoundingBox, and RigidBody_GetBoundingRadius.
 *
 *   The following API functions are only enabled for compound objects:
 *   RigidBody_GetBoundingBoxCompound, RigidBody_GetBoundingBoxLocalCompound,
 *   and RigidBody_GetBoundingRadiusCompound.
 *
 *   The local coordinate space of a child object is not scaled by the parent.
 *   However, the position of the child will be multiplied by the parents scale.
 *   Thus, the scale of the parent does not affect the size of the child and
 *   local position is always 'relative to the parent'. A position of (1, 1, -1)
 *   will always correspond to a point that will roughly coincide with the
 *   right-top-front corner of the parents bounding box (assuming the vertices
 *   of the mesh are contained in a cube that goes from o(-1, -1, -1) to
 *   (1, 1, 1)). When a parent is scaled the positions of children will be
 *   multiplied in order to maintain the same relative position.
 *
 *     RigidBody_Free             : Automatically frees all attached Triggers
 *                                  when called on a parent. Automatically frees
 *                                  all attached children and their Triggers
 *                                  when called on a parent. This function is
 *                                  O(M*N) for parents.
 *     RigidBody_Attach           : Only a single level of attachment is
 *                                  supported. Child objects do not affect the
 *                                  mass or inertia of the parent. Position is
 *                                  relative to the unscaled parent. i.e. it
 *                                  will be multiplied by the current scale.
 *                                  This function is O(1). Warning: if one
 *                                  object is attached to another and a third
 *                                  object happens to be between them this may
 *                                  trap the third object. The same issue may
 *                                  occur when spawning one compound inside
 *                                  another.
 *     RigidBody_Detach           : This function is O(2N).
 *     RigidBody_GetToLocalMatrix : Requires a 3x3 transpose, 3x3 vs 3x1
 *                                  multiplication, 4x4 copy, 3x3 vs 1x1
 *                                  multiplication, and a 4x4 transpose.
 *                                  Children require an additional 3x3 vs 3x3
 *                                  multiplication and 3v3 vs 3x1 multiplcation.
 *     RigidBody_GetToWorldMatrix : Requires a 4x4 copy, 3x3 vs 1x1
 *                                  multiplication, and a 4x4 transpose.
 *                                  Children require an additional 3x3 vs 3x3
 *                                  multiplication and 3v3 vs 3x1 multiplcation.
 *     RigidBody_SetCollidable    : When disabled, the object will pass through
 *                                  others without colliding and will not be
 *                                  returned from ray or shape casts.
 *     RigidBody_SetMass          : The mass of child objects does not affect
 *                                  the mass or inertia of the parent.
 *     RigidBody_GetPos           : Children return the parent position.
 *     RigidBody_GetPosLocal      : Local coordinates are relative to the parent
 *                                  *before* scaling. Requires an additional 3x3
 *                                  vs 3x3 multiplication and 3v3 vs 3x1
 *                                  multiplcation.
 *     RigidBody_SetPosLocal      : Local coordinates are relative to the parent
 *                                  *before* scaling. The given position will be
 *                                  multiplied by the parent's scale.
 *     RigidBody_GetRot           : Children require an additional 3x3 vs 3x3
 *                                  multiplication and 3v3 vs 3x1 multiplcation.
 *     RigidBody_SetScale         : When called on a parent object the positions
 *                                  of all children will be multiplied such that
 *                                  they retain the same relative position.
 *                                  Child scale is not affected by parent scale
 *                                  (i.e. it is not inherited). This function is
 *                                  O(3N).
 *
 * -------------------------------------------------------------------------- */

PHX_API RigidBody*  RigidBody_CreateBox                    ();
PHX_API RigidBody*  RigidBody_CreateBoxFromMesh            (Mesh*);
PHX_API RigidBody*  RigidBody_CreateSphere                 ();
PHX_API RigidBody*  RigidBody_CreateSphereFromMesh         (Mesh*);
PHX_API RigidBody*  RigidBody_CreateHullFromMesh           (Mesh*);
PHX_API void        RigidBody_Free                         (RigidBody*);

PHX_API void        RigidBody_ApplyForce                   (RigidBody*, Vec3f*);
PHX_API void        RigidBody_ApplyTorque                  (RigidBody*, Vec3f*);

PHX_API void        RigidBody_Attach                       (RigidBody*, RigidBody* other, Vec3f*, Quat*);
PHX_API void        RigidBody_Detach                       (RigidBody*, RigidBody* other);

PHX_API void        RigidBody_GetBoundingBox               (RigidBody*, Box3f*);
PHX_API void        RigidBody_GetBoundingBoxCompound       (RigidBody*, Box3f*);
PHX_API void        RigidBody_GetBoundingBoxLocal          (RigidBody*, Box3f*);
PHX_API void        RigidBody_GetBoundingBoxLocalCompound  (RigidBody*, Box3f*);
PHX_API float       RigidBody_GetBoundingRadius            (RigidBody*);
PHX_API float       RigidBody_GetBoundingRadiusCompound    (RigidBody*);

PHX_API RigidBody*  RigidBody_GetParentBody                (RigidBody*);
PHX_API float       RigidBody_GetSpeed                     (RigidBody*);
PHX_API Matrix*     RigidBody_GetToLocalMatrix             (RigidBody*);
PHX_API Matrix*     RigidBody_GetToWorldMatrix             (RigidBody*);
PHX_API void        RigidBody_GetVelocity                  (RigidBody*, Vec3f*);
PHX_API void        RigidBody_GetVelocityA                 (RigidBody*, Vec3f*);

PHX_API void        RigidBody_SetCollidable                (RigidBody*, bool);
PHX_API void        RigidBody_SetCollisionGroup            (RigidBody*, int);
PHX_API void        RigidBody_SetCollisionMask             (RigidBody*, int);
PHX_API void        RigidBody_SetDrag                      (RigidBody*, float linear, float angular);
PHX_API void        RigidBody_SetFriction                  (RigidBody*, float);
PHX_API void        RigidBody_SetKinematic                 (RigidBody*, bool);
PHX_API void        RigidBody_SetRestitution               (RigidBody*, float);
PHX_API void        RigidBody_SetSleepThreshold            (RigidBody*, float linear, float angular);

PHX_API float       RigidBody_GetMass                      (RigidBody*);
PHX_API void        RigidBody_SetMass                      (RigidBody*, float);
PHX_API void        RigidBody_GetPos                       (RigidBody*, Vec3f*);
PHX_API void        RigidBody_GetPosLocal                  (RigidBody*, Vec3f*);
PHX_API void        RigidBody_SetPos                       (RigidBody*, Vec3f*);
PHX_API void        RigidBody_SetPosLocal                  (RigidBody*, Vec3f*);
PHX_API void        RigidBody_GetRot                       (RigidBody*, Quat*);
PHX_API void        RigidBody_GetRotLocal                  (RigidBody*, Quat*);
PHX_API void        RigidBody_SetRot                       (RigidBody*, Quat*);
PHX_API void        RigidBody_SetRotLocal                  (RigidBody*, Quat*);
PHX_API float       RigidBody_GetScale                     (RigidBody*);
PHX_API void        RigidBody_SetScale                     (RigidBody*, float);

PRIVATE RigidBody*  RigidBody_GetPart     (RigidBody*, int);
PRIVATE bool        RigidBody_IsChild     (RigidBody*);
PRIVATE bool        RigidBody_IsCompound  (RigidBody*);
PRIVATE bool        RigidBody_IsParent    (RigidBody*);

#endif


text:
#ifndef PHX_Key
#define PHX_Key

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

#include "Common.h"

PHX_API const Key Key_A;
PHX_API const Key Key_B;
PHX_API const Key Key_C;
PHX_API const Key Key_D;
PHX_API const Key Key_E;
PHX_API const Key Key_F;
PHX_API const Key Key_G;
PHX_API const Key Key_H;
PHX_API const Key Key_I;
PHX_API const Key Key_J;
PHX_API const Key Key_K;
PHX_API const Key Key_L;
PHX_API const Key Key_M;
PHX_API const Key Key_N;
PHX_API const Key Key_O;
PHX_API const Key Key_P;
PHX_API const Key Key_Q;
PHX_API const Key Key_R;
PHX_API const Key Key_S;
PHX_API const Key Key_T;
PHX_API const Key Key_U;
PHX_API const Key Key_V;
PHX_API const Key Key_W;
PHX_API const Key Key_X;
PHX_API const Key Key_Y;
PHX_API const Key Key_Z;

PHX_API const Key Key_N0;
PHX_API const Key Key_N1;
PHX_API const Key Key_N2;
PHX_API const Key Key_N3;
PHX_API const Key Key_N4;
PHX_API const Key Key_N5;
PHX_API const Key Key_N6;
PHX_API const Key Key_N7;
PHX_API const Key Key_N8;
PHX_API const Key Key_N9;

PHX_API const Key Key_F1;
PHX_API const Key Key_F2;
PHX_API const Key Key_F3;
PHX_API const Key Key_F4;
PHX_API const Key Key_F5;
PHX_API const Key Key_F6;
PHX_API const Key Key_F7;
PHX_API const Key Key_F8;
PHX_API const Key Key_F9;
PHX_API const Key Key_F10;
PHX_API const Key Key_F11;
PHX_API const Key Key_F12;
PHX_API const Key Key_F13;
PHX_API const Key Key_F14;
PHX_API const Key Key_F15;
PHX_API const Key Key_F16;
PHX_API const Key Key_F17;
PHX_API const Key Key_F18;
PHX_API const Key Key_F19;
PHX_API const Key Key_F20;
PHX_API const Key Key_F21;
PHX_API const Key Key_F22;
PHX_API const Key Key_F23;
PHX_API const Key Key_F24;

PHX_API const Key Key_KP0;
PHX_API const Key Key_KP1;
PHX_API const Key Key_KP2;
PHX_API const Key Key_KP3;
PHX_API const Key Key_KP4;
PHX_API const Key Key_KP5;
PHX_API const Key Key_KP6;
PHX_API const Key Key_KP7;
PHX_API const Key Key_KP8;
PHX_API const Key Key_KP9;

PHX_API const Key Key_KPNumLock;
PHX_API const Key Key_KPDivide;
PHX_API const Key Key_KPMultiply;
PHX_API const Key Key_KPSubtract;
PHX_API const Key Key_KPAdd;
PHX_API const Key Key_KPEnter;
PHX_API const Key Key_KPDecimal;

PHX_API const Key Key_Backspace;
PHX_API const Key Key_Escape;
PHX_API const Key Key_Return;
PHX_API const Key Key_Space;
PHX_API const Key Key_Tab;
PHX_API const Key Key_Backtick;
PHX_API const Key Key_CapsLock;

PHX_API const Key Key_Minus;
PHX_API const Key Key_Equals;
PHX_API const Key Key_LBracket;
PHX_API const Key Key_RBracket;
PHX_API const Key Key_Backslash;
PHX_API const Key Key_Semicolon;
PHX_API const Key Key_Apostrophe;
PHX_API const Key Key_Comma;
PHX_API const Key Key_Period;
PHX_API const Key Key_Slash;

PHX_API const Key Key_PrintScreen;
PHX_API const Key Key_ScrollLock;
PHX_API const Key Key_Pause;
PHX_API const Key Key_Insert;
PHX_API const Key Key_Home;
PHX_API const Key Key_PageUp;
PHX_API const Key Key_PageDown;
PHX_API const Key Key_Delete;
PHX_API const Key Key_Right;
PHX_API const Key Key_Left;
PHX_API const Key Key_Down;
PHX_API const Key Key_Up;

PHX_API const Key Key_LCtrl;
PHX_API const Key Key_LShift;
PHX_API const Key Key_LAlt;
PHX_API const Key Key_LMeta;
PHX_API const Key Key_RCtrl;
PHX_API const Key Key_RShift;
PHX_API const Key Key_RAlt;
PHX_API const Key Key_RMeta;

#endif


text:
#ifndef PHX_State
#define PHX_State

#include "Common.h"

PHX_API const State State_Null;
PHX_API const State State_Changed;
PHX_API const State State_Pressed;
PHX_API const State State_Down;
PHX_API const State State_Released;

PHX_API cstr  State_ToString  (State);

#endif