/* -----------------------------------------------------------------------------
	GSFramework
	Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */


		#include "binding_helpers.h"
		#include "scene3d/scene.h"
		#include "scene3d/instance.h"
		#include "scene3d/mlight.h"
		#include "scene3d/mobject.h"
		#include "scene3d/mcamera.h"
		#include "scene3d/mtrigger.h"
		#include "scene3d/mconstraint.h"
		#include "scene3d/group.h"
		#include "physic/physic_world.h"
		#include "core/renderer.h"
		#include "core/resource_factories.h"
		#include "script/scripted_object.h"
		#include "script/script_unit.h"
		#include "metafile/nml_object.h"
		#include "tools/scene_merge_object_list.h"
		#include "core/cached_graphic_resource_factory.h"

		using namespace GS;
		using namespace GS::S3D;
		using namespace GS::Script;


//------------------------------------------------------------------------------
SQInteger			GetSceneOrInstance(HSQUIRRELVM vm, int idx, Scene **scene, Instance **instance)
{
	*scene = NULL;
	*instance = NULL;

	CObjectType type;
	if	(!CObject::GetType(vm, idx, type))
		return sq_throwerror(vm, "Invalid object, expected scene or instance.");

	switch (type)
	{
		case typetag_Scene3d:
			CObject::Get(vm, idx, (void **)scene, typetag_Scene3d);
			break;

		case typetag_Item:
		{
			MItem *item;
			CObject::Get(vm, idx, (void **)&item, typetag_Item);

			if	(item->GetItemType() != Type_Instance)
				return sq_throwerror(vm, "Expected scene or instance.");

			*instance = (Instance *)item;
		}
		break;

		default:
			return sq_throwerror(vm, "Expected scene or instance.");
	}
	if	(!*scene && !*instance)
		return sq_throwerror(vm, "Scene/instance object is null.");

	return 0;
}
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
#define	__SQ_GETSCENEORINSTANCE(__S, __I) \
	Scene *__S; \
	Instance *__I; \
	if	(GetSceneOrInstance(vm, __SQ_STACKPOS, &__S, &__I) == -1) \
		return -1; \
	__SQ_GETUPDATESTACK
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
SQInteger			SceneGetGroupList(HSQUIRRELVM vm)
{
	__SQ_GETSINGLESAFEPTR(scene, Scene, typetag_Scene3d)
	sq_newarray(vm, 0);
	ListForeachPtr(Group *, g, scene->GetGroupList())
	{
		CObject::Push(vm, (void *)g, typetag_Group);
		sq_arrayappend(vm, -2);
	}
	return 1;
}
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
SQInteger			SceneGroupActivate(HSQUIRRELVM vm)
{
	__SQ_GETSTART(3)
	__SQ_GETSAFEPTR(s, Scene, typetag_Scene3d)
	__SQ_GETSAFEPTR(g, Group, typetag_Group)
	__SQ_GETBOOL(v)
	__SQ_GETEND
	s->GroupMembersSetActive(g, asbool(v));
	__SQ_RETURN
}
SQInteger			SceneSetupItem(HSQUIRRELVM vm)
{
	__SQ_GETSTART(2)
	__SQ_GETSAFEPTR(s, Scene, typetag_Scene3d)
	__SQ_GETSAFEPTR(i, MItem, typetag_Item)
	__SQ_GETEND
	i->Setup(s->physic_world);
	__SQ_RETURN
}
SQInteger			SceneForceUpdateMassShapePhysicItem(HSQUIRRELVM vm)
{
	__SQ_GETSTART(2)
		__SQ_GETSAFEPTR(s, Scene, typetag_Scene3d)
		__SQ_GETSAFEPTR(i, MItem, typetag_Item)
		__SQ_GETEND
		i->ForceUpdateMassShapePhysic(s->physic_world);
	__SQ_RETURN
}
SQInteger			SceneRenderSetup(HSQUIRRELVM vm)
{
	__SQ_GETSTART(2)
	__SQ_GETSAFEPTR(s, Scene, typetag_Scene3d)
	__SQ_GETSAFEPTR(f, Core::ResourceFactories, typetag_ResourceFactories)
	__SQ_GETEND
	s->RenderSetup(f, false);
	__SQ_RETURN
}
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
SQInteger			SceneResetClock(HSQUIRRELVM vm)
{
	__SQ_GETSINGLESAFEPTR(s, Scene, typetag_Scene3d)
	s->GetClock()->Reset();
	__SQ_RETURN
}
SQInteger			SceneSetFixedDeltaFrame(HSQUIRRELVM vm)
{
	__SQ_GETSTART(2)
	__SQ_GETSAFEPTR(s, Scene, typetag_Scene3d)
	__SQ_GETFLOAT(scale)
	__SQ_GETEND
	s->GetClock()->SetFixedDeltaFramef(scale);
	__SQ_RETURN
}
SQInteger			SceneSetClockScale(HSQUIRRELVM vm)
{
	__SQ_GETSTART(2)
	__SQ_GETSAFEPTR(s, Scene, typetag_Scene3d)
	__SQ_GETFLOAT(scale)
	__SQ_GETEND
	s->GetClock()->SetScalef(scale);
	__SQ_RETURN
}
SQInteger			SceneGetClockScale(HSQUIRRELVM vm)
{
	__SQ_GETSINGLESAFEPTR(s, Scene, typetag_Scene3d)
	__SQ_RETURNFLOAT(s->GetClock()->GetScalef())
}
SQInteger			SceneGetClock(HSQUIRRELVM vm)
{
	__SQ_GETSINGLESAFEPTR(s, Scene, typetag_Scene3d)
	__SQ_RETURNFLOAT(s->GetClock()->Getf())
}
//------------------------------------------------------------------------------

/*
static	void		MergePhysicShape(MItem *to, MItem *from)
{
	if	(!from->physic_item)
		return;

	ListForeachPtr(nPhysicShape *, shape, from->physic_item->GetShapeList())
	{
		nPhysicShape *new_shape = to->physic_item->AddShape();
		new_shape->SetMatrix(from->GetBaseItem()->GetMatrix() * shape->GetMatrix());

		switch (shape->GetType())
		{
			case nPhysicShape::TypeBox:
			case nPhysicShape::TypeCapsule:
			case nPhysicShape::TypeCone:
			case nPhysicShape::TypeSphere:
				new_shape->Set(shape->GetType(), shape->dimensions);
				break;

			case nPhysicShape::TypeConvex:
			case nPhysicShape::TypeMesh:
				new_shape->Set(shape->GetType(), shape->path);
				break;
		}
	}

	to->physic_item->SetPhysicMode(from->physic_item->GetPhysicMode());
}
*/
SQInteger			SceneSetMotion(HSQUIRRELVM vm)
{
	__SQ_GETSTART(3)
	__SQ_GETSCENEORINSTANCE(scene, instance)
	__SQ_GETSTRING(name)
	__SQ_GETFLOAT(blend)
	Automation::SourceGroup *group = NULL;
	if	(scene)
			scene->SetMotion(name, &group, blend);
	else	instance->instance_group->SetMotion(name, &group, blend);
	__SQ_GETEND
	__SQ_RETURNMANAGEDSAFEPTR(group, typetag_AutomationSourceGroup)
}

SQInteger			SceneSetMotionAdd(HSQUIRRELVM vm)
{
	__SQ_GETSTART(3)
	__SQ_GETSCENEORINSTANCE(scene, instance)
	__SQ_GETSTRING(name)
	__SQ_GETFLOAT(blend)
	Automation::SourceGroup *group = NULL;
	if	(scene)
			scene->SetMotion(name, &group, blend, Automation::Player::SourceAdd);
	else	instance->instance_group->SetMotion(name, &group, blend, Automation::Player::SourceAdd);
	__SQ_GETEND
	__SQ_RETURNMANAGEDSAFEPTR(group, typetag_AutomationSourceGroup)
}

SQInteger			SceneGetFileName(HSQUIRRELVM vm)
{
	__SQ_GETSINGLESAFEPTR(scene, Scene, typetag_Scene3d)
	__SQ_RETURNSTRING(scene->name.CutFilePath().toUtf8())
}
SQInteger			SceneGetFilePath(HSQUIRRELVM vm)
{
	__SQ_GETSINGLESAFEPTR(scene, Scene, typetag_Scene3d)
	__SQ_RETURNSTRING(scene->name.CutFileName().toUtf8())
}

SQInteger			SceneSetGlobal(HSQUIRRELVM vm)
{
	__SQ_GETSINGLESAFEPTR(scene, Scene, typetag_Scene3d)
	scene->SetAsScriptGlobalScene(scene->GetVM());
	__SQ_RETURN
}

SQInteger			SceneGetAmbientIntensity(HSQUIRRELVM vm)
{
	__SQ_GETSINGLESAFEPTR(scene, Scene, typetag_Scene3d)
	__SQ_RETURNFLOAT(scene->ambient_intensity)
}

