/* A more complete HoverWare prototype in OADL */
using namespace oadl;

/******************************************************************************
* Useful constants
******************************************************************************/
const
    True = 1, False = 0;

/******************************************************************************
* Attributes
******************************************************************************/
class hwSurface {
    public var
        Color = {1.0, 1.0, 1.0},
        Transparency = 0.0,
        SpecColor = {1.0, 1.0, 1.0},
        Shininess = 0.1,
        Backface = False,
        TwoSided = False,
        Bright = False,
        Invisible = False,
        Wireframe = False,
        Visibility = 0xFFFFFFFF,
        Texture = nil,
        Uncolored = False;
}

class hwOrient {
    public var
        Scale = {1.0, 1.0, 1.0},
        Rotate = {0.0, 0.0, 0.0},
        Pos = {0.0, 0.0, 0.0};
    /*public proc
        matrix()
        {
        }
    */
}

class hwImage {
    public var
        Rows = 0,
        Columns = 0,
        Components = 0,
        Image = nil,
        FileName = nil;
}

const
    HW_TM_MODULATE = 1,
    HW_TM_REPLACE = 2,
    HW_TM_DECAL = 3,
    HW_TM_REPEAT = 1,
    HW_TM_CLAMP = 2,
    HW_TM_EXPLICIT = 1,
    HW_TM_PLANAR = 1,
    HW_TM_SPHERE = 3,
    HW_TM_CYLINDER = 4;
class hwTexture(hwImage,hwOrient) {
    public var
        Apply = HW_TM_MODULATE,
        Bound = HW_TM_REPEAT,
        CoordMode = HW_TM_EXPLICIT,
        Filter = True,
        SampVert = False;
}

/******************************************************************************
* Primitive drawable classes
******************************************************************************/
const
    HW_OPT_NONE = 0,
    HW_OPT_SAVE_DATA = 1,
    HW_OPT_USE_DL = 2,
    HW_OPT_FREE_USER_DATA = 3;

class hwDrawable(hwSurface,hwOrient) {
    public var
        OptLevel = HW_OPT_NONE;
    public proc
        draw() {}
    public proc
        bounds() {}
}

class hwBox(hwDrawable) {
    public var
        Data = nil,
        OptLevel = HW_OPT_NONE;
    var
        dirty,
        data;
    operator {} ()
    {
        dirty = 1;
    }
}

class hwMesh(hwDrawable) {
    public var
        GraphN = 0,
        GraphM = 0,
        HasNormals = False,
        HasRGB = False,
        HasUV = False,
        Data = nil;
}

class hwPolygon(hwDrawable) {
    public var
        HasNormals = False,
        HasRGB = False,
        HasUV = False,
        Data = nil;
}

class hwQuads(hwDrawable) {
    public var
        HasNormals = False,
        HasRGB = False,
        HasUV = False,
        Data = nil;
}

class hwPolyline(hwOrient) {
    public var
        Invisible = False,
        Visibility = 0xFFFFFFFF,
        Color = {1,1,1},
        OptLevel = HW_OPT_NONE,
        Data = nil;
}

class hwPolymarker(hwOrient) {
    public var
        Invisible = False,
        Visibility = 0xFFFFFFFF,
        Color = {1,1,1},
        OptLevel = HW_OPT_NONE,
        Data = nil;
}

class hwTriangles(hwDrawable) {
    public var
        HasNormals = False,
        HasRGB = False,
        HasUV = False,
        Data = nil;
}

class hwGroup(hwOrient) {
    public var
        Invisible = False,
        Visibility = 0xFFFFFFFF,
        Children = nil;
    var
        bboxValid = False,
        bbox;
    public proc
        bounds()
        {
            if( !bboxValid ) {
                var
                    tmpBox, i, n;
                n = Children.length();
                for( i = 0; i < n; i += 1 ) {
                    tmpBox = Children[i].bounds();
                    if( tmpBox == nil ) return nil;
                }
                bboxValid = True;
            }
        }
    public proc
        draw()
        {
            var
                i, n;
            if( !bboxValid ) {
                bounds();
            }
            if( Invisible ) return;

            n = Children.length();
            for( i = 0; i < n; i += 1 ) {
                Children[i].draw();
            }
        }
}

