2b396ccb57
This was SVN commit r887.
267 lines
7.6 KiB
C++
Executable File
267 lines
7.6 KiB
C++
Executable File
#include "precompiled.h"
|
|
|
|
#include "JSInterface_Camera.h"
|
|
#include "scripting/JSInterface_Vector3D.h"
|
|
#include "Camera.h"
|
|
#include "Vector3D.h"
|
|
#include "Matrix3D.h"
|
|
#include "Terrain.h"
|
|
#include "Game.h"
|
|
|
|
JSClass JSI_Camera::JSI_class = {
|
|
"Camera", JSCLASS_HAS_PRIVATE,
|
|
JS_PropertyStub, JS_PropertyStub,
|
|
JSI_Camera::getProperty, JSI_Camera::setProperty,
|
|
JS_EnumerateStub, JS_ResolveStub,
|
|
JS_ConvertStub, JSI_Camera::finalize,
|
|
NULL, NULL, NULL, NULL
|
|
};
|
|
|
|
JSPropertySpec JSI_Camera::JSI_props[] =
|
|
{
|
|
{ "position", JSI_Camera::vector_position, JSPROP_ENUMERATE },
|
|
{ "orientation", JSI_Camera::vector_orientation, JSPROP_ENUMERATE },
|
|
{ "up", JSI_Camera::vector_up, JSPROP_ENUMERATE },
|
|
{ 0 },
|
|
};
|
|
|
|
JSFunctionSpec JSI_Camera::JSI_methods[] =
|
|
{
|
|
{ "lookAt", JSI_Camera::lookAt, 2, 0, 0 },
|
|
{ "getFocus", JSI_Camera::getFocus, 0, 0, 0 },
|
|
{ 0 }
|
|
};
|
|
|
|
void JSI_Camera::init()
|
|
{
|
|
g_ScriptingHost.DefineCustomObjectType( &JSI_class, JSI_Camera::construct, 0, JSI_props, JSI_methods, NULL, NULL );
|
|
}
|
|
|
|
JSI_Camera::Camera_Info::Camera_Info()
|
|
{
|
|
CMatrix3D orient;
|
|
orient.SetXRotation( DEGTORAD( 30 ) );
|
|
orient.RotateY( DEGTORAD( -45 ) );
|
|
orient.Translate( 100, 150, -100 );
|
|
|
|
Camera_Info( orient.GetTranslation(), orient.GetIn(), orient.GetUp() );
|
|
}
|
|
|
|
JSI_Camera::Camera_Info::Camera_Info( const CVector3D& _position )
|
|
{
|
|
Camera_Info();
|
|
position = _position;
|
|
}
|
|
|
|
JSI_Camera::Camera_Info::Camera_Info( const CVector3D& _position, const CVector3D& _orientation )
|
|
{
|
|
Camera_Info( _position, _orientation, CVector3D( 0.0f, 1.0f, 0.0f ) );
|
|
}
|
|
|
|
JSI_Camera::Camera_Info::Camera_Info( const CVector3D& _position, const CVector3D& _orientation, const CVector3D& _up )
|
|
{
|
|
position = _position;
|
|
orientation = _orientation;
|
|
up = _up;
|
|
copy = NULL;
|
|
}
|
|
|
|
JSI_Camera::Camera_Info::Camera_Info( CCamera* _copy )
|
|
{
|
|
copy = _copy;
|
|
position = copy->m_Orientation.GetTranslation();
|
|
orientation = copy->m_Orientation.GetIn();
|
|
up = copy->m_Orientation.GetUp();
|
|
}
|
|
|
|
void JSI_Camera::Camera_Info::update()
|
|
{
|
|
if( copy )
|
|
copy->LookAlong( position, orientation, up );
|
|
}
|
|
|
|
JSBool JSI_Camera::getCamera( JSContext* cx, JSObject* obj, jsval id, jsval* vp )
|
|
{
|
|
JSObject* camera = JS_NewObject( cx, &JSI_Camera::JSI_class, NULL, NULL );
|
|
JS_SetPrivate( cx, camera, new Camera_Info( g_Game->GetView()->GetCamera() ) );
|
|
*vp = OBJECT_TO_JSVAL( camera );
|
|
return( JS_TRUE );
|
|
}
|
|
|
|
JSBool JSI_Camera::setCamera( JSContext* cx, JSObject* obj, jsval id, jsval* vp )
|
|
{
|
|
JSObject* camera = JSVAL_TO_OBJECT( *vp );
|
|
Camera_Info* cameraInfo;
|
|
if( !JSVAL_IS_OBJECT( *vp ) || !( cameraInfo = (Camera_Info*)JS_GetInstancePrivate( cx, camera, &JSI_Camera::JSI_class, NULL ) ) )
|
|
{
|
|
JS_ReportError( cx, "[Camera] Invalid object" );
|
|
}
|
|
else
|
|
g_Game->GetView()->GetCamera()->LookAlong( cameraInfo->position, cameraInfo->orientation, cameraInfo->up );
|
|
return( JS_TRUE );
|
|
}
|
|
|
|
JSBool JSI_Camera::getProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp )
|
|
{
|
|
if( !JSVAL_IS_INT( id ) )
|
|
return( JS_TRUE );
|
|
|
|
Camera_Info* cameraInfo = (Camera_Info*)JS_GetPrivate( cx, obj );
|
|
if( !cameraInfo )
|
|
{
|
|
JS_ReportError( cx, "[Camera] Invalid Reference" );
|
|
return( JS_TRUE );
|
|
}
|
|
|
|
CVector3D* d;
|
|
|
|
switch( g_ScriptingHost.ValueToInt( id ) )
|
|
{
|
|
case vector_position: d = &cameraInfo->position; break;
|
|
case vector_orientation: d = &cameraInfo->orientation; break;
|
|
case vector_up: d = &cameraInfo->up; break;
|
|
default: return( JS_FALSE );
|
|
}
|
|
|
|
JSObject* vector3d = JS_NewObject( g_ScriptingHost.getContext(), &JSI_Vector3D::JSI_class, NULL, NULL );
|
|
JS_SetPrivate( g_ScriptingHost.getContext(), vector3d, new JSI_Vector3D::Vector3D_Info( d, cameraInfo, ( void( IBoundPropertyOwner::* )() )&Camera_Info::update ) );
|
|
*vp = OBJECT_TO_JSVAL( vector3d );
|
|
return( JS_TRUE );
|
|
}
|
|
|
|
JSBool JSI_Camera::setProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp )
|
|
{
|
|
if( !JSVAL_IS_INT( id ) )
|
|
return( JS_TRUE );
|
|
|
|
Camera_Info* cameraInfo = (Camera_Info*)JS_GetPrivate( cx, obj );
|
|
if( !cameraInfo )
|
|
{
|
|
JS_ReportError( cx, "[Camera] Invalid reference" );
|
|
return( JS_TRUE );
|
|
}
|
|
|
|
JSObject* vector3d = JSVAL_TO_OBJECT( *vp );
|
|
JSI_Vector3D::Vector3D_Info* v = NULL;
|
|
|
|
if( JSVAL_IS_OBJECT( *vp ) && ( v = (JSI_Vector3D::Vector3D_Info*)JS_GetInstancePrivate( g_ScriptingHost.getContext(), vector3d, &JSI_Vector3D::JSI_class, NULL ) ) )
|
|
{
|
|
switch( g_ScriptingHost.ValueToInt( id ) )
|
|
{
|
|
case vector_position: cameraInfo->position = *( v->vector ); break;
|
|
case vector_orientation: cameraInfo->orientation = *( v->vector ); break;
|
|
case vector_up: cameraInfo->up = *( v->vector ); break;
|
|
}
|
|
|
|
cameraInfo->update();
|
|
}
|
|
|
|
return( JS_TRUE );
|
|
}
|
|
|
|
JSBool JSI_Camera::lookAt( JSContext* cx, JSObject* obj, unsigned int argc, jsval* argv, jsval* rval )
|
|
{
|
|
assert( argc >= 2 );
|
|
|
|
JSI_Vector3D::Vector3D_Info* v = NULL;
|
|
Camera_Info* cameraInfo = (Camera_Info*)JS_GetPrivate( cx, obj );
|
|
|
|
#define GETVECTOR( jv ) ( ( JSVAL_IS_OBJECT( jv ) && ( v = (JSI_Vector3D::Vector3D_Info*)JS_GetInstancePrivate( g_ScriptingHost.getContext(), JSVAL_TO_OBJECT( jv ), &JSI_Vector3D::JSI_class, NULL ) ) ) ? *(v->vector) : CVector3D() )
|
|
|
|
if( argc <= 3 )
|
|
{
|
|
cameraInfo->position = GETVECTOR( argv[0] );
|
|
cameraInfo->orientation = ( GETVECTOR( argv[1] ) - GETVECTOR( argv[0] ) );
|
|
cameraInfo->orientation.Normalize();
|
|
}
|
|
else
|
|
{
|
|
JS_ReportError( cx, "[Camera] Too many arguments to lookAt" );
|
|
*rval = JSVAL_FALSE;
|
|
return( JS_TRUE );
|
|
}
|
|
|
|
if( argc == 2 )
|
|
{
|
|
cameraInfo->up = CVector3D( 0.0f, 1.0f, 0.0f );
|
|
}
|
|
else if( argc == 3 )
|
|
{
|
|
cameraInfo->up = GETVECTOR( argv[2] );
|
|
}
|
|
|
|
#undef GETVECTOR
|
|
|
|
cameraInfo->update();
|
|
|
|
*rval = JSVAL_TRUE;
|
|
return( JS_TRUE );
|
|
}
|
|
|
|
JSBool JSI_Camera::getFocus( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval )
|
|
{
|
|
// Largely copied from the equivalent method in CCamera
|
|
|
|
Camera_Info* cameraInfo = (Camera_Info*)JS_GetPrivate( cx, obj );
|
|
|
|
CHFTracer tracer( g_Game->GetWorld()->GetTerrain() ); int x, z;
|
|
|
|
CVector3D currentTarget;
|
|
|
|
if( !tracer.RayIntersect( cameraInfo->position, cameraInfo->orientation, x, z, currentTarget ) )
|
|
{
|
|
// Off the edge of the world?
|
|
// Work out where it /would/ hit, if the map were extended out to infinity with average height.
|
|
|
|
currentTarget = cameraInfo->position + cameraInfo->orientation * ( ( 50.0f - cameraInfo->position.Y ) / cameraInfo->orientation.Y );
|
|
}
|
|
|
|
JSObject* vector3d = JS_NewObject( g_ScriptingHost.getContext(), &JSI_Vector3D::JSI_class, NULL, NULL );
|
|
JS_SetPrivate( g_ScriptingHost.getContext(), vector3d, new JSI_Vector3D::Vector3D_Info( currentTarget ) );
|
|
*rval = OBJECT_TO_JSVAL( vector3d );
|
|
return( JS_TRUE );
|
|
}
|
|
|
|
JSBool JSI_Camera::construct( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval )
|
|
{
|
|
JSI_Vector3D::Vector3D_Info* v = NULL;
|
|
|
|
JSObject* camera = JS_NewObject( cx, &JSI_Camera::JSI_class, NULL, NULL );
|
|
|
|
#define GETVECTOR( jv ) ( ( JSVAL_IS_OBJECT( jv ) && ( v = (JSI_Vector3D::Vector3D_Info*)JS_GetInstancePrivate( g_ScriptingHost.getContext(), JSVAL_TO_OBJECT( jv ), &JSI_Vector3D::JSI_class, NULL ) ) ) ? *(v->vector) : CVector3D() )
|
|
|
|
if( argc == 0 )
|
|
{
|
|
JS_SetPrivate( cx, camera, new Camera_Info() );
|
|
}
|
|
else if( argc == 1 )
|
|
{
|
|
JS_SetPrivate( cx, camera, new Camera_Info( GETVECTOR( argv[0] ) ) );
|
|
}
|
|
else if( argc == 2 )
|
|
{
|
|
JS_SetPrivate( cx, camera, new Camera_Info( GETVECTOR( argv[0] ), GETVECTOR( argv[1] ) ) );
|
|
}
|
|
else if( argc == 3 )
|
|
{
|
|
JS_SetPrivate( cx, camera, new Camera_Info( GETVECTOR( argv[0] ), GETVECTOR( argv[1] ), GETVECTOR( argv[2] ) ) );
|
|
}
|
|
else
|
|
{
|
|
JS_ReportError( cx, "[Camera] Too many arguments to constructor" );
|
|
*rval = JSVAL_NULL;
|
|
return( JS_TRUE );
|
|
}
|
|
|
|
#undef GET_VECTOR
|
|
|
|
*rval = OBJECT_TO_JSVAL( camera );
|
|
return( JS_TRUE );
|
|
}
|
|
|
|
void JSI_Camera::finalize( JSContext* cx, JSObject* obj )
|
|
{
|
|
delete( (Camera_Info*)JS_GetPrivate( cx, obj ) );
|
|
}
|
|
|