#pragma once

/********************************************************************************************************************
 ********************************************************************************************************************

                             ______     ______     __  __     __   __   ______
                            /\  == \   /\  __ \   /\ \_\ \   /\ \ / /  /\  ___\
                            \ \  __<   \ \  __ \  \ \____ \  \ \ \'/   \ \  __\
                             \ \_\ \_\  \ \_\ \_\  \/\_____\  \ \__|    \ \_____\
                              \/_/ /_/   \/_/\/_/   \/_____/   \/_/      \/_____/

                                           Ray Traced 3D Game Engine
                                                 Beta Version

                        This proprietary software is provided under license from Raylogic.
      Access and usage of this software must be in accordance with the license found at https://www.raylogic.com

********************************************************************************************************************
********************************************************************************************************************/

#include <new.h>
#include <stdarg.h>
#include <wchar.h>

#ifdef RAYVEDEV
#define RVAPI _declspec(dllexport)
#else
#define RVAPI _declspec(dllimport)
#endif

class ParticlesBridge;
class EntityBridge;
class PrefabBridge;
class SceneBridge;
class OverlayBridge;

namespace Rayve
{
    //  _______                    
    // |__   __|                   
    //    | |_   _ _ __   ___  ___ 
    //    | | | | | '_ \ / _ \/ __|
    //    | | |_| | |_) |  __/\__ \
    //    |_|\__, | .__/ \___||___/
    //        __/ | |              
    //       |___/|_|

    // *************************************************************************************************************
    // Primitive types
    // *************************************************************************************************************

    // $doc "types" "Primitive Types"
    /**/

    // 8-bit unsigned value.
    typedef unsigned char byte;

    // 16-bit unsigned value.
    typedef unsigned short ushort;

    // 32-bit unsigned value.
    typedef unsigned int uint;

    // 64-bit signed value.
    typedef long long slong;

    // 64-bit unsigned value.
    typedef unsigned long long ulong;

    // Wide character.
    typedef wchar_t wchar;

    // Const pointer to wide character string.
    typedef const wchar *wcstr;

    // Const void pointer.
    typedef const void *cptr;

    // Entity key.
    typedef struct EntKey { uint i, v; } EntKey;

    // $docend

    // *************************************************************************************************************
    // String
    // *************************************************************************************************************

    // $doc "string" "String"
    /**/

    // Dynamically sized string using PO2B memory.
    class RVAPI String
    {
    public:
        // Get number of characters in string.
        uint GetLen() const;

        // Check if string ignores case during comparisons.
        bool IsIgnoreCase() const;

        // Implicitly convert this string object to a native C string.
        operator wcstr () const;

        // Assign native [string] to this string.
        String &operator = (wcstr string);

        // Assign [other] string to this string.
        String &operator = (const String &other) { return *this = (wcstr)other; }

        // Append [string] to this string.
        String &operator += (wcstr string);

        // Check if this string is less than [string]. Respects [ignoreCase].
        bool operator < (wcstr string) const { return Compare(*this, string, IsIgnoreCase()) < 0; }

        // Check if this string is less than or equal to [string]. Respects [ignoreCase]
        bool operator <= (wcstr string) const { return Compare(*this, string, IsIgnoreCase()) <= 0; }

        // Check if this string is equal to [string]. Respects [ignoreCase]
        bool operator == (wcstr string) const { return Compare(*this, string, IsIgnoreCase()) == 0; }

        // Check if this string is not equal to [string]. Respects [ignoreCase]
        bool operator != (wcstr string) const { return Compare(*this, string, IsIgnoreCase()) != 0; }

        // Check if this string is greater than or equal to [string]. Respects [ignoreCase]
        bool operator >= (wcstr string) const { return Compare(*this, string, IsIgnoreCase()) >= 0; }

        // Check if this string is greater than [string]. Respects [ignoreCase]
        bool operator > (wcstr string) const { return Compare(*this, string, IsIgnoreCase()) > 0; }

        // Compare [stringA] to [stringB]. Returns -1 if less than, 0 if equal to or 1 if greater than. Respects [ignoreCase].
        static int Compare(wcstr stringA, wcstr stringB, bool ignoreCase = true);

        // Assign [string] to this string. [string] can contain printf style format specifiers.
        // Pass list of arguments [...] to match the format specifiers if any.
        String &Format(uint reserve, wcstr string, ...);

        // Same as Format() except arguments are passed as a stdlib va_list.
        String &FormatArgs(uint reserve, wcstr string, va_list args);

        // Clear string contents.
        String &Clear();

        // Internal.
        void *operator () () const { return (void *)wobj; };

        // Copy constructor.
        String(const String &string);

        // Constructor to create an empty string buffer for storing and manipulating a string.
        // Set [incr] to the estimated maximum characters. [ignoreCase] affects comparisons.
        String(uint incr = 128, int ignoreCase = true);

        // Constructor to create a string object intialized with [string]. [ignoreCase] affects comparisons.
        String(wcstr string, int ignoreCase = true);

        // Destructor.
        ~String();

    private:
        byte wobj[32];
    };

    // $docend

    // *************************************************************************************************************
    // Color
    // *************************************************************************************************************

    // $doc "color" "Color"
    /**/

    // RGBA color.
    class RVAPI Color
    {
    public:
        // Red component.
        float r;

        // Green component.
        float g;

        // Blue component.
        float b;

        // Alpha component
        float a;

        // Get lumenence.
        float GetLumenence() const;

        // Get sum of colors.
        Color operator + (const Color &color) const { return Color(r + color.r, g + color.g, b + color.b); }

        // Get difference of colors.
        Color operator - (const Color &color) const { return Color(r - color.r, g - color.g, b - color.b); }

        // Get product of colors.
        Color operator * (const Color &color) const { return Color(r * color.r, g * color.g, b * color.b); }

        // Get division of colors.
        Color operator / (const Color &color) const { return Color(r / color.r, g / color.g, b / color.b); }

        // Add [color] to this color.
        Color &operator += (const Color &color) { return *this = *this + color; }

        // Subtract [color] from this color.
        Color &operator -= (const Color &color) { return *this = *this - color; }

        // Multiply this color by [color].
        Color &operator *= (const Color &color) { return *this = *this * color; }

        // Divide this color by [color].
        Color &operator /= (const Color &color) { return *this = *this / color; }

        // Normalize color.
        Color &Normalize();

        // Convert color to monochrome.
        Color &Monochrome();

        // Set red, green and blue components.
        Color &SetRGB(float r_, float g_, float b_) { r = r_; g = g_; b = b_; return *this; }

        // Set alpha component.
        Color &SetAlpha(float a_) { a = a_; return *this; }

        // Construct color from components.
        Color(float r, float g, float b, float a = 1) : r(r), g(g), b(b), a(a) {}

        // Construct monochrome color from component value and alpha.
        Color(float n = 0, float a = 1) : r(n), g(n), b(n), a(a) {}

        // Destructor.
        ~Color() {}
    };

    // $docend

    // *************************************************************************************************************
    // Date and Time
    // *************************************************************************************************************

    // $doc "datetime" "Date and Time"
    /**/

    // Date and time.
    class RVAPI DateTime
    {
    public:
        // Milliseconds since 1-1-70.
        slong timestamp;

        // Check if year is a leap year.
        static bool IsLeapYear(uint year);

        // Get date part of date time. Time is set to midnight.
        DateTime GetDate() const;

        // Get year.
        uint GetYear() const;

        // Get month (1 based).
        uint GetMonth() const;

        // Get day (1 based).
        uint GetDay() const;

        // Get hour (0 based).
        uint GetHour() const;

        // Get minute (0 based).
        uint GetMinutes() const;

        // Get second (0 based).
        uint GetSeconds() const;

        // Get day of Year (1 based).
        uint GetDayOfYear() const;

        // Get day of week (1 based).
        uint GetDayOfWeek() const;

        // Get full years from this date/time to [dateTime].
        int GetYearsDiff(const DateTime &dateTime) const;

        // Get full months from this date/time to [dateTime].
        int GetMonthsDiff(const DateTime &dateTime) const;

        // Get full days from this date/time to [dateTime].
        int GetDaysDiff(const DateTime &dateTime) const;

        // Get full hours from this date/time to [dateTime].
        int GetHoursDiff(const DateTime &dateTime) const;

        // Get full minutes from this date/time to [dateTime].
        int GetMinsDiff(const DateTime &dateTime) const;

        // Get full seconds from this date/time to [dateTime].
        int GetSecsDiff(const DateTime &dateTime) const;

        // Get minimum of this date/time and [dateTime].
        DateTime GetMin(const DateTime &dateTime) const;

        // Get maximum of this date/time and [dateTime].
        DateTime GetMax(const DateTime &dateTime) const;

        // Get first day of month.
        DateTime GetFirstOfMonth() const;

        // Get last day of month.
        DateTime GetEndOfMonth() const;

        // Get date/time string. [format] contains wcsftime date/time format specifiers.
        DateTime ToString(String &string, wcstr format) const;

        // Check if this dateTime is less than [dateTime].
        bool operator < (const DateTime &dateTime) const { return timestamp < dateTime.timestamp; }

        // Check if this dateTime is less than or equal to [dateTime].
        bool operator <= (const DateTime &dateTime) const { return timestamp <= dateTime.timestamp; }

        // Check if this dateTime is equal to [dateTime].
        bool operator == (const DateTime &dateTime) const { return timestamp == dateTime.timestamp; }

        // Check if this dateTime is not equal to [dateTime].
        bool operator != (const DateTime &dateTime) const { return timestamp != dateTime.timestamp; }

        // Check if this dateTime is greater than or equal to [dateTime].
        bool operator >= (const DateTime &dateTime) const { return timestamp >= dateTime.timestamp; }

        // Check if this dateTime is greater than [dateTime].
        bool operator > (const DateTime &dateTime) const { return timestamp > dateTime.timestamp; }

        // Get difference of this string and [dateTime].
        slong operator - (const DateTime &dateTime) const { return timestamp - dateTime.timestamp; }

        // Add years to this date/time.
        DateTime AddYears(int years) const;

        // Add months to this date/time.
        DateTime AddMonths(int months) const;

        // Add days to this date/time.
        DateTime AddDays(int days) const;

        // Add hours to this date/time.
        DateTime AddHours(int hours) const;

        // Add minutes to this date/time.
        DateTime AddMins(int mins) const;

        // Add seconds to this date/time.
        DateTime AddSecs(int secs) const;

        // Set this date/time using date and time components.
        DateTime Set(uint year, uint month, uint day, uint hour = 0, uint min = 0, uint sec = 0);

        // Set this date/time using date/time string.
        DateTime Set(wcstr format);

        // Construct date/time using date and time components.
        DateTime(uint year, uint month, uint day, uint hour = 0, uint min = 0, uint sec = 0)
        {
            Set(year, month, day, hour, min, sec);
        }

        // Construct date/time using timestamp.
        DateTime(slong timestamp);

        // Construct date/time using wcsftime format specifiers.
        DateTime(wcstr string);

        // Constuct date/time using current date and time.
        DateTime();

        // Destructor.
        ~DateTime() {}
    };

    // $docend

    // *************************************************************************************************************
    // 2D integer scalar
    // *************************************************************************************************************

    // $doc "s2i" "2D Integer Scalar"
    /**/

    class S2f;

    // 2D integer scalar.
    class RVAPI S2i
    {
    public:
        // X coordinate.
        int x;

        // Y coordinate.
        int y;

        // Check if all coordinates are zero.
        bool operator ! () const { return !x && !y; }

        // Get scalar with negated coordnates.
        S2i operator - () const { return S2i(-x, -y); }

        // Get sum of scalars.
        S2i operator + (const S2i &scalar) const { return S2i(x + scalar.x, y + scalar.y); }

        // Get difference of scalars.
        S2i operator - (const S2i &scalar) const { return S2i(x - scalar.x, y - scalar.y); }

        // Get product of scalars.
        S2i operator * (const S2i &scalar) const { return S2i(x * scalar.x, y * scalar.y); }

        // Get division of scalars.
        S2i operator / (const S2i &scalar) const { return S2i(x / scalar.x, y / scalar.y); }

        // Get modulo of scalars.
        S2i operator % (const S2i &scalar) const { return S2i(x % scalar.x, y % scalar.y); }

        // Add [scalar] to this scalar.
        S2i &operator += (const S2i &scalar) { return *this = *this + scalar; }

        // Subtract [scalar] from this scalar.
        S2i &operator -= (const S2i &scalar) { return *this = *this - scalar; }

        // Multiply this scalar by [scalar].
        S2i &operator *= (const S2i &scalar) { return *this = *this * scalar; }

        // Divide this scalar by [scalar].
        S2i &operator /= (const S2i &scalar) { return *this = *this / scalar; }

        // Modulo this scalar by [scalar].
        S2i &operator %= (const S2i &scalar) { return *this = *this % scalar; }

        // Get minimim of scalars.
        S2i Min(const S2i &scalar) const { return S2i(scalar.x < x ? scalar.x : x, scalar.y < y ? scalar.y : y); }

        // Get maximum of scalars.
        S2i Max(const S2i &scalar) const { return S2i(scalar.x > x ? scalar.x : x, scalar.y > y ? scalar.y : y); }

        // Construct scalar from coordinates.
        S2i(int x, int y) : x(x), y(y) {}

        // Construct scalar from single value.
        S2i(int n = 0) : x(n), y(n) {}

        // Construct scalar from S2f scalar.
        S2i(const S2f &scalar);

        // Destructor.
        ~S2i() {}
    };

    // $docend

    // *************************************************************************************************************
    // 2D float scalar
    // *************************************************************************************************************

    // $doc "s2f" "2D float scalar"
    /**/

    // 2D float scalar.
    class RVAPI S2f
    {
    public:
        // X coordinate.
        float x;

        // Y coordinate.
        float y;

        // Check if all coordinates are zero.
        bool operator ! () const { return !x && !y; }

        // Get scalar with negated coordnates.
        S2f operator - () const { return S2f(-x, -y); }

        // Get sum of scalars.
        S2f operator + (const S2f &scalar) const { return S2f(x + scalar.x, y + scalar.y); }

        // Get difference of scalars.
        S2f operator - (const S2f &scalar) const { return S2f(x - scalar.x, y - scalar.y); }

        // Get product of scalars.
        S2f operator * (const S2f &scalar) const { return S2f(x * scalar.x, y * scalar.y); }

        // Get division of scalars.
        S2f operator / (const S2f &scalar) const { return S2f(x / scalar.x, y / scalar.y); }

        // Add [scalar] to this scalar.
        S2f &operator += (const S2f &scalar) { return *this = *this + scalar; }

        // Subtract [scalar] from this scalar.
        S2f &operator -= (const S2f &scalar) { return *this = *this - scalar; }

        // Multiply this scalar by [scalar].
        S2f &operator *= (const S2f &scalar) { return *this = *this * scalar; }

        // Divide this scalar by [scalar].
        S2f &operator /= (const S2f &scalar) { return *this = *this / scalar; }

        // Get minimim of scalars.
        S2f Min(const S2f &scalar) const { return S2f(scalar.x < x ? scalar.x : x, scalar.y < y ? scalar.y : y); }

        // Get maximum of scalars.
        S2f Max(const S2f &scalar) const { return S2f(scalar.x > x ? scalar.x : x, scalar.y > y ? scalar.y : y); }

        // Construct scalar from S2i scalar.
        S2f(const S2i &scalar) : x((float)scalar.x), y((float)scalar.y) {}

        // Construct scalar from coordinates.
        S2f(float x, float y) : x(x), y(y) {}

        // Construct scalar from single value.
        S2f(float n = 0) : x(n), y(n) {}

        // Destructor.
        ~S2f() {}
    };

    inline S2i::S2i(const S2f &scalar) : x((int)scalar.x), y((int)scalar.y) {}

    // $docend

    // *************************************************************************************************************
    // 3D float scalar
    // *************************************************************************************************************

    // $doc "s3f" "3D float scalar"
    /**/

    class S4f;

    // 3D float scalar.
    class RVAPI S3f
    {
    public:
        // X coordinate.
        float x;

        // Y coordinate.
        float y;

        // Z coordinate.
        float z;

        // Check if all coordinates are zero.
        bool operator ! () const { return !x && !y && !z; }

        // Get scalar with negated coordnates.
        S3f operator - () const { return S3f(-x, -y, -z); }

        // Get sum of scalars.
        S3f operator + (const S3f &scalar) const { return S3f(x + scalar.x, y + scalar.y, z + scalar.z); }

        // Get difference of scalars.
        S3f operator - (const S3f &scalar) const { return S3f(x - scalar.x, y - scalar.y, z - scalar.z); }

        // Get product of scalars.
        S3f operator * (const S3f &scalar) const { return S3f(x * scalar.x, y * scalar.y, z * scalar.z); }

        // Get division of scalars.
        S3f operator / (const S3f &scalar) const { return S3f(x / scalar.x, y / scalar.y, z / scalar.z); }

        // Add [scalar] to this scalar.
        S3f &operator += (const S3f &scalar) { return *this = *this + scalar; }

        // Subtract [scalar] from this scalar.
        S3f &operator -= (const S3f &scalar) { return *this = *this - scalar; }

        // Multiply this scalar by [scalar].
        S3f &operator *= (const S3f &scalar) { return *this = *this * scalar; }

        // Divide this scalar by [scalar].
        S3f &operator /= (const S3f &scalar) { return *this = *this / scalar; }

