/*
-----------------------------------------------------------------------------
This source file is part of OpenSpace3D
For the latest info, see http://www.openspace3d.com

Copyright (c) 2010 I-maginer

This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.

This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt

You may alternatively use this source under the terms of a specific version of
the OpenSpace3D Unrestricted License provided you have obtained such a license from
I-maginer.
-----------------------------------------------------------------------------
*/

/*
 Toolkit based on OpenCV library
 First version : dec 2010
 Author : Bastien BOURINEAU
*/

#include "prerequisites.h"
#include "ArCameraParam.h"
#include "ArManager.h"
#include "ArMarker.h"

#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>

// Scol obj
int OBJMARKERSCOL;
int OBJCAMERAPARAMSCOL; 

// CALLBACK
int NBMARKERCB = 0;
int NBARCAMERAPARAM = 0;

/*! \mainpage Augmented reality Scol Plugin
 *
 * \section intro_sec Introduction
 * This plugin allow Scol Virtual Machine to use AR marker for augmented reality purpose
 * 
 */

/*******************************************
*	CAMERA PARAM
********************************************/
int destroyArCameraParamObj(mmachine m, int handsys, int obj)
{
  ArCameraParam* arCameraParamOBJ = (ArCameraParam*) MMfetch(m, MTOP(obj), 0);
	SAFE_DELETE(arCameraParamOBJ);
	MMstore(m, MTOP(obj), 0, 0);
	
  MMechostr(MSKDEBUG, "ArCameraParam destroyed.\n");
	return 0;
}

/*! @ingroup grpcapture
* \brief _DSarCameraParam : This function destroy a camera parameter
*
* <b>Prototype:</b> fun [ObjArCameraParam] I
* \param ObjArCameraParam : camera parameter to destroy
*
* \return I : return 0 if success or NIL otherwise
*/
int _DSarCameraParam(mmachine m)
{
#ifdef	_SCOL_DEBUG_
	MMechostr(MSKDEBUG, "_DSarCameraParam\n");
#endif
	
	int obj = MMget(m, 0);
	if (obj == NIL)
  {
    MMset(m, 0, NIL);
    return 0;
  }
	
	OBJdelTM(m, OBJCAMERAPARAMSCOL, obj);
  
	MMset(m, 0, ITOM(0));	

#ifdef	_SCOL_DEBUG_
	MMechostr(MSKDEBUG, "ok\n");
#endif
	return 0;
}

/*! @ingroup grpcapture
* \brief _CRarCameraParam : This function create a new camera parameter
*
* <b>Prototype:</b> fun [Chn I I F F P] ObjArCameraParam
* \param Chn : Scol channel
* \param I : camera picture width
* \param I : camera picture height
* \param F : camera near clip
* \param F : camera far clip
* \param P : camera parameter definition file (openCV yaml)
*
* \return ObjArCameraParam : new camera param object, NIL on error
*/
int _CRarCameraParam(mmachine m)
{
#ifdef	_SCOL_DEBUG_
	MMechostr(MSKDEBUG,"_CRarCameraParam\n");
#endif

	int ifile = MMpull(m);
	int ffarclip = MMpull(m);
	int fnearclip = MMpull(m);
	int sheight = MMpull(m);
	int swidth = MMpull(m);

  if ((swidth == NIL) || (sheight == NIL))
	{
		MMset(m, 0, NIL);
		return 0;
	}
	
	int width = 1;
	int height = 1;

	if (MTOI(swidth) > 1)
		width = MTOI(swidth);
	if (MTOI(sheight) > 1)
		height = MTOI(sheight);

	float nearclip = 0.001;
	if(fnearclip != NIL)
		nearclip = MTOF(fnearclip);

	float farclip = 100000.0;
	if(ffarclip != NIL)
		farclip = MTOF(ffarclip);

	std::string yamlfile("");
  if (ifile != NIL)
    yamlfile = MMstartstr(m, MTOP(ifile));
	
	ArCameraParam* ArCameraParamOBJ = new ArCameraParam(width, height, nearclip, farclip, yamlfile);

  if (!ArCameraParamOBJ)
  {
		MMechostr(MSKDEBUG, "Failed to create camera param\n");
		MMset(m, 0, NIL);
    return 0;
	}

  int cameraParam = MMmalloc(m, 1, TYPETAB);
	if (cameraParam == NIL)
  {
		SAFE_DELETE(ArCameraParamOBJ);
		MMset(m, 0, NIL);
    return MERRMEM;
	}
	
	MMstore(m, cameraParam, 0, (int)ArCameraParamOBJ);
	MMpush(m, PTOM(cameraParam));

#ifdef	_SCOL_DEBUG_
	MMechostr(MSKDEBUG,"ok\n");
#endif
	return OBJcreate(m, OBJCAMERAPARAMSCOL, (int)ArCameraParamOBJ, NIL, NIL);
}


