/*****************************************************************************
 * $LastChangedDate: 2011-03-17 19:59:52 -0400 (Thu, 17 Mar 2011) $
 * @file
 * @author  Jim E. Brooks  http://www.palomino3d.org
 * @brief   Interface of C functions for Lua scripts.
 * @remarks @remarks module.txt documents how to export new C++ classes to Lua.
 *
 * ----------------------------
 * -- THIS IS AUTO-GENERATED --
 * ----------------------------
 *
 *//*
 * LEGAL:   COPYRIGHT (C) 2008 JIM E. BROOKS
 *          THIS SOURCE CODE IS RELEASED UNDER THE TERMS
 *          OF THE GNU GENERAL PUBLIC LICENSE VERSION 2 (GPL 2).
 *****************************************************************************/

#include "base/module.hh"
using namespace base;
#include "object/module.hh"
#include "object/object.hh"
using namespace object;
#include "graph/module.hh"
#include "graph/model_cache.hh"
using namespace graph;
#include "lua_bind/module.hh"
#include "lua_bind/bind.hh"

namespace lua {


namespace bind {

#define BIND_CLASS_NAME      "Object"
#define BIND_METATABLE_NAME  LUABIND_METATABLE_STRING(BIND_CLASS_NAME)

//==============================================================================
// C functions called by Lua that access C++ objects.
//==============================================================================
// Need a function to check typesig because of macro/template limitations.
#if ! DOXYGEN
INTERN void
CheckTypesigObject( shptr<Object> obj )
{
    CHECK_TYPESIG(obj,TYPESIG_OBJECT);
}
#endif // ! DOXYGEN

/*****************************************************************************
 * Lua's garbage collector indirectly invokes this C++ destructor.
 *****************************************************************************/
INTERN int 
Object_Destroy( lua_State* L ) 
{ 
   try { 

        return DESTROY_USERDATA_SHPTR<Object>( L, CheckTypesigObject );
    
   } CATCH_LUA_EXCEPTION 
   return 0; 
} 

/*****************************************************************************
 * table Object:GetMatrix()
 *****************************************************************************/
INTERN int 
Object_GetMatrix( lua_State* L ) 
{ 
   try { 

        shptr<Object> object = POP_USERDATA_AS_SHPTR<Object>( L );
        CHECK_TYPESIG(object,TYPESIG_OBJECT);
        PUSH_TABLE_FROM_MATRIX( L, object->GetMatrix() );
        return 1;  // stack items to return
    
   } CATCH_LUA_EXCEPTION 
   return 0; 
} 

/*****************************************************************************
 * string Object:GetName()
 *****************************************************************************/
INTERN int 
Object_GetName( lua_State* L ) 
{ 
   try { 

        Object* object = POP_USERDATA_AS_SHPTR<Object>( L ).PTR();
        CHECK_TYPESIG(object,TYPESIG_OBJECT);
        lua_pushstring( L, object->GetName().c_str() );
        return 1;  // stack items to return
    
   } CATCH_LUA_EXCEPTION 
   return 0; 
} 

/*****************************************************************************
 * int Object:GetObjectCount()
 *****************************************************************************/
INTERN int 
Object_GetObjectCount( lua_State* L ) 
{ 
   try { 

        lua_pushnumber( L, Object::GetObjectCount() );
        return 1;  // stack items to return
    
   } CATCH_LUA_EXCEPTION 
   return 0; 
} 

/*****************************************************************************
 * Vec3 Object:GetPosition()
 *****************************************************************************/
INTERN int 
Object_GetPosition( lua_State* L ) 
{ 
   try { 

        shptr<Object> object = POP_USERDATA_AS_SHPTR<Object>( L );
        CHECK_TYPESIG(object,TYPESIG_OBJECT);
        const WorldVertex pos = object->GetPosition();
        PUSH_VECTOR3( L, pos );
        return 1;  // stack items to return
    
   } CATCH_LUA_EXCEPTION 
   return 0; 
} 

/*****************************************************************************
 * number Object:GetRawPtr()
 *****************************************************************************/
INTERN int 
Object_GetRawPtr( lua_State* L ) 
{ 
   try { 

        Object* object = POP_USERDATA_AS_SHPTR<Object>( L ).PTR();
        CHECK_TYPESIG(object,TYPESIG_OBJECT);
        lua_pushnumber( L, long(static_cast<Object*>(object)) );
        return 1;  // stack items to return
    
   } CATCH_LUA_EXCEPTION 
   return 0; 
} 

/*****************************************************************************
 * bool Object:IfCollidable()
 *****************************************************************************/
INTERN int 
Object_IfCollidable( lua_State* L ) 
{ 
   try { 

        shptr<Object> object = POP_USERDATA_AS_SHPTR<Object>( L );
        CHECK_TYPESIG(object,TYPESIG_OBJECT);
        lua_pushboolean( L, object->IfCollidable() );
        return 1;  // stack items to return
    
   } CATCH_LUA_EXCEPTION 
   return 0; 
} 

/*****************************************************************************
 * bool Object:IfCollision()
 *****************************************************************************/
INTERN int 
Object_IfCollision( lua_State* L ) 
{ 
   try { 

        shptr<Object> object = POP_USERDATA_AS_SHPTR<Object>( L );
        CHECK_TYPESIG(object,TYPESIG_OBJECT);
        lua_pushboolean( L, object->IfCollision() );
        return 1;  // stack items to return
    
   } CATCH_LUA_EXCEPTION 
   return 0; 
} 

/*****************************************************************************
 * bool Object:IfCollisionFatal()
 *****************************************************************************/
INTERN int 
Object_IfCollisionFatal( lua_State* L ) 
{ 
   try { 

        shptr<Object> object = POP_USERDATA_AS_SHPTR<Object>( L );
        CHECK_TYPESIG(object,TYPESIG_OBJECT);
        lua_pushboolean( L, object->IfCollisionFatal() );
        return 1;  // stack items to return
    
   } CATCH_LUA_EXCEPTION 
   return 0; 
} 

/*****************************************************************************
 * bool Object:IfZombie()
 *****************************************************************************/
INTERN int 
Object_IfZombie( lua_State* L ) 
{ 
   try { 

        shptr<Object> object = POP_USERDATA_AS_SHPTR<Object>( L );
        CHECK_TYPESIG(object,TYPESIG_OBJECT);
        lua_pushboolean( L, object->IfZombie() );
        return 1;  // stack items to return
    
   } CATCH_LUA_EXCEPTION 
   return 0; 
} 

/*****************************************************************************
 * Object:New( x,y,z|Vec3, modelPathname, scale, ModelCache.LOAD_SHARED|LOAD_COPY )
 *****************************************************************************/
INTERN int 
Object_New( lua_State* L ) 
{ 
   try { 

        const bool        loadCopy  = POP_BOOL( L );
        const fp          scale     = POP_FP( L );
        const string      modelName = POP_STRING( L );
        const WorldVertex pos       = POP_VECTOR3<WorldVertex>( L );

        // Load 3D model.
        shptr<Graph> graph = GET_MODEL_CACHE().LoadModel( modelName, scale, loadCopy );
        shptr<Object> object = new Object( graph, pos );

        return NEW_USERDATA_SHPTR<Object>( L, object, BIND_METATABLE_NAME );
    
   } CATCH_LUA_EXCEPTION 
   return 0; 
} 

/*****************************************************************************
 * Object:Reset()
 *****************************************************************************/
INTERN int 
Object_Reset( lua_State* L ) 
{ 
   try { 

        shptr<Object> object = POP_USERDATA_AS_SHPTR<Object>( L );
        CHECK_TYPESIG(object,TYPESIG_OBJECT);
        object->Reset();
    
   } CATCH_LUA_EXCEPTION 
   return 0; 
} 

/*****************************************************************************
 * Object:Rotate( axis, radian )
 *****************************************************************************/
INTERN int 
Object_Rotate( lua_State* L ) 
{ 
   try { 

        const fp   radian = POP_FP( L );
        const uint axis   = POP_INT( L );
        shptr<Object> object = POP_USERDATA_AS_SHPTR<Object>( L );
        CHECK_TYPESIG(object,TYPESIG_OBJECT);
        object->Rotate( axis, radian );
    
   } CATCH_LUA_EXCEPTION 
   return 0; 
} 

/*****************************************************************************
 * Object:SetCollidable( bool )
 *****************************************************************************/
INTERN int 
Object_SetCollidable( lua_State* L ) 
{ 
   try { 

        const bool f = POP_BOOL( L );
        shptr<Object> object = POP_USERDATA_AS_SHPTR<Object>( L );
        CHECK_TYPESIG(object,TYPESIG_OBJECT);
        object->SetCollidable( f );
    
   } CATCH_LUA_EXCEPTION 
   return 0; 
} 

/*****************************************************************************
 * Object:SetCollision( int )
 *****************************************************************************/
INTERN int 
Object_SetCollision( lua_State* L ) 
{ 
   try { 

        const int collision = POP_INT( L );
        shptr<Object> object = POP_USERDATA_AS_SHPTR<Object>( L );
        CHECK_TYPESIG(object,TYPESIG_OBJECT);
        object->SetCollision( static_cast<Object::eCollision>( collision ) );
    
   } CATCH_LUA_EXCEPTION 
   return 0; 
} 

/*****************************************************************************
 * Object:SetMatrix( matrix )
 *****************************************************************************/
INTERN int 
Object_SetMatrix( lua_State* L ) 
{ 
   try { 

        Matrix m; POP_TABLE_INTO_MATRIX( L, m );
        shptr<Object> object = POP_USERDATA_AS_SHPTR<Object>( L );
        CHECK_TYPESIG(object,TYPESIG_OBJECT);
        object->SetMatrix( m, Object::PLACEMENT );
    
   } CATCH_LUA_EXCEPTION 
   return 0; 
} 

/*****************************************************************************
 * Object:SetPosition( x,y,z|Vec3 )
 *****************************************************************************/
INTERN int 
Object_SetPosition( lua_State* L ) 
{ 
   try { 

        const WorldVertex pos = POP_VECTOR3<WorldVertex>( L );
        shptr<Object> object = POP_USERDATA_AS_SHPTR<Object>( L );
        CHECK_TYPESIG(object,TYPESIG_OBJECT);
        object->SetPosition( pos );
    
   } CATCH_LUA_EXCEPTION 
   return 0; 
} 

/*****************************************************************************
 * Object:Zombify()
 *****************************************************************************/
INTERN int 
Object_Zombify( lua_State* L ) 
{ 
   try { 

        shptr<Object> object = POP_USERDATA_AS_SHPTR<Object>( L );
        CHECK_TYPESIG(object,TYPESIG_OBJECT);
        object->Zombify();
    
   } CATCH_LUA_EXCEPTION 
   return 0; 
} 

//==============================================================================
// Register binding with Lua. 
//==============================================================================

#if ! DOXYGEN 

INTERN const struct luaL_reg sMethodTable[] =
{
  { "New", Object_New },
  { "__gc", Object_Destroy },
  { "GetMatrix", Object_GetMatrix },
  { "GetName", Object_GetName },
  { "GetObjectCount", Object_GetObjectCount },
  { "GetPosition", Object_GetPosition },
  { "GetRawPtr", Object_GetRawPtr },
  { "IfCollidable", Object_IfCollidable },
  { "IfCollision", Object_IfCollision },
  { "IfCollisionFatal", Object_IfCollisionFatal },
  { "IfZombie", Object_IfZombie },
  { "Reset", Object_Reset },
  { "Rotate", Object_Rotate },
  { "SetCollidable", Object_SetCollidable },
  { "SetCollision", Object_SetCollision },
  { "SetMatrix", Object_SetMatrix },
  { "SetPosition", Object_SetPosition },
  { "Zombify", Object_Zombify },
  { NULL, NULL }
};

void
RegisterObject( lua_State* L )
{
    REGISTER_BINDING( L,
                      BIND_METATABLE_NAME,
                      BIND_CLASS_NAME,
                      sMethodTable );
}

#endif // ! DOXYGEN 

} // namespace bind 

} // namespace lua 