        // Get dot product of scalars.
        float Dot(const S3f &scalar) const { return x * scalar.x + y * scalar.y + z * scalar.z; }

        // Get cross product of scalars.
        S3f Cross(const S3f &scalar) const
        {
            return S3f(y * scalar.z - z * scalar.y, z * scalar.x - x * scalar.z, x * scalar.y - y * scalar.x);
        }

        // Get angle between scalars.
        float Angle(const S3f &scalar) const;

        // Get angle of scalar on X/Y plane.
        float AngleXY() const;

        // Get angle of scalar on X/Z plane.
        float AngleXZ() const;

        // Get angle of scalar on Y/Z plane.
        float AngleYZ() const;

        // Get magnitude squared of scalar.
        float MagSqr() const;

        // Get magnitued of scalar.
        float Mag() const;

        // Get mininum of scalars.
        S3f Min(const S3f &scalar) const
        {
            return S3f(scalar.x < x ? scalar.x : x, scalar.y < y ? scalar.y : y, scalar.z < z ? scalar.z : z);
        }

        // Get maximum of scalars.
        S3f Max(const S3f &scalar) const
        {
            return S3f(scalar.x > x ? scalar.x : x, scalar.y > y ? scalar.y : y, scalar.z > z ? scalar.z : z);
        }

        // Normalized scalar.
        S3f &Normalize();

        // Construct scalar from coordinates.
        S3f(float x, float y, float z) : x(x), y(y), z(z) {}

        // Construct scalar from single value.
        S3f(float n = 0) : x(n), y(n), z(n) {}

        // Construct scalar from S4f scalar.
        S3f(const S4f &scalar);

        // Destructor.
        ~S3f() {}
    };

    // $docend

    // *************************************************************************************************************
    // 4D float scalar
    // *************************************************************************************************************

    // $doc "s4f" "4D float scalar"
    /**/

    // 4D float scalar.
    class RVAPI S4f
    {
    public:
        // X coordinate.
        float x;

        // Y coordinate.
        float y;

        // Z coordinate.
        float z;

        // Homogeneous coordinate.
        float w;

        // Construct scalar from S4f scalar.
        S4f(const S3f &scalar, float w) : x(scalar.x), y(scalar.y), z(scalar.z), w(w) {}

        // Construct scalar from coordinates.
        S4f(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) {}

        // Construct scalar from S4f scalar.
        S4f(float n = 0, float w = 0) : x(n), y(n), z(n), w(w) {}

        // Destructor.
        ~S4f() {}
    };

    inline S3f::S3f(const S4f &scalar) : x(scalar.x), y(scalar.y), z(scalar.z) {}

    // $docend

    // *************************************************************************************************************
    // 2D integer box
    // *************************************************************************************************************

    // $doc "b2i" "2D Integer Box"
    /**/

    // 2D integer box.
    class RVAPI B2i
    {
    public:
        // Minimum point.
        S2i a;

        // Maximum point.
        S2i b;

        // Check if box has a positive area.
        bool IsValid() const { return b.x > a.x && b.y > a.y; };

        // Check if box intersects [scalar].
        bool IsIntersect(const S2i &scalar) const;

        // Check if this box intersects [box].
        bool IsIntersect(const B2i &box) const;

        // Check if [box] is inside this box.
        bool IsInside(const B2i &box) const;

        // Get box dimensions.
        S2i Dims() const { return b - a; }

        // Get box area.
        int Area() const { return (b.x - a.x) * (b.y - a.y); }

        // Check if box points are both zero.
        bool operator ! () const { return !a && !b; }

        // Get sum of boxes.
        B2i operator + (const B2i &box) const { return B2i(a + box.a, b + box.b); }

        // Get difference of boxes.
        B2i operator - (const B2i &box) const { return B2i(a - box.a, b - box.b); }

        // Get product of boxes.
        B2i operator * (const B2i &box) const { return B2i(a * box.a, b * box.b); }

        // Get division of boxes.
        B2i operator / (const B2i &box) const { return B2i(a / box.a, b / box.b); }

        // Get modulo of boxes.
        B2i operator % (const B2i &box) const { return B2i(a % box.a, b % box.b); }

        // Add [box] to this box.
        B2i &operator += (const B2i &box) { return *this = *this + box; }

        // Subtract [box] from this box.
        B2i &operator -= (const B2i &box) { return *this = *this - box; }

        // Multiply this box by [box].
        B2i &operator *= (const B2i &box) { return *this = *this * box; }

        // Divide this box by [box].
        B2i &operator /= (const B2i &box) { return *this = *this / box; }

        // Modulo this box by [box].
        B2i &operator %= (const B2i &box) { return *this = *this % box; }

        // Get point within this box using normalized coordinates [x] and [y].
        S2i Point(float x, float y) const;

        // Get intersection of this box and [box].
        B2i Intersect(const B2i &box) const;

        // Constrain [scalar] inside this box.
        S2i Constrain(const S2i &scalar) const;

        // Constrain [box] inside this box.
        B2i Constrain(const B2i &box) const;

        // Resize this box to enclose [scalar].
        void Enclose(const S2i &scalar);

        // Resize this box to enclose [box].
        void Enclose(const B2i &box);

        // Construct box from scalar origin and dimensions. Pass true to [dimsMode] parameter.
        B2i(const S2i &scalarA, const S2i &scalarB, bool/*dimsMode*/) : a(scalarA), b(scalarA + scalarB) {}

        // Construct box from scalars.
        B2i(const S2i &scalarA, const S2i &scalarB) : a(scalarA), b(scalarB) {}

        // Construct box from origin and dimensions. Pass true to [dimsMode] parameter.
        B2i(int ax, int ay, int dx, int dy, bool/*dimsMode*/) : a(ax, ay), b(ax + dx, ay + dy) {}

        // Construct box from coordinates.
        B2i(int ax, int ay, int bx, int by) : a(ax, ay), b(bx, by) {}

        // Construct box from single coordinate value.
        B2i(int n = 0) : a(n), b(n) {}

        // Destruct box.
        ~B2i() {}
    };

    // $docend

    // *************************************************************************************************************
    // 2D float box
    // *************************************************************************************************************

    // $doc "b2f" "2D Float Bbox"
    /**/

    // 2D float box.
    class RVAPI B2f
    {
    public:
        // Minimum point.
        S2f a;

        // Maximum point.
        S2f b;

        // Check if box has a positive area.
        bool IsValid() const { return b.x > a.x && b.y > a.y; };

        // Check if box intersects [scalar].
        bool IsIntersect(const S2f &scalar) const;

        // Check if this box intersects [box].
        bool IsIntersect(const B2f &box) const;

        // Check [box] is inside this box.
        bool IsInside(const B2f &box) const;

        // Get box dimensions.
        S2f Dims() const { return b - a; }

        // Get box area.
        float Area() const { return (b.x - a.x) * (b.y - a.y); }

        // Check if box points are both zero.
        bool operator ! () const { return !a && !b; }

        // Get sum of boxes.
        B2f operator + (const B2f &box) const { return B2f(a + box.a, b + box.b); }

        // Get difference of boxes.
        B2f operator - (const B2f &box) const { return B2f(a - box.a, b - box.b); }

        // Get product of boxes.
        B2f operator * (const B2f &box) const { return B2f(a * box.a, b * box.b); }

        // Get division of boxes.
        B2f operator / (const B2f &box) const { return B2f(a / box.a, b / box.b); }

        // Add [box] to this box.
        B2f &operator += (const B2f &box) { return *this = *this + box; }

        // Subtract [box] from this box.
        B2f &operator -= (const B2f &box) { return *this = *this - box; }

        // Multiply this box by [box].
        B2f &operator *= (const B2f &box) { return *this = *this * box; }

        // Divide this box by [box].
        B2f &operator /= (const B2f &box) { return *this = *this / box; }

        // Get point within this box using normalized coordinates [x] and [y].
        S2f Point(float x, float y) const;

        // Get intersection of this box and [box].
        B2f Intersect(const B2f &box) const;

        // Constrain [scalar] inside this box.
        S2f Constrain(const S2f &scalar) const;

        // Constrain [box] inside this box.
        B2f Constrain(const B2f &box) const;

        // Resize this box to enclose [scalar].
        void Enclose(const S2f &scalar);

        // Resize this box to enclose [box].
        void Enclose(const B2f &box);

        // Construct box from scalar origin and dimensions. Pass true to [dimsMode].
        B2f(const S2f &scalarA, const S2f &scalarB, bool/*dimsMode*/) : a(scalarA), b(scalarA + scalarB) {}

        // Construct box from scalars.
        B2f(const S2f &scalarA, const S2f &scalarB) : a(scalarA), b(scalarB) {}

        // Construct box from origin and dimensions. Pass true to [dimsMode].
        B2f(float ax, float ay, float dx, float dy, bool/*dimsMode*/) : a(ax, ay), b(ax + dx, ay + dy) {}

        // Construct box from coordinates.
        B2f(float ax, float ay, float bx, float by) : a(ax, ay), b(bx, by) {}

        // Construct box from single coordinate value.
        B2f(float n = 0) : a(n), b(n) {}

        // Destruct box.
        ~B2f() {}
    };

    // $docend

    // *************************************************************************************************************
    // 3D float box
    // *************************************************************************************************************

    // $doc "b3f" "3D Float Box"
    /**/

    // 3D float box.
    class RVAPI B3f
    {
    public:
        // Minimum point.
        S3f a;

        // Maximum point.
        S3f b;

        // Check if box has a positive area.
        bool IsValid() const { return b.x > a.x && b.y > a.y && b.z > a.z; };

        // Check if box intersects [scalar].
        bool IsIntersect(const S3f &scalar) const;

        // Check if this box intersects [box].
        bool IsIntersect(const B3f &box) const;

        // Check [box] is inside this box.
        bool IsInside(const B3f &box) const;

        // Get box dimensions.
        S3f Dims() const { return b - a; }

        // Get box volume.
        float Volume() const { return (b.x - a.x) * (b.y - a.y) * (b.z - a.z); }

        // Check if box points are both zero.
        bool operator ! () const { return !a && !b; }

        // Get sum of boxes.
        B3f operator + (const B3f &box) const { return B3f(a + box.a, b + box.b); }

        // Get difference of boxes.
        B3f operator - (const B3f &box) const { return B3f(a - box.a, b - box.b); }

        // Get product of boxes.
        B3f operator * (const B3f &box) const { return B3f(a * box.a, b * box.b); }

        // Get division of boxes.
        B3f operator / (const B3f &box) const { return B3f(a / box.a, b / box.b); }

        // Add [box] to this box.
        B3f &operator += (const B3f &box) { return *this = *this + box; }

        // Subtract [box] from this box.
        B3f &operator -= (const B3f &box) { return *this = *this - box; }

        // Multiply this box by [box].
        B3f &operator *= (const B3f &box) { return *this = *this * box; }

        // Divide this box by [box].
        B3f &operator /= (const B3f &box) { return *this = *this / box; }

        // Get point within this box using normalized coordinates [x], [y] and [z].
        S3f Point(float x, float y, float z) const;

        // Get intersection of this box and [box].
        B3f Intersect(const B3f &box) const;

        // Get [scalar] constrained to this box.
        S3f Constrain(const S3f &scalar) const;

        // Get [box] constrained to this box.
        B3f Constrain(const B3f &box) const;

        // Resize this box to enclose [scalar].
        void Enclose(const S3f &scalar);

        // Resize this box to enclose [box].
        void Enclose(const B3f &box);

        // Construct box from scalar origin and dimensions. Pass true to [dimsMode] parameter.
        B3f(const S3f &scalarA, const S3f &scalarB, bool/*dimsMode*/) : a(scalarA), b(scalarA + scalarB) {}

        // Construct box from scalars.
        B3f(const S3f &scalarA, const S3f &scalarB) : a(scalarA), b(scalarB) {}

        // Construct box from coordinates.
        B3f(float ax, float ay, float az, float bx, float by, float bz) : a(ax, ay, az), b(bx, by, bz) {}

        // Construct box from origin and dimensions. Pass true to [dimsMode] parameter.
        B3f(float ax, float ay, float az, float dx, float dy, float dz, bool/*dimsMode*/) : a(ax, ay, az), b(ax + dx, ay + dy, az + dz) {}

        // Construct box from single coordinate value.
        B3f(float n = 0) : a(n), b(n) {}

        // Destruct box.
        ~B3f() {}
    };

    // $docend

    // *************************************************************************************************************
    // 3D matrix
    // *************************************************************************************************************

    // $doc "m4f" "3D Matrix"
    /**/

    // 3D matrix.
    class RVAPI M4f
    {
    public:
        // X vector.
        S4f x;

        // Y vector.
        S4f y;

        // Z vector.
        S4f z;

        // Homogeneous vector.
        S4f w;

        // Get this matrix transformed by [matrix].
        M4f operator * (const M4f &matrix) const;

        // Transform this matrix by [matrix].
        M4f &operator *= (const M4f &matrix) { return *this = *this * matrix; }

        // Get this matrix inverted.
        M4f Invert() const;

        // Normailze this matrix.
        M4f &Normalize();

        // Construct uninitialized matrix.
        M4f() {}

        // Destructor.
        ~M4f() {}
    };

    // Get [scalar] transformed by [matrix].
    RVAPI S4f operator * (const S4f &scalar, const M4f &matrix);

    // Transform [scalar] by [matrix].
    inline const S4f &operator *= (S4f &scalar, const M4f &matrix) { return scalar = scalar * matrix; }

    // Identity matrix.
    class RVAPI M4fIdent : public M4f
    {
    public:
        // Constructor.
        M4fIdent();
    };

    // Translate matrix.
    class RVAPI M4fTrans : public M4f
    {
    public:
        // Construct matrix from [scalar].
        M4fTrans(const S3f &scalar);

        // Construct matrix from coordinates.
        M4fTrans(float x, float y, float z);

        // Construct matrix from single value.
        M4fTrans(float n = 0);
    };

    // Scale matrix.
    class RVAPI M4fScale : public M4f
    {
    public:
        // Construct matrix from [scalar].
        M4fScale(const S3f &scalar);

        // Construct matrix from axis scale values.
        M4fScale(float x, float y, float z);

        // Construct matrix from single value.
        M4fScale(float n = 1);
    };

    // X rotation matrix.
    class RVAPI M4fRotX : public M4f
    {
    public:
        // Construct matrix from [angle].
        M4fRotX(float angle);
    };

    // Y rotation matrix.
    class RVAPI M4fRotY : public M4f
    {
    public:
        // Construct matrix from [angle].
        M4fRotY(float angle);
    };

    // Z rotation matrix.
    class RVAPI M4fRotZ : public M4f
    {
    public:
        // Construct matrix from [angle].
        M4fRotZ(float angle);
    };

    // Rotation matrix.
    class RVAPI M4fRot : public M4f
    {
    public:
        // Construct matrix from [axis] and [angle].
        M4fRot(const S3f &axis, float angle);
    };

    // Alignment matrix.
    class RVAPI M4fAlign : public M4f
    {
    public:
        // Construct matrix to align from [scalarA] to [scalarB].
        M4fAlign(const S3f &scalarA, const S3f &scalarB);
    };

    // Look at matrix.
    class RVAPI M4fLookAt : public M4f
    {
    public:
        // Construct matrix to look from [eye] to [at] while maintaining [up].
        M4fLookAt(const S3f &eye, const S3f &at, const S3f &up);
    };

    // Untranslated matrix.
    class RVAPI M4fTransOut : public M4f
    {
    public:
        // Construct matrix from [matrix] with translation removed and stored in [trans].
        M4fTransOut(const M4f &matrix, S3f &trans);
    };

    // Restored translation matrix.
    class RVAPI M4fTransIn : public M4f
    {
    public:
        // Construct matrix from [matrix] with translation restored from [trans].
        M4fTransIn(const M4f &matrix, const S3f &trans);
    };

    // $docend

    // *************************************************************************************************************
    // 2D meta position
    // *************************************************************************************************************

    // $doc "metapos" "Meta Position"
    /**/

    // 2D meta position is used for resolution independent positioning 2D elements on an overlay.
    // Coordinates for pos, handle or dims can be normalized or in pixels. If the coordinate is
    // in range -1 to 1 the coordinate is normalized. Outside this range, the coordinate is in pixels.
    // Negative coordinates are relative to the opposite side. Pixel coordinates use a virtual screen
    // size of 1920x1080. Internally Rayve will scale the virtual pixel coordinates to match the
    // real screen resolution.
    class RVAPI MetaPos
    {
    public:
        // Position.
        S2f pos;

        // Local origin.
        S2f handle;

        // Dimensions.
        S2f dims;

        // Flags.
        uint flags;

        // These flags are needed in special cases where a value is already DPI scaled, or where
        // values less than or equal to 1 need to be pixel values instead of normalized, or negative 
        // values need to be used directly instead of wrapping from the opposite side.
        enum Flags
        {
            // Don't DPI scale x position.
            NOSCALE_POSX = 0x0001,

            // Don't DPI scale y position.
            NOSCALE_POSY = 0x0002,

            // Don't DPI scale z position.
            NOSCALE_POS = 0x0003,

            // Don't DPI scale handle x.
            NOSCALE_HDLX = 0x0004,

            // Don't DPI scale handle y.
            NOSCALE_HDLY = 0x0008,

            // Don't DPI scale handle z.
            NOSCALE_HDL = 0x000C,