SQInteger			SceneSetAmbientIntensity(HSQUIRRELVM vm)
{
	__SQ_GETSTART(2)
	__SQ_GETSAFEPTR(scene, Scene, typetag_Scene3d)
	__SQ_GETFLOAT(i)
	__SQ_GETEND
	scene->ambient_intensity = i;
	__SQ_RETURN
}

SQInteger			SceneGetAmbientColor(HSQUIRRELVM vm)
{
	__SQ_GETSINGLESAFEPTR(scene, Scene, typetag_Scene3d)
	__SQ_RETURNVECTOR(scene->ambient_color)
}

SQInteger			SceneSetAmbientColor(HSQUIRRELVM vm)
{
	__SQ_GETSTART(2)
	__SQ_GETSAFEPTR(scene, Scene, typetag_Scene3d)
	__SQ_GETVECTORTO(scene->ambient_color, scene)
	__SQ_GETEND
	__SQ_RETURN
}

SQInteger			SceneGetBackgroundColor(HSQUIRRELVM vm)
{
	__SQ_GETSINGLESAFEPTR(scene, Scene, typetag_Scene3d)
	__SQ_RETURNVECTOR(scene->background_color)
}

SQInteger			SceneSetBackgroundColor(HSQUIRRELVM vm)
{
	__SQ_GETSTART(2)
	__SQ_GETSAFEPTR(scene, Scene, typetag_Scene3d)
	__SQ_GETVECTORTO(scene->background_color, scene)
	__SQ_GETEND
	__SQ_RETURN
}

SQInteger			SceneEnd(HSQUIRRELVM vm)
{
	__SQ_GETSINGLESAFEPTR(scene, Scene, typetag_Scene3d)
	scene->flags.Set(Scene::FlagEnd);
	__SQ_RETURN
}

SQInteger			SceneRaytraceTriggerList(HSQUIRRELVM vm)
{
	Scene *scene;
	if	(!CObject::Get(vm, -4, (void **)&scene, typetag_Scene3d))
		return -1;

	Vector4 s, d;
	GetVector(vm, -3, s);
	GetVector(vm, -2, d);

	float l;
	sq_getfloat(vm, -1, &l);
	sq_pop(vm, 4);

	MItem *hit = NULL;
	if	(scene)
		hit = (MItem *)scene->RaytraceTriggerList(s, d, l);
	CObject::Push(vm, (void *)hit, typetag_Item);
	return 1;
}

SQInteger			ScenePhysicAllocateCollisionNode(HSQUIRRELVM vm)
{	__ERR__(__LOG__ << "ScenePhysicAllocateCollisionNode is obsolete.\n", 0)}

SQInteger			ScenePhysicEnableDeactivation(HSQUIRRELVM vm)
{
	return 0;
}

SQInteger			SceneSetItemStatic(HSQUIRRELVM vm)
{
	__SQ_GETSTART(3)
	__SQ_GETSAFEPTR(scene, Scene, typetag_Scene3d)
	__SQ_GETSAFEPTR(item, MItem, typetag_Item)
	__SQ_GETBOOL(v)
	__SQ_GETEND
	scene->SetItemStatic(item, asbool(v));
	__SQ_RETURN
}

//------------------------------------------------------------------------------
#define	__SQ_GETSCENESCRIPTOBJECT(__SRC) GS::Script::ScriptedObject *scripted_object = __SRC->scripted_object; if (!scripted_object) return sq_throwerror(vm, "No script system in scene!");

SQInteger			SceneGetScriptInstance(HSQUIRRELVM vm)
{
	__SQ_GETSINGLESAFEPTR(scene, Scene, typetag_Scene3d)
	__SQ_GETSCENESCRIPTOBJECT(scene)
	if	(!scripted_object->GetUnitList().GetCount())
		return sq_throwerror(vm, "No script unit");
	Script::SquirrelObject *o = (Script::SquirrelObject *)scripted_object->GetUnitList()[0]->Self();
	__SQ_RETURNOBJECT(o->object);
}
SQInteger			SceneGetScriptInstanceFromClass(HSQUIRRELVM vm)
{
	__SQ_GETSTART(2)
	__SQ_GETSAFEPTR(scene, Scene, typetag_Scene3d)
	__SQ_GETSTRING(_class)
	__SQ_GETSCENESCRIPTOBJECT(scene)

	Script::Unit *_unit = 0;
	ListForeachPtr(Script::Unit *, unit, scripted_object->GetUnitList())
		if	(unit->script_class == _class)
		{
			_unit = unit;
			break;
		}

	__SQ_GETEND

	if	(_unit)
	{
		if	(!_unit->IsOpen())
			return sq_throwerror(vm, "Script unit is not open");

		__SQ_RETURNOBJECT(((Script::SquirrelObject *)_unit->Self())->object);
	}
	return sq_throwerror(vm, "Script unit not found");
}
SQInteger			SceneSetScript(HSQUIRRELVM vm)
{
	__SQ_GETSTART(3)
	__SQ_GETSAFEPTR(scene, Scene, typetag_Scene3d)
	__SQ_GETSTRING(script_file)
	__SQ_GETSTRING(script_class)
	__SQ_GETSCENESCRIPTOBJECT(scene)
	if	(Script::Unit *unit = scripted_object->GetUnitList().GetCount() ? scripted_object->GetUnitList()[0] : scripted_object->AddUnit(scripted_object->NewUnit()))
	{
		unit->script_file = script_file;
		unit->script_class = script_class;
	}
	__SQ_GETEND
	__SQ_RETURN
}
SQInteger			SceneRemoveAllScripts(HSQUIRRELVM vm)
{
	__SQ_GETSTART(1)
	__SQ_GETSAFEPTR(scene, Scene, typetag_Scene3d)
	__SQ_GETSCENESCRIPTOBJECT(scene)

	scripted_object->RemoveAllUnit();

	__SQ_GETEND
	__SQ_RETURN
}
//------------------------------------------------------------------------------

SQInteger			ScenePreloadResources(HSQUIRRELVM vm)
{
	__SQ_GETSTART(2)
	__SQ_GETSAFEPTR(f, Core::ResourceFactories, typetag_ResourceFactories)
	__SQ_GETSTRING(path)
	bool r = Scene::PreloadResources(*f->render, path);
	__SQ_GETEND
	__SQ_RETURNBOOL(r)
}

//-----------------------------------------------------------------------------
SQInteger			SceneFromNML(HSQUIRRELVM vm)
{
	__SQ_GETSTART(2)
	__SQ_GETSAFEPTR(scene, Scene, typetag_Scene3d)
	__SQ_GETSTRING(path)
	Group *group = NULL;
	if	(!scene->FromMetaFileStoreGroup(path, &group))
		return sq_throwerror(vm, "Failed to load scene.");
	scene->InstanceSetup();
	__SQ_GETEND
	__SQ_RETURNSAFEPTR(group, typetag_Group)
}
SQInteger			SceneFromNMLStoreGroup(HSQUIRRELVM vm)
{
	__SQ_GETSTART(3)
	__SQ_GETSAFEPTR(scene, Scene, typetag_Scene3d)
	__SQ_GETSTRING(path)
	__SQ_GETINT(flag)
	Group *group = NULL;
	if	(!scene->FromMetaFileStoreGroup(path, &group, flag))
		return sq_throwerror(vm, "Failed to load scene.");
	scene->InstanceSetup();
	__SQ_GETEND
	__SQ_RETURNSAFEPTR(group, typetag_Group)
}
//-----------------------------------------------------------------------------

SQInteger			SceneDeleteGroup(HSQUIRRELVM vm)
{
	__SQ_GETSTART(2)
	__SQ_GETSAFEPTR(scene, Scene, typetag_Scene3d)
	__SQ_GETSAFEPTR(group, Group, typetag_Group)
	__SQ_GETEND
	scene->DeleteGroupAndMembers(group);
	__SQ_RETURN
}

SQInteger			SceneReset(HSQUIRRELVM vm)
{
	__SQ_GETSINGLESAFEPTR(scene, Scene, typetag_Scene3d)
	scene->Reset();
	__SQ_RETURN
}

SQInteger			SceneSetPhysicContactSolverIteration(HSQUIRRELVM vm)
{	return 0;	}

SQInteger			SceneSetPhysicConstraintSolverIteration(HSQUIRRELVM vm)
{	return 0;	}

SQInteger			SceneRecordLocation(HSQUIRRELVM vm)
{
	__SQ_GETSINGLESAFEPTR(scene, Scene, typetag_Scene3d)
	scene->RecordAllItemLocation();
	__SQ_RETURN
}

SQInteger			SceneGetPhysicFrequency(HSQUIRRELVM vm)
{
	__SQ_GETSINGLESAFEPTR(scene, Scene, typetag_Scene3d)
	__SQ_RETURNFLOAT(scene->physic_world ? 1.f / scene->physic_world->GetTimestep() : 0.f)
}