/*! @ingroup grpbitmap
* \brief _GETarProjectionMatrix : This function return the projection matrix from a camera parameter
* <b>Prototype:</b> fun [ObjArCameraParam I I] [[F F F F] [F F F F] [F F F F] [F F F F]]
* \param ObjArCameraParam : camera parameter object
* \param I : screen width
* \param I : screen height
*
* \return [[F F F F] [F F F F] [F F F F] [F F F F]] : Projection matrix
*/
int _GETarProjectionMatrix(mmachine m)
{
	#ifdef	_SCOL_DEBUG_
	MMechostr(MSKDEBUG, "_GETarProjectionMatrix\n");
	#endif
	
	int iheight = MMpull(m);
	int iwidth = MMpull(m);
	int obj = MMpull(m);
	if ((obj == NIL) || (iheight == NIL) || (iwidth == NIL))
  {
    MMpush(m, NIL);
    return 0;
  }

	ArCameraParam* cameraParamOBJ = (ArCameraParam*) MMfetch(m, MTOP(obj), 0);
  if (cameraParamOBJ == NULL)
  {
    MMpush(m, NIL);
    return 0;
  }	

	double proj_mat[16];
	cameraParamOBJ->GetProjectionMatrix(proj_mat, cv::Size(MTOI(iwidth), MTOI(iheight)));

	int tupleMat = MMmalloc(m, 4, TYPETAB);
  if(tupleMat==NIL)				
  {
    MMpush(m, NIL);
		return MERRMEM;
  }

	int tupleMat0 = MMmalloc(m, 4, TYPETAB);
  if(tupleMat0==NIL)				
  {
    MMpush(m, NIL);
		return MERRMEM;
  }

	MMstore(m, tupleMat0, 0, FTOM(static_cast<float>(proj_mat[0])));
	MMstore(m, tupleMat0, 1, FTOM(static_cast<float>(proj_mat[4])));
	MMstore(m, tupleMat0, 2, FTOM(static_cast<float>(proj_mat[8])));
	MMstore(m, tupleMat0, 3, FTOM(static_cast<float>(proj_mat[12])));
	MMpush(m, PTOM(tupleMat0));

	int tupleMat1 = MMmalloc(m, 4, TYPETAB);
  if(tupleMat1==NIL)				
  {
    MMpush(m, NIL);
		return MERRMEM;
  }

	MMstore(m, tupleMat1, 0, FTOM(static_cast<float>(proj_mat[1])));
	MMstore(m, tupleMat1, 1, FTOM(static_cast<float>(proj_mat[5])));
	MMstore(m, tupleMat1, 2, FTOM(static_cast<float>(proj_mat[9])));
	MMstore(m, tupleMat1, 3, FTOM(static_cast<float>(proj_mat[13])));
	MMpush(m, PTOM(tupleMat1));

	int tupleMat2 = MMmalloc(m, 4, TYPETAB);
  if(tupleMat2==NIL)				
  {
    MMpush(m, NIL);
		return MERRMEM;
  }

	MMstore(m, tupleMat2, 0, FTOM(static_cast<float>(proj_mat[2])));
	MMstore(m, tupleMat2, 1, FTOM(static_cast<float>(proj_mat[6])));
	MMstore(m, tupleMat2, 2, FTOM(static_cast<float>(proj_mat[10])));
	MMstore(m, tupleMat2, 3, FTOM(static_cast<float>(proj_mat[14])));
	MMpush(m, PTOM(tupleMat2));

	int tupleMat3 = MMmalloc(m, 4, TYPETAB);
  if(tupleMat==NIL)				
  {
    MMpush(m, NIL);
		return MERRMEM;
  }

	MMstore(m, tupleMat3, 0, FTOM(static_cast<float>(proj_mat[3])));
	MMstore(m, tupleMat3, 1, FTOM(static_cast<float>(proj_mat[7])));
	MMstore(m, tupleMat3, 2, FTOM(static_cast<float>(proj_mat[11])));
	MMstore(m, tupleMat3, 3, FTOM(static_cast<float>(proj_mat[15])));
	MMpush(m, PTOM(tupleMat3));

	MMstore(m, tupleMat, 0, MMget(m, 3));
	MMstore(m, tupleMat, 1, MMget(m, 2));
	MMstore(m, tupleMat, 2, MMget(m, 1));
	MMstore(m, tupleMat, 3, MMget(m, 0));

  MMpull(m);
  MMpull(m);
  MMpull(m);
  MMpull(m);
  MMpush(m, PTOM(tupleMat));

	#ifdef	_SCOL_DEBUG_
		MMechostr(MSKDEBUG, "ok\n");
	#endif
		return 0;
}