            // Don't DPI scale x dimension.
            NOSCALE_DIMSX = 0x0010,

            // Don't DPI scale y dimension.
            NOSCALE_DIMSY = 0x0020,

            // Don't DPI scale z dimension.
            NOSCALE_DIMS = 0x0030,

            // Don't normalize x position.
            NONORM_POSX = 0x0040,

            // Don't normalize y position.
            NONORM_POSY = 0x0080,

            // Don't normalize position.
            NONORM_POS = 0x00C0,

            // Don't DPI scale.
            NOSCALE = 0x003F,

            // Don't wrap negative coordinates.
            NOWRAP = 0x0100
        };

        // Resolve meta position to real screen coordinates based on the
        // real screen coordinates of the parent rectangle [pRect].
        B2i Resolve(const B2i &pRect) const;

        // Construct meta position using position scalar, handle scalar and dimension scalar.
        MetaPos(const S2f &pos, const S2f &handle, const S2f &dims, uint flags = 0)
            : pos(pos), handle(handle), dims(dims), flags(flags) {
        }

        // Construct meta position using position coordinates, handle coordinates and dimension coordinates.
        MetaPos(float px, float py, float hx, float hy, float dx, float dy, uint flags = 0)
            : pos(px, py), handle(hx, hy), dims(dx, dy), flags(flags) {
        }

        // Constructor.
        MetaPos() {}

        // Destructor.
        ~MetaPos() {}
    };

    // $docend

    //  __  __                                 
    // |  \/  |                                
    // | \  / | ___ _ __ ___   ___  _ __ _   _ 
    // | |\/| |/ _ \ '_ ` _ \ / _ \| '__| | | |
    // | |  | |  __/ | | | | | (_) | |  | |_| |
    // |_|  |_|\___|_| |_| |_|\___/|_|   \__, |
    //                                    __/ |
    //                                   |___/ 

    // *************************************************************************************************************
    // Memory
    // *************************************************************************************************************

    // $doc "memory" "Memory Classes"
    /**/

    // Destruct callback for cleaning up item.
    typedef void (*FDestruct)(void *ptr);

    // Compare keys callback indicating key order. Returns -1 when [a] is less than [b],
    // 0 when [a] equals [b] and 1 when [a] is greater than [b].
    typedef int (*FCompareKeys)(cptr a, cptr b);

    // Construct [key] using [mem]. Usage: new (mem) T(key).
    typedef void (*FConstructKey)(void *mem, cptr key);

    // Power of 2 bucketed (PO2B) memory heap.
    class RVAPI HeapMem
    {
    public:
        // Allocate [size] memory.
        static void *Alloc(uint size);

        // Free memory. [ptr] is set to zero.
        static void Free(void **ptr);

        // Start printing memory allocations.
        static void Mark();

        // Stop printing memory allocations.
        static void Unmark();
    };

    // Array PO2B memory.
    class RVAPI ArrayMem
    {
    public:
        // Get item count.
        uint GetCount() const;

        // Get item at [index]. Negative [index] offsets from end.
        void *GetItem(int index) const;

        // Check if array is empty.
        bool operator ! () const { return GetCount() == 0; }

        // Add item. [at] is index of insertion. Negative [at] offsets from end. 
        // [index] pointer receives index of added item if non-zero.
        // Returns memory to use with new. Usage: new (array.Add()) Type().
        void *Add(int at = -1, int *index = 0);

        // Delete item at [index]. Negative [index] offsets from end.
        void Delete(int index = -1);

        // Remove all items.
        void Clear();

        // Internal.
        void *operator () () const { return (void *)wobj; }

        // Construct array with items of size [itemSize]. Set [incr] to estimated max number of items.
        // [Destruct] callback is called on items being deleted.
        ArrayMem(uint itemSize, uint incr, FDestruct Destruct);

        // Destructor. Destruct callback is called on remaining items.
        ~ArrayMem();

    private:
        byte wobj[64];
    };

    // List PO2B memory.
    class RVAPI ListMem
    {
    public:
        // Check if original item exists.
        bool IsItem(int index, int ver) const;

        // Get item count.
        uint GetCount() const;

        // Get item version.
        uint GetVer(void *item) const;

        // Get first item. Sets [index] iteration variable.
        void *GetFirst(int &index) const;

        // Get last item. Sets [index] iteration variable.
        void *GetLast(int &index) const;

        // Get previous item using [index] iteration variable.
        void *GetPrev(int &index) const;

        // Get next item using [index] iteration variable.
        void *GetNext(int &index) const;

        // Get item at [index]. Negative [index] offsets from end.
        void *GetItem(int index) const;

        // Check if list is empty.
        bool operator ! () const { return GetCount() == 0; }

        // Add item. [index] pointer receives index of added item if non-zero.
        // Returns memory to use with new. Usage: new (list.Add()) Type().
        void *Add(int *index = 0, int *ver = 0);

        // Delete item at [index]. Negative [index] offsets from end.
        void Delete(int index);

        // Delete all items.
        void Clear();

        // Internal.
        void *operator () () const { return (void *)wobj; }

        // Initialize list with items of size [itemSize]. Set [incr] to estimated max number of items.
        // [Destruct] callback is called on items being deleted.
        ListMem(uint itemSize, uint incr, FDestruct Destruct);

        // Destruct queue. Destruct callback is called on remaining items.
        ~ListMem();

    private:
        byte wobj[192];
    };

    // Queue PO2B memory.
    class RVAPI QueueMem
    {
    public:
        // Get item count.
        uint GetCount() const;

        // Get item at front of queue.
        void *GetItem() const;

        // Check if queue is empty.
        bool operator ! () const { return GetCount() == 0; }

        // Add item to end of queue. Returns memory to use with new. Usage: new (queue.Add()) Type().
        void *Add();

        // Delete item from front of queue.
        void Delete();

        // Delete all items.
        void Clear();

        // Internal.
        void *operator () () const { return (void *)wobj; }

        // Construct queue with items of size [itemSize]. Set [incr] to estimated max number of items.
        // [Destruct] callback is called on items being deleted.
        QueueMem(uint itemSize, uint incr, FDestruct Destruct);

        // Deconstuct queue. Destruct is called on remaining items.
        ~QueueMem();

    private:
        byte wobj[96];
    };

    // Map PO2B memory
    class RVAPI MapMem
    {
    public:
        // Get item count.
        uint GetCount() const;

        // Get key by [index]. Iterating through the map with [index] returns items in key order.
        void *GetKey(uint index) const;

        // Get item by [index].Iterating through the map with [index] returns items in key order.
        void *GetItem(uint index) const;

        // Check if map is empty.
        bool operator ! () const { return GetCount() == 0; }

        // Find item by [key].
        void *Find(cptr key) const;

        // Add item using [key]. Returns memory to use with new. Usage: new (map.Add()) Type().
        void *Add(cptr key);

        // Delete item using [key].
        void Delete(cptr key);

        // Delete all items.
        void Clear();

        // Internal.
        void *operator () () const { return (void *)wobj; }

        // Construct map with items of size [itemSize] and keys of [keySize]. Set [incr] to estimated max number 
        // of items. [CompareKeys] is called when keys need to be compared. [Constructkey] is called when a key
        // needs to be constructed. [Destruct] is called on items being deleted.
        MapMem(uint itemSize, uint keySize, uint incr, FCompareKeys CompareKeys,
            FConstructKey ConstructKey, FDestruct IDestruct, FDestruct KDestruct);

        // Destruct map. Destruct callback is called on remaining items.
        ~MapMem();

    private:
        byte wobj[256];
    };

    // $docend

    // *************************************************************************************************************
    // Array
    // *************************************************************************************************************

    // $doc "array" "Array"
    /**/

    // Dynamically sized array using PO2B memory. Also see class ArrayMem in Memory section for 
    // additional functions used by this template.
    template<typename T> class Array : public ArrayMem
    {
    public:
        // Ignore iterator class.
        class const_iterator
        {
        public:
            typedef const_iterator self_type;
            typedef const T value_type;
            typedef const T &reference;
            typedef const T *pointer;
            typedef int difference_type;

            int index() const { return n; };

            self_type operator++() { n++; return *this; }
            self_type operator++(int ignore) { self_type i = *this; n++; return i; }
            reference operator*() const { return (*array)[n]; }
            pointer operator->() const { return &(*array)[n]; }
            bool operator==(const self_type &rhs) const { return n == rhs.n; }
            bool operator!=(const self_type &rhs) const { return n != rhs.n; }

            const_iterator(const Array<T> &array, int n) : array(&array), n(n) {}
            const_iterator() : array(0), n(0) {}

        private:
            const Array<T> *array;
            int n;
        };

        // Ignore iterator class.
        class iterator
        {
        public:
            typedef iterator self_type;
            typedef T value_type;
            typedef T &reference;
            typedef T *pointer;
            typedef int difference_type;

            int index() const { return n; };

            self_type operator++() { n++; return *this; }
            self_type operator++(int ignore) { self_type i = *this; n++; return i; }
            reference operator*() const { return (*array)[n]; }
            pointer operator->() const { return &(*array)[n]; }
            bool operator==(const self_type &rhs) const { return n == rhs.n; }
            bool operator!=(const self_type &rhs) const { return n != rhs.n; }

            iterator(Array<T> &array, int n) : array(&array), n(n) {}
            iterator() : array(0), n(0) {}

        private:
            Array<T> *array;
            int n;
        };

        // Ignore iterator class.
        class const_reverse_iterator
        {
        public:
            typedef const_reverse_iterator self_type;
            typedef const T value_type;
            typedef const T &reference;
            typedef const T *pointer;
            typedef int difference_type;

            int index() const { return n; };

            self_type operator++() { n--; return *this; }
            self_type operator++(int ignore) { self_type i = *this; n--; return i; }
            reference operator*() const { return (*array)[n]; }
            pointer operator->() const { return &(*array)[n]; }
            bool operator==(const self_type &rhs) const { return n == rhs.n; }
            bool operator!=(const self_type &rhs) const { return n != rhs.n; }

            const_reverse_iterator(const Array<T> &array, int n) : array(&array), n(n) {}
            const_reverse_iterator() : array(0), n(0) {}

        private:
            const Array<T> *array;
            int n;
        };

        // Ignore iterator class.
        class reverse_iterator
        {
        public:
            typedef reverse_iterator self_type;
            typedef T value_type;
            typedef T &reference;
            typedef T *pointer;
            typedef int difference_type;

            int index() const { return n; };

            self_type operator++() { n--; return *this; }
            self_type operator++(int ignore) { self_type i = *this; n--; return i; }
            reference operator*() const { return (*array)[n]; }
            pointer operator->() const { return &(*array)[n]; }
            bool operator==(const self_type &rhs) const { return n == rhs.n; }
            bool operator!=(const self_type &rhs) const { return n != rhs.n; }

            reverse_iterator(Array<T> &array, int n) : array(&array), n(n) {}
            reverse_iterator() : array(0), n(0) {}

        private:
            Array<T> *array;
            int n;
        };

        // Get constant begin iterator.
        const_iterator begin() const { return const_iterator(*this, 0); }

        // Get constant end iterator.
        const_iterator end() const { return const_iterator(*this, GetCount()); }

        // Get begin iterator.
        iterator begin() { return iterator(*this, 0); }

        // Get end iterator.
        iterator end() { return iterator(*this, GetCount()); }

        // Get constant reverse begin iterator.
        const_reverse_iterator rbegin() const { return const_reverse_iterator(*this, GetCount() - 1); }

        // Get constant reverse end iterator.
        const_reverse_iterator rend() const { return const_reverse_iterator(*this, -1); }

        // Get reverse begin iterator.
        reverse_iterator rbegin() { return reverse_iterator(*this, GetCount() - 1); }

        // Get reverse end iterator.
        reverse_iterator rend() { return reverse_iterator(*this, -1); }

        // Get item using [index]. Negative index offsets from end.
        T &operator [] (int index) const { return *(T *)GetItem(index); }

        // Construct array using estimated max items for [incr].
        Array(uint incr = 8) : ArrayMem((uint)sizeof(T), incr, Destruct) {}

        // Destructor.
        ~Array() {}

    private:
        static void Destruct(void *ptr) { ((T *)ptr)->~T(); }
    };

    // $docend

    // *************************************************************************************************************
    // List
    // *************************************************************************************************************

    // $doc "list" "List"
    /**/

    // Dynamically sized list using PO2B memory. Made for items that are. Also see class ListMem in Memory section 
    // for additional functions used by this template.
    template<typename T> class List : public ListMem
    {
    public:
        // Ignore iterator class.
        class const_iterator
        {
        public:
            typedef const_iterator self_type;
            typedef const T value_type;
            typedef const T &reference;
            typedef const T *pointer;
            typedef int difference_type;

            int index() const { return n; };

            self_type operator++() { list->GetNext(n); return *this; }
            self_type operator++(int ignore) { self_type i = *this; list->GetNext(n); return i; }
            reference operator*() const { return (*list)[n]; }
            pointer operator->() const { return &(*list)[n]; }
            bool operator==(const self_type &rhs) const { return n == rhs.n; }
            bool operator!=(const self_type &rhs) const { return n != rhs.n; }

            const_iterator(const List<T> &list, int n) : list(&list), n(n) {}
            const_iterator() : list(0), n(0) {}

        private:
            const List<T> *list;
            int n;
        };

        // Ignore iterator class.
        class iterator
        {
        public:
            typedef iterator self_type;
            typedef T value_type;
            typedef T &reference;
            typedef T *pointer;
            typedef int difference_type;

            int index() const { return n; };

            self_type operator++() { list->GetNext(n); return *this; }
            self_type operator++(int ignore) { self_type i = *this; list->GetNext(n); return i; }
            reference operator*() const { return (*list)[n]; }
            pointer operator->() const { return &(*list)[n]; }
            bool operator==(const self_type &rhs) const { return n == rhs.n; }
            bool operator!=(const self_type &rhs) const { return n != rhs.n; }

            iterator(List<T> &list, int n) : list(&list), n(n) {}
            iterator() : list(0), n(0) {}

        private:
            List<T> *list;
            int n;
        };

        // Ignore iterator class.
        class const_reverse_iterator
        {
        public:
            typedef const_reverse_iterator self_type;
            typedef const T value_type;
            typedef const T &reference;
            typedef const T *pointer;
            typedef int difference_type;

            int index() const { return n; };

            self_type operator++() { list->GetPrev(n); return *this; }
            self_type operator++(int ignore) { self_type i = *this; list->GetPrev(n); return i; }
            reference operator*() const { return (*list)[n]; }
            pointer operator->() const { return &(*list)[n]; }
            bool operator==(const self_type &rhs) const { return n == rhs.n; }
            bool operator!=(const self_type &rhs) const { return n != rhs.n; }

            const_reverse_iterator(const List<T> &list, int n) : list(&list), n(n) {}
            const_reverse_iterator() : list(0), n(0) {}

        private:
            const List<T> *list;
            int n;
        };

        // Ignore iterator class.
        class reverse_iterator
        {
        public:
            typedef reverse_iterator self_type;
            typedef T value_type;
            typedef T &reference;
            typedef T *pointer;
            typedef int difference_type;

            int index() const { return n; };

            self_type operator++() { list->GetPrev(n); return *this; }
            self_type operator++(int ignore) { self_type i = *this; list->GetPrev(n); return i; }
            reference operator*() const { return (*list)[n]; }
            pointer operator->() const { return &(*list)[n]; }
            bool operator==(const self_type &rhs) const { return n == rhs.n; }
            bool operator!=(const self_type &rhs) const { return n != rhs.n; }

            reverse_iterator(List<T> &list, int n) : list(&list), n(n) {}
            reverse_iterator() : list(0), n(0) {}

        private:
            List<T> *list;
            int n;
        };

        // Get constant begin iterator.
        const_iterator begin() const { int index = 0; GetFirst(index); return const_iterator(*this, index); }

        // Get constant end iterator.
        const_iterator end() const { int index = 0; GetLast(index); GetNext(index);	return const_iterator(*this, index); }

        // Get begin iterator.
        iterator begin() { int index = 0; GetFirst(index); return iterator(*this, index); }

        // Get end iterator.
        iterator end() { int index = 0; GetLast(index); GetNext(index); return iterator(*this, index); }

        // Get constant reverse begin iterator.
        const_reverse_iterator rbegin() const { int index = 0; GetLast(index); return const_reverse_iterator(*this, index); }

        // Get constant reverse end iterator.
        const_reverse_iterator rend() const { int index = 0; GetFirst(index); GetPrev(index); return const_reverse_iterator(*this, index); }

        // Get reverse begin iterator.
        reverse_iterator rbegin() { int index = 0; GetLast(index); return reverse_iterator(*this, index); }

        // Get reverse end iterator.
        reverse_iterator rend() { int index = 0; GetFirst(index); GetPrev(index); return reverse_iterator(*this, index); }

        // Get first item. Initializes index iterator.
        T *GetFirst(int &index) const { return (T *)ListMem::GetFirst(index); }

        // Get last item. Initializes index iterator.
        T *GetLast(int &index) const { return (T *)ListMem::GetLast(index); }

        // Get previous item. Index iterator must be intialized with GetLast().
        T *GetPrev(int &index) const { return (T *)ListMem::GetPrev(index); }

        // Get next item. Index iterator must be intialized with GetFirst().
        T *GetNext(int &index) const { return (T *)ListMem::GetNext(index); }

        // Get item at [index].
        T &operator [] (int index) const { return *(T *)GetItem(index); }

        // Constructor using estimated max items for [incr].
        List(uint incr = 8) : ListMem((uint)sizeof(T), incr, Destruct) {}

        // Destructor.
        ~List() {}

    private:
        static void Destruct(void *ptr) { ((T *)ptr)->~T(); }
    };