SQInteger			SceneSetPhysicFrequency(HSQUIRRELVM vm)
{
	__SQ_GETSTART(2)
	__SQ_GETSAFEPTR(scene, Scene, typetag_Scene3d)
	__SQ_GETFLOAT(timestep)
	__SQ_GETEND
	if	(scene->physic_world)
		scene->physic_world->SetTimestep(1.f / timestep);
	__SQ_RETURN
}

SQInteger			SceneSetGravity(HSQUIRRELVM vm)
{
	__SQ_GETSTART(2)
	__SQ_GETSAFEPTR(scene, Scene, typetag_Scene3d)
	__SQ_GETVECTOR(g)
	__SQ_GETEND
	if	(scene->physic_world)
		scene->physic_world->SetGravity(g);
	__SQ_RETURN
}

SQInteger			SceneSave(HSQUIRRELVM vm)
{
	__SQ_GETSTART(2)
	__SQ_GETSAFEPTR(scene, Scene, typetag_Scene3d)
	__SQ_GETSTRING(path)
	bool r = NML::SaveToFile(*scene, path);
	__SQ_GETEND
	__SQ_RETURNBOOL(r)
}
//------------------------------------------------------------------------------

SQInteger			SceneFindConstraint(HSQUIRRELVM vm)
{
	__SQ_GETSTART(2)
	__SQ_GETSCENEORINSTANCE(scene, instance)
	__SQ_GETSTRING(name)
	__SQ_GETEND
	MConstraint *c = scene->FindItemByType <MConstraint> (name);
	if	(!c)
		return sq_throwerror(vm, String::Format("Constraint '%s' not found.", name));
	__SQ_RETURNSAFEPTR(c, typetag_Constraint)
}
SQInteger			SceneFindGroup(HSQUIRRELVM vm)
{
	__SQ_GETSTART(2)
	__SQ_GETSCENEORINSTANCE(scene, instance)
	__SQ_GETSTRING(name)
	Group *group = scene ? scene->FindGroup(name) : instance->instance_group->GetGroup(name);
	if	(!group)
		return sq_throwerror(vm, String::Format("Group '%s' not found.", name));
	__SQ_GETEND
	__SQ_RETURNSAFEPTR(group, typetag_Group)
}
SQInteger			SceneFindItem(HSQUIRRELVM vm)
{
	__SQ_GETSTART(2)
	__SQ_GETSCENEORINSTANCE(scene, instance)
	__SQ_GETSTRING(name)
	MItem	*item = scene ? scene->Item(name) : instance->instance_group->Item(name);
	if	(!item)
		return sq_throwerror(vm, String::Format("Item '%s' not found.", name));
	__SQ_GETEND
	__SQ_RETURNSAFEPTR(item, typetag_Item)
}
SQInteger			SceneFindItemChild(HSQUIRRELVM vm)
{
	__SQ_GETSTART(3)
	__SQ_GETSCENEORINSTANCE(scene, instance)
	__SQ_GETSAFEPTR(item, MItem, typetag_Item)
	__SQ_GETSTRING(name)
	MItem	*child = scene ? scene->Item(name, item) : NULL;
	if	(!child)
		return sq_throwerror(vm, String::Format("Child item '%s' not found", name));
	__SQ_GETEND
	__SQ_RETURNSAFEPTR(child, typetag_Item)
}
//------------------------------------------------------------------------------

SQInteger			SceneDeleteContent(HSQUIRRELVM vm)
{
	__SQ_GETSINGLESAFEPTR(scene, Scene, typetag_Scene3d)
	scene->Clear(true);
	__SQ_RETURN
}

SQInteger			SceneFlushDeletionQueue(HSQUIRRELVM vm)
{
	__SQ_GETSINGLESAFEPTR(scene, Scene, typetag_Scene3d)
	scene->ProcessItemRemovalQueue();
	__SQ_RETURN
}

SQInteger			SceneSetRenderless(HSQUIRRELVM vm)
{
	__SQ_GETSTART(2)
	__SQ_GETSAFEPTR(scene, Scene, typetag_Scene3d)
	__SQ_GETBOOL(v)
	__SQ_GETEND
	scene->flags.Raise(Scene::FlagRenderless, asbool(v));
	__SQ_RETURN
}
SQInteger			ScenePushRenderable(HSQUIRRELVM vm)
{
	__SQ_GETSTART(2)
	__SQ_GETSAFEPTR(scene, Scene, typetag_Scene3d)
	__SQ_GETSAFEPTR(renderer, Renderer, typetag_Renderer)
	__SQ_GETEND
	scene->PushRenderable(*renderer);
	__SQ_RETURN
}
SQInteger			SceneRenderUI(HSQUIRRELVM vm)
{
	__SQ_GETSTART(2)
	__SQ_GETSAFEPTR(scene, Scene, typetag_Scene3d)
	__SQ_GETSAFEPTR(renderer, Renderer, typetag_Renderer)
	__SQ_GETEND
	scene->RenderUI(*renderer);
	__SQ_RETURN
}

SQInteger			SceneUpdate(HSQUIRRELVM vm)
{
	__SQ_GETSINGLESAFEPTR(scene, Scene, typetag_Scene3d)
	scene->Update();
	__SQ_RETURN
}

SQInteger			SceneRegisterAsPropertyCallback(HSQUIRRELVM vm)
{
	__SQ_GETSTART(2)
	__SQ_GETSAFEPTR(scene, Scene, typetag_Scene3d)
	__SQ_GETSAFEPTR(renderer, Renderer, typetag_Renderer)
	__SQ_GETEND
	renderer->SetEnvironmentInterface(scene->irenderer_environment);
	__SQ_RETURN
}

SQInteger			ScenePrintItemList(HSQUIRRELVM vm)
{
	__SQ_GETSINGLESAFEPTR(scene, Scene, typetag_Scene3d)
	scene->DumpContentToLog();
	__SQ_RETURN
}

SQInteger			SceneAddObject(HSQUIRRELVM vm)
{
	__SQ_GETSTART(2)
	__SQ_GETSAFEPTR(scene, Scene, typetag_Scene3d)
	__SQ_GETSTRING(name)
	MObject *o = new MObject;
	if	(!o)
		return sq_throwerror(vm, String::Format("Failed to allocate object '%s'.", name));
	o->name = name;
	scene->AddItem(o, true);
	o->Setup(scene->physic_world);
  	o->Reset();
	__SQ_GETEND
	__SQ_RETURNSAFEPTR(o, typetag_Object);
}

SQInteger			SceneDeleteObject(HSQUIRRELVM vm)
{
	__SQ_GETSTART(2)
	__SQ_GETSAFEPTR(scene, Scene, typetag_Scene3d)
	__SQ_GETSAFEPTR(object, MObject, typetag_Object)
	__SQ_GETEND
	scene->QueueItemRemoval(object);
	__SQ_RETURN
}

SQInteger			SceneAddTrigger(HSQUIRRELVM vm)
{
	__SQ_GETSTART(2)
	__SQ_GETSAFEPTR(scene, Scene, typetag_Scene3d)
	__SQ_GETSTRING(name)
	MTrigger *t = new MTrigger;
	if	(!t)
		return sq_throwerror(vm, String::Format("Failed to allocate trigger '%s'.", name));
	t->name = name;
	scene->AddItem(t, true);
	t->Setup(scene->physic_world);
  	t->Reset();
	__SQ_GETEND
	__SQ_RETURNSAFEPTR(t, typetag_Trigger);
}

SQInteger			SceneDeleteTrigger(HSQUIRRELVM vm)
{
	__SQ_GETSTART(2)
	__SQ_GETSAFEPTR(scene, Scene, typetag_Scene3d)
	__SQ_GETSAFEPTR(trigger, MTrigger, typetag_Trigger)
	__SQ_GETEND
	scene->QueueItemRemoval(trigger);
	__SQ_RETURN
}

SQInteger			SceneAddCamera(HSQUIRRELVM vm)
{
	__SQ_GETSTART(2)
	__SQ_GETSAFEPTR(scene, Scene, typetag_Scene3d)
	__SQ_GETSTRING(name)
	MCamera *c = new MCamera;
	if	(!c)
		return sq_throwerror(vm, String::Format("Failed to allocate camera '%s'.", name));
	c->name = name;
	scene->AddItem(c, true);
	c->Setup(scene->physic_world);
  	c->Reset();
	__SQ_GETEND
	__SQ_RETURNSAFEPTR(c, typetag_Camera);
}

SQInteger			SceneGetCurrentCamera(HSQUIRRELVM vm)
{
	__SQ_GETSINGLESAFEPTR(scene, Scene, typetag_Scene3d)
	__SQ_RETURNSAFEPTR((MCamera *)scene->current_camera, typetag_Camera)
}
SQInteger			SceneSetCurrentCamera(HSQUIRRELVM vm)
{
	__SQ_GETSTART(2)
	__SQ_GETSAFEPTR(scene, Scene, typetag_Scene3d)
	__SQ_GETSAFEPTR(camera, MCamera, typetag_Camera)
	__SQ_GETEND
	scene->current_camera = camera;
	__SQ_RETURN
}

