////////////////////////////////////////////////////////
//
// GEM - Graphics Environment for Multimedia
//
// mdanks@cybermed.ucsd.edu
//
// Implementation file
//
//    Copyright (c) 1997-1998 Mark Danks.
//    For information on usage and redistribution, and for a DISCLAIMER OF ALL
//    WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
//
/////////////////////////////////////////////////////////

#include "gemwin.h"

#include "Base/GemMan.h"

CPPEXTERN_NEW_WITH_ONE_ARG(gemwin, t_floatarg, A_DEFFLOAT)

/////////////////////////////////////////////////////////
//
// gemwin
//
/////////////////////////////////////////////////////////
// Constructor
//
/////////////////////////////////////////////////////////
gemwin :: gemwin(t_floatarg framespersecond)
{
    if (framespersecond <= 0.) framespersecond = 20.;
    GemMan::frameRate((float)framespersecond);
}

/////////////////////////////////////////////////////////
// Destructor
//
/////////////////////////////////////////////////////////
gemwin :: ~gemwin()
{
    GemMan::destroyWindow();
}

/////////////////////////////////////////////////////////
// bangMess
//
/////////////////////////////////////////////////////////
void gemwin :: bangMess()
{
    if ( GemMan::windowExists() )
    {
        GemMan::swapBuffers();
    }
    else error("GEM: no window");
}

/////////////////////////////////////////////////////////
// intMess
//
/////////////////////////////////////////////////////////
void gemwin :: intMess(int state)
{
    if (state) GemMan::startRendering();
    else GemMan::stopRendering();
}

/////////////////////////////////////////////////////////
// createMess
//
/////////////////////////////////////////////////////////
void gemwin :: createMess()
{
    if ( !GemMan::windowExists() )
    {
        if ( !GemMan::createWindow() )
        {
            error("GEM: no window made");
            return;
        }
        GemMan::swapBuffers();	
        GemMan::swapBuffers();	
        post("GEM: window created");
    }
    else error("GEM: window already made");
}

/////////////////////////////////////////////////////////
// bufferMess
//
/////////////////////////////////////////////////////////
void gemwin :: bufferMess(int buf)
{
    if (buf == 1) GemMan::m_buffer = 1;
    else GemMan::m_buffer = 2;
}

/////////////////////////////////////////////////////////
// dimensionsMess
//
/////////////////////////////////////////////////////////
void gemwin :: dimensionsMess(int width, int height)
{
    if ( width <= 0)
    {
        error("GEM: width");
        return;
    }
    
    if ( height <= 0 )
    {
        error ("GEM: height");
        return;
    }
    GemMan::m_width = width;
    GemMan::m_height = height;
}

/////////////////////////////////////////////////////////
// colorMess
//
/////////////////////////////////////////////////////////
void gemwin :: colorMess(float red, float green, float blue)
{
    glClearColor(red, green, blue, 0.);
    GemMan::m_clear_color[0] = red;
    GemMan::m_clear_color[1] = green;
    GemMan::m_clear_color[2] = blue;
}

/////////////////////////////////////////////////////////
// ambientMess
//
/////////////////////////////////////////////////////////
void gemwin :: ambientMess(float red, float green, float blue)
{
    GemMan::m_mat_ambient[0] = red;
    GemMan::m_mat_ambient[1] = green;
    GemMan::m_mat_ambient[2] = blue;
}

/////////////////////////////////////////////////////////
// specularMess
//
/////////////////////////////////////////////////////////
void gemwin :: specularMess(float red, float green, float blue)
{
    GemMan::m_mat_specular[0] = red;
    GemMan::m_mat_specular[1] = green;
    GemMan::m_mat_specular[2] = blue;
}

/////////////////////////////////////////////////////////
// shininessMess
//
/////////////////////////////////////////////////////////
void gemwin :: shininessMess(float val)
{
    GemMan::m_mat_shininess = val;
}