    // $docend

    // *************************************************************************************************************
    // Queue
    // *************************************************************************************************************

    // $doc "queue" "Queue"
    /**/

    // Dynamically sized first-in first-out queue using PO2B memory. Also see class QueueMem in 
    // Memory section for additional functions used by this template.
    template<typename T> class Queue : public QueueMem
    {
    public:
        // Remove item at front of queue.
        T &GetItem() { return *(T *)QueueMem::GetItem(); }

        // Construct queue using estimated maximum items for [incr]. 
        Queue(uint incr = 8) : QueueMem((uint)sizeof(T), incr, Destruct) {}

        // Destructor.
        ~Queue() {}

    private:
        static void Destruct(void *ptr) { ((T *)ptr)->~T(); }
    };

    // $docend

    // *************************************************************************************************************
    // Map
    // *************************************************************************************************************

    // $doc "map" "Map"
    /**/

    // Dynamically sized map using PO2B memory. Also see class MapMem in Memory section for 
    // additional functions used by this template.
    template<typename K, typename I>
    class Map : public MapMem
    {
    public:
        // Ignore iterator class.
        class const_iterator
        {
        public:
            struct Pair { const K &key; const I &item; };
            typedef const_iterator self_type;
            typedef const Pair value_type;
            typedef value_type reference;
            typedef int difference_type;

            const K &Key() const { return map->GetKey(n); }
            const I &Item() const { return map->GetItem(n); }

            self_type operator++() { n++; return *this; }
            self_type operator++(int ignore) { self_type i = *this; n++; return i; }
            reference operator*() const { return { map->GetKey(n), map->GetItem(n) }; }
            bool operator==(const self_type &rhs) const { return n == rhs.n; }
            bool operator!=(const self_type &rhs) const { return n != rhs.n; }

            const_iterator(const Map<K, I> &map, int n) : map(&map), n(n) {}
            const_iterator() : map(0), n(0) {}

        private:
            const Map<K, I> *map;
            int n;
        };

        // Ignore iterator class.
        class iterator
        {
        public:
            struct Pair { const K &key; I &item; };
            typedef iterator self_type;
            typedef Pair value_type;
            typedef value_type reference;
            typedef int difference_type;

            const K &Key() const { return map->GetKey(n); }
            I &Item() const { return map->GetItem(n); }

            self_type operator++() { n++; return *this; }
            self_type operator++(int ignore) { self_type i = *this; n++; return i; }
            reference operator*() const { return { map->GetKey(n), map->GetItem(n) }; }
            bool operator==(const self_type &rhs) const { return n == rhs.n; }
            bool operator!=(const self_type &rhs) const { return n != rhs.n; }

            iterator(Map<K, I> &map, int n) : map(&map), n(n) {}
            iterator() : map(0), n(0) {}

        private:
            Map<K, I> *map;
            int n;
        };

        // Ignore iterator class.
        class const_reverse_iterator
        {
        public:
            struct Pair { const K &key; const I &item; };
            typedef const_reverse_iterator self_type;
            typedef const Pair value_type;
            typedef value_type reference;
            typedef int difference_type;

            const K &Key() const { return map->GetKey(n); }
            const I &Item() const { return map->GetItem(n); }

            self_type operator++() { n--; return *this; }
            self_type operator++(int ignore) { self_type i = *this; n--; return i; }
            reference operator*() const { return { map->GetKey(n), map->GetItem(n) }; }
            bool operator==(const self_type &rhs) const { return n == rhs.n; }
            bool operator!=(const self_type &rhs) const { return n != rhs.n; }

            const_reverse_iterator(const Map<K, I> &map, int n) : map(&map), n(n) {}
            const_reverse_iterator() : map(0), n(0) {}

        private:
            const Map<K, I> *map;
            int n;
        };

        // Ignore iterator class.
        class reverse_iterator
        {
        public:
            struct Pair { const K &key; I &item; };
            typedef reverse_iterator self_type;
            typedef Pair value_type;
            typedef value_type reference;
            typedef int difference_type;

            const K &Key() const { return map->GetKey(n); }
            I &Item() const { return map->GetItem(n); }

            self_type operator++() { n--; return *this; }
            self_type operator++(int ignore) { self_type i = *this; n--; return i; }
            reference operator*() const { return { map->GetKey(n), map->GetItem(n) }; }
            bool operator==(const self_type &rhs) const { return n == rhs.n; }
            bool operator!=(const self_type &rhs) const { return n != rhs.n; }

            reverse_iterator(Map<K, I> &map, int n) : map(&map), n(n) {}
            reverse_iterator() : map(0), n(0) {}

        private:
            Map<K, I> *map;
            int n;
        };

        // Get constant begin iterator.
        const_iterator begin() const { return const_iterator(*this, 0); }

        // Get constant end iterator.
        const_iterator end() const { return const_iterator(*this, GetCount()); }

        // Get begin iterator.
        iterator begin() { return iterator(*this, 0); }

        // Get end iterator.
        iterator end() { return iterator(*this, GetCount()); }

        // Get constant reverse begin iterator.
        const_reverse_iterator rbegin() const { return const_reverse_iterator(*this, GetCount() - 1); }

        // Get constant reverse end iterator.
        const_reverse_iterator rend() const { return const_reverse_iterator(*this, -1); }

        // Get reverse begin iterator.
        reverse_iterator rbegin() { return reverse_iterator(*this, GetCount() - 1); }

        // Get reverse end iterator.
        reverse_iterator rend() { return reverse_iterator(*this, -1); }

        // Find item by [key].
        void *Find(const K &key) const { return MapMem::Find(&key); }

        // Add item using [key]. Returns memory to use with new. Usage: new (map.Add()) Type().
        void *Add(const K &key) { return MapMem::Add(&key); }

        // Delete item using [key].
        void Delete(const K &key) { return MapMem::Delete(&key); }

        // Get key at index. Sequential access by index returns keys in key order.
        K &GetKey(int index) const { return *(K *)MapMem::GetKey(index); }

        // Get item at index. Sequential access by index returns items in key order.
        I &GetItem(int index) const { return *(I *)MapMem::GetItem(index); }

        // Get item using key. Returns 0 if not found.
        I *operator [] (const K &key) const { return (I *)Find(key); }

        // Construct map using estimated maximum elemements for [incr].
        Map(uint incr = 8) : MapMem((uint)sizeof(I), (uint)sizeof(K), incr, CompareKeys, ConstructKey, IDestruct, KDestruct) {}

        // Destructor.
        ~Map() {}

    private:
        static int  CompareKeys(cptr a_, cptr b_) { K &a = *(K *)a_; K &b = *(K *)b_; return a < b ? -1 : a > b ? 1 : 0; }
        static void ConstructKey(void *mem, cptr key) { new (mem) K(*(K *)key); }
        static void IDestruct(void *ptr) { ((I *)ptr)->~I(); }
        static void KDestruct(void *ptr) { ((K *)ptr)->~K(); }
    };

    // $docend

    // *************************************************************************************************************
    // Span
    // *************************************************************************************************************

    // $doc "span" "Span"
    /**/

    // Stores a fixed-size array of items locally without allocating from the heap. Can be used to store an 
    // array of items as a local variable in a function or as member variable in a class. Template param [M] 
    // is the maximum items the array can hold.
    template<typename T, uint M = 8>
    class Span
    {
    public:
        // Ignore iterator class.
        class const_iterator
        {
        public:
            typedef const_iterator self_type;
            typedef const T value_type;
            typedef const T &reference;
            typedef const T *pointer;
            typedef int difference_type;

            int index() const { return n; };

            self_type operator++() { n++; return *this; }
            self_type operator++(int ignore) { self_type i = *this; n++; return i; }
            reference operator*() const { return (*span)[n]; }
            pointer operator->() const { return &(*span)[n]; }
            bool operator==(const self_type &rhs) const { return n == rhs.n; }
            bool operator!=(const self_type &rhs) const { return n != rhs.n; }

            const_iterator(const Span<T, M> &span, int n) : span(&span), n(n) {}
            const_iterator() : span(0), n(0) {}

        private:
            const Span<T, M> *span;
            int n;
        };

        // Ignore iterator class.
        class iterator
        {
        public:
            typedef iterator self_type;
            typedef T value_type;
            typedef T &reference;
            typedef T *pointer;
            typedef int difference_type;

            int index() const { return n; };

            self_type operator++() { n++; return *this; }
            self_type operator++(int ignore) { self_type i = *this; n++; return i; }
            reference operator*() const { return (*span)[n]; }
            pointer operator->() const { return &(*span)[n]; }
            bool operator==(const self_type &rhs) const { return n == rhs.n; }
            bool operator!=(const self_type &rhs) const { return n != rhs.n; }

            iterator(Span<T, M> &span, int n) : span(&span), n(n) {}
            iterator() : span(0), n(0) {}

        private:
            Span<T, M> *span;
            int n;
        };

        // Ignore iterator class.
        class const_reverse_iterator
        {
        public:
            typedef const_reverse_iterator self_type;
            typedef const T value_type;
            typedef const T &reference;
            typedef const T *pointer;
            typedef int difference_type;

            int index() const { return n; };

            self_type operator++() { n--; return *this; }
            self_type operator++(int ignore) { self_type i = *this; n--; return i; }
            reference operator*() const { return (*span)[n]; }
            pointer operator->() const { return &(*span)[n]; }
            bool operator==(const self_type &rhs) const { return n == rhs.n; }
            bool operator!=(const self_type &rhs) const { return n != rhs.n; }

            const_reverse_iterator(const Span<T, M> &span, int n) : span(&span), n(n) {}
            const_reverse_iterator() : span(0), n(0) {}

        private:
            const Span<T, M> *span;
            int n;
        };

        // Ignore iterator class.
        class reverse_iterator
        {
        public:
            typedef reverse_iterator self_type;
            typedef T value_type;
            typedef T &reference;
            typedef T *pointer;
            typedef int difference_type;

            int index() const { return n; };

            self_type operator++() { n--; return *this; }
            self_type operator++(int ignore) { self_type i = *this; n--; return i; }
            reference operator*() const { return (*span)[n]; }
            pointer operator->() const { return &(*span)[n]; }
            bool operator==(const self_type &rhs) const { return n == rhs.n; }
            bool operator!=(const self_type &rhs) const { return n != rhs.n; }

            reverse_iterator(Span<T, M> &span, int n) : span(&span), n(n) {}
            reverse_iterator() : span(0), n(0) {}

        private:
            Span<T, M> *span;
            int n;
        };

        // Get constant begin iterator.
        const_iterator begin() const { return const_iterator(*this, 0); }

        // Get constant end iterator.
        const_iterator end() const { return const_iterator(*this, GetCount()); }

        // Get begin iterator.
        iterator begin() { return iterator(*this, 0); }

        // Get end iterator.
        iterator end() { return iterator(*this, GetCount()); }

        // Get constant reverse begin iterator.
        const_reverse_iterator rbegin() const { return const_reverse_iterator(*this, GetCount() - 1); }

        // Get constant reverse end iterator.
        const_reverse_iterator rend() const { return const_reverse_iterator(*this, -1); }

        // Get reverse begin iterator.
        reverse_iterator rbegin() { return reverse_iterator(*this, GetCount() - 1); }

        // Get reverse end iterator.
        reverse_iterator rend() { return reverse_iterator(*this, -1); }

        // Get item count.
        uint GetCount() const { return count; }

        // Check if array is empty.
        bool operator ! () const { return !count; }

        // Get item at index
        T &operator [](int index) const { if (index < 0) index += count; return ((T *)buf)[index]; }

        // Add item to end of array. Returns memory to use with new. Usage: new (array.Add()) T().
        void *Add() { return &(*this)[count++]; }

        // Delete item at end of array.
        void Delete() { ((T &)(*this)[--count]).~T(); }

        // Clear all items from array.
        void Clear() { while (count) Delete(); }

        // Constuctor. See template parameter [M] for setting capacity.
        Span() : count(0) {}

        // Destructor.
        ~Span() { Clear(); }

    private:
        T buf[M];
        uint count;
    };

    // $docend

    // *************************************************************************************************************
    // Safe pointer
    // *************************************************************************************************************

    // $doc "safeptr" "Safe Pointer"
    /**/

    // Use safe pointer to automatically delete allocated memory that goes out of scope.
    template<typename T>
    class SafePtr
    {
    public:
        // Get object referenced by pointer.
        T &operator * () const { return *ptr; }

        // Get member accessor.
        T *operator -> () const { return ptr; }

        // Get pointer.
        T *operator () () const { return ptr; }

        // Get item at [index] if pointer is an array of items of <T>.
        T &operator [] (int index) const { return ptr[index]; }

        // Check if no pointer is assigned.
        bool operator ! () const { return !ptr; }

        // Assign pointer after releasing any existing pointer.
        void *operator = (T *ptr_) { Release(); return ptr = ptr_; }

        // Returns memory to use with new. Usage: new (safePtr.Alloc<K>()) Type().
        // Any current pointer is released before new memory pointer is allocated.
        template<typename K = T>
        void *Alloc() { Release(); return ptr = (T *)HeapMem::Alloc(sizeof(K)); }

        // Release memory pointer.
        void Release() { if (ptr) { ptr->~T(); HeapMem::Free((void **)&ptr); } }

        // Construct safe pointer using [ptr] or 0.
        SafePtr(T *ptr = 0) : ptr(ptr) {}

        // Destructor.
        ~SafePtr() { Release(); }

    private:
        T *ptr;
    };

    // $docend

    //   _____                           _ 
    //  / ____|                         | |
    // | |  __  ___ _ __   ___ _ __ __ _| |
    // | | |_ |/ _ \ '_ \ / _ \ '__/ _` | |
    // | |__| |  __/ | | |  __/ | | (_| | |
    //  \_____|\___|_| |_|\___|_|  \__,_|_|

    // *************************************************************************************************************
    // Numeric functions
    // *************************************************************************************************************

    // $doc "numfuncs" "Numeric Functions"
    /**/

    // Adjust [n] to the next higher multiple of [p2]. The [p2] must be a power of 2.
    // Example: RVSnap(24) == 32;
    RVAPI ulong Snap(ulong n, uint p2);

    // Get the shift [n] that is the next higher power of 2 above [n].
    // Example: 1 &lt;&lt; RVShift(24) == 32.
    RVAPI uint Shift(ulong n);

    // Get random int between [min] and [max] inclusive.
    RVAPI int RndInt(int min, int max);

    // Get random float between [min] and [max] inclusive.
    RVAPI float RndFlt(float min, float max);

    // Clamp int [n] within range inclusive.
    RVAPI int ClampInt(int n, int low, int high);

    // Clamp float [n] within range inclusive.
    RVAPI float ClampFlt(float n, float low, float high);

    // Bounce int [n] off end of range inclusive.
    RVAPI int BounceInt(int n, int low, int high);

    // Bounce float [n] off end of range inclusive.
    RVAPI float BounceFlt(float n, float low, float high);

    // Wrap int [n] around range inclusive.
    RVAPI  int WrapInt(int n, int low, int high);

    // Wrap float [n] around range inclusive.
    RVAPI float WrapFlt(float n, float low, float high);

    // Get int [n]'s normalized range position.
    RVAPI float NormInt(int n, int low, int high);

    // Get float [n]'s normalized range position.
    RVAPI float NormFlt(float n, float low, float high);

    // Normalize [angle].
    RVAPI float NormAngle(float angle);

    // Get angle between angles.
    RVAPI float AngleDelta(float angleA, float angleB);

    // Convert radian angle [rad] to normalized angle.
    RVAPI float RadToNA(float rad);

    // Convert normalized angle [angle] to radian angle.
    RVAPI float NAToRad(float angle);

    // Get minimum of 2 int values.
    RVAPI int MinInt(int a, int b);

    // Get minimum of 2 float values.
    RVAPI float MinFlt(float a, float b);

    // Get maximum of 2 int values.
    RVAPI int MaxInt(int a, int b);

    // Get maximum of 2 float values.
    RVAPI float MaxFlt(float a, float b);

    // Get absolute [n] of int [n].
    RVAPI int AbsInt(int n);

    // Get absolute [n] of float [n].
    RVAPI float AbsFlt(float n);

    // Get sign of int [n].
    RVAPI int SignInt(int n);

    // Get sign of float [n].
    RVAPI int SignFlt(float n);

    // Determine if difference between float values are within [epsilon].
    RVAPI float EqualFlt(float a, float b, float epsilon = .0001f);

    // Determine if difference between double values are within [epsilon].
    RVAPI double EqualDbl(double a, double b, double epsilon = .0000001f);

    // Swap int values.
    RVAPI void SwapInt(int &a, int &b);

    // Swap float values.
    RVAPI void SwapFlt(float &a, float &b);

    // $docend

    // *************************************************************************************************************
    // Performance timer
    // *************************************************************************************************************

    // $doc "timer" "Performance Timer"
    /**/

    // Hardware high resolution timer.
    class RVAPI Timer
    {
    public:
        // Get seconds elapsed since timer was started. Must be called often. If the gap between calls exceeds 
        // .25f seconds the call is considered invalid and the seconds from the last valid call is returned.
        double GetSecs() const;