SQInteger			SceneAddLight(HSQUIRRELVM vm)
{
	__SQ_GETSTART(2)
	__SQ_GETSAFEPTR(scene, Scene, typetag_Scene3d)
	__SQ_GETSTRING(name)
	MLight *l = new MLight;
	if	(!l)
		return sq_throwerror(vm, String::Format("Failed to create light '%s'.", name));
	l->name = name;
	scene->AddItem(l, true);
	l->Setup(scene->physic_world);
  	l->Reset();
	__SQ_GETEND
	__SQ_RETURNSAFEPTR(l, typetag_Light);
}

SQInteger			SceneDuplicateItem(HSQUIRRELVM vm)
{
	__SQ_GETSTART(2)
	__SQ_GETSAFEPTR(scene, Scene, typetag_Scene3d)
	__SQ_GETSAFEPTR(item, MItem, typetag_Item)
	__SQ_GETEND
	__SQ_RETURNSAFEPTR(scene && item ? scene->DuplicateItem(item) : NULL, typetag_Item)
}

SQInteger			SceneMergeItems(HSQUIRRELVM vm)
{	
	__SQ_GETSTART(5)
	__SQ_GETSAFEPTR(scene, Scene, typetag_Scene3d)
	__SQ_GETSTRING(name)
	__SQ_GETSAFEPTR(f, Core::ResourceFactories, typetag_ResourceFactories)
	__SQ_GETINT(nb_item)

	if	(nb_item > 0)
	{			
		SharedList <MItem *> merge_list;

		// get the list of item
		sq_pushnull(vm);//null iterator
 		for(int i=0; i<nb_item; ++i)
		{
			sq_next(vm, __SQ_STACKPOS-1 );
			MItem *itemA; if (!GS::Script::CObject::Get(vm, __sq_stackpos, (void **)&itemA, typetag_Item)) return -1; if (!itemA) return sq_throwerror(vm, "Object is null");

			merge_list.Add(itemA);
			sq_pop(vm,2);
		}
		sq_pop(vm,1); //pops the null iterator

		__SQ_GETEND

		sMItem out_i;

		if(scene)
		{
			SceneMergeObjectList merge_tool;
			Core::sGeometry out_g;
			
			merge_tool.Merge(scene, merge_list, *f->graphic, out_i, out_g);
			
			if(out_g.IsValid())
			{
				// Save merged geometry to disk.
				String merged_name(scene->name.CutFileName()+name+String(".nmg"));
				NML::SaveToFile(*out_g, merged_name);

				// Set geometry and setup merged object.
				if	(MObject *object = (MObject *)out_i.c_ptr())
				{
					object->geometry = merged_name;
					object->name = name;
					object->RenderSetup(f);
					__SQ_RETURNSAFEPTR(out_i.c_ptr(), typetag_Item)
				}
			}
		}
	}
	__SQ_RETURNSAFEPTR(NULL, typetag_Item)
}

SQInteger			SceneGetItemList(HSQUIRRELVM vm)
{
	__SQ_GETSTART(1)
	__SQ_GETSCENEORINSTANCE(scene, instance)
	__SQ_GETEND

	const SharedList <MItem *> *list = NULL;
	if	(scene)
		list = &scene->GetItemList();
	else
		list = &instance->instance_group->GetItemList();

	sq_newarray(vm, 0);
	ListForeachPtr(MItem *, i, *list)
	{
		// Skip items with no base item (e.g. const raints): they are not
		// positionable, and exposing them as typetag_Item makes scripts crash
		// when calling ItemGetWorldPosition/GetMatrix (MConstraint::GetBaseItem
		// returns NULL -> null Item::GetMatrix() -> access violation -> paf memory error).
		if	(!i->GetBaseItem())
			continue;

		CObject::Push(vm, (void *)i, typetag_Item);
		sq_arrayappend(vm, -2);
	}
	return 1;
}

SQInteger			SceneGetItemChildrenList(HSQUIRRELVM vm)
{
	__SQ_GETSTART(2)
	__SQ_GETSAFEPTR(scene, Scene, typetag_Scene3d)
	__SQ_GETSAFEPTR(item, MItem, typetag_Item)
	__SQ_GETEND

	sq_newarray(vm, 0);
	if	(scene)
		ListForeachPtr(MItem *, i, scene->GetItemList())
			if	(i->GetBaseItem()->GetParent() == item->GetBaseItem())
			{
				CObject::Push(vm, (void *)i, typetag_Item);
				sq_arrayappend(vm, -2);
			}
	return 1;
}

SQInteger			SceneDeleteItem(HSQUIRRELVM vm)
{
	__SQ_GETSTART(2)
	__SQ_GETSAFEPTR(scene, Scene, typetag_Scene3d)
	__SQ_GETSAFEPTR(item, MItem, typetag_Item)
	__SQ_GETEND
	scene->QueueItemRemoval(item);
	__SQ_RETURN
}

SQInteger			SceneDeleteLight(HSQUIRRELVM vm)
{
	__SQ_GETSTART(2)
	__SQ_GETSAFEPTR(scene, Scene, typetag_Scene3d)
	__SQ_GETSTRING(name)
	scene->QueueItemRemoval(scene->FindItemByType <MLight> (name));
	__SQ_GETEND
	__SQ_RETURN
}

SQInteger			SceneDeleteAllLights(HSQUIRRELVM vm)
{
	__SQ_GETSINGLESAFEPTR(scene, Scene, typetag_Scene3d)
	ListForeachPtr(MItem *, i, scene->GetItemList())
		if	(i->GetItemType() == Type_Light)
			scene->QueueItemRemoval(i);
	__SQ_RETURN
}
SQInteger ItemSetActive(HSQUIRRELVM vm) {
	__SQ_GETSTART(2)
	__SQ_GETSAFEPTR(item, MItem, typetag_Item)
	__SQ_GETBOOL(active)
	__SQ_GETEND
	item->mitem_flags.Raise(MItem::Flag_IsActive, active);
	__SQ_RETURN
}
SQInteger			SceneCollisionRaytrace(HSQUIRRELVM vm)
{
	__SQ_GETSTART(6)
	__SQ_GETSAFEPTR(scene, Scene, typetag_Scene3d)
	__SQ_GETVECTOR(from)
	__SQ_GETVECTOR(direction)
	__SQ_GETINT(mask)
	__SQ_GETINT(shape_mask)
	__SQ_GETFLOAT(max_distance)
	__SQ_GETEND

	if	(!scene->physic_world)
		return sq_throwerror(vm, "No collision system in scene.");

	PhysicTrace result;
	bool hit = scene && scene->physic_world->Raytrace(from, direction, result, mask, shape_mask, max_distance);

	sq_newtable(vm);

	sq_pushstring(vm, "hit", 3);
	sq_pushbool(vm, hit);
	sq_newslot(vm, -3, false);

	if	(hit)
	{
		sq_pushstring(vm, "shape", 5);
		CObject::Push(vm, (void *)result.s, typetag_ColShape);
		sq_newslot(vm, -3, false);

		sq_pushstring(vm, "item", 4);
		CObject::Push(vm, (void *)((MItem *)result.i->GetUserPointer()), typetag_Item);
		sq_newslot(vm, -3, false);

		sq_pushstring(vm, "material", 8);
		sq_pushstring(vm, result.m, result.m.Len());
		sq_newslot(vm, -3, false);

		sq_pushstring(vm, "p", 1);
		PushVector(vm, result.p);
		sq_newslot(vm, -3, false);

		sq_pushstring(vm, "n", 1);
		PushVector(vm, result.n);
		sq_newslot(vm, -3, false);

		sq_pushstring(vm, "d", 1);
		sq_pushfloat(vm, Vector4::Dist(from, result.p));
		sq_newslot(vm, -3, false);
	}
	return 1;
}

SQInteger			SceneSetFog(HSQUIRRELVM vm)
{
	__SQ_GETSTART(5)
	__SQ_GETSAFEPTR(scene, Scene, typetag_Scene3d)
	__SQ_GETBOOL(enable)
	__SQ_GETCOLOR(color)
	__SQ_GETFLOAT(n)
	__SQ_GETFLOAT(f)
	__SQ_GETEND
	scene->fog_color = color;
	scene->fog_near = enable ? n : 0;
	scene->fog_far = enable ? f : 0;
	__SQ_RETURN
}