/*******************************************
*	AR MARKER
********************************************/

int destroyMarkerObj(mmachine m,int handsys,int obj)
{
  ArMarker* MarkerOBJ = (ArMarker*) MMfetch(m, MTOP(obj), 0);
	ArManager::GetInstance()->RemoveMarker(MarkerOBJ);
	
	MMstore(m, MTOP(obj), 0, 0);
	
  MMechostr(MSKDEBUG, "ArMarker destroyed.\n");
	return 0;
}

/*! @ingroup grpcapture
* \brief _DSarMarker : This function destroy a capture device
*
* <b>Prototype:</b> fun [ObjArMarker] I
* \param ObjArMarker : ArMarker to destroy
*
* \return I : return 0 if success or NIL otherwise
*/
int _DSarMarker(mmachine m)
{
#ifdef	_SCOL_DEBUG_
	MMechostr(MSKDEBUG, "_DSarMarker\n");
#endif
	
	int obj = MMget(m, 0);
	if (obj == NIL)
  {
    MMset(m, 0, NIL);
    return 0;
  }
	
	OBJdelTM(m, OBJMARKERSCOL, obj);
  
	MMset(m, 0, ITOM(0));	

#ifdef	_SCOL_DEBUG_
	MMechostr(MSKDEBUG, "ok\n");
#endif
	return 0;
}

/*! @ingroup grpcapture
* \brief _CRarMarker : This function create a new capture device from a device index
*
* <b>Prototype:</b> fun [Chn I F] ObjArMarker
* \param Chn : Scol channel
* \param I : Device index (from 0) or NIL for first found
* \param F : Marker size in meter
*
* \return ObjArMarker : new ArMarker object, NIL on error
*/
int _CRarMarker(mmachine m)
{
#ifdef	_SCOL_DEBUG_
	MMechostr(MSKDEBUG,"_CRarMarker\n");
#endif

  int iSize = MMpull(m);
  int idx = MMpull(m);
  if ((idx == NIL) || (iSize == NIL))
	{
		MMset(m, 0, NIL);
		return 0;
	}

  ArMarker* MarkerOBJ = ArManager::GetInstance()->AddMarker(MTOI(idx), MTOF(iSize));

  if (!MarkerOBJ)
  {
		MMechostr(MSKDEBUG, "Failed to create marker\n");
		MMset(m, 0, NIL);
    return 0;
	}

  int marker = MMmalloc(m, 1, TYPETAB);
	if (marker == NIL)
  {
		ArManager::GetInstance()->RemoveMarker(MarkerOBJ);
		MMset(m, 0, NIL);
    return MERRMEM;
	}
	
	MMstore(m, marker, 0, (int)MarkerOBJ);
	MMpush(m, PTOM(marker));

#ifdef	_SCOL_DEBUG_
	MMechostr(MSKDEBUG,"ok\n");
#endif
	return OBJcreate(m, OBJMARKERSCOL, (int)MarkerOBJ, NIL, NIL);
}