        // Start timer. Delay start by +/- [delay] seconds.
        void Start(float delay = 0);

        // Stop timer.
        void Stop();

        // Clear timer.
        void Clear();

        // Internal.
        void *operator () () const { return (void *)wobj; }

        // Constructor.
        Timer();

        // Destructor.
        ~Timer();

    private:
        byte wobj[32];
    };

    // $docend

    // *************************************************************************************************************
    // Animated value
    // *************************************************************************************************************

    // $doc "ianimvalue" "Animated Value Interface"
    /**/

    // Interface for animated values.
    class RVAPI IAnimValue
    {
    public:
        // Animation modes
        enum class Mode
        {
            // Animation stops at range boundry.
            CLAMP,

            // Animation continues from opposite range boundry.
            WRAP,

            // Animation reverses at range boundry.
            BOUNCE
        };

        // Internal.
        void *operator () () const { return wobj; }

        IAnimValue(void *wobj);
        ~IAnimValue();

    private:
        void *wobj;
    };

    // $docend

    // *************************************************************************************************************
    // Animated float interface
    // *************************************************************************************************************

    // $doc "ianimfloat" "Animated Float Interface"
    /**/

    // Animates a floating point value.
    class RVAPI IAnimFloat : public IAnimValue
    {
    public:
        // Animate value.
        float Animate();

        // Start animation.
        void Start();

        // Stop animation.
        void Stop();

        // Clear animation.
        void Clear();

        // Pass2 animation.
        void Pass2();

        // Set animation to run from [low] to [high] for [span] seconds using [mode] behavior, possibly in [reverse]
        // and using a discreet [interval]. 
        void Set(float span, float low, float high, Mode mode = Mode::CLAMP, bool reverse = false, double interval = 0);

        // Constructor.
        IAnimFloat(void *wobj) : IAnimValue(wobj) {}

        // Destructor.
        ~IAnimFloat() {}
    };

    // $docend

    // *************************************************************************************************************
    // Animated integer interface
    // *************************************************************************************************************

    // $doc "ianimint" "Animated Integer Interface"
    /**/

    // Interface for animating an integer.
    class RVAPI IAnimInt : public IAnimValue
    {
    public:
        // Animate value.
        int Animate();

        // Start animation.
        void Start();

        // Stop animation.
        void Stop();

        // Clear animation.
        void Clear();

        // Pass2 animation.
        void Pass2();

        // Set animation to run from [low] to [high] for [span] seconds using [mode] behavior, possibly in [reverse]. 
        void Set(float span, int low, int high, Mode mode = Mode::CLAMP, bool reverse = false);

        // Constructor.
        IAnimInt(void *wobj) : IAnimValue(wobj) {}

        // Destructor.
        ~IAnimInt() {}
    };

    // $docend

    // *************************************************************************************************************
    // Animated float
    // *************************************************************************************************************

    // $doc "animfloat" "Animated Float"
    /**/

    // Animates a floating point value. See base class for methods.
    class RVAPI AnimFloat : public IAnimFloat
    {
    public:
        // Constructor.
        AnimFloat();

        // Destructor.
        ~AnimFloat();

    private:
        byte wobj[64];
    };

    // $docend

    // *************************************************************************************************************
    // Animated integer
    // *************************************************************************************************************

    // $doc "animint" "Animated Integer"
    /**/

    // Animates an integer value. See base class for methods.
    class RVAPI AnimInt : public IAnimInt
    {
    public:
        // Constructor.
        AnimInt();

        // Destructor.
        ~AnimInt();

    private:
        byte wobj[96];
    };

    // $docend

    // *************************************************************************************************************
    // File path
    // *************************************************************************************************************

    // $doc "path" "File Path Builder"
    /**/

    // Simplifies building a file path.
    class RVAPI Path
    {
    public:
        // Check if non-empty.
        bool operator ! () const;

        // Get native string.
        operator wcstr () const;

        // Get name part.
        wcstr GetName() const;

        // Get extension part.
        wcstr GetExt() const;

        // Get name and extension part.
        wcstr GetNameAndExt() const;

        // Get directory part.
        wcstr GetDir() const;

        // Set path.
        void operator = (wcstr string);

        // Append slash then add [part].
        void operator &= (wcstr part);

        // Append [part].
        void operator += (wcstr part);

        // Remove [n] part(s) from end of path.
        void Up(uint n = 1);

        // Make path lower case.
        void ToLower();

        // Clear path.
        void Clear();

        // Internal.
        void *operator () () const { return (void *)wobj; }

        // Constructor.
        Path();

        // Destructor.
        ~Path();

    private:
        byte wobj[64];
    };

    // $docend

    // *************************************************************************************************************
    // File
    // *************************************************************************************************************

    // $doc "file" "File Handle"
    /**/

    // File handle.
    class RVAPI File
    {
    public:
        //  Get size.
        ulong GetSize() const;

        // Get current file position.
        ulong GetOffset() const;

        // Read integer [value].
        void ReadInt(int &value);

        // Read float [value].
        void ReadFloat(float &value);

        // Read [value].
        void ReadString(String &value);

        // Write integer [value].
        void WriteInt(int value);

        // Write float [value].
        void WriteFloat(float value);

        // Write string [value].
        void WriteString(wcstr value);

        // Truncate file.
        void Truncate();

        // Set file position to [offset] bytes from start of file.
        void SeekFromStart(slong offset);

        // Set file position to [offset] bytes from current file postion.
        void SeekFromCur(slong offset);

        // Set file position to [offset] bytes from end of file.
        void SeekFromEnd(slong offset);

        // Open file at [path]. [mode] is stdio file mode string. Only binary supported.
        void Open(wcstr path, wcstr mode);

        // Close file.
        void Close();

        // Internal.
        void *operator () () const { return (void *)wobj; }

        // Construct and open file at [path]. [mode] is stdio file mode string. Only binary supported.
        File(wcstr path, wcstr mode) : File() { Open(path, mode); }

        // Constructor.
        File();

        // Destructor.
        ~File();

    private:
        byte wobj[64];
    };

    // $docend

    // *************************************************************************************************************
    // File system
    // *************************************************************************************************************

    // $doc "filesys" "File System Functions"
    /**/

    // File system functions.
    class RVAPI FileSys
    {
    public:
        // Check if file exists at [path].
        static bool IsFile(wcstr path);

        // Check if directory exists at [path].
        static bool IsDir(wcstr path);

        // Check if directory is empty at [path].
        static bool IsDirEmpty(wcstr path);

        // Get file date/time at [path].
        static DateTime GetFileDate(wcstr path);

        // Get directory date/time at [path].
        static DateTime GetDirDate(wcstr path);

        // Get file size at [path].
        static uint GetFileSize(wcstr path);

        // Get directory size at [path].
        static uint GetDirSize(wcstr path);

        // Get temp directory at [path].
        static void GetTempDir(String &path);

        // Get app directory at [path].
        static void GetAppDataDir(String &path);

        // Get documents directory at [path].
        static void GetDocsDir(String &path);

        // Get desktop directory at [path].
        static void GetDesktopDir(String &path);

        // Get absolute path of [path].
        static void GetAbsPath(String &abs, wcstr rel);

        // Set current directory to [path].
        static void GetCurDir(String &path);

        // Get list of files at [path]. [list] must be an array of String items.
        // Filter files by passing wildcards to [filter].
        static void GetFiles(wcstr path, Array<String> &files, wcstr filter = 0);

        // Get list of directories at [path]. [list] must be an array of String items.
        // Filter files by passing wildcards to [filter].
        static void GetDirs(wcstr path, Array<String> &dirs, wcstr filter = 0);

        // Copy file at [from] to location [to]. Ignore error if [noError].
        static void CopyFile(wcstr from, wcstr to, bool noError = false);

        // Delete file at [path]. Ignore error if [noError]
        static void DeleteFile(wcstr path, bool noError = false);

        // Rename file at [oldPath] to location [newPath]. Ignore error if [noError].
        static void RenameFile(wcstr from, wcstr to);

        // Rename directory at [oldPath] to location [newPath]. Ignore error if [noError].
        static void RenameDir(wcstr from, wcstr to);

        // Rename directory at [oldPath] to location [newPath].  Ignore error if [noError].
        static void MoveDir(wcstr from, wcstr to);

        // Create directory at [path].
        static void CreateDir(wcstr path);

        // Delete directory at [path].
        static void DeleteDir(wcstr path);

        // Select directory using Windows OS dialog at [path].
        static void SelectDir(const String &path);

        // Set current directory to app's home directory.
        static void SetCurDir();

        // Set current directory to [path].
        static void SetCurDir(wcstr path);
    };

    // $docend

    // *************************************************************************************************************
    // System functions
    // *************************************************************************************************************

    // $doc "sysfuncs" "System Functions"
    /**/

    // System functions.
    class RVAPI System
    {
    public:
        // Print message using stdargs.
        static void PrintArgs(wcstr msg, va_list args);

        // Get environment variable. [name] is case sensitive.
        static void GetEnvVar(const String &value, wcstr name);

        // Get CPU thread count.
        static uint GetThreadCount();

        // Pause execution for [ms] milliseconds.
        static void Wait(uint ms);
    };

    // $docend

    //  _____ _   _ _____  _    _ _______ 
    // |_   _| \ | |  __ \| |  | |__   __|
    //   | | |  \| | |__) | |  | |  | |   
    //   | | | . ` |  ___/| |  | |  | |   
    //  _| |_| |\  | |    | |__| |  | |   
    // |_____|_| \_|_|     \____/   |_|   

    // *************************************************************************************************************
    // Keys
    // *************************************************************************************************************

    // $doc "keys" "Keys"
    /**/

    // Keys
    enum class Key
    {
        SPACE = 32, APOSTROPHE = 39, COMMA = 44, MINUS = 45, PERIOD = 46, SLASH = 47, N0 = 48, N1 = 49, N2 = 50,
        N3 = 51, N4 = 52, N5 = 53, N6 = 54, N7 = 55, N8 = 56, N9 = 57, SEMICOLON = 59, EQUAL = 61, A = 65, B = 66,
        C = 67, D = 68, E = 69, F = 70, G = 71, H = 72, I = 73, J = 74, K = 75, L = 76, M = 77, N = 78, O = 79,
        P = 80, Q = 81, R = 82, S = 83, T = 84, U = 85, V = 86, W = 87, X = 88, Y = 89, Z = 90, LEFT_BRACKET = 91,
        BACKSLASH = 92, RIGHT_BRACKET = 93, GRAVE_ACCENT = 96, WORLD_1 = 161, WORLD_2 = 162, ESCAPE = 256,
        ENTER = 257, TAB = 258, BACKSPACE = 259, INSERT = 260, DELETE = 261, RIGHT = 262, LEFT = 263, DOWN = 264,
        UP = 265, PAGE_UP = 266, PAGE_DOWN = 267, HOME = 268, END = 269, CAPS_LOCK = 280, SCROLL_LOCK = 281,
        NUM_LOCK = 282, PRINT_SCREEN = 283, PAUSE = 284, F1 = 290, F2 = 291, F3 = 292, F4 = 293, F5 = 294, F6 = 295,
        F7 = 296, F8 = 297, F9 = 298, F10 = 299, F11 = 300, F12 = 301, F13 = 302, F14 = 303, F15 = 304, F16 = 305,
        F17 = 306, F18 = 307, F19 = 308, F20 = 309, F21 = 310, F22 = 311, F23 = 312, F24 = 313, F25 = 314,
        KP_0 = 320, KP_1 = 321, KP_2 = 322, KP_3 = 323, KP_4 = 324, KP_5 = 325, KP_6 = 326, KP_7 = 327, KP_8 = 328,
        KP_9 = 329, KP_DECIMAL = 330, KP_DIVIDE = 331, KP_MULTIPLY = 332, KP_SUBTRACT = 333, KP_ADD = 334,
        KP_ENTER = 335, KP_EQUAL = 336, LEFT_SHIFT = 340, LEFT_CONTROL = 341, LEFT_ALT = 342, LEFT_SUPER = 343,
        RIGHT_SHIFT = 344, RIGHT_CONTROL = 345, RIGHT_ALT = 346, RIGHT_SUPER = 347, MENU = 348
    };

    // $docend

    // *************************************************************************************************************
    // Key modifiers
    // *************************************************************************************************************

    // $doc "keymods" "Key Modifiers"
    /**/

    // Key modifiers
    enum ModKey
    {
        MOD_SHIFT_LEFT = 1, MOD_SHIFT_RIGHT = 2, MOD_SHIFT = 3, MOD_CONTROL_LEFT = 4, MOD_CONTROL_RIGHT = 8,
        MOD_CONTROL = 12, MOD_ALT_LEFT = 16, MOD_ALT_RIGHT = 32, MOD_ALT = 48, MOD_SUPER_LEFT = 64,
        MOD_SUPER_RIGHT = 128, MOD_SUPER = 192
    };

    // $docend

    // *************************************************************************************************************
    // User input
    // *************************************************************************************************************

    // $doc "input" "User Input"
    /**/

    // Keyboard, mouse and SpaceMouse input.
    class RVAPI Input
    {
    public:
        // Hardware cursor shapes.
        enum class CursorShape
        {
            // Arrow.
            ARROW,

            // Insert beam. 
            IBEAM,

            // Crosshair.
            CROSSHAIR,

            // Hand.
            HAND,

            // Horzizontal resize.
            HRESIZE,

            // Vertical resize.
            VRESIZE
        };

        // Check if [key] is in a pressed state.
        static bool IsKey(Key key);

        // Check what modifier keys [modKeys] are in a pressed state using modifier key flags. Modifier key flags 
        // can be or'd together. Pressed modifier keys must match the flags exactly.
        static bool IsModKeys(uint modKeys);

        // Check if mouse button [btn] is currently in pressed state. 
        static bool IsMseBtn(int btn = -1);

        // Get position of 3D mouse.
        static S3f Get3DMsePos();

        // Get rotation axis vector of 3D mouse.
        static S3f Get3DMseRot();

        // Get currently pressed 3D mouse button.
        static int  Get3DMseBtn();

        // Get mouse position. 
        static S2i GetMsePos();

        // Get distance in pixels the mouse has moved since last polling.
        static S2i GetMseMove();

        // Get [wheel] move amount.
        static bool GetWheel(S2i &wheel);

        // Check if mouse button [btn] matches next event on queue. Pop event from queue if match.
        static bool PopMseBtn(uint btn);

        // Get next mouse button [btn] event from queue. Pop event from queue if found.
        static bool GetMseBtn(uint &btn);

        // Check if character [ch] matches next event on queue. Pop event from queue if match.
        static bool PopChar(wchar ch);

        // Get next character [ch] event from queue. Pop event from queue if found.
        static bool GetChar(wchar &ch);

        // Check if [key] matches next event on queue. Pop event from queue if match.
        static bool PopKey(Key key);

        // Get next [key] event from queue. Pop key from queue if found.
        static bool GetKey(Key &key);

        // Save clipboard text to [string].
        static wcstr GetClipboardText(String &string);

        // Set clipboard text.
        static void SetClipboardText(wcstr text);

        // Set cursor shape.
        static void SetCursor(CursorShape shape);

        // Show/Hide cursor.
        static void ShowCursor(bool show = true);
    };

    // $docend

    // *************************************************************************************************************
    // Six degrees of freedom controller
    // *************************************************************************************************************

    // $doc "sixdof" "Six DOF"
    /**/

    // Movement for cameras or other objects while game is in development. When the right mouse button is not pressed, 
    // movement can be controlled by a 3DConnexion SpaceMouse, if connected. When the right mouse button is pressed, 
    // movement is controlled by the mouse and the WASD/QE keys, or the arrow keys. Speed is controlled by R(faster) 
    // or F(slower). View is not automatically orientated to the scene up vector to allow more flexibility. Use the 
    // mouse wheel to manage the Z rotation. By default Z adjustments are coarse. With shift key, Z adjustments are 
    // finer.
    class RVAPI SixDof
    {
    public:
        // Update position.
        void Update(M4f &pos);

        // Internal.
        void *operator () () const { return (void *)wobj; }

        // Constructor.
        SixDof();

        // Destructor.
        ~SixDof();

    private:
        byte wobj[16];
    };

    // $docend

    // *************************************************************************************************************
    // UI Events
    // *************************************************************************************************************

    // $doc "uievents" "User Interface Events"
    /**/

    // Generates user interface events. Predefined user interface controls are not provided, Use UIEvents with 
    // visual overlay components to build custom user interface elements.
    class RVAPI UIEvents
    {
    public:
        // Generated event.
        enum class Event
        {
            // No event
            NONE,

            // Mouse down event
            MOUSEDOWN,

            // Mouse up event.
            MOUSEUP,

            // Single mouse click event.
            SINGLECLICK,

            // Double mouse click event.
            DOUBLECLICK,

            // Triple click event.
            TRIPLECLICK,

            // Wheel scroll up.
            WHEELUP,

            // Wheel scroll down.
            WHEELDOWN,

            // Start drag.
            STARTDRAG,

            // Dragging.
            DRAG,

            // End drag.
            ENDDRAG,

            // Drop event.
            DROP,

            // Key input event.
            KEY,

            // Character input event.
            CHAR,

            // Window resize event.
            RESIZE,

            // Window close event.
            CLOSE
        };

        // Input state.
        enum class State
        {
            // Disabled state.
            DISABLED,

            // Normal state.
            NORMAL,