SQInteger			SceneGetTimeOfDay(HSQUIRRELVM vm)
{
	__SQ_GETSINGLESAFEPTR(scene, Scene, typetag_Scene3d)
	__SQ_RETURNFLOAT(scene->time_of_day)
}
SQInteger			SceneSetTimeOfDay(HSQUIRRELVM vm)
{
	__SQ_GETSTART(2)
	__SQ_GETSAFEPTR(scene, Scene, typetag_Scene3d)
	__SQ_GETFLOAT(t)
	__SQ_GETEND
	scene->time_of_day = t;
	__SQ_RETURN
}

SQInteger			SceneSetFlagDebugPhysic(HSQUIRRELVM vm)
{
	__SQ_GETSTART(2)
	__SQ_GETSAFEPTR(scene, Scene, typetag_Scene3d)
	__SQ_GETBOOL(enable)
	__SQ_GETEND
		scene->flags.Raise(GS::S3D::Scene::FlagDebugPhysics, enable);
	__SQ_RETURN
}

SQInteger			SceneSetSkyShader(HSQUIRRELVM vm)
{
	__SQ_GETSTART(2)
	__SQ_GETSAFEPTR(scene, Scene, typetag_Scene3d)
	__SQ_GETSTRING(s)
	__SQ_GETEND
	scene->skybox_shader = s;
	__SQ_RETURN
}
SQInteger			SceneSetSkyLayer(HSQUIRRELVM vm)
{
	__SQ_GETSTART(3)
	__SQ_GETSAFEPTR(scene, Scene, typetag_Scene3d)
	__SQ_GETSTRING(s)
	__SQ_GETINT(n)
	__SQ_GETEND
	if	((n < 0) || (n > 1))
		return sq_throwerror(vm, "Invalid sky layer index.");
	scene->skybox_layer[n] = s;
	__SQ_RETURN
}

SQInteger			SceneGetFogColor(HSQUIRRELVM vm)
{
	__SQ_GETSINGLESAFEPTR(scene, Scene, typetag_Scene3d)
	__SQ_RETURNCOLOR(scene->fog_color)
}

SQInteger			SceneGetFogNear(HSQUIRRELVM vm)
{
	__SQ_GETSINGLESAFEPTR(scene, Scene, typetag_Scene3d)
	__SQ_RETURNFLOAT(scene->fog_near)
}

SQInteger			SceneGetFogFar(HSQUIRRELVM vm)
{
	__SQ_GETSINGLESAFEPTR(scene, Scene, typetag_Scene3d)
	__SQ_RETURNFLOAT(scene->fog_far)
}

//------------------------------------------------------------------------------
SQInteger			SceneItemActivate(HSQUIRRELVM vm)
{
	__SQ_GETSTART(3)
	__SQ_GETSAFEPTR(scene, Scene, typetag_Scene3d)
	__SQ_GETSAFEPTR(item, MItem, typetag_Item)
	__SQ_GETBOOL(active)
	__SQ_GETEND	
	scene->QueueItemActivation(item, asbool(active));
	__SQ_RETURN
}
SQInteger			SceneItemActivateHierarchy(HSQUIRRELVM vm)
{
	__SQ_GETSTART(3)
	__SQ_GETSAFEPTR(scene, Scene, typetag_Scene3d)
	__SQ_GETSAFEPTR(item, MItem, typetag_Item)
	__SQ_GETBOOL(active)
	__SQ_GETEND	
	scene->QueueItemActivation(item, asbool(active), true);
	__SQ_RETURN
}
//------------------------------------------------------------------------------
SQInteger			SceneProcessItemActivationQueue(HSQUIRRELVM vm)
{
	__SQ_GETSTART(1)
	__SQ_GETSAFEPTR(scene, Scene, typetag_Scene3d)
	__SQ_GETEND	
	scene->ProcessItemActivationQueue();
	__SQ_RETURN
}
//------------------------------------------------------------------------------