/*! @ingroup grpbitmap
* \brief _UPDATEarMarkers : This function apply a blur into a bitmap
* <b>Prototype:</b> fun [ObjBitmap ObjArCameraParam I I] ObjBitmap
* \param ObjBitmap : Bitmap to analyze
* \param ObjArCameraParam : camera parameter object
* \param I : 1 if bitmap is mirrored, 0 otherwise
* \param I : 1 if debug is activated, 0 otherwise
*
* \return ObjBitmap : return same bitmap if success or NIL otherwise
*/
int _UPDATEarMarkers(mmachine m)
{
#ifdef	_SCOL_DEBUG_
	MMechostr(MSKDEBUG, "_UPDATEarMarkers\n");
#endif

	int idebug = MMpull(m);
  int imirror = MMpull(m);
	int iarcameraparam = MMpull(m);
	int bitmap = MMget(m, 0);

	if ((bitmap == NIL) || (iarcameraparam == NIL))
	{
    MMset(m, 0, NIL);
    return 0;
	}
	
	PtrObjVoid OB = (PtrObjVoid) MMstart(m, MTOP(bitmap));
	PtrObjBitmap B = (PtrObjBitmap) MMstart(m, MTOP(OB->Buffer));
	cv::Mat imagesrc(B->TailleH, B->TailleW, CV_8UC3, B->bits, B->BPL);
	 
  bool revert = false;
  if ((imirror != NIL) && (MTOI(imirror) == 1))
    revert = true;

	bool debug = false;
	if((idebug != NIL) && (MTOI(idebug) == 1))
		debug = true;

	ArCameraParam* arcameraparam = (ArCameraParam*) MMfetch(m, MTOP(iarcameraparam), 0);
	if (arcameraparam == 0)
	{
    MMset(m, 0, NIL);
    return 0;
	}

	//cv::Mat imagedest(B->TailleH, B->TailleW, CV_8UC3);
	//cv::Laplacian(imagesrc, imagedest, 0, 1, 1, 1, cv::BORDER_TRANSPARENT);

	ArManager::GetInstance()->UpdateMarkers(imagesrc, *arcameraparam, revert, debug);

	if(debug)
		memcpy(B->bits, imagesrc.data, ((B->TailleW * B->TailleH) * 3));

#ifdef	_SCOL_DEBUG_
	MMechostr(MSKDEBUG, "ok\n");
#endif
	return 0;
}

/*! @ingroup grpbitmap
* \brief _GETarMarkerBitmap : This function return a marker bitmap
* <b>Prototype:</b> fun [Chn ObjArMarker I] ObjBitmap
* \param Chn : scol channel
* \param ObjArMarker : Marker which give the bitmap 
* \param I : Size of the returned bitmap
*
* \return ObjBitmap : bitmap of a marker
*/
int _GETarMarkerBitmap (mmachine m)
{
	#ifdef	_SCOL_DEBUG_
	MMechostr(MSKDEBUG, "_GETarMarkerBitmap\n");
	#endif

	int ssize = MMpull(m);
	int markerTab = MMpull(m);
	if(markerTab == NIL)
	{
    MMset(m, 0, NIL);
    return 0;
	}
	
	ArMarker* arMarker = (ArMarker*)MMfetch(m, MTOP(markerTab), 0);
	if(arMarker == 0)
	{
    MMset(m, 0, NIL);
    return 0;
	}
	
	int size = 16;
	if ((ssize != NIL) && (MTOI(ssize) > 7))
		size = MTOI(ssize);

	cv::Mat mbitmap = arMarker->GetMarkerBitmap(size);

	//create scol bitmap
	//stack : channel
	
	//push the size w h
	MMpush(m, ITOM(size));
	MMpush(m, ITOM(size));
	
	//stack : channel sizew sizeh
	//push _CRbitmap
	if ((MMpush(m, Msearchinsyspak(m, "_CRbitmap"))) < 0)
	{
		MMechostr(0, "\n_GETarMarkerBitmap : error interpreting _CRbitmap");
		MMpull(m);
		MMpull(m);
		MMset(m, 0, NIL);
		return 0;
	}

	//execute scol cmd
	Minterpreter(m);
	
	int objbmp = MMget(m, 0);
	if (objbmp == NIL)
	{
		MMset(m, 0, NIL);
		return 0;
	}

	PtrObjVoid OB = (PtrObjVoid) MMstart(m, MTOP(objbmp));
  PtrObjBitmap B = (PtrObjBitmap) MMstart(m, MTOP(OB->Buffer));

  // create some temp variables
  int x=0;
  int y=0;
  int byteSRC=0;
  int byteDST=0;

  // traverse all pixels...
  for (y=0; y<B->TailleH; y++)
    for (x=0; x<B->TailleW; x++)
    {
       byteSRC = x + y*B->TailleW; // original has only 1 channels
       byteDST = x*3 + y*B->TailleW*3;

       // copy 3 bytes from source to destination
       B->bits[byteDST] = mbitmap.data[byteSRC];//b
       B->bits[byteDST+1] = mbitmap.data[byteSRC];//g
       B->bits[byteDST+2] = mbitmap.data[byteSRC];//r
    }

	#ifdef	_SCOL_DEBUG_
		MMechostr(MSKDEBUG, "ok\n");
	#endif
		return 0;
}