            // Hovered state.
            HOVERED,

            // Highlighted state.
            HIGHLIGHTED,

            // Clicked state.
            CLICKED,

            // Static state.
            STATIC
        };

        // Control attributes.
        enum Attribs
        {
            // Accept wheel events.
            WHEEL = 1,

            // Can drag.
            DRAGGABLE = 2,

            // Does not get events.
            STATIC = 4
        };

        // Check if state change.
        bool IsStateChange() const;

        // Check if selected.
        bool IsSelected() const;

        // Check if disabled.
        bool IsDisabled() const;

        // Get character from character event.
        wchar GetChar() const;

        // Get mouse click position.
        S2i GetMseClickPos() const;

        // Get state.
        State GetState() const;

        // Get state color.
        Color GetStateColor() const;

        // Get focused host entity.
        Event GetEvent() const;

        // Get focused host entity.
        static EntKey GetFocused();

        // Get clicked host entity.
        static EntKey GetClicked();

        // Get dragged host entity.
        static EntKey GetDragged();

        // Get dropped host entity.
        static EntKey GetDropped();

        // Update events inside parent rectangle.
        Event Update(const B2i &pRect);

        // Set disabled.
        void SetDisabled(bool disabled = true);

        // Set selected.
        void SetSelected(bool selected = true);

        // Set this events object to receive keyboard events.
        void SetFocus();

        // Clear keyboard focus.
        static void ClearFocus();

        // Clear all pending events.
        static void ClearEvents();

        // Internal.
        void *operator () () const { return (void *)wobj; }

        // Construct UI events object. [host] is the entity that contains this element. [stateColors] 
        // allows overriding the color multiplier used for shading element state, or pass 0 for the defaults. 
        // [attribs] is a combination of the attribs flags or 0. [maxClicks] is the maximum number of 
        // mouse clicks the element will wait for. Default is 1.
        UIEvents(EntKey host, Color *stateColors = 0, uint attribs = 0, uint maxClicks = 1);

        // Destructor.
        ~UIEvents();

    private:
        byte wobj[128];
    };

    // $docend

    //  _____  _               _
    // |  __ \| |             (_)
    // | |__) | |__  _   _ ___ _  ___ ___
    // |  ___/| '_ \| | | / __| |/ __/ __|
    // | |    | | | | |_| \__ \ | (__\__ \
    // |_|    |_| |_|\__, |___/_|\___|___/
    //				__/ |
    //			   |___/

    // *************************************************************************************************************
    // Collision shapes
    // *************************************************************************************************************

    // $doc "collshape" "Collision Shapes"
    /**/

    // Physics collision shape. [trs] matrices are a special use of matrices where translation is stored in vector[0], 
    // rotation is stored in vector[1] and scale is stored in vector[2].
    class RVAPI CollShape
    {
    public:
        // Set collsion shape properties. [density] is the relative weight of the shape with a default of 1.
        // [friction] range is 0=no friction 1=full friction. [restitution] range is 0=no bounce 1=full bounce.
        // If [sensor] is true, shape reports collisions, but does not collide.
        void SetProps(float density, float friction, float restitution, bool sensor = false);

        // Internal.
        void *operator () () const { return (void *)wobj; }

        // Constructor.
        CollShape(void *wobj);

        // Destructor.
        virtual ~CollShape();
    private:
        void *wobj;
    };

    // Sphere collision shape.
    class RVAPI CollSphere : public CollShape
    {
    public:
        // Construct sphere shape with translation, rotation, scale.
        CollSphere(const M4f &trs);

        // Destructor.
        ~CollSphere() override;

    private:
        byte wobj[192];
    };

    // Cube collision shape.
    class RVAPI CollCube : public CollShape
    {
    public:
        // Construct cube shape with translation, rotation, scale.
        CollCube(const M4f &trs);

        // Destructor.
        ~CollCube() override;

    private:
        byte wobj[192];
    };

    // Cone collision shape.
    class RVAPI CollCone : public CollShape
    {
    public:
        // Construct cone shape with translation, rotation, scale.
        CollCone(const M4f &trs);

        // Destructor.
        ~CollCone() override;

    private:
        byte wobj[192];
    };

    // Cylinder collision shape.
    class RVAPI CollCylinder : public CollShape
    {
    public:
        // Construct cylinder shape with translation, rotation, scale.
        CollCylinder(const M4f &trs);

        // Destructor.
        ~CollCylinder() override;

    private:
        byte wobj[192];
    };

    // Capsule collision shape.
    class RVAPI CollCapsule : public CollShape
    {
    public:
        // Construct capsule shape with translation, rotation, scale.
        CollCapsule(const M4f &trs);

        // Destructor.
        ~CollCapsule() override;

    private:
        byte wobj[192];
    };

    // Geometry collision mesh.
    class RVAPI CollGeom : public CollShape
    {
    public:
        // Construct geometry collision mesh with path to mesh file.
        CollGeom(wcstr path);

        // Destructor.
        ~CollGeom() override;

    private:
        byte wobj[256];
    };

    // $docend

    // *************************************************************************************************************
    // Body
    // *************************************************************************************************************

    // $doc "body" "Physics Body"
    /**/

    // Physics body.
    class RVAPI Body
    {
    public:
        // Body type.
        enum class Type
        {
            // Fixed object. Does not react to collisions.
            STATIC,

            // Movable object. Does not react to collisions.
            KINEMATIC,

            // Movable object. Reacts to collisions.
            DYNAMIC,

            // Does not participate in the physics simulation.
            NONE
        };

        struct Contact
        {
            // Contact state of intersected objects.
            enum class State
            {
                // Contact is new.
                NEW,

                // Contact is active.
                ACTIVE,

                // Contact is ending.
                ENDING
            };

            // Contact state.
            State state;

            // Normal of contact on other body.
            S3f norm;

            // Point of contact on this body.
            S3f selfPt;

            // Point of contact on other body.
            S3f otherPt;

            // Other reference.
            void *ref;

            // Contact ID.
            uint id;
        };

        // Get world space position.
        M4f GetPos() const;

        // Get angular velocity.
        S3f GetAngVel() const;

        // Get linear velocity.
        S3f GetLinVel() const;

        // Get host entity from contact.
        EntKey GetHost(const Contact &contact) const;

        // Get first contact. Initializes [index] iterator. Returns 0 if no contact.
        const Contact *GetFirstContact(int &index) const;

        // Get next contact. Updates [index] iterator. Returns 0 if no contact.
        const Contact *GetNextContact(int &index) const;

        // Add cone joint between bodies. [angle] is maximum movement angle.
        uint AddConeJoint(Body &other, float angle);

        // Add revolute (hinge) joint between this body and [other] body. [posA] is world space joint position on this body. 
        // [posB] is world space joint position on other body. [lowerAngle] is low angle limit, or zero for no limit. 
        // [upperAngle] is high angle limit, or zero for no limit. [speed] is motor speed, or zero for no motor. [maxTorque] 
        // is maximum motor torque, or zero if no motor. Returns joint ID
        uint AddRevoluteJoint(Body &other, const M4f &posA, const M4f &posB, float lowerAngle, float upperAngle, float speed, float maxTorque);

        // Add sphere joint between this body and other body. [posA] is world space joint position on this body. 
        // [posB] is world space joint position on other body. Returns joint ID.
        uint AddSphereJoint(Body &other, const S3f &posA, const S3f &posB);

        // Add weld (fixed) joint between this body and [other] body. Returns joint ID.
        uint AddWeldJoint(Body &other);

        // Add spring joint between this body and [other] body. [posA] is world space joint position on this body. 
        // [posB] is world space joint position on other body. [length] is pring length. [freq] is spring frequency. 
        // [damp] is spring damping. Set [collideConnected] to true if connected body should collide with self.
        // Returns joint ID.
        uint AddSpringJoint(Body &other, const S3f &posA, const S3f &posB, float length, float freq, float damp, bool collideConnected = true);

        // Remove joint with [id].
        void RemoveJoint(uint id);

        // Apply force. [force] is force vector in world space. Set [wake] true if force should wake body.
        void ApplyForce(const S3f &force, bool wake = true);

        // Apply force at body point. [force] is orce vector in world space.
        // [pos] is force position in world space.  Set [wake] true if force should wake body.
        void ApplyForce(const S3f &force, const S3f &pos, bool wake = true);

        // Apply torque. [torque] is torque vector in world space. Set [wake] true if force should wake body.
        void ApplyTorque(const S3f &torque, bool wake = true);

        // Apply angular impulse. [imp] is impulse vector in world space. Set [wake] true if force should wake body.
        void ApplyAngImp(const S3f &imp, bool wake = true);

        // Apply linear impulse. [imp] is impulse vector in world space. Set [wake] true if force should wake body.
        void ApplyLinImp(const S3f &imp, bool wake = true);

        // Apply linear impulse at point. [imp] is mpulse vector in world space. [pos] is impulse position in world space. 
        // Set [wake] true if force should wake body.
        void ApplyLinImp(const S3f &imp, const S3f &pos, bool wake = true);

        // Set angular damping. [damp] is damping vector.
        void SetAngDamp(const S3f &damp);

        // Set linear damping. [damp] is damping vector.
        void SetLinDamp(const S3f &damp);

        // Set angular velocity. [vel] is velocity vector.
        void SetAngVel(const S3f &vel);

        // Set linear velocity. [vel] is velocity vector.
        void SetLinVel(const S3f &vel);

        // Wake/Sleep body. Set [awake] to true to wake body, false to sleep body.
        void SetAwake(bool awake);

        // Set gravity effect. [scale] is gravity scale. Default is 1.
        void SetGravityScale(const S3f &scale);

        // Set world space position. [pos] is position matrix.
        void SetPos(const M4f &pos);

        // Add collision shape. [shape] is collision shape.
        void AddCollShape(const CollShape &shape);

        // Set physics properties. [mass] is mass value. Default is 1. [center] is center of mass. Default is (0, 0, 0).
        // [inertiaX] is x inertia tensor. Normally use (1, 0, 0). [inertiaY] is y inertia tensor. Normally use (0, 1, 0).
        // [inertiaZ] is z inertia tensor. Normally use (0, 0, 1).
        void SetProps(float mass, const S3f &center = S3f(0, 0, 0), const S3f &inertiaX = S3f(1, 0, 0),
            const S3f &inertiaY = S3f(0, 1, 0), const S3f &inertiaZ = S3f(0, 0, 1));

        // Internal.
        void *operator () () const { return (void *)wobj; }

        // Construct physics body. [host] is host entity. [type] is body type. [pos] is initial body position. [collMask] 
        // is collision bit mask. Only bodies with same bits collide. 0=collide all. [rotMask] flags restrict rotation. 
        // 1=X 2=Y 4=Z. Set [wantContacts] to true if collision contacts are wanted.
        Body(EntKey host, Type type, const M4f &pos, uint collMask = 0, uint rotMask = 0, bool wantContacts = false);

        // Destructor.
        ~Body();

    private:
        byte wobj[320];
    };

    // $docend

    // *************************************************************************************************************
    // World
    // *************************************************************************************************************

    // $doc "world" "Physics World"
    /**/

    // Physics world.
    class RVAPI World
    {
    public:
        // Query result.
        struct QueryResult
        {
            // Contact position.
            S3f pos;

            // Contact normal.
            S3f normal;

            // Reference.
            void *ref;
        };

        // Query results array.
        typedef Array<QueryResult> QueryResults;

        // Convert query result reference to host entity.
        EntKey GetQueryResultHost(const QueryResult &result) const;

        // Query world using AABB. results must be array of RVWorldQueryResult. Returns true if any hits.
        bool Query(QueryResults &results, const B3f &aabb);

        // Query world for first intersection with ray. Ray goes from [posA] to [posB].
        // [queryResults] must be array of RVWorldQueryResult. Returns true if any hits.
        bool RayCast(QueryResults &results, const S3f &posA, const S3f &posB);

        // Query world for all intersections with ray. Ray goes from [posA] to [posB].
        // [queryResults] must be array of RVWorldQueryResult. Returns true if any hits.
        bool RayCastAll(QueryResults &results, const S3f &posA, const S3f &posB);

        // Set gravity. Default is -9.8f.
        void SetGravity(const S3f &gravity);

        // Enable/Disable sleeping.
        void SetSleeping(bool enable = true);

        // Set physics solver iterations. [vel] is number of velocity iterations (default 12). 
        // [pos] is number of position iterations (default 2).
        void SetIter(uint vel, uint pos);

        // Advance world simulation.
        void Step();

        // Internal.
        void *operator () () const { return (void *)wobj; }

        // Constructor.
        World(void *wobj);

    private:
        void *wobj;

        friend SceneBridge;
    };

    // $docend

    //                        _       
    //     /\                | |      
    //    /  \   ___ ___  ___| |_ ___ 
    //   / /\ \ / __/ __|/ _ \ __/ __|
    //  / ____ \\__ \__ \  __/ |_\__ \
    // /_/    \_\___/___/\___|\__|___/

    // *************************************************************************************************************
    // Assets
    // *************************************************************************************************************

    // $doc "assets" "Assets"
    /**/

    // Assets loading.
    class RVAPI Assets
    {
    public:
        // Begin asynchronous assets load. [path] is relative to assets root folder.
        // Multiple loads will combine assets in memory.
        static void BeginLoadAsync(wcstr path);

        // Asynchronous load of assets. Call frequently from main code to load assets.
        // The normalized return value can be used to track progress.
        static float LoadAsync();

        // Call when asynchronous assets load is complete.
        static void EndLoadAsync();

        // Synchronous load of assets. Blocks until all assets are loaded. [path] is relative 
        // to assets root folder. Multiple loads will combine assets in memory.
        static void Load(wcstr path);

        // Unload all assets. Very important to call this before loading assets, unless
        // assets are being shared between scenes.
        static void Clear();
    };

    // $docend

    //  ___  _____     ____  _     _           _       
    // |__ \|  __ \   / __ \| |   (_)         | |      
    //    ) | |  | | | |  | | |__  _  ___  ___| |_ ___ 
    //   / /| |  | | | |  | | '_ \| |/ _ \/ __| __/ __|
    //  / /_| |__| | | |__| | |_) | |  __/ (__| |_\__ \
    // |____|_____/   \____/|_.__/| |\___|\___|\__|___/
    //                           _/ |                  
    //                          |__/                   

    // *************************************************************************************************************
    // Color overlay element
    // *************************************************************************************************************

    // $doc "colorelem" "Overlay Color Element"
    /**/

    // Overlay color element.
    class RVAPI ColorElem
    {
    public:
        // Get relolution independent element rectangle using parent rectangle [pRect].
        B2i GetRect(const B2i &pRect) const;

        // Get meta position.
        const MetaPos &GetMetaPos() const;

        // Draw color box. [pRect] is parent rectangle for resolving meta position.
        // [stateColor] is multiplied with text color and can be a literal color or 
        // the state color returned from UI events object.
        void Draw(const B2i &pRect, const Color &stateColor = Color(1, 1, 1)) const;

        // Show/Hide color element.
        void Show(bool show = true);

        // Set color.
        void SetColor(const Color &color);

        // Set meta position.
        void SetMetaPos(const MetaPos &metaPos);

        // Internal.
        void *operator () () const { return (void *)wobj; }

        // Construct color element at [z] order. Higher z overlays lower z.
        ColorElem(uint z);

        // Destructor.
        ~ColorElem();

    private:
        byte wobj[96];
    };

    // $docend

    // *************************************************************************************************************
    // Image overlay element
    // *************************************************************************************************************

    // $doc "imageelem" "Overlay Image Element"
    /**/

    // Overlay image element.
    class RVAPI ImageElem
    {
    public:
        // Get frame dimensions.
        S2i GetFrameDims() const;

        // Resolve relolution independent element rectangle using parent rectangle [pRect].
        B2i GetRect(const B2i &pRect) const;

        // Get meta position.
        const MetaPos &GetMetaPos() const;

        // Draw image. [pRect] is parent rectangle for resolving meta position. [stateColor] is multiplied 
        // with text color and can be a literal color or the state color returned from UI events object.
        void Draw(const B2i &pRect, const Color &stateColor = Color(1)) const;

        // Show/hide element.
        void Show(bool show = true);

        // Set frame.
        void SetFrame(uint frame);

        // Set frame color.
        void SetColor(const Color &color);

        // Set meta position.
        void SetMetaPos(const MetaPos &metaPos);

        // Internal.
        void *operator () () const { return (void *)wobj; }

        // Construct image element. [imageElem] is image element. [name] is name of image asset. [z] is z order. 
        // Higher z overlays lower z.[baseFrame] is rectangle of first animation frame in image. Use coordinates
        // of 1920x1080 version for all resolutions. [cols] is number of animation frame columns. [frameCount] is 
        // total number of frames.
        ImageElem(wcstr name, uint z, const B2i &baseFrame = B2i(), uint cols = 1, uint frameCount = 1);

        // Destructor.
        ~ImageElem();

    private:
        byte wobj[96];
    };

    // $docend

    // *************************************************************************************************************
    // Text overlay element
    // *************************************************************************************************************

    // $doc "textelem" "Overlay Text Element"
    /**/

    // Overlay text element.
    class RVAPI TextElem
    {
    public:
        // Get text and store in [string].
        wcstr GetText(String &string) const;

        // Get text element boundary rectangle using parent rectangle [pRect].
        B2i GetRect(const B2i &pRect) const;

        // Get meta position.
        const MetaPos &GetMetaPos() const;