//----------------------------------------------h,v
void		RegisterSceneBinding(HSQUIRRELVM vm)
//----------------------------------------------
{
/*#
	Topic: Scene
	Related: Camera,Object,Light,Trigger,Item
	Type: Scene
	Type: Record
#*/

/*#
	Section: SceneClock
	Desc: Clock
#*/
	/*#
		Func: SceneResetClock
		Proto: void:Scene
		Desc: Reset engine clock. This function can be used to prevent the engine from taking a large clock step after a long script operation has been run.
		Example:
function LoadLevelBlock(level_scene, block_path)
{
	// Import the level block scene into the level_scene.
	SceneLoad(level_scene, block_path)

	// The load operation is known to take some time,
	// so in order to prevent clock-dependent components
	// from going nuts, we reset the level scene clock.
	SceneResetClock(level_scene)
}
	#*/
	sq_register(vm, SceneResetClock, "SceneResetClock", _SC(".x"));
	/*#
		Func: SceneSetClockScale
		Proto: void:Scene,float
		Desc: Set engine clock scale. All clock dependent components in the engine are affected by this scale.
	#*/
	sq_register(vm, SceneSetClockScale, "SceneSetClockScale", _SC(".xn"));
	/*#
		Func: SceneGetClockScale
		Proto: float:Scene
		Desc: Get engine clock scale.
	#*/
	sq_register(vm, SceneGetClockScale, "SceneGetClockScale", _SC(".x"));
	/*#
		Func: SceneSetFixedDeltaFrame
		Proto: void:Scene,float
		Desc: Force a constant fixed delta frame value. Note: All clock dependent components will become frame rate dependent.
		Example: SceneSetFixedDeltaFrame(scene, 1.0 / 60.0) // Lock dt_clock to 60 frame per second (1/60th between 2 frames).
	#*/
	sq_register(vm, SceneSetFixedDeltaFrame, "SceneSetFixedDeltaFrame", _SC(".xn"));

/*#
	Section: SceneMotion
	Desc: Motion
#*/
	/*#
		Func: SceneSetMotion
		Proto: AnimationSourceGroup:Scene,string name,float blend
		Desc: Set motion on all scene items, specify the blend duration, stop all current animation sources.
	#*/
	sq_register(vm, SceneSetMotion, "SceneSetMotion", _SC(".xsn"));
	/*#
		Func: SceneSetMotionAdd
		Proto: AnimationSourceGroup:Scene,string name,float blend
		Desc: Set motion on all scene items, specify the blend duration, current sources are not stopped.
	#*/
	sq_register(vm, SceneSetMotionAdd, "SceneSetMotionAdd", _SC(".xsn"));

/*#
	Section: SceneIO
	Desc: I/O
#*/
	/*#
		Func: ScenePreloadResources
		Proto: bool:String path, RenderResourceFactory factory
		Desc: Load all scene resources and their dependencies.<br>
		As long as the render factory cache is not explicitly emptied, all subsequent load requests will return a cached resource instance. 
		This function can be used to implement streaming by preloading scene instance resources and instantiating/deinstantiating level <em>blocks</em> on the fly without requiring a complete load.

		Example:
if (ScenePreloadResources("level/block_dark_street.nms", g_factory))
	print("Dark street resources loaded.");
	#*/
	sq_register(vm, ScenePreloadResources, "ScenePreloadResources", _SC(".xs"));
	/*#
		Func: SceneLoad
		Proto: bool:Scene,string
		Desc: Append a scene to this scene, returns true on success, false otherwise.
		See: SceneLoadAndStoreGroup
	#*/
	sq_register(vm, SceneFromNML, "SceneLoad", _SC(".xs"));
	sq_register(vm, SceneFromNML, "SceneFromFile", _SC(".xs"));
	sq_register(vm, SceneFromNML, "SceneFromNML", _SC(".xs"));
	/*#
		Func: SceneLoadAndStoreGroup
		Proto: Group:Scene scene_to_import_to,string path,ImportFlag import_flag
		Desc: Append a scene to this scene, store all appended content (item, light, group, etc...) in a group.

		Example:
class LevelScene
{
	diablo_ai		=	0
	diablo_fist		=	0

	function OnSetup(scene)
	{
		// Import the Diablo AI character into this scene.
		diablo_ai = SceneLoadAndStoreGroup(scene, "enemy/ai/diablo.nms")

		// Grab item 'fist' from this specific copy of the Diablo scene.
		diablo_fist = GroupFindItem(diablo_ai, "fist")
	}
}
	#*/
	sq_register(vm, SceneFromNMLStoreGroup, "SceneLoadAndStoreGroup", _SC(".xsi"));
	sq_register(vm, SceneFromNMLStoreGroup, "SceneFromFileStoreGroup", _SC(".xsi"));
	sq_register(vm, SceneFromNMLStoreGroup, "SceneFromNMLStoreGroup", _SC(".xsi"));
	/*#
		Func: SceneSave
		Proto: bool:Scene,string
		Desc: Save scene content to file. Returns true on success, false otherwise.<br>
		The created scene can be directly opened in the editor provided that it has been saved in the same directory as the source scene. If not, resource path remapping will be required.
	#*/
	sq_register(vm, SceneSave, "SceneSave", _SC(".xs"));

/*#
	Section: SceneManagement
	Desc: Management
#*/
	/*#
		Func: SceneRenderSetup
		Proto: void:Scene,ResourceFactory
		Desc: Setup all scene render resources.
	#*/
	sq_register(vm, SceneRenderSetup, "SceneRenderSetup", _SC(".xx"));
	/*#
		Func: SceneDeleteItem
		Proto: void:Scene,item
		Desc: Delete an item from scene.
	#*/
	sq_register(vm, SceneDeleteItem, "SceneDeleteItem", _SC(".xx"));
	/*#
		Func: SceneEnd
		Proto: void:Scene
		Desc: Signal scene end. Calling this function when executing or previewing a scene will exit the viewer.
		See: ProjectEnd
	#*/
	sq_register(vm, SceneEnd, "SceneEnd", _SC(".x"));
	/*#
		Func: SceneSetGlobal
		Proto: void:Scene
		Desc: Assign a scene to the script VM global variable g_scene. The engine does this automatically before calling scene and item callbacks.
	#*/
	sq_register(vm, SceneSetGlobal, "SceneSetGlobal", _SC(".x"));

	/*#
		Func: SceneGetScriptInstance
		Proto: instance:Scene
		Desc: Return the script instance for a scene. The scene first script unit instance is returned.
		See: SceneGetScriptInstanceFromClass

		Example:
local instance = SceneGetScriptInstance(g_scene)

// Instance can be used to call the script assigned to the scene.
instance->TurnLightOn()
	#*/
	sq_register(vm, SceneGetScriptInstance, "SceneGetScriptInstance", _SC(".x"));
	/*#
		Func: SceneGetScriptInstanceFromClass
		Proto: Instance:Scene scene,string class_name
		Desc: Return the script instance of a specific script for a scene.

		Example:
// Get the scene script instance of class SceneLightManager.
local instance = SceneGetScriptInstanceFromClass(g_scene, "SceneLightManager")

// Instance can be used to call the SceneLightManager instance assigned to the scene.
instance->TurnLightOn()
	#*/
	sq_register(vm, SceneGetScriptInstanceFromClass, "SceneGetScriptInstanceFromClass", _SC(".xs"));

	/*#
		Func: SceneSetScript
		Proto: void:Scene scene,string script_path,string script_class
		Desc: Set the scene script file and class to instantiate on the scene script unit. Current script unit settings will be overwritten.
	#*/
	sq_register(vm, SceneSetScript, "SceneSetScript", _SC(".xss"));
	/*#
		Func: SceneRemoveAllScripts
		Proto: void:Scene scene
		Desc: remove all scripts from this scene.
	#*/
	sq_register(vm, SceneRemoveAllScripts, "SceneRemoveAllScripts", _SC(".x"));

	/*#
		Func: SceneGetFileName
		Proto: String:Scene
		Desc: Return the scene file name, without the path.
		See: SceneGetFilePath
	#*/
	sq_register(vm, SceneGetFileName, "SceneGetFileName", _SC(".x"));
	/*#
		Func: SceneGetFilePath
		Proto: String:Scene
		Desc: Return the scene file path.
		See: SceneGetFileName
	#*/
	sq_register(vm, SceneGetFilePath, "SceneGetFilePath", _SC(".x"));
	/*#
		Func: SceneReset
		Proto: void:Scene
		Desc: Reset a scene object. Note: All items are move back to their default transformation if recorded.
		See: SceneRecordLocation
	#*/
	sq_register(vm, SceneReset, "SceneReset", _SC(".x"));
	/*#
		Func: SceneUpdate
		Proto: void:Scene
		Desc: Update scene, run all logic, physic and call script callbacks.
	#*/
	sq_register(vm, SceneUpdate, "SceneUpdate", _SC(".x"));
	/*#
		Func: SceneSetRenderless
		Proto: void:Scene,bool
		Desc: Controls automatic rendering of the scene. If a scene is renderless it is up to the user to implement its rendering code.
		See: ScenePushRenderable, RendererRenderQueue, RendererRenderQueueReset, SceneRegisterAsPropertyCallback

		Example:
class RenderLessScene
{
	function OnSetup(scene)
	{
		// Set the scene to be renderless.
		SceneSetRenderless(scene, true)
	}

	function OnRender(scene)
	{
		// Register the scene as the renderer property provider.
		// Such properties as: ambient color, skybox and light rig are passed through this provider.
		SceneRegisterAsPropertyCallback(scene, g_render)

		// Push scene renderable to the renderer.
		ScenePushRenderable(scene, g_render)

		// Render renderable.
		RendererRenderQueue(g_render)

		// Reset renderable so that it does not get drawn by the next render call.
		RendererRenderQueueReset(g_render)
	}
}
	#*/
	sq_register(vm, SceneSetRenderless, "SceneSetRenderless", _SC(".xb"));
	/*#
		Func: ScenePushRenderable
		Proto: void:Scene,Renderer
		Desc: Push the scene renderable onto the renderer render queue.
	#*/
	sq_register(vm, ScenePushRenderable, "ScenePushRenderable", _SC(".xx"));
	/*#
		Func: SceneRenderUI
		Proto: void:Scene,Renderer
		Desc: Render the ui of the scene.
	#*/
	sq_register(vm, SceneRenderUI, "SceneRenderUI", _SC(".xx"));
	
	/*#
		Func: SceneRecordLocation
		Proto: void:Scene
		Desc: For each item, record the current transformation as the default transformation. The default transformation is used to move items to their original transformation when a scene reset is performed.
		See: SceneReset
	#*/
	sq_register(vm, SceneRecordLocation, "SceneRecordLocation", _SC(".x"));

	/*#
		Func: SceneSetItemStatic
		Proto: void:Scene,Item,bool
		Desc: Flag item as static. The item will be stored in a spatial structure such as a quadtree with other static items to improve culling performance.
		Note: If  a static item is moved culling errors will happen.
	#*/
	sq_register(vm, SceneSetItemStatic, "SceneSetItemStatic", _SC(".xxb"));

	/*#
		Func: SceneDeleteContent
		Proto: void:Scene
		Desc: Delete all scene content.
	#*/
	sq_register(vm, SceneDeleteContent, "SceneDeleteContent", _SC(".x"));
	/*#
		Func: SceneFlushDeletionQueue
		Proto: void:Scene
		Desc: Immediately delete all items marked for deletion.
	#*/
	sq_register(vm, SceneFlushDeletionQueue, "SceneFlushDeletionQueue", _SC(".x"));

	/*#
		Func: SceneGetCurrentCamera
		Proto: camera:scene
		Desc: Get scene current camera.
	#*/
	sq_register(vm, SceneGetCurrentCamera, "SceneGetCurrentCamera", _SC(".x"));
	/*#
		Func: SceneSetCurrentCamera
		Proto: void:scene,camera
		Desc: Set camera as scene current camera.
	#*/
	sq_register(vm, SceneSetCurrentCamera, "SceneSetCurrentCamera", _SC(".xx"));

	/*#
		Func: SceneAddCamera
		Proto: camera:scene,string name
		Desc: Create a new camera.
	#*/
	sq_register(vm, SceneAddCamera, "SceneAddCamera", _SC(".xs"));
	/*#
		Func: SceneAddLight
		Proto: Light:Scene,string name
		Desc: Add a new light to scene.
	#*/
	sq_register(vm, SceneAddLight, "SceneAddLight", _SC(".xs"));
	/*#
		Func: SceneDeleteLight
		Proto: void:Scene,Light
		Desc: Delete light from scene.
	#*/
	sq_register(vm, SceneDeleteLight, "SceneDeleteLight", _SC(".xs"));
	/*#
		Func: SceneDeleteAllLights
		Proto: void:Scene
		Desc: Delete all lights from scene.
	#*/
	sq_register(vm, SceneDeleteAllLights, "SceneDeleteAllLights", _SC(".x"));
	/*#
		Func: SceneAddObject
		Proto: Object:Scene,string name
		Desc: Add a new object to scene.
	#*/
	sq_register(vm, SceneAddObject, "SceneAddObject", _SC(".xs"));
	/*#
		Func: SceneDeleteObject
		Proto: void:Scene,Object
		Desc: Delete object from scene.
	#*/
	sq_register(vm, SceneDeleteObject, "SceneDeleteObject", _SC(".xx"));
	/*#
		Func: SceneAddTrigger
		Proto: Trigger:Scene,string name
		Desc: Add a new trigger to scene.
	#*/
	sq_register(vm, SceneAddTrigger, "SceneAddTrigger", _SC(".xs"));
	/*#
		Func: SceneDeleteTrigger
		Proto: void:Scene,Trigger
		Desc: Delete trigger from scene.
	#*/
	sq_register(vm, SceneDeleteTrigger, "SceneDeleteTrigger", _SC(".xx"));

	/*#
		Func: SceneGetGroupList
		Proto: array:Scene
		Desc: Return an array containing all scene groups.
	#*/
	sq_register(vm, SceneGetGroupList, "SceneGetGroupList", _SC(".x"));
	/*#
		Func: SceneGroupActivate
		Proto: void:Scene,Group,bool active
		Desc: Set group member items active flag, effectively stops all physic, collision and display operations from happening on all group items.
	#*/
	sq_register(vm, SceneGroupActivate, "SceneGroupActivate", _SC(".xxb"));
	/*#
		Func: SceneItemActivate
		Proto: void:Scene,Item,bool active
		Desc: Set item active flag, when set to false this will stop all physic, collision and display operations from happening for this item.
	#*/
	sq_register(vm, SceneItemActivate, "SceneItemActivate", _SC(".xxb"));
	/*#
		Func: SceneItemActivateHierarchy
		Proto: void:Scene,Item,bool active
		Desc: Set item active flag on an item and its children recursively.
	#*/
	sq_register(vm, SceneItemActivateHierarchy, "SceneItemActivateHierarchy", _SC(".xxb"));
	/*#
		Func: SceneProcessItemActivationQueue
		Proto: void:Scene
		Desc: process the SceneProcessItemActivationQueue.
	#*/
	sq_register(vm, SceneProcessItemActivationQueue, "SceneProcessItemActivationQueue", _SC(".x"));
			/*#
		Func: ItemSetActive
		Proto: void:Scene,Item,bool active
		Desc: Set item active flag, when set to false this will stop all physic, collision and display operations from happening for this item.
	#*/
	sq_register(vm, ItemSetActive, "ItemSetActive", _SC(".xb"));
	
/*#
	Section: SceneEnvironment
	Desc: Environment
#*/
	/*#
		Func: SceneGetAmbientIntensity
		Proto: float:Scene
		Desc: Get the scene ambient intensity.
	#*/
	sq_register(vm, SceneGetAmbientIntensity, "SceneGetAmbientIntensity", _SC(".x"));
	/*#
		Func: SceneSetAmbientIntensity
		Proto: void:Scene,float
		Desc: Set the scene ambient intensity.
	#*/
	sq_register(vm, SceneSetAmbientIntensity, "SceneSetAmbientIntensity", _SC(".xn"));
	/*#
		Func: SceneGetAmbientColor
		Proto: Vector:Scene
		Desc: Get the scene ambient color.
	#*/
	sq_register(vm, SceneGetAmbientColor, "SceneGetAmbientColor", _SC(".x"));
	/*#
		Func: SceneSetAmbientColor
		Proto: void:Scene,Vector
		Desc: Set the scene ambient color.
		Example: SceneSetAmbientColor(g_scene, Vector(1.0, 0.0, 0.0)) // Pure red ambient.
	#*/
	sq_register(vm, SceneSetAmbientColor, "SceneSetAmbientColor", _SC(".xx"));
	/*#
		Func: SceneGetBackgroundColor
		Proto: Vector:Scene
		Desc: Get the scene background color.
	#*/
	sq_register(vm, SceneGetBackgroundColor, "SceneGetBackgroundColor", _SC(".x"));
	/*#
		Func: SceneSetBackgroundColor
		Proto: void:Scene,Vector
		Desc: Set the scene background color.
		Example: SceneSetAmbientColor(g_scene, Vector(0.0, 1.0, 0.0)) // Pure green background.
	#*/
	sq_register(vm, SceneSetBackgroundColor, "SceneSetBackgroundColor", _SC(".xx"));
	/*#
		Func: SceneGetFogColor
		Proto: Vector:Scene
		Desc: Return the fog color.
	#*/
	sq_register(vm, SceneGetFogColor, "SceneGetFogColor", _SC(".x"));
	/*#
		Func: SceneGetFogNear
		Proto: float:Scene
		Desc: Return the fog Z near.
	#*/
	sq_register(vm, SceneGetFogNear, "SceneGetFogNear", _SC(".x"));
	/*#
		Func: SceneGetFogFar
		Proto: float:Scene
		Desc: Return the fog Z far.
	#*/
	sq_register(vm, SceneGetFogFar, "SceneGetFogFar", _SC(".x"));
	/*#
		Func: SceneSetFog
		Proto: void:Scene,bool enable,Vector color,float z_near,float z_far
		Desc: Control scene fog.
		Example:
// Set a white fog starting 10 meters from the camera and fully covering view at 50 meters from the camera.
SceneSetFog(g_scene, true, Vector(1.0, 1.0, 1.0), Mtr(10), Mtr(50))
	#*/
	sq_register(vm, SceneSetFog, "SceneSetFog", _SC(".xbxnn"));
	
	/*#
		Func: SceneSetFlagDebugPhysic
		Proto: void:Scene, bool active
		Desc: Activate/Deactivate the flag debug physic.
	#*/
	sq_register(vm, SceneSetFlagDebugPhysic, "SceneSetFlagDebugPhysic", _SC(".xb"));
	
	/*#
		Func: SceneGetTimeOfDay
		Proto: float:Scene
		Desc: Get time of day as a normalized value.
	#*/
	sq_register(vm, SceneGetTimeOfDay, "SceneGetTimeOfDay", _SC(".x"));
	/*#
		Func: SceneSetTimeOfDay
		Proto: void:Scene,float time
		Desc: Set time of day as a normalized value.
	#*/
	sq_register(vm, SceneSetTimeOfDay, "SceneSetTimeOfDay", _SC(".xn"));
	/*#
		Func: SceneSetSkyShader
		Proto: void:Scene,string shader
		Desc: Set sky shader name file.
	#*/
	sq_register(vm, SceneSetSkyShader, "SceneSetSkyShader", _SC(".xs"));
	/*#
		Func: SceneSetSkyLayer
		Proto: void:Scene,string picture_layer,int index_sky_layer
		Desc: Set sky layer picture.
	#*/
	sq_register(vm, SceneSetSkyLayer, "SceneSetSkyLayer", _SC(".xsi"));
	
/*#
	Section: SceneRender
	Desc: Rendering
#*/
	/*#
		Func: SceneRegisterAsPropertyCallback
		Proto: void:Scene,Renderer
		Desc: Register a scene as the renderer property callback.
	#*/
	sq_register(vm, SceneRegisterAsPropertyCallback, "SceneRegisterAsPropertyCallback", _SC(".xx"));

/*#
	Section: SceneDebug
	Desc: Debug/profile
#*/
	/*#
		Func: ScenePrintItemList
		Proto: void:Scene
		Desc: Dump scene item list to log.
	#*/
	sq_register(vm, ScenePrintItemList, "ScenePrintItemList", _SC(".x"));

/*#
	Section: SceneItem
	Desc: Item management
#*/
	/*#
		Func: SceneGetItemList
		Proto: Array:Scene|Instance
		Desc: Returns an array of all items in the scene.
	#*/
	sq_register(vm, SceneGetItemList, "SceneGetItemList", _SC(".x"));
	/*#
		Func: SceneGetItemChildrenList
		Proto: Array:Scene,Item
		Desc: Returns an array of all the children items in the scene of a given parent item.
	#*/
	sq_register(vm, SceneGetItemChildrenList, "SceneGetItemChildrenList", _SC(".xx"));
	/*#
		Func: SceneFindItem
		Proto: Item:Scene|Instance,string
		Desc: Find an item in scene.
	#*/
	sq_register(vm, SceneFindItem, "SceneFindItem", _SC(".xs"));
	/*#
		Func: SceneFindItemChild
		Proto: void:Scene|Instance,Item parent,string child_name
		Desc: Find child item of a given item in scene.
	#*/
	sq_register(vm, SceneFindItemChild, "SceneFindItemChild", _SC(".xxs"));
	/*#
		Func: SceneSetupItem
		Proto: void:Scene,Item
		Desc: Setup an item. You need to call ItemRenderSetup() to setup the render object of this item.
	#*/
	sq_register(vm, SceneSetupItem, "SceneSetupItem", _SC(".xx"));
	/*#
	Func: SceneForceUpdateMassShapePhysicItem
	Proto: void:Scene,Item
	Desc:for to update the mass from the shape physic if the item and rigid is already created.
	#*/
	sq_register(vm, SceneForceUpdateMassShapePhysicItem, "SceneForceUpdateMassShapePhysicItem", _SC(".xx"));	
	/*#
		Func: SceneDuplicateItem
		Proto: void:Scene,Item
		Desc: Duplicate an item and all its properties, returns the new instance.<br>You need to call SceneSetupItem() and ItemRenderSetup() on the new instance if you use this function at runtime.
	#*/
	sq_register(vm, SceneDuplicateItem, "SceneDuplicateItem", _SC(".xx"));

	/*#
		Func: SceneMergeItems
		Proto: Object:Scene, RenderResourceFactory factory, nb item, array item
		Desc: Merge 2 items together.
	#*/
	sq_register(vm, SceneMergeItems, "SceneMergeItems", _SC(".xsxia"));

/*#
	Section: SceneGroup
	Desc: Group management
#*/
	/*#
		Func: SceneDeleteGroup
		Proto: void:Scene|Instance,Group
		Desc: Delete a group and all its members from a scene.
	#*/
	sq_register(vm, SceneDeleteGroup, "SceneDeleteGroup", _SC(".xx"));
	/*#
		Func: SceneFindGroup
		Proto: Group:Scene|Instance,string name
		Desc: Find a group in scene from its name.
	#*/
	sq_register(vm, SceneFindGroup, "SceneFindGroup", _SC(".xs"));

/*#
	Section: ScenePhysic
	Desc: Physic
#*/
	/*#
		Func: ScenePhysicAllocateCollisionNode
		Proto: void:Scene,int max_node, int max_contact
		Desc: Allocate physic system internal structures. A collision node is used for each collision occurring during the collision detection phase. Many contacts can be generated for each collision occurring.
	#*/
	sq_register(vm, ScenePhysicAllocateCollisionNode, "ScenePhysicAllocateCollisionNode", _SC(".xii"));
	/*#
		Func: ScenePhysicEnableDeactivation
		Proto: void:Scene,bool
		Desc: Enable or disable physic system item deactivation.
	#*/
	sq_register(vm, ScenePhysicEnableDeactivation, "ScenePhysicEnableDeactivation", _SC(".xb"));
	/*#
		Func: SceneSetPhysicContactSolverIteration
		Proto: void:Scene,int
		Desc: Set the number of iteration used by the physic contact solver.
	#*/
	sq_register(vm, SceneSetPhysicContactSolverIteration, "SceneSetPhysicContactSolverIteration", _SC(".xi"));
	/*#
		Func: SceneSetPhysicConstraintSolverIteration
		Proto: void:Scene,int
		Desc: Set the number of iteration used by the physic constraint solver.
	#*/
	sq_register(vm, SceneSetPhysicConstraintSolverIteration, "SceneSetPhysicConstraintSolverIteration", _SC(".xi"));
	/*#
		Func: SceneSetPhysicFrequency
		Proto: void:Scene,float
		Desc: Set the physic system update frequency (default: 75 Hertz).
	#*/
	sq_register(vm, SceneSetPhysicFrequency, "SceneSetPhysicFrequency", _SC(".xn"));
	/*#
		Func: SceneGetPhysicFrequency
		Proto: float:Scene
		Desc: Returns the physic system update frequency in Hertz.
	#*/
	sq_register(vm, SceneGetPhysicFrequency, "SceneGetPhysicFrequency", _SC(".x"));
	/*#
		Func: SceneSetGravity
		Proto: void:Scene,Vector
		Desc: Set default physic system gravity (Default: Earth gravity: 0.0, -9.8, 0.0).
		Note: This only affects the gravity for newly created items. In order to modify the gravity for a given item please use the item Physics functions.
	#*/
	sq_register(vm, SceneSetGravity, "SceneSetGravity", _SC(".xx"));
	/*#
		Func: SceneFindConstraint
		Proto: Constraint:Scene,string name
		Desc: Find a constraint in scene from its name.
	#*/
	sq_register(vm, SceneFindConstraint, "SceneFindConstraint", _SC(".xs"));

/*#
	Section: SceneCollision
	Desc: Collision
#*/
	/*#
		Func: SceneCollisionRaytrace
		Proto: TraceResult:Scene,Vector from,Vector direction,int collision_mask,ShapeMask,float max_distance
		Desc: Raytrace the collision system, collision shape type and collision ids can be filtered through bit mask usage.
	#*/
	sq_register(vm, SceneCollisionRaytrace, "SceneCollisionRaytrace", _SC(".xxxiin"));
	/*#
		Func: SceneRaytraceTriggerList
		Proto: Item:Scene,Vector ray_origin,Vector ray_direction,float ray_length
		Desc: Raytrace scene triggers, return the trigger item hit.
	#*/
	sq_register(vm, SceneRaytraceTriggerList, "SceneRaytraceTriggerList", _SC(".xxxn"));

	// Push defines.
	sq_pushroottable(vm);

	/*#
		Struct: TraceResult
		Member: bool hit: true if the ray hit something, false otherwise.
		Member: Item item: Item hit by the ray.
		Member: ColShape shape: Collision shape hit by the ray.
		Member: Material material: Material at hit point.
		Member: Vector p: Hit point location in world space.
		Member: Vector n: Hit point normal in world space.
		Member: float d: Distance to hit point from ray origin.
	#*/

	/*#
		Enum: ImportFlag
		Values: ImportFlagCamera,ImportFlagLight,ImportFlagObject,ImportFlagTrigger,ImportFlagGroup,ImportFlagMotion,ImportFlagGlobals,ImportFlagCollision,ImportFlagPhysic,ImportFlagPath,ImportFlagAll
	#*/
#if	1
	sq_pushstring(vm, "FlagLoadCamera", -1); sq_pushinteger(vm, SceneIOCamera); sq_newslot(vm, -3, true);
	sq_pushstring(vm, "FlagLoadLight", -1); sq_pushinteger(vm, SceneIOLight); sq_newslot(vm, -3, true);
	sq_pushstring(vm, "FlagLoadObject", -1); sq_pushinteger(vm, SceneIOObject); sq_newslot(vm, -3, true);
	sq_pushstring(vm, "FlagLoadTrigger", -1); sq_pushinteger(vm, SceneIOTrigger); sq_newslot(vm, -3, true);
	sq_pushstring(vm, "FlagLoadGroup", -1); sq_pushinteger(vm, SceneIOGroup); sq_newslot(vm, -3, true);
	sq_pushstring(vm, "FlagLoadSettings", -1); sq_pushinteger(vm, SceneIOSettings); sq_newslot(vm, -3, true);
	sq_pushstring(vm, "FlagLoadGlobals", -1); sq_pushinteger(vm, SceneIOGlobals); sq_newslot(vm, -3, true);
	sq_pushstring(vm, "FlagLoadMotion", -1); sq_pushinteger(vm, SceneIOMotion); sq_newslot(vm, -3, true);
	sq_pushstring(vm, "FlagLoadCollision", -1); sq_pushinteger(vm, SceneIOCollision); sq_newslot(vm, -3, true);
	sq_pushstring(vm, "FlagLoadPhysic", -1); sq_pushinteger(vm, SceneIOPhysic); sq_newslot(vm, -3, true);
	sq_pushstring(vm, "FlagLoadPath", -1); sq_pushinteger(vm, SceneIOPath); sq_newslot(vm, -3, true);
	sq_pushstring(vm, "FlagLoadAll", -1); sq_pushinteger(vm, SceneIOAll); sq_newslot(vm, -3, true);
#endif
	sq_pushstring(vm, "ImportFlagCamera", -1); sq_pushinteger(vm, SceneIOCamera); sq_newslot(vm, -3, true);
	sq_pushstring(vm, "ImportFlagLight", -1); sq_pushinteger(vm, SceneIOLight); sq_newslot(vm, -3, true);
	sq_pushstring(vm, "ImportFlagObject", -1); sq_pushinteger(vm, SceneIOObject); sq_newslot(vm, -3, true);
	sq_pushstring(vm, "ImportFlagTrigger", -1); sq_pushinteger(vm, SceneIOTrigger); sq_newslot(vm, -3, true);
	sq_pushstring(vm, "ImportFlagInstance", -1); sq_pushinteger(vm, SceneIOInstance); sq_newslot(vm, -3, true);
	sq_pushstring(vm, "ImportFlagGroup", -1); sq_pushinteger(vm, SceneIOGroup); sq_newslot(vm, -3, true);
	sq_pushstring(vm, "ImportFlagSettings", -1); sq_pushinteger(vm, SceneIOSettings); sq_newslot(vm, -3, true);
	sq_pushstring(vm, "ImportFlagGlobals", -1); sq_pushinteger(vm, SceneIOGlobals); sq_newslot(vm, -3, true);
	sq_pushstring(vm, "ImportFlagMotion", -1); sq_pushinteger(vm, SceneIOMotion); sq_newslot(vm, -3, true);
	sq_pushstring(vm, "ImportFlagCollision", -1); sq_pushinteger(vm, SceneIOCollision); sq_newslot(vm, -3, true);
	sq_pushstring(vm, "ImportFlagPhysic", -1); sq_pushinteger(vm, SceneIOPhysic); sq_newslot(vm, -3, true);
	sq_pushstring(vm, "ImportFlagPath", -1); sq_pushinteger(vm, SceneIOPath); sq_newslot(vm, -3, true);
	sq_pushstring(vm, "ImportFlagAll", -1); sq_pushinteger(vm, SceneIOAll); sq_newslot(vm, -3, true);

	sq_pushstring(vm, "NullItem", -1); CObject::Push(vm, NULL, typetag_Item); sq_newslot(vm, -3, true);

	sq_pop(vm, 1);
}