/*! @ingroup grpbitmap
* \brief _GETarMarkerPosition : This function return a marker position
* <b>Prototype:</b> fun [ObjArMarker] [F F F]
* \param ObjArMarker : Marker which takes position 
*
* \return [F F F] : Position if success, NIL otherwise
*/
int _GETarMarkerPosition(mmachine m)
{
	#ifdef	_SCOL_DEBUG_
	MMechostr(MSKDEBUG, "_GETarMarkerPosition\n");
	#endif

	int markerTab = MMget(m, 0);
	if(markerTab == NIL)
	{
    MMset(m, 0, NIL);
    return 0;
	}

	ArMarker* arMarker = (ArMarker*)MMfetch(m, MTOP(markerTab), 0);
	if(arMarker == 0)
	{
    MMset(m, 0, NIL);
    return 0;
	}

	Vector3 markerPosition = arMarker->GetPosition();

	int tuplePos = MMmalloc(m, 3, TYPETAB);
  if(tuplePos==NIL)
  {
    MMset(m, 0, NIL);
		return 0;
  }
  
  MMstore(m, tuplePos, 0, FTOM(markerPosition.x));
  MMstore(m, tuplePos, 1, FTOM(markerPosition.y));
  MMstore(m, tuplePos, 2, FTOM(markerPosition.z));
  MMset(m, 0, PTOM(tuplePos));

	#ifdef	_SCOL_DEBUG_
		MMechostr(MSKDEBUG, "ok\n");
	#endif
		return 0;
}

/*! @ingroup grpbitmap
* \brief _GETarMarkerPixelPosition : This function return a marker position
* <b>Prototype:</b> fun [ObjArMarker] [I I I]
* \param ObjArMarker : Marker which takes position 
*
* \return [I I I] : X, Y position and marker size in pixel if success, NIL otherwise
*/
int _GETarMarkerPixelPosition(mmachine m)
{
	#ifdef	_SCOL_DEBUG_
	MMechostr(MSKDEBUG, "_GETarMarkerPixelPosition\n");
	#endif

	int markerTab = MMget(m, 0);
	if(markerTab == NIL)
	{
    MMset(m, 0, NIL);
    return 0;
	}

	ArMarker* arMarker = (ArMarker*)MMfetch(m, MTOP(markerTab), 0);
	if(arMarker == 0)
	{
    MMset(m, 0, NIL);
    return 0;
	}

	Vector3 markerPosition = arMarker->GetPixelPosition();

	int tuplePos = MMmalloc(m, 3, TYPETAB);
  if(tuplePos==NIL)
  {
    MMset(m, 0, NIL);
		return 0;
  }
  
  MMstore(m, tuplePos, 0, ITOM((int)markerPosition.x));
  MMstore(m, tuplePos, 1, ITOM((int)markerPosition.y));
  MMstore(m, tuplePos, 2, ITOM((int)markerPosition.z));
  MMset(m, 0, PTOM(tuplePos));

	#ifdef	_SCOL_DEBUG_
		MMechostr(MSKDEBUG, "ok\n");
	#endif
		return 0;
}

/*! @ingroup grpbitmap
* \brief _GETarMarkerOrientation : This function return a marker orientation
* <b>Prototype:</b> fun [ObjArMarker] [F F F F]
* \param ObjArMarker : Marker which takes orientation 
*
* \return [F F F F] : Orientation Quaternion
*/
int _GETarMarkerOrientation(mmachine m)
{
	#ifdef	_SCOL_DEBUG_
	MMechostr(MSKDEBUG, "_GETarMarkerOrientation\n");
	#endif

	int markerTab = MMget(m, 0);
	if(markerTab == NIL)
	{
    MMset(m, 0, NIL);
    return 0;
	}

	ArMarker* arMarker = (ArMarker*)MMfetch(m, MTOP(markerTab), 0);
	if(arMarker == 0)
	{
    MMset(m, 0, NIL);
    return 0;
	}

	Quaternion markerOrientation = arMarker->GetOrientation();

	int tupleQuat = MMmalloc(m, 4, TYPETAB);
  if(tupleQuat==NIL)				
  {
    MMset(m, 0, NIL);
		return 0;
  }

	MMstore(m, tupleQuat, 0, FTOM(markerOrientation.x));
	MMstore(m, tupleQuat, 1, FTOM(markerOrientation.y));
	MMstore(m, tupleQuat, 2, FTOM(markerOrientation.z));
	MMstore(m, tupleQuat, 3, FTOM(markerOrientation.w));
  MMset(m, 0, PTOM(tupleQuat));

	#ifdef	_SCOL_DEBUG_
		MMechostr(MSKDEBUG, "ok\n");
	#endif
		return 0;
}