        // Get x position of character at [cn].
        uint GetCharX(int cn) const;

        // Get character at x position.
        uint GetCharN(uint cx) const;

        // Get character.
        uint GetLen() const;

        // Check if text element has any text.
        bool operator ! () const;

        // Get character.
        wchar operator [] (int n) const;

        // Draw text. [pRect] is parent rectangle for resolving meta position. [stateColor] is multiplied 
        // with text color and can be a literal color or the state color returned from UI events object.
        void Draw(const B2i &pRect, const Color &stateColor = Color(1)) const;

        // Show/hide element.
        void Show(bool show = true);

        // Add text using named font or 0 for default.
        void AddText(wcstr text, uint fontID = 0, const Color &color = Color(1));

        // Clear text.
        void Clear();

        // Set color. Start color change at [start] character and end at [end] character.
        void SetColor(const Color &color, int start = 0, int end = -1);

        // Set meta position.
        void SetMetaPos(const MetaPos &metaPos);

        // Internal.
        void *operator () () const { return (void *)wobj; }

        // Construct text element at [z] order. Higher z overlays lower z. Set [incr] to estimated max 
        // number of characters.
        TextElem(uint z, uint incr = 64);

        // Destructor.
        ~TextElem();

    private:
        byte wobj[128];
    };

    // $docend

    // *************************************************************************************************************
    // Input overlay element
    // *************************************************************************************************************

    // $doc "inputelem" "Overlay Input Element"
    /**/

    // Overlay input element that provides text input capability.
    class RVAPI InputElem
    {
    public:
        // Character validation callback. Return true to allow character.
        typedef bool (*FValidate)(wchar ch);

        // Get key from last update if any.
        Key GetKey() const;

        // Get meta position.
        const MetaPos &GetMetaPos() const;

        // Get resolution independent element rectangle using parent rectangle [pRect].
        B2i GetRect(const B2i &pRect) const;

        // Draw input element.
        void Draw(const B2i &pRect) const;

        // Show input element.
        void Show(bool show = true);

        // Update input element.
        void Update(const B2i &pRect);

        // Set meta position.
        void SetMetaPos(const MetaPos &metaPos);

        // Internal.
        void *operator () () const { return (void *)wobj; }

        // Construct input element. 
        InputElem(wcstr fontID, const Color &bColor, const Color &fColor,
            uint len, uint z, uint incr = 128, FValidate Validate = 0);

        // Destructor.
        ~InputElem();

    private:
        byte wobj[384];
    };

    // $docend

    //  ____  _____     ____  _     _           _       
    // |___ \|  __ \   / __ \| |   (_)         | |      
    //   __) | |  | | | |  | | |__  _  ___  ___| |_ ___ 
    //  |__ <| |  | | | |  | | '_ \| |/ _ \/ __| __/ __|
    //  ___) | |__| | | |__| | |_) | |  __/ (__| |_\__ \
    // |____/|_____/   \____/|_.__/| |\___|\___|\__|___/
    //                            _/ |                  
    //                           |__/                   

    // *************************************************************************************************************
    // Geometry
    // *************************************************************************************************************

    // $doc "geom" "Geometry"
    /**/

    // Geometry base class.
    class RVAPI Geometry
    {
    public:
        // Get position.
        const M4f &GetPos() const;

        // Set position.
        void SetPos(const M4f &pos);

        // Internal.
        void *operator () () const { return (void *)wobj; }

        // Constructor.
        Geometry(void *geom);

        // Destructor.
        virtual ~Geometry();

    private:
        void *wobj;
    };

    // $docend

    // *************************************************************************************************************
    // Mesh
    // *************************************************************************************************************

    // $doc "mesh" "Mesh"
    /**/

    // Mesh.
    class RVAPI Mesh : public Geometry
    {
    public:
        // Internal.
        void *operator () () const { return (void *)wobj; }

        // Construct mesh on [host] entity at [pos] using asset [assetName].
        Mesh(EntKey host, wcstr assetName, const M4f &pos = M4fIdent());

        // Destructor.
        ~Mesh() override;

    private:
        byte wobj[128];
    };

    // $docend

    // *************************************************************************************************************
    // Animated mesh
    // *************************************************************************************************************

    // $doc "animmesh" "Animated Mesh"
    /**/

    // GPU Animated mesh.
    class RVAPI AnimMesh : public Geometry
    {
    public:
        // Get frame count.
        uint GetFrameCount() const;

        // Check if animation is done.
        bool operator ! () const;

        // Start asynchronous animation.
        uint Animate();

        // Wait for animation.
        void Wait();

        // Begin asynchronous animation. Adjust by +/- [delay] seconds.
        void Start(float delay = 0);

        // End asynchronous animation.
        void Stop();

        // Pass2 animation.
        void Pass2();

        // Clear animation.
        void Clear();

        // Set animation to [name] using [mode] behavior, possibly in [reverse].
        void SetAnim(wcstr name, AnimInt::Mode mode = AnimInt::Mode::CLAMP, bool reverse = false);

        // Internal.
        void *operator () () const { return (void *)wobj; }

        // Construct animated mesh with [host] entity, animation [name] and mesh position [pos].
        AnimMesh(EntKey host, wcstr animName, const M4f &pos = M4fIdent());

        // Destructor.
        ~AnimMesh() override;

    private:
        byte wobj[1664];
    };

    // $docend

    // *************************************************************************************************************
    // Particles
    // *************************************************************************************************************

    // $doc "particles" "Particles"
    /**/

    // High performance GPU particle renderer that can be used to build many types of particle systems.
    // No prebuilt particle system is provided by the engine.
    class RVAPI Particles : public Geometry
    {
    public:
        // Begin particle add. All particles must be re-added each OnAnimate(). Call SetPColor(), SetPMat()
        // and SetPPos() for each particle. SetPPos() must be called last for each particle. Call ndAdd() 
        // after all particles are added.
        void BeginAdd();

        // Set particle color.
        void SetPColor(const Color &color);

        // Set particle material.
        void SetPMat(wcstr matName);

        // Set particle position. Call this last on each particle.
        void SetPPos(const M4f &pos);

        // End particle add.
        void EndAdd();

        // Animate particles with the BeginAdd() / EndAdd() set of functions. Call this function in
        // OnPass1() callback and pair with Wait() in OnPass2() callback.
        void Animate();

        // Wait for particle rendering.
        void Wait();

        // Internal.
        void *operator () () const { return (void *)wobj; }

        // Construct particles. [host] is the entity hosting this particles object. [capacity] is the 
        // maximum number of particles that can be added. [pos] is particles position. [fps] is the
        // number of particle updates per second.
        Particles(EntKey host, uint capacity, const M4f &pos, float fps = 30);

        // Destructor.
        virtual ~Particles();

    protected:
        virtual void OnAnimate() {};

    private:
        byte wobj[1280];

        friend ParticlesBridge;
    };

    // $docend

    // *************************************************************************************************************
    // Animated material
    // *************************************************************************************************************

    // $doc "animmat" "Animated Material"
    /**/

    // Animated material.
    class RVAPI AnimMat
    {
    public:
        // Update material animation.
        void Update();

        // Internal.
        void *operator () () const { return (void *)wobj; }

        // Initialize animated material with geometry and material name.
        AnimMat(Geometry &geom, wcstr matName);

        // Release animated material.
        ~AnimMat();

    private:
        byte wobj[64];
    };

    // $docend

    // *************************************************************************************************************
    // Color animation
    // *************************************************************************************************************

    // $doc "coloranim" "Color Animation"
    /**/

    // Color animation. See base class for more methods.
    class RVAPI ColorAnim : public IAnimFloat
    {
    public:
        // Animate color. Returns normalized animation time T.
        float Animate();

        // Set color animation to animate color from [colorA] to [colorB] over [span] seconds using animation mode [mode].
        // Set [reverse] to true to play animation in reverse.
        void Set(const Color &colorA, const Color &colorB, float span, Mode mode = Mode::CLAMP, bool reverse = false);

        // Internal.
        void *operator () () const { return (void *)wobj; }

        // Construct animation using animated material [animMat].
        ColorAnim(AnimMat &animMat);

        // Destructor
        ~ColorAnim();

    private:
        byte wobj[128];
    };

    // $docend

    // *************************************************************************************************************
    // Image animation
    // *************************************************************************************************************

    // $doc "imageanim" "Image Animation"
    /**/

    // Image animation. See base class for more methods.
    class RVAPI ImageAnim : public IAnimInt
    {
    public:
        // Get frame count.
        uint GetFrameCount() const;

        // Animate image and return frame number.
        uint Animate();

        // Set image animation to animate [frameCount] frames organized in [colCount] columns 
        // at [fps] frames per second using [mode] animation mode. Set [reverse] to true to 
        // play animation in reverse.
        void Set(const S2i &dims, uint frameCount, uint columnCount,
            float fps = 30, Mode mode = Mode::CLAMP, bool reverse = false);

        // Internal.
        void *operator () () const { return (void *)wobj; }

        // Construct image animation using animated material [animMat].
        ImageAnim(AnimMat &animMat);

        // Destructor.
        ~ImageAnim();

    private:
        byte wobj[128];
    };

    // $docend

    // *************************************************************************************************************
    // Camera
    // *************************************************************************************************************

    // $doc "camera" "Camera"
    /**/

    // Views the scene from a location.
    class RVAPI Camera
    {
    public:
        // Get position.
        const M4f &GetPos() const;

        // Set tone color. [tone] influences the overall scene color. 
        // The default tone is neutral (1, 1, 1).
        void SetTone(const Color &color);

        // Set background color.
        void SetBgd(const Color &color);

        // Set background ambient light.
        void SetAmbient(float ambient);

        // The ray gap is the offset from the surface for ray bounces. The default is .0001f meters.
        // For large outdoor scenes this value may have to be scaled higher to smooth shadows. 
        // Experiment with increases in value.
        void SetRayGap(float gap);

        // Set focal ratio. .1f=wide to 3.0f=narrow. Default=.4f.
        void SetFocalRatio(float fr);

        // Set view distance in meters. Default is 999.
        void SetViewDist(float dist);

        // Set viewport dimensions. Coordinates are normalized.
        void SetViewPort(float x1, float y1, float x2, float y2);

        // Set position.
        void SetPos(const M4f &pos);

        // Internal.
        void *operator () () const { return (void *)wobj; }

        // Construct camera at [z] order in the viewport. Higher z overlays lower z. 
        // [n] is the camera number within the z order. z and n together must be unique.
        Camera(const M4f &pos, uint z = 0, uint n = 0);

        // Destructor.
        ~Camera();

    private:
        byte wobj[640];
    };

    // $docend

    // *************************************************************************************************************
    // Light
    // *************************************************************************************************************

    // $doc "light" "Light"
    /**/

    // Generates light in the scene. There is only one light type. This single light type can fill
    // many roles including an omni light, a spot light or an environment light, based on settings. 
    // A light can also be static, dynamic or a probe that receives light from other lights or probes.
    class RVAPI Light
    {
    public:
        // Light flags.
        enum Flags
        {
            // Recalculate each frame.
            DYNAMIC = 1,

            // Is light probe.
            PROBE = 2
        };

        // Get position.
        const M4f &GetPos() const;

        // Get color.
        const Color &GetColor() const;

        // Set color.
        void SetColor(const Color &color);

        // Set range. [range] is in meters. [falloff] is 0=Hardest edge to 2048=Smoothest edge.
        void SetRange(float range, float falloff = 0);

        // Set spherical opening. [aperture] is 0=no spherical opening to 1=full spherical opening.
        // [falloff] is 0=Hardest edge to 2048=Smoothest edge.
        void SetAperture(float aperture, float falloff = 0);

        // Set position.
        void SetPos(const M4f &pos);

        // Internal.
        void *operator () () const { return (void *)wobj; }

        // Construct light at position [pos]. [flags] is combination of light flags or 0. For probe lights,
        // [level] is the light probe level. 0 is the highest level probe. Lower level probes receive light 
        // from higher level probes. [response] is the probes's response time to light in seconds to help 
        // smooth light changes. 
        Light(const M4f &pos, uint flags = Flags::DYNAMIC, uint level = 0, float delay = 0);

        // Destructor.
        ~Light();

    private:
        byte wobj[192];
    };

    // $docend

    // *************************************************************************************************************
    // Sound
    // *************************************************************************************************************

    // $doc "sound" "Sound"
    /**/

    // Generates audio in a scene.
    class RVAPI Sound
    {
    public:
        // Check if sound is currently playing.
        bool IsPlaying() const;

        // Play sound.
        void Play();

        // Pause sound.
        void Pause();

        // Stop sound.
        void Stop();

        // Set [gain] to normalized value.
        void SetGain(float gain);

        // Set [pitch] to normalized value. 1 = no change. higher = higher pitch. lower = lower pitch. 
        void SetPitch(float pitch);

        // Set velocity vector.
        void SetVelocity(const S3f &vel);

        // Set range in meters. Loudest when less than [min]. Not audible when greater than [max].
        void SetRange(float min, float max);

        // Set cone angle. Loudest when less than [inner]. At outer gain when greater than [outer]. 
        // [gain] is outer volume.
        void SetCone(float inner, float outer, float gain);

        // Enable/Disable looping.
        void SetLoop(bool enable);

        // Set position.
        void SetPos(const M4f &pos);

        // Set sound source.
        void SetSource(wcstr assetName);

        // Stream sound from file. [path] is file location relative to assets root.
        void SetStream(wcstr path);

        // Internal.
        void *operator () () const { return (void *)wobj; }

        // Constructor.
        Sound();

        // Destructor.
        ~Sound();

    private:
        byte wobj[1024];
    };

    // $docend

    // *************************************************************************************************************
    // Listener
    // *************************************************************************************************************

    // $doc "listener" "Listener"
    /**/

    // Listens to audio in the scene.
    class RVAPI Listener
    {
    public:
        // Set listener gain.
        static void SetGain(float gain);

        // Set listener velocity vector.
        static void SetVel(const S3f &vel);

        // Set listener position.
        static void SetPos(const M4f &pos);
    };

    // $docend

    //  ______                                           _    
    // |  ____|                                         | |   
    // | |__ _ __ __ _ _ __ ___   _____      _____  _ __| | __
    // |  __| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
    // | |  | | | (_| | | | | | |  __/\ V  V / (_) | |  |   < 
    // |_|  |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\

    // *************************************************************************************************************
    // State
    // *************************************************************************************************************

    // $doc "state" "State"
    /**/

    // These macros define a state mechanism in any class that receives OnPass1() and/or OnPass2() updates.
    // This enables a class to use SetPass1State()/SetPass2State() to redirect the update callbacks to any class member 
    // functions as needed to alter logic (state) of the object. 
    /**/

    // Put this last in the OnPass1() callback.
    #define RVPASS1STATE if (pass1State) (*this.*pass1State)();

    // Put this last in the OnPass2() callback.
    #define RVPASS2STATE if (pass2State) (*this.*pass2State)();

    // Put this in the private section of the class and set [_CLASS_] to the class name. This defines SetPass1State()
    // /SetPass2State() functions that can set a member function to begin receiving updates. The syntax for passing
    // a member function to the call is: SetPass1State(&MyClass::MyFunction).
    #define RVSTATEFUNCS(_CLASS_) \
    typedef void (_CLASS_:: *FState)();\
    FState pass1State = 0, pass2State = 0;\
    void SetPass1State(FState func) { pass1State = func; }\
    void SetPass2State(FState func) { pass2State = func; }

    // $docend

    // *************************************************************************************************************
    // Entity
    // *************************************************************************************************************

    // $doc "entity" "Entity"
    /**/

    // An object used in a scene or overlay. An entity has no functionality of its own, but uses components 
    // to provide functionality. An entity can be part of a hierarchy and have a super entity (parent) and
    // sub entities (children). The engine owns entities after they are added to a scene or overlay, so they 
    // don't have to be explicity destroyed. Entity usage must be after a scene is finalized and before the
    // scene is released.
    class RVAPI Entity
    {
    public:
        // Get key.
        EntKey GetKey() const;

        // Get externally assigned type id.
        uint GetType() const;

        // Get subentity count.
        uint GetSubEntCount() const;

        // Get super entity.
        template<typename K = Entity>
        K &GetSupEnt() const { return (K &)GetSupEnt_(); }

        // Get entity subentity at [n].
        template<typename K = Entity>
        K &GetSubEnt(uint n) const { return (K &)GetSubEnt_(n); }

        // Remove all subentities.
        void ClearSubEnts();

        // Manually Pass1 update entity. Also update subentities if [recur] is true.
        void Pass1(bool recur = true);

        // Manually Pass2 update entity. Also update subentities if [recur] is true.
        void Pass2(bool recur = true);

        // Destroy entity at end of scene updates.
        void Destroy();

        // Internal.
        void *operator () () const;

        // Internal.
        static uint reserved();

        // Constructor.
        Entity();

        // Destructor.
        virtual ~Entity();

    protected:
        // Pass1 callback.
        virtual void OnPass1() {}

        // Pass2 callback.
        virtual void OnPass2() {}

        // Serialization callback.
        virtual void OnSerialize(File &/*file*/) const {}

    private:
        Entity &GetSupEnt_() const;
        Entity &GetSubEnt_(uint n) const;

        friend EntityBridge;
    };

    // $docend

    // *************************************************************************************************************
    // Entities
    // *************************************************************************************************************

    // $doc "entities" "Entities List"
    /**/