const
    HW_TEXT_ALIGN_LEFT = 0,
    HW_TEXT_ALIGN_CENTER = 1,
    HW_TEXT_ALIGN_RIGHT = 2,

    HW_TEXT_ALIGN_TOP = 0,
    HW_TEXT_ALIGN_BOTTOM = 2,

    HW_TEXT_ALIGN_FRONT = 0,
    HW_TEXT_ALIGN_BACK = 2;

class hwText {
    public var
        Data = nil,
        Surface = {hwSurface{}, hwSurface{}, hwSurface{}},
        Pos = {0,0,0},
        Dir = {1,0,0},
        Up = {0,1,0},
        Scale = 1.0,
        Extrude = {0,0,0.25},
        Align = {HW_TEXT_ALIGN_CENTER, HW_TEXT_ALIGN_CENTER,
                        HW_TEXT_ALIGN_CENTER};
}
/******************************************************************************
* Derived drawable classes
******************************************************************************/

class hwCone(hwMesh) {
    public var
        GraphN = 9,
        GraphM = 17,
        Radius = {1,1},
        Height = 1.0,
        LonRange = {0,360},
        HasNormals = True;
}

class hwDisc(hwPolygon) {
    public var
        GraphN = 17,
        Radius = 1.0;
}

class hwRing(hwMesh) {
    public var
        GraphN = 9,
        GraphM = 17,
        Radius = {0.5,1.0},
        LonRange = {0,360};
}

class hwSphere(hwMesh) {
    public var
        GraphN = 9,
        GraphM = 17,
        Radius = 1.0,
        LatRange = {-90,90},
        LonRange = {0,360},
        HasNormals = True;
}

class hwSurfRev(hwMesh) {
    public var
        LonRange = {0,360},
        HasNormals = True;
}

class hwTorus(hwMesh) {
    public var
        GraphN = 17,
        GraphM = 17,
        Radius = {0.5,1.0},
        LatRange = {0,360},
        LonRange = {0,360},
        HasNormals = True;
}

/******************************************************************************
* Lights/camera/environ/etc
******************************************************************************/

class hwCamera {
    public var
        Pos = {0,0,-1.4},
        Dir = {0,0,1},
        Up = {0,1,0},
        Field = 90,
        Aspect = 1.0,
        Planes = {0.4, 2.4},
        Perspective = False;
}

class hwEnviron {
    public var
        BackgroundColor = {0,0,0},
        AmbientFactor = 0.5,
        AmbientColor = {1,1,1},
        Fog = False,
        FogColor = {0,0,0},
        Lighting = True;
}

class hwFile {
    public var
        FileName = nil;
}

class hwLight {
    public var
        Color = {1,1,1},
        Positional = False,
        Pos = {0,0,-1},
        Dir = {0,0,1},
        Cutoff = 0.0,
        LightExp = 0.0,
        Atten = 0.0;
}

/******************************************************************************
* Action!
******************************************************************************/
class hwSpinner {
    public var
        Children = nil,
        Invisible = False,
        Visibility = 0xFFFFFFFF,
        PosType = nil,
        DirType = nil,
        UpType = nil,
        ScaleType = nil,
        PosParams = nil,
        DirParams = nil,
        UpParams = nil,
        ScaleParams = nil,
        PosTimes = nil,
        DirTimes = nil,
        UpTimes = nil,
        ScaleTimes = nil,
        Lifetime = {0,1e38},
        CycleType = 0.0,
        Offset = 0.0,
        Delay = 0.0;
}

class hwTimer {
    public var
        Lifetime = {0,1e38},
        Equation = {0,1},
        CycleTime = 0.0,
        Children = nil;
}