/*! @ingroup grpbitmap
* \brief _ISarMarkerVisible : This function return a marker visibility
* <b>Prototype:</b> fun [ObjArMarker] I
* \param ObjArMarker : Marker visible or not 
*
* \return I : 1 if marker is visible, 0 or NIL otherwise
*/
int _ISarMarkerVisible(mmachine m)
{
	#ifdef	_SCOL_DEBUG_
	MMechostr(MSKDEBUG, "_ISarMarkerVisible\n");
	#endif

	int markerTab = MMget(m, 0);
	if(markerTab == NIL)
	{
    MMset(m, 0, NIL);
    return 0;
	}

	ArMarker* arMarker = (ArMarker*)MMfetch(m, MTOP(markerTab), 0);
	if(arMarker == 0)
	{
    MMset(m, 0, NIL);
    return 0;
	}

	int visible = (arMarker->IsVisible()) ? 1 : 0;

  MMset(m, 0, ITOM(visible));

	#ifdef	_SCOL_DEBUG_
		MMechostr(MSKDEBUG, "ok\n");
	#endif
		return 0;
}

/*! @ingroup grpbitmap
* \brief _GETarMarkerSize: This function return a marker bitmap
* <b>Prototype:</b> fun [ObjArMarker] F
* \param ObjArMarker : Marker
*
* \return F : Size of a marker in meter if success or NIL otherwise
*/
int _GETarMarkerSize (mmachine m)
{
	#ifdef	_SCOL_DEBUG_
	MMechostr(MSKDEBUG, "_GETarMarkerSize\n");
	#endif

	int markerTab = MMpull(m);
	if(markerTab == NIL)
	{
    MMset(m, 0, NIL);
    return 0;
	}
	
	ArMarker* arMarker = (ArMarker*)MMfetch(m, MTOP(markerTab), 0);
	if(arMarker == 0)
	{
    MMset(m, 0, NIL);
    return 0;
	}
	
  float size = arMarker->GetSize();

	MMpush(m, FTOM(size));

	#ifdef	_SCOL_DEBUG_
		MMechostr(MSKDEBUG, "ok\n");
	#endif
		return 0;
}

/*! @ingroup grpbitmap
* \brief _SETarMarkerSize: This function return a marker bitmap
* <b>Prototype:</b> fun [ObjArMarker F] I
* \param ObjArMarker : Marker
* \param F : Size of the marker in meter
*
* \return I : 0 if success or NIL otherwise
*/
int _SETarMarkerSize (mmachine m)
{
	#ifdef	_SCOL_DEBUG_
	MMechostr(MSKDEBUG, "_SETarMarkerSize\n");
	#endif

  int isize = MMpull(m);
	int markerTab = MMpull(m);
	if((markerTab == NIL) || (isize == NIL))
	{
    MMset(m, 0, NIL);
    return 0;
	}
	
	ArMarker* arMarker = (ArMarker*)MMfetch(m, MTOP(markerTab), 0);
	if(arMarker == 0)
	{
    MMset(m, 0, NIL);
    return 0;
	}
	
  float size = MTOF(isize);

  arMarker->SetSize(size);

	MMpush(m, ITOM(0));

	#ifdef	_SCOL_DEBUG_
		MMechostr(MSKDEBUG, "ok\n");
	#endif
		return 0;
}

/*
*********************************************
* SCOL PART
*********************************************
*/

/*Declaration*/
//! Nb of Scol functions or types
#define NbAtkPKG 15

/*!
*	Scol function names
*/
char *AtkName[NbAtkPKG] =
{
	"ObjArMarker",
	"ObjArCameraParam",
	"_CRarMarker",
	"_DSarMarker",
	"_UPDATEarMarkers",
	"_GETarMarkerBitmap",
	"_GETarMarkerPosition",
  "_GETarMarkerPixelPosition",
	"_GETarMarkerOrientation",
	"_ISarMarkerVisible",
	"_CRarCameraParam",
	"_DSarCameraParam",
	"_GETarProjectionMatrix",
  "_GETarMarkerSize",
  "_SETarMarkerSize"
};