    // Holds entities and maintains data oriented order. Memory is allocated in blocks. Blocksize and 
    // block increment is settable in the scene or overlay. Majority of entities should be contained in 
    // a single block while larger outlier entities can be contained across multiple blocks. Increment
    // is the number blocks to allocate each time the entity list needs to expand. Increment doubles each 
    // expansion. Metrics are output when the engine is closed.
    class RVAPI Entities
    {
    public:
        // Check if entity referenced by [entkey] exists.
        bool Exists(EntKey entKey) const;

        // Get entity using [entKey].
        Entity &operator [] (EntKey entKey) const;

        // Add entity to list and return entity memory. Usage: new (entities.Add<Type>()) Type(). [entity] is entity to
        // add. [type] is caller defined type id. [entKey] receives the the new entity's entity key if non-zero pointer. 
        // [supEnt] is a pointer to a super entity or 0. If super entity key is provided, this entity will become a sub 
        // entity of the super entity.
        template<typename K>
        void *Add(uint type = 0, EntKey *entKey = 0, Entity *supEnt = 0) { return Add_(sizeof(K), type, entKey, supEnt); }

        // Destroy entity referenced by [entKey].
        void DestroyEntity(EntKey entKey);

        // Internal.
        void *operator () () const { return (void *)wobj; }

        // Constructor.
        Entities(void *wobj) : wobj(wobj) {}

        // Destructor.
        ~Entities() {}

    private:
        void *wobj;

        void *Add_(uint size, uint type = 0, EntKey *entKey = 0, Entity *supEnt = 0);
    };

    // $docend

    // *************************************************************************************************************
    // Prefab
    // *************************************************************************************************************

    // $doc "prefab" "Prefab"
    /**/

    // Walks a prefab hierarchy calling a virtual function for each object, which is used to create 
    // entities for types of objects. A stack is maintained that can be used for setting up an entity 
    // in relation to ancestor entities. When indexing objects on the prefab stack, the top of the stack
    // is -1 and progressively negative indices move towards bottom of stack. Prefab usage must be after
    // a scene is finalized and before the scene is released.
    class RVAPI Prefab
    {
    public:
        // Callback to load entity type.
        typedef void (*FOnLoadType)(Prefab &prefab);

        // Get marker position.
        const M4f &GetMarker(wcstr name) const;

        // Check if object at [n] index on stack exists. 
        bool IsObject(int n) const;

        // Check if name matches [name].
        bool IsObjName(wcstr name, int n = -1) const;

        // Check if type matches [type].
        bool IsObjType(wcstr type, int n = -1) const;

        // Get object non-qualified name at [n] index on stack.
        wcstr GetObjBaseName(int n = -1) const;

        // Get object type at [n] index on stack. 
        wcstr GetObjType(int n = -1) const;

        // Get object qualified name at [n] index on stack.
        wcstr GetObjName(int n = -1) const;

        // Get object hull path at [n] index on stack.
        wcstr GetObjHullPath(int n = -1) const;

        // Get object local position at [n] index on stack.
        const M4f &GetObjPos(int n = -1) const;

        // Get object entity at [n] index on stack. A reference to a created entity can be attached
        // to an object for reference by child objects. Use this function to get the entity reference. 
        Entity &GetObjEnt(int n = -1) const;

        // Set node entity at [n] index on stack. A reference to a created entity can be attached to 
        // an object for reference by child objects. Use this function to set the entity reference. 
        void SetObjEnt(Entity *entity, int n = -1);

        // Load prefab from [path] and placed at [pos] in scene.
        void Load(wcstr path, const M4f &pos = M4fIdent());

        // Constructor.
        Prefab();

        // Destructor.
        virtual ~Prefab();

    protected:
        virtual void OnLoadObject() {}

    private:
        byte wobj[448];

        friend PrefabBridge;
    };

    // $docend

    // *************************************************************************************************************
    // Overlay
    // *************************************************************************************************************

    // $doc "overlay" "Overlay"
    /**/

    // 2D layer over the 3D scene. Overlay usage must be after a scene is finalized and before the scene is released.
    class RVAPI Overlay
    {
    public:
        // Get entities.
        Entities GetEntities() const;

        // Get image dims.
        S2i GetImageDims(uint imageID) const;

        // Get font height.
        uint GetFontHeight(uint fontID) const;

        // Get character width.
        uint GetCharWidth(uint fontID, wchar c) const;

        // Get character advance.
        uint GetCharAdvance(uint fontID, wchar c) const;

        // Get font ID.
        uint GetFontID(wcstr name) const;

        // Get image ID.
        uint GetImageID(wcstr name) const;

        // Get exit code.
        int GetExitCode() const;

        // Set exit code.
        void SetExitCode(int exitCode);

        // Set clip region. Resolve meta position using parent rectangle [pRect].
        void SetClip(const MetaPos &metaPos, const B2i &pRect);

        // Reset clip region to entire overlay.
        void SetClip();

        // Erase overlay.
        void Erase();

        // Manual forward update.
        void Pass1();

        // Manual reverse udpate.
        void Pass2();

        // Internal.
        void *operator () () const;

        // Construct overlay. See Entities comments about [blockSize] and [incr].
        Overlay(uint blockSize = 512, uint incr = 64);

        // Destructor.
        virtual ~Overlay();

    protected:
        // Pass1 callback.
        virtual void OnPass1() {}

        // Pass2 callback.
        virtual void OnPass2() {}

    private:
        friend OverlayBridge;
    };

    // $docend

    // *************************************************************************************************************
    // Scene
    // *************************************************************************************************************

    // $doc "scene" "Scene"
    /**/

    // 3D layer. Scene usage must be while the engine is running.
    class Scene
    {
    public:
        // Get ray query host entity.
        RVAPI EntKey GetRQIHost() const;

        // Get ray query hit normal.
        RVAPI const S3f &GetRQINormal() const;

        // Get ray query hit position.
        RVAPI const S3f &GetRQIPos() const;

        // Get static entities.
        RVAPI Entities GetStaticEntities() const;

        // Get dynamic entities.
        RVAPI Entities GetDynamicEntities() const;

        // Get current overlay.
        template<typename K = Overlay>
        K &GetOverlay() const { return *(K *)overlay(); }

        // Get current world.
        World GetWorld() const;

        // Add camera.
        RVAPI void AddCamera(Camera &camera);

        // Remove camera.
        RVAPI void RemoveCamera(Camera &camera);

        // Add light.
        RVAPI void AddLight(Light &light);

        // Update light.
        RVAPI void UpdateLight(Light &light);

        // Remove light.
        RVAPI void RemoveLight(Light &light);

        // Add geometry.
        RVAPI void AddGeometry(Geometry &geom);

        // Update geometry.
        RVAPI void UpdateGeometry(Geometry &geom);

        // Remove geometry.
        RVAPI void RemoveGeometry(Geometry &geom);

        // Set fog. [seeing] is distance in meters fog starts. [density] is the opaqueness
        // of the fog. [curve] is softness of fog edge. Default = 1.
        RVAPI void SetFog(const Color &color, float seeing = 0, float density = 1, float curve = 1);

        // Clear fog.
        RVAPI void ClearFog();

        // Set scene light grid parameters. [dim] is the dimension of the light grid in meters.
        // [div] is number of divisions on the grid axis. [origin] is origin of the light grid,
        // default = (0,0,0). Any light outside of the light grid is an environment light.
        RVAPI void SetLightGrid(float dimX, float dimY, float dimZ, float divX, float divY,
            float divZ, float originX = 0, float originY = 0, float originZ = 0);

        // Show skybox.
        RVAPI void ShowSkybox(wcstr name);

        // Hide skybox.
        RVAPI void HideSkybox();

        // Incorporate loaded assets into scene.
        RVAPI void Finalize();

        // Run scene and return exit code when finished.
        RVAPI int Run();

        // Manual forward.
        RVAPI void Pass1();

        // Set ray query screen position.
        RVAPI void SetRQIPos(const S2i &pos);

        // Set scene exit code. This is a caller defined value. -1 is reserved for app close.
        RVAPI void SetExitCode(int exitCode);

        // Enable/Disable probe.
        RVAPI void EnableProbe(bool enable = true);

        // Serialize entities to [file].
        RVAPI void Serialize(File &file) const;

        // Allocate memory for overlay. Usage: new (scene.AllocOverlay<OverlayType>()) OverlayType().
        template<typename K = Overlay>
        void *AllocOverlay() { return overlay.Alloc<K>(); }

        // Internal.
        RVAPI void *operator () () const;

        // Construct scene with static and dynamic entities settings. See Entities comments.
        RVAPI Scene(uint sBlockSize = 512, uint sIncr = 32, uint dBlockSize = 512, uint dIncr = 32);

        // Destructor.
        RVAPI virtual ~Scene();

    protected:
        // Pass1 callback.
        RVAPI virtual void OnPass1() {}

    private:
        SafePtr<Overlay> overlay;

        friend SceneBridge;
    };

    // $docend

    // *************************************************************************************************************
    // Engine Configuration
    // *************************************************************************************************************

    // $doc "engcfg" "Engine Configuration"
    /**/

    // Engine configuration. Usage must be after API is created and before engine is started.
    class RVAPI EngCfg
    {
    public:
        // Presentation mode.
        enum class PresMode
        {
            // Rendered display buffer is shown immediately. Not synced to vertical blank. 
            // Visible tearing is possible.
            IMMED,

            // Rendered display buffer is queued. Latest buffer can replace a waiting buffer. 
            // Synced to vertical blank. No tearing.
            MAILBOX,

            // Rendered display buffer is queued. Synced to vertical blank. No tearing.
            FIFO,

            // Rendered display buffer is queued. If the buffer is queued late, it will be 
            // hown without waiting for next vertical blank, otherwise buffers are synced 
            // to vertical blank. No tearing, unless a late buffer is inserted.
            RELAXED
        };

        // Window flags.
        enum WinFlags
        {
            // Window is shown with no border or border controls.
            WINDOW_BORDERLESS = 1,

            // Start in full screen. Overriden by stored settings.
            WINDOW_FULLSCREEN = 2
        };

        // Trace flags.
        enum TraceFlags
        {
            // Enable refraction.
            TRACE_REFRACTION = 1,

            // Enable reflection. 
            TRACE_REFLECTION = 2
        } RVTraceFlags;

        // Probe mode.
        enum class ProbeMode
        {
            // No probe.
            NONE,

            // FPS only.
            FPS,

            // FPS and metrics.
            METRICS
        };

        // Set stage maxes. Only need to set these if engine complains. [dwStageMB] Display stage MB's
        // or 0 to not change. [swStageMB] Scene stage MB's or 0 to not change. [twStageMB] Task stage 
        // MB's or 0 to not change.
        void SetStageMaxes(uint dwStageMB, uint swStageMB, uint twStageMB);

        // Set display maximums. Only need to set these if engine complains. [maxBufs] Maximum buffers 
        // or 0 to not change. [maxImgs] Maximum images or 0 to not change. [maxUfms] Maxumum uniform 
        // buffers or 0 to not change. [maxAccels] Maximum acceleration structures or 0 to not change.
        void SetDisplayMaxes(uint maxBufs, uint maxUfms, uint maxImgs, uint maxAccels);

        // Set screen maximums. Only need to set these if engine complains. [maxBufs] Maximum buffers 
        // or 0 to not change. [maxImgs] Maximum images or 0 to not change. [maxUfms] Maxumum uniform 
        // buffers or 0 to not change. [maxAccels] Maximum acceleration structures or 0 to not change.
        void SetSceneMaxes(uint maxBufs, uint maxUfms, uint maxImgs, uint maxAccels);

        // Set task maximums. Only need to set these if engine complains. [maxBufs] Maximum buffers or
        // 0 to not change. [maxImgs] Maximum images or 0 to not change. [maxUfms] Maxumum uniform 
        // buffers or 0 to not change. [maxAccels] Maximum acceleration structures or 0 to not change.
        void SetTaskMaxes(uint maxBufs, uint maxUfms, uint maxImgs, uint maxAccels);

        // Set window parameters. [title] is window title. Default="Test" [w] is width of window as either 
        // a factor of desktop width (when le 1), or as number of pixels (when gt 1). If zero, width is 
        // based off [h] and display aspect ratio. Default=0. [h] is height of window as either factor of 
        // desktop height (when le 1), or as number of pixels (when gt 1). If zero, height is based off [w]
        // and display aspect ratio. If [w] and [h] are both zero, app is started in full screen mode. 
        // Default=.75. [monitor] is monitor number to open window on. Default=0. [flags] are 
        // window flags. Default=0.
        void SetWindow(wcstr title, float w, float h, uint monitor, uint flags);

        // Set presentation mode. Default=Mailbox. [minSwapChainSize] is minumum number of
        // swap chains for display buffering. Range is 1-4. Default=2.
        void SetPresMode(PresMode presMode, uint minSwapChainSize);

        // Set app major, minor and patch version. Default=0,0,0.
        void SetAppVer(uint major, uint minor, uint patch);

        // Set GPU heap page megabytes. Default=128.
        void SetGPUHeapConfig(uint gpuPageMB);

        // Enable/Disable showcase mode. Showcasing sets background to black while maintaining skybox reflections.
        void SetShowcase(bool enable);

        // Set normal map range in meters. Normal mapping is disabled beyond this range. This helps
        // with performance and screen 'jaggies'. Default=35.
        void SetNormMapRange(float range);

        // Enable/Disable half resolution mode. Half resolution mode uses half the display resolution 
        // for internal rendering then scales the final result to full display resolution.
        void SetHalfRes(bool enable);

        // Set ray tracing flags. 
        void SetTrace(uint trace);

        // Set probe mode.
        void SetProbeMode(ProbeMode mode);

        // Scale import metallic and smoothness.
        void SetMatScale(float metallic, float smooth);

        // Set random seed. If [seed] is zero, the random sequence changes every run. If [seed] is non-zero, 
        // each non-zero seed value has its own unique random sequence, which stays the same every run.
        void SetRndSeed(uint seed);
    };

    // $docend

    // *************************************************************************************************************
    // Visuals
    // *************************************************************************************************************

    // $doc "visuals" "Visuals"
    /**/

    // Live update of display visuals. Usage must be while engine is started.
    class RVAPI Visuals
    {
    public:
        // Get probe mode.
        static EngCfg::ProbeMode GetProbeMode();

        // Get full screen mode.
        static bool GetFullScreen();

        // Get half resolution.
        static bool GetHalfRes();

        // Get trace flags.
        static uint GetTrace();

        // Set probe mode.
        static void SetProbeMode(EngCfg::ProbeMode probeMode);

        // Set full screen mode.
        static void SetFullScreen(bool fullScreen);

        // Set half resolution.
        static void SetHalfRes(bool halfRes);

        // Set trace flags. 1=Reflection 2=Refraction 4=Secondary reflection 8=Secondary refraction 16=Lighting.
        static void SetTrace(uint trace);

        // Invoke display settings after making changes.
        static void Invoke();
    };

    // $docend

    // *************************************************************************************************************
    // Engine
    // *************************************************************************************************************

    #define RVWR ENG().GetWindowRect()

    // $doc "engine" "Engine"
    /**/

    // Top level control. Engine usage must be after the API is created and before the API is destroyed.
    class Engine : public EngCfg
    {
    public:
        // Check if display was resized this frame.
        RVAPI bool IsResize() const;

        // Check if currently in full screen mode.
        RVAPI bool IsFullScreen() const;

        // Get global.
        RVAPI static Engine &GetGlobal();

        // Get monitor count.
        RVAPI uint GetMonitorCount() const;

        // Get window rectangle.
        RVAPI B2i GetWindowRect() const;

        // Get elapsed seconds since last frame.
        RVAPI double GetElapsed() const;

        // Get current scene.
        template<typename K = Scene>
        K &GetScene() const { return *(K *)scene(); }

        // Start engine.
        RVAPI void Start();

        // Allocate scene memory. Usage: new (engine.AllocScene<SceneType>()) SceneType().
        template<typename K = Scene>
        void *AllocScene() { return scene.Alloc<K>(); }

        // Constructor.
        RVAPI Engine();

        // Destructor.
        RVAPI ~Engine();

    private:
        SafePtr<Scene> scene;
    };

    // Engine global.
    inline Engine &ENG() { return Engine::GetGlobal(); }

    // Scene global.
    template<typename K = Scene>
    K &SCN() { return (K &)(ENG().GetScene()); }

    // Overlay global.
    template<typename K = Overlay>
    K &OVL() { return (K &)(ENG().GetScene().GetOverlay()); }

    // $docend

    // *************************************************************************************************************
    //  API
    // *************************************************************************************************************

    // $doc "api" "Rayve API"
    /**/

    // Rayve API initialization.
    class RVAPI API
    {
    public:
        // Function signature for message callbacks.
        typedef void (*FMessage)(wcstr msg);

        // Throw exception.
        static void Error(wcstr msg);

        // Print message.
        static void Print(wcstr msg, ...);

        // Show in-game message then pause game until spacebar is pressed.
        static void Pause(wcstr msg, ...);

        // Construct API. Must be first function called when program starts. [domain] and [app] are 
        // names used when creating a temp folder for the game. [Print] overrides where Rayve 
        // prints messages. [Error] is called when an exception occurs. 
        API(wcstr domain, wcstr app, FMessage Print = 0, FMessage Error = 0);

        // Destructor.
        ~API();
    };

    // $docend
}

