// K-3D
// Copyright (c) 1995-2004, Timothy M. Shead
//
// Contact: tshead@k-3d.com
//
// This program is free software; you can redistri_engineute 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.
//
// This program is distri_engineuted 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 this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

/** \file
		\brief Implements objects for wrapping the RenderMan API
		\author Tim Shead (tshead@k-3d.com)
*/

#include <k3dsdk/irenderman.h>
#include <boost/static_assert.hpp>
#include <jsapi.h>

namespace libk3djavascript
{

// Forward declarations;
k3d::ri::irender_engine& engine(JSContext* Context, JSObject* Object);

/// Provides scoped disabling of inline type declarations in the generated RIB
class disable_inline_types
{
public:
	disable_inline_types(k3d::ri::irender_engine& Engine) :
		m_engine(Engine),
		m_old_state(m_engine.set_inline_types(false))
	{
	}

	~disable_inline_types()
	{
		m_engine.set_inline_types(m_old_state);
	}

private:
	disable_inline_types(const disable_inline_types&);
	disable_inline_types& operator=(const disable_inline_types&);

	k3d::ri::irender_engine& m_engine;
	const bool m_old_state;
};

/// Converts a JavaScript value to a bool
const bool to_bool(JSContext* Context, jsval Value)
{
	JSBool result = JS_FALSE;
	assert_warning(JS_TRUE == JS_ValueToBoolean(Context, Value, &result));

	return JS_TRUE == result ? true : false;
}

/// Converts a JavaScript value to a RenderMan real
const k3d::ri::real to_real(JSContext* Context, jsval Value)
{
	k3d::ri::real result = 0;
	assert_warning(JS_TRUE == JS_ValueToNumber(Context, Value, &result));
	
	return result;
}

/// Converts a JavaScript array to an array of RenderMan reals
const k3d::ri::reals to_reals(JSContext* Context, jsval Value)
{
	k3d::ri::reals results;

	JSObject* object = 0;
	return_val_if_fail(JS_TRUE == JS_ValueToObject(Context, Value, &object), results);
	return_val_if_fail(object, results);
	
	jsuint array_length = 0;
	return_val_if_fail(JS_TRUE == JS_GetArrayLength(Context, object, &array_length), results);
	
	for(jsuint index = 0; index != array_length; ++index)
		{
			jsval array_element;
			return_val_if_fail(JS_TRUE == JS_GetElement(Context, object, index, &array_element), results);

			results.push_back(to_real(Context, array_element));			
		}

	return results;
}

/// Converts a JavaScript number value to a RenderMan integer
const k3d::ri::integer to_integer(JSContext* Context, jsval Value)
{
	k3d::ri::integer result = 0;
	jsint __result;
	assert_warning(JS_TRUE == JS_ValueToInt32(Context, Value, &__result));
	result = static_cast<k3d::ri::integer>(__result);
	
	return result;
}

/// Converts an JavaScript array to an array of RenderMan integers
const k3d::ri::integers to_integers(JSContext* Context, jsval Value)
{
	k3d::ri::integers results;

	JSObject* object = 0;
	return_val_if_fail(JS_TRUE == JS_ValueToObject(Context, Value, &object), results);
	return_val_if_fail(object, results);
	
	jsuint array_length = 0;
	return_val_if_fail(JS_TRUE == JS_GetArrayLength(Context, object, &array_length), results);
	
	for(jsuint index = 0; index != array_length; ++index)
		{
			jsval array_element;
			return_val_if_fail(JS_TRUE == JS_GetElement(Context, object, index, &array_element), results);
			
			results.push_back(to_integer(Context, array_element));
		}
			
	return results;
}

/// Converts a JavaScript number value to a RenderMan unsigned integer
const k3d::ri::integer to_unsigned_integer(JSContext* Context, jsval Value)
{
	k3d::ri::integer result = 0;
	jsint __result;
	assert_warning(JS_TRUE == JS_ValueToInt32(Context, Value, &__result));
	result = static_cast<k3d::ri::integer>(__result);
	
	return result;
}

/// Converts an JavaScript array to an array of RenderMan unsigned integers
const k3d::ri::unsigned_integers to_unsigned_integers(JSContext* Context, jsval Value)
{
	k3d::ri::unsigned_integers results;

	JSObject* object = 0;
	return_val_if_fail(JS_TRUE == JS_ValueToObject(Context, Value, &object), results);
	return_val_if_fail(object, results);
	
	jsuint array_length = 0;
	return_val_if_fail(JS_TRUE == JS_GetArrayLength(Context, object, &array_length), results);
	
	for(jsuint index = 0; index != array_length; ++index)
		{
			jsval array_element;
			return_val_if_fail(JS_TRUE == JS_GetElement(Context, object, index, &array_element), results);
			
			results.push_back(to_unsigned_integer(Context, array_element));
		}
			
	return results;
}

/// Converts a JavaScript string to a RenderMan string
const k3d::ri::string to_string(JSContext* Context, jsval Value)
{
	return JS_GetStringBytes(JS_ValueToString(Context, Value));
}

/// Converts an JavaScript array to an array of RenderMan strings
const k3d::ri::strings to_strings(JSContext* Context, jsval Value)
{
	k3d::ri::strings results;

	JSObject* object = 0;
	return_val_if_fail(JS_TRUE == JS_ValueToObject(Context, Value, &object), results);
	return_val_if_fail(object, results);
	
	jsuint array_length = 0;
	return_val_if_fail(JS_TRUE == JS_GetArrayLength(Context, object, &array_length), results);
	
	for(jsuint index = 0; index != array_length; ++index)
		{
			jsval array_element;
			return_val_if_fail(JS_TRUE == JS_GetElement(Context, object, index, &array_element), results);
			
			results.push_back(to_string(Context, array_element));
		}
			
	return results;
}

/// Converts a JavaScript array to a RenderMan point
const k3d::ri::point to_point(JSContext* Context, jsval Value)
{
	k3d::ri::reals a(to_reals(Context, Value));
	return_val_if_fail(3 == a.size(), k3d::ri::point(k3d::vector3(0, 0, 0)));
	
	return k3d::ri::point(k3d::vector3(a[0], a[1], a[2]));
}

/// Converts a JavaScript array to a RenderMan color
const k3d::ri::color to_color(JSContext* Context, jsval Value)
{
	k3d::ri::reals a(to_reals(Context, Value));
	return_val_if_fail(3 == a.size(), k3d::ri::color(0, 0, 0));
	
	return k3d::ri::color(a[0], a[1], a[2]);
}

/// Converts a set of JavaScript number values to a fixed-size array
template<int array_size>
const boost::array<k3d::ri::real, array_size> to_fixed_real_array(JSContext* Context, jsval Value)
{
	k3d::ri::reals a(to_reals(Context, Value));
	
	boost::array<k3d::ri::real, array_size> results;
	std::copy(a.begin(), a.end(), results.begin());
	
	return results;
}

/// Converts a JavaScript object to a RenderMan parameter list
const k3d::ri::parameter_list to_parameters(JSContext* Context, jsval Value)
{
	k3d::ri::parameter_list result;

	// If the value is empty, we're done ...
	if(JSVAL_IS_NULL(Value))
		return result;

	// Treat the value as an associative array ...
	JSObject* object = 0;
	return_val_if_fail(JS_TRUE == JS_ValueToObject(Context, Value, &object), result);
	if(!object)
		return result;

	// Get the set of all properties of the array ...
	JSIdArray* const properties = JS_Enumerate(Context, object);
	return_val_if_fail(properties, result);

	// For each property ...
	for(jsid* id = properties->vector; id != properties->vector + properties->length; ++id)
		{
			// Lookup the property name ...
			jsval name;
			return_val_if_fail(JS_TRUE == JS_IdToValue(Context, *id, &name), result);

			// Get the property value ...
			jsval value;
			return_val_if_fail(JS_TRUE == JS_GetProperty(Context, object, to_string(Context, name).c_str(), &value), result);
			return_val_if_fail(!JSVAL_IS_VOID(value), result);

			// The property value must be a non-empty array ...
			jsuint length = 0;
			return_val_if_fail(JS_TRUE == JS_GetArrayLength(Context, JSVAL_TO_OBJECT(value), &length), result);
			if(0 == length)
				continue;

			// Test the first element of the array to descover its type ...
			jsval first_element;
			JS_GetElement(Context, JSVAL_TO_OBJECT(value), 0, &first_element);
			if(JSVAL_IS_STRING(first_element))
				{
					// Must be an array of strings ...
					k3d::ri::strings array;
					for(jsuint i = 0; i != length; ++i)
						{
							jsval element;
							JS_GetElement(Context, JSVAL_TO_OBJECT(value), i, &element);
							array.push_back(to_string(Context, element));
						}

					/** \todo Handle type declaration better, here */
					result.push_back(k3d::ri::parameter(to_string(Context, name), k3d::ri::VERTEX, array));
				}
			else
				{
					// Must be an array of reals ...
					k3d::ri::reals array;
					for(jsuint i = 0; i != length; ++i)
						{
							jsval element;
							JS_GetElement(Context, JSVAL_TO_OBJECT(value), i, &element);
							array.push_back(to_real(Context, element));
						}

					/** \todo Handle type declaration better, here */
					result.push_back(k3d::ri::parameter(to_string(Context, name), k3d::ri::VERTEX, array));
				}
		}

	return result;
}

//light_handle_t RiAreaLightSourceV(const std::string Name, const parameter_list& Parameters = parameter_list())
JSBool RiAreaLightSourceV(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	disable_inline_types types(engine(Context, Object));
	
	const k3d::ri::light_handle light = engine(Context, Object).RiAreaLightSourceV(to_string(Context, argv[0]), to_parameters(Context, argv[1]));
	*Result = INT_TO_JSVAL(light);
	return JS_TRUE;
}

//void RiAtmosphereV(const std::string Name, const parameter_list& Parameters = parameter_list())
JSBool RiAtmosphereV(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	disable_inline_types types(engine(Context, Object));

	engine(Context, Object).RiAtmosphereV(to_string(Context, argv[0]), to_parameters(Context, argv[1]));
	return JS_TRUE;
}

//void RiAttributeBegin()
JSBool RiAttributeBegin(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiAttributeBegin();
	return JS_TRUE;
}

//void RiAttributeEnd()
JSBool RiAttributeEnd(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiAttributeEnd();
	return JS_TRUE;
}

//void RiAttributeV(const std::string Name, const parameter_list& Parameters = parameter_list())
JSBool RiAttributeV(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	disable_inline_types types(engine(Context, Object));

	engine(Context, Object).RiAttributeV(to_string(Context, argv[0]), to_parameters(Context, argv[1]));
	return JS_TRUE;
}

//void RiBasis(double UBasis[16], const uint32_t UStep, double VBasis[16], const uint32_t VStep)
JSBool RiBasis(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	if(JSVAL_IS_STRING(argv[0]) && JSVAL_IS_STRING(argv[2]))
		engine(Context, Object).RiBasis(to_string(Context, argv[0]), to_unsigned_integer(Context, argv[1]), to_string(Context, argv[2]), to_unsigned_integer(Context, argv[3]));
	else
		engine(Context, Object).RiBasis(to_fixed_real_array<16>(Context, argv[0]), to_unsigned_integer(Context, argv[1]), to_fixed_real_array<16>(Context, argv[2]), to_unsigned_integer(Context, argv[3]));
	return JS_TRUE;
}

//void RiBound(double Bound[6])
JSBool RiBound(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiBound(to_fixed_real_array<6>(Context, argv[0]));
	return JS_TRUE;
}

//void RiClipping(const double Hither, const double Yon)
JSBool RiClipping(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiClipping(to_real(Context, argv[0]), to_real(Context, argv[1]));
	return JS_TRUE;
}

//void RiColor(const color& Color)
JSBool RiColor(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiColor(to_color(Context, argv[0]));
	return JS_TRUE;
}

//void RiColorSamples(const uint32_t ParameterCount, double nRGB[], double RGBn[])
JSBool RiColorSamples(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiColorSamples(to_unsigned_integer(Context, argv[0]), to_reals(Context, argv[1]), to_reals(Context, argv[2]));
	return JS_TRUE;
}

//void RiComment(const std::string Comment)
JSBool RiComment(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiComment(to_string(Context, argv[0]));
	return JS_TRUE;
}

//void RiConcatTransform(double Transform[16])
JSBool RiConcatTransform(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiConcatTransform(to_fixed_real_array<16>(Context, argv[0]));
	return JS_TRUE;
}

//void RiConeV(const double Height, const double Radius, const double ThetaMax, const parameter_list& Parameters = parameter_list())
JSBool RiConeV(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	disable_inline_types types(engine(Context, Object));

	engine(Context, Object).RiConeV(to_real(Context, argv[0]), to_real(Context, argv[1]), to_real(Context, argv[2]), to_parameters(Context, argv[3]));
	return JS_TRUE;
}

//void RiCoordinateSystem(const std::string Space)
JSBool RiCoordinateSystem(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiCoordinateSystem(to_string(Context, argv[0]));
	return JS_TRUE;
}

//void RiCoordSysTransform(const std::string Space)
JSBool RiCoordSysTransform(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiCoordSysTransform(to_string(Context, argv[0]));
	return JS_TRUE;
}

//void RiCropWindow(const double XMin, const double XMax, const double YMin, const double YMax)
JSBool RiCropWindow(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiCropWindow(to_real(Context, argv[0]), to_real(Context, argv[1]), to_real(Context, argv[2]), to_real(Context, argv[3]));
	return JS_TRUE;
}

//void RiCurvesV(const std::string Degree, const uint32_t ParameterCountCurves, const uint32_t ParameterCountVerts[], std::string Wrap, const parameter_list& Parameters = parameter_list())
JSBool RiCurvesV(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	disable_inline_types types(engine(Context, Object));

	engine(Context, Object).RiCurvesV(to_string(Context, argv[0]), to_unsigned_integers(Context, argv[1]), to_string(Context, argv[2]), to_parameters(Context, argv[3]));
	return JS_TRUE;
}

//void RiCylinderV(const double Radius, const double ZMin, const double ZMax, const double ThetaMax, const parameter_list& Parameters = parameter_list())
JSBool RiCylinderV(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	disable_inline_types types(engine(Context, Object));

	engine(Context, Object).RiCylinderV(to_real(Context, argv[0]), to_real(Context, argv[1]), to_real(Context, argv[2]), to_real(Context, argv[3]), to_parameters(Context, argv[4]));
	return JS_TRUE;
}

//void RiDeclare(const std::string Name, const std::string Type)
JSBool RiDeclare(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiDeclare(to_string(Context, argv[0]), to_string(Context, argv[1]));
	return JS_TRUE;
}

//void RiDeformationV(const std::string Name, const parameter_list& Parameters = parameter_list())
JSBool RiDeformationV(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	disable_inline_types types(engine(Context, Object));

	engine(Context, Object).RiDeformationV(to_string(Context, argv[0]), to_parameters(Context, argv[1]));
	return JS_TRUE;
}

//void RiDepthOfField(const double FStop, const double FocalLength, const double FocalDistance)
JSBool RiDepthOfField(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiDepthOfField(to_real(Context, argv[0]), to_real(Context, argv[1]), to_real(Context, argv[2]));
	return JS_TRUE;
}

//void RiDetail(double Bound[6])
JSBool RiDetail(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiDetail(to_fixed_real_array<6>(Context, argv[0]));
	return JS_TRUE;
}

//void RiDetailRange(const double MinVis, const double LowTran, const double UpTran, const double MaxVis)
JSBool RiDetailRange(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiDetailRange(to_real(Context, argv[0]), to_real(Context, argv[1]), to_real(Context, argv[2]), to_real(Context, argv[3]));
	return JS_TRUE;
}

//void RiDiskV(double Height, double Radius, double ThetaMax, const parameter_list& Parameters = parameter_list())
JSBool RiDiskV(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	disable_inline_types types(engine(Context, Object));

	engine(Context, Object).RiDiskV(to_real(Context, argv[0]), to_real(Context, argv[1]), to_real(Context, argv[2]), to_parameters(Context, argv[3]));
	return JS_TRUE;
}

//void RiDisplacementV(const std::string Name, const parameter_list& Parameters = parameter_list())
JSBool RiDisplacementV(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiDisplacementV(to_string(Context, argv[0]), to_parameters(Context, argv[1]));
	return JS_TRUE;
}

//void RiDisplayV(const std::string Name, const std::string Type, const std::string Mode, const parameter_list& Parameters = parameter_list())
JSBool RiDisplayV(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	disable_inline_types types(engine(Context, Object));

	engine(Context, Object).RiDisplayV(to_string(Context, argv[0]), to_string(Context, argv[1]), to_string(Context, argv[2]), to_parameters(Context, argv[3]));
	return JS_TRUE;
}

//void RiErrorHandler(std::string Style)
JSBool RiErrorHandler(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiErrorHandler(to_string(Context, argv[0]));
	return JS_TRUE;
}

//void RiExposure(const double Gain, const double Gamma)
JSBool RiExposure(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiExposure(to_real(Context, argv[0]), to_real(Context, argv[1]));
	return JS_TRUE;
}

//void RiExteriorV(const std::string Name, const parameter_list& Parameters = parameter_list())
JSBool RiExteriorV(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	disable_inline_types types(engine(Context, Object));

	engine(Context, Object).RiExteriorV(to_string(Context, argv[0]), to_parameters(Context, argv[1]));
	return JS_TRUE;
}

//void RiFormat(const uint32_t XResolution, const uint32_t YResolution, const double AspectRatio)
JSBool RiFormat(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiFormat(to_integer(Context, argv[0]), to_integer(Context, argv[1]), to_real(Context, argv[2]));
	return JS_TRUE;
}

//void RiFrameAspectRatio(const double AspectRatio)
JSBool RiFrameAspectRatio(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiFrameAspectRatio(to_real(Context, argv[0]));
	return JS_TRUE;
}

//void RiFrameBegin(const uint32_t FrameNumber)
JSBool RiFrameBegin(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiFrameBegin(to_integer(Context, argv[0]));
	return JS_TRUE;
}

//void RiFrameEnd()
JSBool RiFrameEnd(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiFrameEnd();
	return JS_TRUE;
}

//void RiGeneralPolygonV(const uint32_t LoopCount, const uint32_t VertexCounts[], const parameter_list& Parameters = parameter_list())
JSBool RiGeneralPolygonV(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	disable_inline_types types(engine(Context, Object));

	engine(Context, Object).RiGeneralPolygonV(to_unsigned_integers(Context, argv[0]), to_parameters(Context, argv[1]));
	return JS_TRUE;
}

//void RiGeometricApproximation(const std::string Type, const double Value)
JSBool RiGeometricApproximation(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiGeometricApproximation(to_string(Context, argv[0]), to_real(Context, argv[1]));
	return JS_TRUE;
}

//void RiGeometricRepresentation(const std::string Type)
JSBool RiGeometricRepresentation(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiGeometricRepresentation(to_string(Context, argv[0]));
	return JS_TRUE;
}

//void RiGeometryV(const std::string Type, const parameter_list& Parameters = parameter_list())
JSBool RiGeometryV(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	disable_inline_types types(engine(Context, Object));

	engine(Context, Object).RiGeometryV(to_string(Context, argv[0]), to_parameters(Context, argv[1]));
	return JS_TRUE;
}

//void RiHiderV(const std::string Type, const parameter_list& Parameters = parameter_list())
JSBool RiHiderV(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	disable_inline_types types(engine(Context, Object));

	engine(Context, Object).RiHiderV(to_string(Context, argv[0]), to_parameters(Context, argv[1]));
	return JS_TRUE;
}

//void RiHyperboloidV(double Point1[3], double Point2[3], const double ThetaMax, const parameter_list& Parameters = parameter_list())
JSBool RiHyperboloidV(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	disable_inline_types types(engine(Context, Object));

	engine(Context, Object).RiHyperboloidV(to_point(Context, argv[0]), to_point(Context, argv[1]), to_real(Context, argv[2]), to_parameters(Context, argv[3]));
	return JS_TRUE;
}

//void RiIdentity()
JSBool RiIdentity(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiIdentity();
	return JS_TRUE;
}

//void RiIlluminate(const uint32_t LightHandle, const bool OnOff)
JSBool RiIlluminate(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiIlluminate(to_integer(Context, argv[0]), to_bool(Context, argv[1]));
	return JS_TRUE;
}

//void RiImagerV(const std::string Name, const parameter_list& Parameters = parameter_list())
JSBool RiImagerV(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	disable_inline_types types(engine(Context, Object));

	engine(Context, Object).RiImagerV(to_string(Context, argv[0]), to_parameters(Context, argv[1]));
	return JS_TRUE;
}

//void RiInteriorV(const std::string Name, const parameter_list& Parameters = parameter_list())
JSBool RiInteriorV(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	disable_inline_types types(engine(Context, Object));

	engine(Context, Object).RiInteriorV(to_string(Context, argv[0]), to_parameters(Context, argv[1]));
	return JS_TRUE;
}

//light_handle_t RiLightSourceV(const std::string Name, const parameter_list& Parameters = parameter_list())
JSBool RiLightSourceV(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	disable_inline_types types(engine(Context, Object));

	const k3d::ri::light_handle light = engine(Context, Object).RiLightSourceV(to_string(Context, argv[0]), to_parameters(Context, argv[1]));
	*Result = INT_TO_JSVAL(light);
	return JS_TRUE;
}

//void RiMakeCubeFaceEnvironmentV(const std::string px, const std::string nx, const std::string py, const std::string ny, const std::string pz, const std::string nz, const std::string texturename, const double fov, const std::string swrap, const std::string twrap, const std::string filterfunc, const double swidth, const double twidth, const parameter_list& Parameters = parameter_list())
JSBool RiMakeCubeFaceEnvironmentV(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	disable_inline_types types(engine(Context, Object));

	engine(Context, Object).RiMakeCubeFaceEnvironmentV(to_string(Context, argv[0]), to_string(Context, argv[1]), to_string(Context, argv[2]), to_string(Context, argv[3]), to_string(Context, argv[4]), to_string(Context, argv[5]), to_string(Context, argv[6]), to_real(Context, argv[7]), to_string(Context, argv[8]), to_string(Context, argv[9]), to_string(Context, argv[10]), to_real(Context, argv[11]), to_real(Context, argv[12]), to_parameters(Context, argv[13]));
	return JS_TRUE;
}

//void RiMakeLatLongEnvironmentV(const std::string picturename, const std::string texturename, const std::string filterfunc, const double swidth, const double twidth, const parameter_list& Parameters = parameter_list())
JSBool RiMakeLatLongEnvironmentV(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	disable_inline_types types(engine(Context, Object));

	engine(Context, Object).RiMakeLatLongEnvironmentV(to_string(Context, argv[0]), to_string(Context, argv[1]), to_string(Context, argv[2]), to_real(Context, argv[3]), to_real(Context, argv[4]), to_parameters(Context, argv[5]));
	return JS_TRUE;
}

//void RiMakeShadowV(const std::string picturename, const std::string texturename, const parameter_list& Parameters = parameter_list())
JSBool RiMakeShadowV(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	disable_inline_types types(engine(Context, Object));

	engine(Context, Object).RiMakeShadowV(to_string(Context, argv[0]), to_string(Context, argv[1]), to_parameters(Context, argv[2]));
	return JS_TRUE;
}

//void RiMakeTextureV(const std::string picturename, const std::string texturename, const std::string swrap, const std::string twrap, const std::string filterfunc, const double swidth, const double twidth, const parameter_list& Parameters = parameter_list())
JSBool RiMakeTextureV(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	disable_inline_types types(engine(Context, Object));

	engine(Context, Object).RiMakeTextureV(to_string(Context, argv[0]), to_string(Context, argv[1]), to_string(Context, argv[2]), to_string(Context, argv[3]), to_string(Context, argv[4]), to_real(Context, argv[5]), to_real(Context, argv[6]), to_parameters(Context, argv[7]));
	return JS_TRUE;
}

//void RiMatte(const bool OnOff)
JSBool RiMatte(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiMatte(to_bool(Context, argv[0]));
	return JS_TRUE;
}

//void RiMotionBeginV(const uint32_t ParameterCount, const double Times[])
JSBool RiMotionBeginV(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiMotionBeginV(to_reals(Context, argv[0]));
	return JS_TRUE;
}

//void RiMotionEnd()
JSBool RiMotionEnd(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiMotionEnd();
	return JS_TRUE;
}

//void RiNewline()
JSBool RiNewline(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiNewline();
	return JS_TRUE;
}

//void RiNuPatchV(const uint32_t UCount, const uint32_t UOrder, double UKnot[], const double UMin, const double UMax, const uint32_t VCount, const uint32_t VOrder, double VKnot[], const double VMin, const double VMax, const parameter_list& Parameters = parameter_list())
JSBool RiNuPatchV(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	disable_inline_types types(engine(Context, Object));

	engine(Context, Object).RiNuPatchV(to_unsigned_integer(Context, argv[0]), to_unsigned_integer(Context, argv[1]), to_reals(Context, argv[2]), to_real(Context, argv[3]), to_real(Context, argv[4]), to_unsigned_integer(Context, argv[5]), to_unsigned_integer(Context, argv[6]), to_reals(Context, argv[7]), to_real(Context, argv[8]), to_real(Context, argv[9]), to_parameters(Context, argv[10]));
	return JS_TRUE;
}

//object_handle_t RiObjectBegin()
JSBool RiObjectBegin(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	const k3d::ri::object_handle object = engine(Context, Object).RiObjectBegin();
	*Result = INT_TO_JSVAL(object);
	return JS_TRUE;
}

//void RiObjectEnd()
JSBool RiObjectEnd(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiObjectEnd();
	return JS_TRUE;
}

//void RiObjectInstance(const uint32_t Object)
JSBool RiObjectInstance(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiObjectInstance(to_integer(Context, argv[0]));
	return JS_TRUE;
}

//void RiOpacity(const color& Opacity)
JSBool RiOpacity(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiOpacity(to_color(Context, argv[0]));
	return JS_TRUE;
}

//void RiOptionV(const std::string Name, const parameter_list& Parameters = parameter_list())
JSBool RiOptionV(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	disable_inline_types types(engine(Context, Object));

	engine(Context, Object).RiOptionV(to_string(Context, argv[0]), to_parameters(Context, argv[1]));
	return JS_TRUE;
}

//void RiOrientation(const std::string Orientation)
JSBool RiOrientation(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiOrientation(to_string(Context, argv[0]));
	return JS_TRUE;
}

//void RiParaboloidV(const double RMax, const double ZMin, const double ZMax, const double ThetaMax, const parameter_list& Parameters = parameter_list())
JSBool RiParaboloidV(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	disable_inline_types types(engine(Context, Object));

	engine(Context, Object).RiParaboloidV(to_real(Context, argv[0]), to_real(Context, argv[1]), to_real(Context, argv[2]), to_real(Context, argv[3]), to_parameters(Context, argv[4]));
	return JS_TRUE;
}

//void RiPatchMeshV(const std::string Type, const uint32_t UCount, std::string UWrap, const uint32_t VCount, std::string VWrap, const parameter_list& Parameters = parameter_list())
JSBool RiPatchMeshV(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	disable_inline_types types(engine(Context, Object));

	engine(Context, Object).RiPatchMeshV(to_string(Context, argv[0]), to_unsigned_integer(Context, argv[1]), to_string(Context, argv[2]), to_unsigned_integer(Context, argv[3]), to_string(Context, argv[4]), to_parameters(Context, argv[5]));
	return JS_TRUE;
}

//void RiPatchV(const std::string Type, const parameter_list& Parameters = parameter_list())
JSBool RiPatchV(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	disable_inline_types types(engine(Context, Object));

	engine(Context, Object).RiPatchV(to_string(Context, argv[0]), to_parameters(Context, argv[1]));
	return JS_TRUE;
}

//void RiPerspective(const double FieldOfView)
JSBool RiPerspective(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiPerspective(to_real(Context, argv[0]));
	return JS_TRUE;
}

//void RiPixelFilter(const std::string FilterName, const double XWidth, const double YWidth)
JSBool RiPixelFilter(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiPixelFilter(to_string(Context, argv[0]), to_real(Context, argv[1]), to_real(Context, argv[2]));
	return JS_TRUE;
}

//void RiPixelSamples(const double XSamples, const double YSamples)
JSBool RiPixelSamples(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiPixelSamples(to_real(Context, argv[0]), to_real(Context, argv[1]));
	return JS_TRUE;
}

//void RiPixelVariance(const double Variation)
JSBool RiPixelVariance(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiPixelVariance(to_real(Context, argv[0]));
	return JS_TRUE;
}

//void RiPointsGeneralPolygonsV(const uint32_t PolygonCount, uint32_t LoopCounts[], uint32_t VertexCounts[], uint32_t Vertices[], const parameter_list& Parameters = parameter_list())
JSBool RiPointsGeneralPolygonsV(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	disable_inline_types types(engine(Context, Object));

	engine(Context, Object).RiPointsGeneralPolygonsV(to_unsigned_integers(Context, argv[0]), to_unsigned_integers(Context, argv[1]), to_unsigned_integers(Context, argv[2]), to_parameters(Context, argv[3]));
	return JS_TRUE;
}

//void RiPointsPolygonsV(const uint32_t PolygonCount, const std::vector<uint32_t>& VertexCounts, const std::vector<uint32_t>& Vertices, const parameter_list& Parameters = parameter_list())
JSBool RiPointsPolygonsV(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	disable_inline_types types(engine(Context, Object));

	engine(Context, Object).RiPointsPolygonsV(to_unsigned_integers(Context, argv[0]), to_unsigned_integers(Context, argv[1]), to_parameters(Context, argv[2]));
	return JS_TRUE;
}

//void RiPointsV(const uint32_t VertexCount, const parameter_list& Parameters = parameter_list())
JSBool RiPointsV(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	disable_inline_types types(engine(Context, Object));

	engine(Context, Object).RiPointsV(to_integer(Context, argv[0]), to_parameters(Context, argv[1]));
	return JS_TRUE;
}

//void RiPolygonV(const uint32_t VertexCount, const parameter_list& Parameters = parameter_list())
JSBool RiPolygonV(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	disable_inline_types types(engine(Context, Object));

	engine(Context, Object).RiPolygonV(to_integer(Context, argv[0]), to_parameters(Context, argv[1]));
	return JS_TRUE;
}

//void RiProjectionV(const std::string Name, const parameter_list& Parameters = parameter_list())
JSBool RiProjectionV(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	disable_inline_types types(engine(Context, Object));

	engine(Context, Object).RiProjectionV(to_string(Context, argv[0]), to_parameters(Context, argv[1]));
	return JS_TRUE;
}

//void RiQuantize(const std::string Type, const int32_t One, const int32_t QMin, const int32_t QMax, const double Amplitude)
JSBool RiQuantize(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiQuantize(to_string(Context, argv[0]), to_integer(Context, argv[1]), to_integer(Context, argv[2]), to_integer(Context, argv[3]), to_real(Context, argv[4]));
	return JS_TRUE;
}

//void RiReadArchive(const std::string Archive)
JSBool RiReadArchive(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiReadArchive(to_string(Context, argv[0]));
	return JS_TRUE;
}

//void RiRelativeDetail(const double RelativeDetail)
JSBool RiRelativeDetail(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiRelativeDetail(to_real(Context, argv[0]));
	return JS_TRUE;
}

//void RiReverseOrientation()
JSBool RiReverseOrientation(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiReverseOrientation();
	return JS_TRUE;
}

//void RiRotate(const double angle, const double DX, const double DY, const double DZ)
JSBool RiRotate(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiRotate(to_real(Context, argv[0]), to_real(Context, argv[1]), to_real(Context, argv[2]), to_real(Context, argv[3]));
	return JS_TRUE;
}

//void RiScale(const double DX, const double DY, const double DZ)
JSBool RiScale(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiScale(to_real(Context, argv[0]), to_real(Context, argv[1]), to_real(Context, argv[2]));
	return JS_TRUE;
}

//void RiScreenWindow(const double Left, const double Right, const double Bottom, const double Top)
JSBool RiScreenWindow(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiScreenWindow(to_real(Context, argv[0]), to_real(Context, argv[1]), to_real(Context, argv[2]), to_real(Context, argv[3]));
	return JS_TRUE;
}

//void RiShadingInterpolation(const std::string Type)
JSBool RiShadingInterpolation(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiShadingInterpolation(to_string(Context, argv[0]));
	return JS_TRUE;
}

//void RiShadingRate(const double Size)
JSBool RiShadingRate(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiShadingRate(to_real(Context, argv[0]));
	return JS_TRUE;
}

//void RiShutter(const double SMin, const double SMax)
JSBool RiShutter(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiShutter(to_real(Context, argv[0]), to_real(Context, argv[1]));
	return JS_TRUE;
}

//void RiSides(const uint32_t Sides)
JSBool RiSides(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiSides(to_integer(Context, argv[0]));
	return JS_TRUE;
}

//void RiSkew(const double Angle, const double DX1, const double DY1, const double DZ1, const double DX2, const double DY2, const double DZ2)
JSBool RiSkew(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiSkew(to_real(Context, argv[0]), to_real(Context, argv[1]), to_real(Context, argv[2]), to_real(Context, argv[3]), to_real(Context, argv[4]), to_real(Context, argv[5]), to_real(Context, argv[6]));
	return JS_TRUE;
}

//void RiSolidBegin(const std::string Type)
JSBool RiSolidBegin(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiSolidBegin(to_string(Context, argv[0]));
	return JS_TRUE;
}

//void RiSolidEnd()
JSBool RiSolidEnd(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiSolidEnd();
	return JS_TRUE;
}

//void RiSphereV(const double Radius, const double ZMin, const double ZMax, const double ThetaMax, const parameter_list& Parameters = parameter_list())
JSBool RiSphereV(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	disable_inline_types types(engine(Context, Object));

	engine(Context, Object).RiSphereV(to_real(Context, argv[0]), to_real(Context, argv[1]), to_real(Context, argv[2]), to_real(Context, argv[3]), to_parameters(Context, argv[4]));
	return JS_TRUE;
}

//void RiStructure(const std::string Structure)
JSBool RiStructure(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiStructure(to_string(Context, argv[0]));
	return JS_TRUE;
}

//void RiSubdivisionMeshV(const std::string Scheme, const uint32_t PolygonCount, uint32_t VertexCounts[], uint32_t Vertices[], const uint32_t TagCount, const strings_t& Tags, uint32_t ArgCounts[], uint32_t IntegerArgs[], double FloatArgs[], const parameter_list& Parameters = parameter_list())
JSBool RiSubdivisionMeshV(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	disable_inline_types types(engine(Context, Object));

	engine(Context, Object).RiSubdivisionMeshV(to_string(Context, argv[0]), to_unsigned_integers(Context, argv[1]), to_unsigned_integers(Context, argv[2]), to_strings(Context, argv[3]), to_unsigned_integers(Context, argv[4]), to_integers(Context, argv[5]), to_reals(Context, argv[6]), to_parameters(Context, argv[7]));
	return JS_TRUE;
}

//void RiSurfaceV(const std::string Name, const parameter_list& Parameters = parameter_list())
JSBool RiSurfaceV(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	disable_inline_types types(engine(Context, Object));

	engine(Context, Object).RiSurfaceV(to_string(Context, argv[0]), to_parameters(Context, argv[1]));
	return JS_TRUE;
}

//void RiTextureCoordinates(const double S1, const double T1, const double S2, const double T2, const double S3, const double T3, const double S4, const double T4)
JSBool RiTextureCoordinates(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiTextureCoordinates(to_real(Context, argv[0]), to_real(Context, argv[1]), to_real(Context, argv[2]), to_real(Context, argv[3]), to_real(Context, argv[4]), to_real(Context, argv[5]), to_real(Context, argv[6]), to_real(Context, argv[7]));
	return JS_TRUE;
}

//void RiTorusV(const double MajorRadius, const double MinorRadius, const double PhiMin, const double PhiMax, const double ThetaMax, const parameter_list& Parameters = parameter_list())
JSBool RiTorusV(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	disable_inline_types types(engine(Context, Object));

	engine(Context, Object).RiTorusV(to_real(Context, argv[0]), to_real(Context, argv[1]), to_real(Context, argv[2]), to_real(Context, argv[3]), to_real(Context, argv[4]), to_parameters(Context, argv[5]));
	return JS_TRUE;
}

//void RiTransformBegin()
JSBool RiTransformBegin(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiTransformBegin();
	return JS_TRUE;
}

//void RiTransform(double Transform[16])
JSBool RiTransform(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiTransform(to_fixed_real_array<16>(Context, argv[0]));
	return JS_TRUE;
}

//void RiTransformEnd()
JSBool RiTransformEnd(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiTransformEnd();
	return JS_TRUE;
}

//void RiTranslate(const double DX, const double DY, const double DZ)
JSBool RiTranslate(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiTranslate(to_real(Context, argv[0]), to_real(Context, argv[1]), to_real(Context, argv[2]));
	return JS_TRUE;
}

//void RiTrimCurve(const uint32_t LoopCount, uint32_t CuveCounts[], uint32_t Order[], double Knot[], double AMin[], double AMax[], const uint32_t ParameterCount, double U[], double V[], double W[])
JSBool RiTrimCurve(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiTrimCurve(to_unsigned_integer(Context, argv[0]), to_unsigned_integers(Context, argv[1]), to_unsigned_integers(Context, argv[2]), to_reals(Context, argv[3]), to_reals(Context, argv[4]), to_reals(Context, argv[5]), to_unsigned_integers(Context, argv[6]), to_reals(Context, argv[7]), to_reals(Context, argv[8]), to_reals(Context, argv[9]));
	return JS_TRUE;
}

//void RiWorldBegin()
JSBool RiWorldBegin(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiWorldBegin();
	return JS_TRUE;
}

//void RiWorldEnd()
JSBool RiWorldEnd(JSContext* Context, JSObject* Object, uintN argc, jsval* argv, jsval* Result)
{
	engine(Context, Object).RiWorldEnd();
	return JS_TRUE;
}

JSClass ri_engine_class =
{
	"ri_engine", JSCLASS_HAS_PRIVATE, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
};

JSPropertySpec ri_engine_properties[] =
{
	{0}
};

JSFunctionSpec ri_engine_methods[] =
{
	{ "AreaLightSource", RiAreaLightSourceV, 2, 0, 0 },
	{ "Atmosphere", RiAtmosphereV, 2, 0, 0 },
	{ "Attribute", RiAttributeV, 2, 0, 0 },
	{ "AttributeBegin", RiAttributeBegin, 0, 0, 0 },
	{ "AttributeEnd", RiAttributeEnd, 0, 0, 0 },
	{ "Basis", RiBasis, 4, 0, 0 },
	{ "Bound", RiBound, 1, 0, 0 },
	{ "Clipping", RiClipping, 2, 0, 0 },
	{ "Color", RiColor, 1, 0, 0 },
	{ "Comment", RiComment, 1, 0, 0 },
	{ "ConcatTransform", RiConcatTransform, 1, 0, 0 },
	{ "Cone", RiConeV, 4, 0, 0 },
	{ "CoordSysTransform", RiCoordSysTransform, 1, 0, 0 },
	{ "CoordinateSystem", RiCoordinateSystem, 1, 0, 0 },
	{ "CropWindow", RiCropWindow, 4, 0, 0 },
	{ "Curves", RiCurvesV, 4, 0, 0 },
	{ "Cylinder", RiCylinderV, 5, 0, 0 },
	{ "Declare", RiDeclare, 2, 0, 0 },
	{ "Deformation", RiDeformationV, 2, 0, 0 },
	{ "DepthOfField", RiDepthOfField, 3, 0, 0 },
	{ "Detail", RiDetail, 1, 0, 0 },
	{ "DetailRange", RiDetailRange, 4, 0, 0 },
	{ "Disk", RiDiskV, 4, 0, 0 },
	{ "Displacement", RiDisplacementV, 2, 0, 0 },
	{ "Display", RiDisplayV, 4, 0, 0 },
	{ "ErrorHandler", RiErrorHandler, 1, 0, 0 },
	{ "Exposure", RiExposure, 2, 0, 0 },
	{ "Exterior", RiExteriorV, 2, 0, 0 },
	{ "Format", RiFormat, 3, 0, 0 },
	{ "FrameAspectRatio", RiFrameAspectRatio, 1, 0, 0 },
	{ "FrameBegin", RiFrameBegin, 1, 0, 0 },
	{ "FrameEnd", RiFrameEnd, 0, 0, 0 },
	{ "GeneralPolygon", RiGeneralPolygonV, 2, 0, 0 },
	{ "GeometricApproximation", RiGeometricApproximation, 2, 0, 0 },
	{ "GeometricRepresentation", RiGeometricRepresentation, 1, 0, 0 },
	{ "Geometry", RiGeometryV, 2, 0, 0 },
	{ "Hider", RiHiderV, 2, 0, 0 },
	{ "Hyperboloid", RiHyperboloidV, 4, 0, 0 },
	{ "Identity", RiIdentity, 0, 0, 0 },
	{ "Illuminate", RiIlluminate, 2, 0, 0 },
	{ "Imager", RiImagerV, 2, 0, 0 },
	{ "Interior", RiInteriorV, 2, 0, 0 },
	{ "LightSource", RiLightSourceV, 2, 0, 0 },
	{ "MakeCubeFaceEnvironment", RiMakeCubeFaceEnvironmentV, 13, 0, 0 },
	{ "MakeLatLongEnvironment", RiMakeLatLongEnvironmentV, 6, 0, 0 },
	{ "MakeShadow", RiMakeShadowV, 3, 0, 0 },
	{ "MakeTexture", RiMakeTextureV, 8, 0, 0 },
	{ "Matte", RiMatte, 1, 0, 0 },
	{ "MotionBegin", RiMotionBeginV, 1, 0, 0 },
	{ "MotionEnd", RiMotionEnd, 0, 0, 0 },
	{ "Newline", RiNewline, 0, 0, 0 },
	{ "NuPatch", RiNuPatchV, 11, 0, 0 },
	{ "ObjectBegin", RiObjectBegin, 0, 0, 0 },
	{ "ObjectEnd", RiObjectEnd, 0, 0, 0 },
	{ "ObjectInstance", RiObjectInstance, 1, 0, 0 },
	{ "Opacity", RiOpacity, 1, 0, 0 },
	{ "Option", RiOptionV, 2, 0, 0 },
	{ "Orientation", RiOrientation, 1, 0, 0 },
	{ "Paraboloid", RiParaboloidV, 5, 0, 0 },
	{ "Patch", RiPatchV, 2, 0, 0 },
	{ "PatchMesh", RiPatchMeshV, 6, 0, 0 },
	{ "Perspective", RiPerspective, 1, 0, 0 },
	{ "PixelFilter", RiPixelFilter, 3, 0, 0 },
	{ "PixelSamples", RiPixelSamples, 2, 0, 0 },
	{ "PixelVariance", RiPixelVariance, 1, 0, 0 },
	{ "Points", RiPointsV, 2, 0, 0 },
	{ "PointsGeneralPolygons", RiPointsGeneralPolygonsV, 4, 0, 0 },
	{ "PointsPolygons", RiPointsPolygonsV, 3, 0, 0 },
	{ "Polygon", RiPolygonV, 2, 0, 0 },
	{ "Projection", RiProjectionV, 2, 0, 0 },
	{ "Quantize", RiQuantize, 5, 0, 0 },
	{ "ReadArchive", RiReadArchive, 1, 0, 0 },
	{ "RelativeDetail", RiRelativeDetail, 1, 0, 0 },
	{ "ReverseOrientation", RiReverseOrientation, 0, 0, 0 },
	{ "Rotate", RiRotate, 4, 0, 0 },
	{ "Scale", RiScale, 3, 0, 0 },
	{ "ScreenWindow", RiScreenWindow, 4, 0, 0 },
	{ "ShadingInterpolation", RiShadingInterpolation, 1, 0, 0 },
	{ "ShadingRate", RiShadingRate, 1, 0, 0 },
	{ "Shutter", RiShutter, 2, 0, 0 },
	{ "Sides", RiSides, 1, 0, 0 },
	{ "Skew", RiSkew, 7, 0, 0 },
	{ "SolidBegin", RiSolidBegin, 1, 0, 0 },
	{ "SolidEnd", RiSolidEnd, 0, 0, 0 },
	{ "Sphere", RiSphereV, 4, 0, 0 },
	{ "Structure", RiStructure, 1, 0, 0 },
	{ "SubdivisionMesh", RiSubdivisionMeshV, 8, 0, 0 },
	{ "Surface", RiSurfaceV, 2, 0, 0 },
	{ "TextureCoordinates", RiTextureCoordinates, 8, 0, 0 },
	{ "Torus", RiTorusV, 6, 0, 0 },
	{ "TrandformEnd", RiTransformEnd, 0, 0, 0 },
	{ "Transform", RiTransform, 1, 0, 0 },
	{ "TransformBegin", RiTransformBegin, 0, 0, 0 },
	{ "Translate", RiTranslate, 3, 0, 0 },
	{ "TrimCurve", RiTrimCurve, 10, 0, 0 },
	{ "WorldBegin", RiWorldBegin, 0, 0, 0 },
	{ "WorldEnd", RiWorldEnd, 0, 0, 0 },
	{0}
};

k3d::ri::irender_engine& engine(JSContext* Context, JSObject* Object)
{
	return *reinterpret_cast<k3d::ri::irender_engine*>(JS_GetInstancePrivate(Context, Object, &ri_engine_class, 0));
}

JSObject* create_renderman_engine(k3d::ri::irender_engine& Engine, JSContext* Context)
{
	// Create the generic object instance ...
	JSObject* const object = JS_NewObject(Context, &ri_engine_class, 0, 0);

	// Set the wrapped-object's interface ...
	JS_SetPrivate(Context, object, &Engine);

	// Set object methods ...
	JS_DefineFunctions(Context, object, ri_engine_methods);

	return object;
}

} // namespace libk3djavascript