/*!
*	Pointers to C functions that manipulate the VM for each scol function previously defined
*/
int (*AtkFunc[NbAtkPKG])(mmachine m)=
{
	NULL,
	NULL,
	_CRarMarker,
	_DSarMarker,
	_UPDATEarMarkers,
	_GETarMarkerBitmap,
	_GETarMarkerPosition,
  _GETarMarkerPixelPosition,
	_GETarMarkerOrientation,
	_ISarMarkerVisible,
	_CRarCameraParam,
	_DSarCameraParam,
	_GETarProjectionMatrix,
  _GETarMarkerSize,
  _SETarMarkerSize
};

/*!
*	Nb of arguments of each scol function
*/
int AtkNArg[NbAtkPKG]=
{
	TYPTYPE,
  TYPTYPE,
	3,														// _CRarMarker
	1,														// _DSarMarker
	4,														// _UPDATEarMarkers
	3,                            // _GETarMarkerBitmap
	1,														// _GETarMarkerPosition
  1,                            // _GETarMarkerPixelPosition
	1,														// _GETarMarkerOrientation
	1,														// _ISarMarkerVisible
	6,														// _CRarCameraParam
	1,  													// _DSarCameraParam
	3,														// _GETarProjectionMatrix
  1,                            // _GETarMarkerSize
  2                             // _SETarMarkerSize
};

/*!
*	Prototypes of the scol functions
*/
char* AtkType[NbAtkPKG]=
{
	NULL,
  NULL,
	"fun [Chn I F] ObjArMarker",																										// _CRarMarker
	"fun [ObjArMarker] I",																													// _DSarMarker
	"fun [ObjBitmap ObjArCameraParam I I] ObjBitmap",  															// _UPDATEarMarkers
	"fun [Chn ObjArMarker I] ObjBitmap",																						// _GETarMarkerBitmap
	"fun [ObjArMarker] [F F F]",																										// _GETarMarkerPosition
  "fun [ObjArMarker] [I I I]",                                                    // _GETarMarkerPixelPosition
	"fun [ObjArMarker] [F F F F]",																									// _GETarMarkerOrientation
	"fun [ObjArMarker] I",																													// _ISarMarkerVisible
	"fun [Chn I I F F P] ObjArCameraParam",			  																	// _CRarCameraParam
  "fun [ObjArCameraParam] I",  													                          // _DSarCameraParam
	"fun [ObjArCameraParam I I] [[F F F F] [F F F F] [F F F F] [F F F F]]", 				// _GETarProjectionMatrix
  "fun [ObjArMarker] F",                                                          // _GETarMarkerSize,
  "fun [ObjArMarker F] I"                                                         // _SETarMarkerSize
};



// Everything inside _cond and _endcond is ignored by doxygen
//! \cond

/*!
* \brief Load the packages in Scol virtual machine
* \param mmachine : the scol machine
*/
int LoadArToolkit(mmachine m)
{
	int k;
  MMechostr(MSKDEBUG," > Loading ArToolkit\n");

	// initialize marker detector singleton
	ArManager::GetInstance();
	OBJMARKERSCOL = OBJregister(NBMARKERCB, 0, destroyMarkerObj, "OBJMARKERSCOL");
	OBJCAMERAPARAMSCOL = OBJregister(NBARCAMERAPARAM, 0, destroyArCameraParamObj, "OBJARCAMERAPARAMSCOL");

	k = PKhardpak(m, "BitmapToolkitEngine", NbAtkPKG, AtkName, AtkFunc, AtkNArg, AtkType);
	MMechostr(MSKDEBUG," > Successfully Loaded\n");
	return k;
}

/*!
* \brief Load the packages in Scol virtual machine
* \param mmachine : the scol machine
*/
int UnloadArToolkit()
{
	MMechostr(MSKDEBUG,"\n");
  MMechostr(MSKDEBUG," > Unloading ArToolkit\n");
	
	// kill marker detector singleton
	ArManager::GetInstance()->Kill();
	MMechostr(MSKDEBUG," > Successfully Unloaded\n\n");
	return 0;
}

//! \endcond