0ad/source/maths/scripting/JSInterface_Vector3D.cpp
2011-07-16 23:24:14 +00:00

210 lines
5.6 KiB
C++

/* Copyright (C) 2009 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#include "precompiled.h"
#include "JSInterface_Vector3D.h"
#include "scripting/JSConversions.h"
#include "scripting/ScriptingHost.h"
JSClass JSI_Vector3D::JSI_class = {
"Vector3D", JSCLASS_HAS_PRIVATE,
JS_PropertyStub, JS_PropertyStub,
JSI_Vector3D::getProperty, JSI_Vector3D::setProperty,
JS_EnumerateStub, JS_ResolveStub,
JS_ConvertStub, JSI_Vector3D::finalize,
NULL, NULL, NULL, NULL
};
JSPropertySpec JSI_Vector3D::JSI_props[] =
{
{ "x", JSI_Vector3D::component_x, JSPROP_ENUMERATE },
{ "y", JSI_Vector3D::component_y, JSPROP_ENUMERATE },
{ "z", JSI_Vector3D::component_z, JSPROP_ENUMERATE },
{ 0 }
};
JSFunctionSpec JSI_Vector3D::JSI_methods[] =
{
{ "toString", JSI_Vector3D::toString, 0, 0 },
{ 0 }
};
void JSI_Vector3D::init()
{
g_ScriptingHost.DefineCustomObjectType(&JSI_class, JSI_Vector3D::construct, 0, JSI_props, JSI_methods, NULL, NULL);
}
JSI_Vector3D::Vector3D_Info::Vector3D_Info()
{
owner = NULL;
vector = new CVector3D();
}
JSI_Vector3D::Vector3D_Info::Vector3D_Info(float x, float y, float z)
{
owner = NULL;
vector = new CVector3D(x, y, z);
}
JSI_Vector3D::Vector3D_Info::Vector3D_Info(const CVector3D& copy)
{
owner = NULL;
vector = new CVector3D(copy.X, copy.Y, copy.Z);
}
JSI_Vector3D::Vector3D_Info::Vector3D_Info(CVector3D* attach, IPropertyOwner* _owner)
{
owner = _owner;
updateFn = NULL;
freshenFn = NULL;
vector = attach;
}
JSI_Vector3D::Vector3D_Info::Vector3D_Info(CVector3D* attach, IPropertyOwner* _owner, void(IPropertyOwner::*_updateFn)(void))
{
owner = _owner;
updateFn = _updateFn;
freshenFn = NULL;
vector = attach;
}
JSI_Vector3D::Vector3D_Info::Vector3D_Info(CVector3D* attach, IPropertyOwner* _owner, void(IPropertyOwner::*_updateFn)(void),
void(IPropertyOwner::*_freshenFn)(void))
{
owner = _owner;
updateFn = _updateFn;
freshenFn = _freshenFn;
vector = attach;
}
JSI_Vector3D::Vector3D_Info::~Vector3D_Info()
{
if (!owner)
delete (vector);
}
JSBool JSI_Vector3D::getProperty(JSContext* cx, JSObject* obj, jsid id, jsval* vp)
{
if (!JSID_IS_INT(id))
return JS_TRUE;
Vector3D_Info* vectorInfo = (Vector3D_Info*)JS_GetInstancePrivate(cx, obj, &JSI_Vector3D::JSI_class, NULL);
if (!vectorInfo)
return JS_FALSE;
CVector3D* vectorData = vectorInfo->vector;
if (vectorInfo->owner && vectorInfo->freshenFn)
((vectorInfo->owner)->*(vectorInfo->freshenFn))();
switch (JSID_TO_INT(id))
{
case component_x:
return JS_NewNumberValue(cx, vectorData->X, vp);
case component_y:
return JS_NewNumberValue(cx, vectorData->Y, vp);
case component_z:
return JS_NewNumberValue(cx, vectorData->Z, vp);
}
return JS_FALSE;
}
JSBool JSI_Vector3D::setProperty(JSContext* cx, JSObject* obj, jsid id, JSBool UNUSED(strict), jsval* vp)
{
if (!JSID_IS_INT(id))
return JS_TRUE;
Vector3D_Info* vectorInfo = (Vector3D_Info*)JS_GetInstancePrivate(cx, obj, &JSI_Vector3D::JSI_class, NULL);
if (!vectorInfo)
return JS_FALSE;
CVector3D* vectorData = vectorInfo->vector;
if (vectorInfo->owner && vectorInfo->freshenFn)
((vectorInfo->owner)->*(vectorInfo->freshenFn))();
switch (JSID_TO_INT(id))
{
case component_x:
vectorData->X = ToPrimitive<float> (*vp);
break;
case component_y:
vectorData->Y = ToPrimitive<float> (*vp);
break;
case component_z:
vectorData->Z = ToPrimitive<float> (*vp);
break;
}
if (vectorInfo->owner && vectorInfo->updateFn)
((vectorInfo->owner)->*(vectorInfo->updateFn))();
return JS_TRUE;
}
JSBool JSI_Vector3D::construct(JSContext* cx, uintN argc, jsval* vp)
{
JSObject* vector = JS_NewObject(cx, &JSI_Vector3D::JSI_class, NULL, NULL);
if (argc == 0)
{
JS_SetPrivate(cx, vector, new Vector3D_Info());
JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(vector));
return JS_TRUE;
}
JSU_REQUIRE_PARAMS(3);
try
{
float x = ToPrimitive<float> (JS_ARGV(cx, vp)[0]);
float y = ToPrimitive<float> (JS_ARGV(cx, vp)[1]);
float z = ToPrimitive<float> (JS_ARGV(cx, vp)[2]);
JS_SetPrivate(cx, vector, new Vector3D_Info(x, y, z));
JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(vector));
return JS_TRUE;
}
catch (PSERROR_Scripting_ConversionFailed)
{
// Invalid input (i.e. can't be coerced into doubles) - fail
JS_ReportError(cx, "Invalid parameters to Vector3D constructor");
return JS_FALSE;
}
}
void JSI_Vector3D::finalize(JSContext* cx, JSObject* obj)
{
delete ((Vector3D_Info*)JS_GetPrivate(cx, obj));
}
JSBool JSI_Vector3D::toString(JSContext* cx, uintN UNUSED(argc), jsval* vp)
{
char buffer[256];
Vector3D_Info* vectorInfo = (Vector3D_Info*)JS_GetInstancePrivate(cx, JS_THIS_OBJECT(cx, vp), &JSI_Vector3D::JSI_class, NULL);
if (!vectorInfo)
return JS_FALSE;
if (vectorInfo->owner && vectorInfo->freshenFn)
((vectorInfo->owner)->*(vectorInfo->freshenFn))();
CVector3D* vectorData = vectorInfo->vector;
sprintf_s(buffer, ARRAY_SIZE(buffer), "[object Vector3D: ( %f, %f, %f )]", vectorData->X, vectorData->Y, vectorData->Z);
JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(JS_NewStringCopyZ(cx, buffer)));
return JS_TRUE;
}