/////////////////////////////////////////////////////////
// static member function
//
/////////////////////////////////////////////////////////
void gemwin :: obj_setupCallback(t_class *classPtr)
{
    class_addbang(classPtr, (t_method)&gemwin::bangMessCallback);
    class_addfloat(classPtr, (t_method)&gemwin::floatMessCallback);

    class_addmethod(classPtr, (t_method)&gemwin::createMessCallback,
    	    gensym("create"), A_NULL);
    class_addmethod(classPtr, (t_method)&gemwin::bufferMessCallback,
    	    gensym("buffer"), A_FLOAT, A_NULL);
    class_addmethod(classPtr, (t_method)&gemwin::dimensionsMessCallback,
    	    gensym("dimen"), A_FLOAT, A_FLOAT, A_NULL);
    class_addmethod(classPtr, (t_method)&gemwin::colorMessCallback,
    	    gensym("color"), A_FLOAT, A_FLOAT, A_FLOAT, A_NULL);

    class_addmethod(classPtr, (t_method)&gemwin::ambientMessCallback,
    	    gensym("ambient"), A_FLOAT, A_FLOAT, A_FLOAT, A_NULL);
    class_addmethod(classPtr, (t_method)&gemwin::specularMessCallback,
    	    gensym("specular"), A_FLOAT, A_FLOAT, A_FLOAT, A_NULL);
    class_addmethod(classPtr, (t_method)&gemwin::shininessMessCallback,
    	    gensym("shininess"), A_FLOAT, A_NULL);

    // just call GemMan directly
    class_addmethod(classPtr, (t_method)&gemwin::resetMessCallback,
    	    gensym("reset"), A_NULL);
    class_addmethod(classPtr, (t_method)&gemwin::destroyMessCallback,
    	    gensym("destroy"), A_NULL);
    class_addmethod(classPtr, (t_method)&gemwin::printMessCallback,
    	    gensym("print"), A_NULL);
    class_addmethod(classPtr, (t_method)&gemwin::profileMessCallback, 
    	    gensym("profile"), A_FLOAT, A_NULL);
    class_addmethod(classPtr, (t_method)&gemwin::lightingMessCallback, 
    	    gensym("lighting"), A_FLOAT, A_NULL);
    class_addmethod(classPtr, (t_method)&gemwin::frameMessCallback,
    	    gensym("frame"), A_FLOAT, A_NULL);
}
void gemwin :: printMessCallback(void *)
{
    GemMan::printInfo();
}
void gemwin :: profileMessCallback(void *, t_floatarg state)
{
	GemMan::m_profile = (int)state;
}
void gemwin :: lightingMessCallback(void *, t_floatarg state)
{
    GemMan::lightingOnOff((int)state);
}
void gemwin :: destroyMessCallback(void *)
{
    GemMan::destroyWindow();
}
void gemwin :: resetMessCallback(void *)
{
    GemMan::resetState();
}
void gemwin :: frameMessCallback(void *, t_floatarg rate)
{
    GemMan::frameRate((float)rate);
}

void gemwin :: bangMessCallback(void *data)
{
    GetMyClass(data)->bangMess();
}
void gemwin :: floatMessCallback(void *data, t_float state)
{
    GetMyClass(data)->intMess((int)state);
}
void gemwin :: createMessCallback(void *data)
{
    GetMyClass(data)->createMess();
}
void gemwin :: bufferMessCallback(void *data, t_floatarg buf)
{
    GetMyClass(data)->bufferMess((int)buf);
}
void gemwin :: dimensionsMessCallback(void *data, t_floatarg width, t_floatarg height)
{
    GetMyClass(data)->dimensionsMess((int)width, (int)height);
}
void gemwin :: colorMessCallback(void *data, t_floatarg red, t_floatarg green, t_floatarg blue)
{
    GetMyClass(data)->colorMess((float)red, (float)green, (float)blue);
}
void gemwin :: ambientMessCallback(void *data, t_floatarg red, t_floatarg green, t_floatarg blue)
{
    GetMyClass(data)->ambientMess((float)red, (float)green, (float)blue);
}
void gemwin :: specularMessCallback(void *data, t_floatarg red, t_floatarg green, t_floatarg blue)
{
    GetMyClass(data)->specularMess((float)red, (float)green, (float)blue);
}
void gemwin :: shininessMessCallback(void *data, t_floatarg val)
{
    GetMyClass(data)->shininessMess((float)val);
}
