Some of my helper-classes

Started by
1 comment, last by LDenninger 19 years, 8 months ago
Just in case someone might find a use for them : here's my code to register some stuff to use simple 2d/3d vectors, RGBA-colors, and a simple vertex-class. I created them to let users draw lines/triangles and whatever from scripts. No guarantee that everything is as it should be - I'm presenting it as-is :) Oh, it includes my ASArray.h stuff - it compiles but I have never tested the Array-implementation !!! ASD3DUtils.h :

#ifndef _AS_D3D_UTILS_
#define _AS_D3D_UTILS_

#pragma once

#include <math.h>
#include <D3DX9Math.h>

//
// forward declares (prevents includes thus reducing compiletime)
//
class asIScriptEngine;
class asIScriptContext;



//---------------------------------------------------------------------------------------------------------------------
//	Utility functions
//---------------------------------------------------------------------------------------------------------------------


//
// gClamp - clamps variables between a min and a max value
//
template<typename T>
__forceinline const T&	gClamp(const T& inValue, const T& inLow, const T& inHigh){ if (inValue<inLow) return inLow; else if (inValue>inHigh) return inHigh; else return inValue; }
// Template uses references : for floats it's faster not using references
__forceinline float		gClamp(float inValue, float inLow, float inHigh)		{ if (inValue<inLow) return inLow; else if (inValue>inHigh) return inHigh; else return inValue; }




//---------------------------------------------------------------------------------------------------------------------
//
//	Vector math :
//
//	Vectors are derived from the D3DX structs, so all D3DX-VectorMath functions will accept them as input.
//
//---------------------------------------------------------------------------------------------------------------------



//
// Vector2 : 2 dimensional vector
//
struct Vector2 : public D3DXVECTOR2
{
							Vector2() : D3DXVECTOR2() { }
							Vector2(const float * inData) : D3DXVECTOR2(inData) { }
							Vector2(const D3DXFLOAT16 * inData) : D3DXVECTOR2(inData) { }
							Vector2(float inX, float inY) : D3DXVECTOR2(inX, inY) { }
							
	float					SquareLength() const				{ return x*x + y*y; }
	float					Length() const						{ return float(sqrt(SquareLength())); }
	float					Dot(const Vector2 &inRHS) const		{ return x*inRHS.x + y*inRHS.y; }
	float					Cross(const Vector2 &inRHS) const	{ return x * inRHS.y - y * inRHS.x; }
							
	void					Normalize()							{ float length = Length(); if (length != 0.0f) { x/=length;y/=length; } }
	Vector2					Normalized() const					{ Vector2 v(*this); v.Normalize(); return v; }

	Vector2					GetPerpendicular() const			{ return Vector2(-y, x); }
	Vector2					GetNormalizedPerpendicular() const	{ return Vector2(-y, x).Normalized(); }

	// script functions
	static void	_cdecl		ASConstruct(Vector2 & inThis);
	static Vector2 & _cdecl	ASAssign(const Vector2 & inSource, Vector2 & inDest);
	static Vector2 _cdecl	ASOperatorAdd(const Vector2 & inLHS, const Vector2 & inRHS);
	static Vector2 _cdecl	ASOperatorSub(const Vector2 & inLHS, const Vector2 & inRHS);
	static Vector2 _cdecl	ASOperatorMul(const Vector2 & inLHS, const float inRHS);
	static Vector2 _cdecl	ASOperatorDiv(const Vector2 & inLHS, const float inRHS);
	static bool	_cdecl		ASOperatorEqual(const Vector2 & inLHS, const Vector2 &inRHS);
	static bool	_cdecl		ASOperatorNotEqual(const Vector2 & inLHS, const Vector2 &inRHS);

	void					Set(float inX, float inY)			{ x = inX; y = inY; }
	void					Add(Vector2 & inRHS)				{ x+= inRHS.x; y+=inRHS.y; }
	void					Sub(Vector2 & inRHS)				{ x-= inRHS.x; y-=inRHS.y; }
	void					Scale(float inScale)				{ x*= inScale; y*=inScale; }
	void					Blend(const Vector2 & inOther, float inFactor)		{ x = x + (inOther.x - x) * inFactor; y = y + (inOther.y - y) * inFactor; }

	inline bool				operator == (const Vector2 & inRHS) const	{ return ((inRHS.x == x) && (inRHS.y == y)); }
	inline bool				operator != (const Vector2 & inRHS) const	{ return ((inRHS.x != x) || (inRHS.y != y)); }
	inline const Vector2	operator - () const							{ return Vector2(-x, -y); }
	inline const Vector2	operator + (const Vector2 & inRHS) const	{ return Vector2(x+inRHS.x, y+inRHS.y); }
	inline const Vector2	operator - (const Vector2 & inRHS) const	{ return Vector2(x-inRHS.x, y-inRHS.y); }
	inline const Vector2	operator * (const float & inF) const		{ return Vector2(x*inF, y*inF); }
	inline const Vector2	operator / (const float & inF) const		{ return Vector2(x/inF, y/inF); }
	inline Vector2&			operator += (const Vector2 & inRHS)			{ x+=inRHS.x; y+=inRHS.y; return *this; }
	inline Vector2&			operator -= (const Vector2 & inRHS)			{ x-=inRHS.x; y-=inRHS.y; return *this; }
	inline Vector2&			operator *= (const float & inF)				{ x*=inF; y*=inF; return *this; }
	inline Vector2&			operator /= (const float & inF)				{ x/=inF; y/=inF; return *this; }

	static const Vector2	sZero;
	static const Vector2	sOne;
};



//
// Vector3 : 3 dimensional vector
//
struct Vector3 : public D3DXVECTOR3
{
							Vector3() : D3DXVECTOR3() { }
							Vector3(const float * inData) : D3DXVECTOR3(inData) { }
							Vector3(const D3DXFLOAT16 * inData) : D3DXVECTOR3(inData) { }
							Vector3(float inX, float inY, float inZ) : D3DXVECTOR3(inX, inY, inZ) { }
							
	float					SquareLength() const				{ return x*x + y*y + z*z; }
	float					Length() const						{ return float(sqrt(SquareLength())); }
	float					Dot(const Vector3 &inRHS) const		{ return x*inRHS.x + y*inRHS.y + z*inRHS.z; }
	Vector3					Cross(const Vector3 &inRHS) const	{ return Vector3(y * inRHS.z - z * inRHS.y,	z * inRHS.x - x * inRHS.z,	x * inRHS.y - y * inRHS.x); }
						
	void					Normalize()							{ float length = Length(); if (length != 0.0f) { x/=length;y/=length;z/=length; } }
	Vector3					Normalized() const					{ Vector3 v(*this); v.Normalize(); return v; }

	// script functions
	static void	_cdecl		ASConstruct(Vector3 & inThis);
	static Vector3&	_cdecl	ASAssign(const Vector3 & inSource, Vector3 & inDest);
	static Vector3 _cdecl	ASOperatorAdd(const Vector3 & inLHS, const Vector3 & inRHS);
	static Vector3 _cdecl	ASOperatorSub(const Vector3 & inLHS, const Vector3 & inRHS);
	static Vector3 _cdecl	ASOperatorMul(const Vector3 & inLHS, const float inRHS);
	static Vector3 _cdecl	ASOperatorDiv(const Vector3 & inLHS, const float inRHS);
	static bool	_cdecl		ASOperatorEqual(const Vector3 & inLHS, const Vector3 &inRHS);
	static bool _cdecl		ASOperatorNotEqual(const Vector3 & inLHS, const Vector3 &inRHS);

	void					Set(float inX, float inY, float inZ)	{ x = inX; y = inY; z = inZ; }
	void					Add(Vector3 & inRHS)				{ x+= inRHS.x; y+=inRHS.y; z+=inRHS.z; }
	void					Sub(Vector3 & inRHS)				{ x-= inRHS.x; y-=inRHS.y; z-=inRHS.z;}
	void					Scale(float inScale)				{ x*= inScale; y*=inScale; z*=inScale;}
	void					Blend(const Vector3 & inOther, float inFactor)		{ x = x + (inOther.x - x) * inFactor; y = y + (inOther.y - y) * inFactor; z = z + (inOther.z - z) * inFactor; }

	inline bool				operator == (const Vector3 & inRHS) const	{ return ((inRHS.x == x) && (inRHS.y == y) && (inRHS.z == z)); }
	inline bool				operator != (const Vector3 & inRHS) const	{ return ((inRHS.x != x) || (inRHS.y != y) || (inRHS.z != z)); }
	inline const Vector3	operator - () const							{ return Vector3(-x, -y, -z); }
	inline const Vector3	operator + (const Vector3 & inRHS) const	{ return Vector3(x+inRHS.x, y+inRHS.y, z+inRHS.z); }
	inline const Vector3	operator - (const Vector3 & inRHS) const	{ return Vector3(x-inRHS.x, y-inRHS.y, z-inRHS.z); }
	inline const Vector3	operator * (const float & inF) const		{ return Vector3(x*inF, y*inF, z*inF); }
	inline const Vector3	operator / (const float & inF) const		{ return Vector3(x/inF, y/inF, z/inF); }
	inline Vector3&			operator += (const Vector3 & inRHS)			{ x+=inRHS.x; y+=inRHS.y; z+=inRHS.z; return *this; }
	inline Vector3&			operator -= (const Vector3 & inRHS)			{ x-=inRHS.x; y-=inRHS.y; z-=inRHS.z; return *this; }
	inline Vector3&			operator *= (const float & inF)				{ x*=inF; y*=inF; z*=inF; return *this; }
	inline Vector3&			operator /= (const float & inF)				{ x/=inF; y/=inF; z/=inF; return *this; }

	static const Vector3	sZero;
	static const Vector3	sOne;
};


//---------------------------------------------------------------------------------------------------------------------
//	Colors :
//---------------------------------------------------------------------------------------------------------------------

struct RGBAColor
{
							RGBAColor() : mRGBA(0xFFFFFFFF) {}
							RGBAColor(DWORD inColor) : mRGBA(inColor) { }
							RGBAColor(const RGBAColor & inOther) : mRGBA(inOther.mRGBA) { }

							RGBAColor(unsigned char inR, unsigned char inG, unsigned char inB, unsigned char inA = 255) : mR(inR), mG(inG), mB(inB), mA(inA) { }
							RGBAColor(float inR, float inG, float inB, float inA) : mR(gClamp(int(inR*255.0f), 0, 255)), mG(gClamp(int(inG*255.0f), 0, 255)), mB(gClamp(int(inB*255.0f), 0, 255)), mA(gClamp(int(inA*255.0f), 0, 255)) { }

	inline void				Set(DWORD inColor)																				{ mRGBA = inColor; }
	void					SetComponents(unsigned char inRed, unsigned char inGreen, unsigned char inBlue, unsigned char inAlpha)	{ mR=inRed; mG=inGreen; mB=inBlue; mA=inAlpha; }
	void					SetComponentsF(float inRed, float inGreen, float inBlue, float inAlpha)	{ mR=(unsigned char)(inRed*255.0f); mG=(unsigned char)(inGreen*255.0f); mB=(unsigned char)(inBlue*255.0f); mA=(unsigned char)(inAlpha*255.0f); }

	void					Set(unsigned char inRed, unsigned char inGreen, unsigned char inBlue, unsigned char inAlpha)	{ mR=inRed; mG=inGreen; mB=inBlue; mA=inAlpha; }
	void					Blend(const RGBAColor & inOther, float inFactor);

	inline operator			DWORD() const										{ return mRGBA; } ///< Cast RGBAColor to a DWORD

	// script functions
	static void	_cdecl		ASConstruct(RGBAColor & inData);
	static RGBAColor & _cdecl	ASAssign(const RGBAColor & inSource, RGBAColor & inDest);
	static RGBAColor _cdecl	ASOperatorAdd(const RGBAColor & inLHS, const RGBAColor & inRHS);
	static RGBAColor _cdecl	ASOperatorSub(const RGBAColor & inLHS, const RGBAColor & inRHS);
	static RGBAColor _cdecl	ASOperatorMul(const RGBAColor & inLHS, const float inRHS);
	static RGBAColor _cdecl	ASOperatorDiv(const RGBAColor & inLHS, const float inRHS);
	static bool	_cdecl		ASOperatorEqual(const RGBAColor & inLHS, const RGBAColor &inRHS);
	static bool	_cdecl		ASOperatorNotEqual(const RGBAColor & inLHS, const RGBAColor &inRHS);

	inline bool				operator == (const RGBAColor & inRHS) const	{ return inRHS.mRGBA == mRGBA; }
	inline bool				operator != (const RGBAColor & inRHS) const	{ return inRHS.mRGBA != mRGBA; }
	inline const RGBAColor	operator + (const RGBAColor & inRHS) const	{ return RGBAColor((unsigned char)gClamp(int(mR) + int(inRHS.mR), 0, 255), (unsigned char)gClamp(int(mG) + int(inRHS.mG), 0, 255), (unsigned char)gClamp(int(mB) + int(inRHS.mB), 0, 255), (unsigned char)gClamp(int(mA) + int(inRHS.mA), 0, 255)); }
	inline const RGBAColor	operator - (const RGBAColor & inRHS) const	{ return RGBAColor((unsigned char)gClamp(int(mR) - int(inRHS.mR), 0, 255), (unsigned char)gClamp(int(mG) - int(inRHS.mG), 0, 255), (unsigned char)gClamp(int(mB) - int(inRHS.mB), 0, 255), (unsigned char)gClamp(int(mA) - int(inRHS.mA), 0, 255)); }
	inline const RGBAColor	operator * (const float & inF) const		{ float fac = (1.0f / 255.0f) * inF; return RGBAColor(gClamp(float(mR) * fac, 0.0f, 1.0f), gClamp(float(mG) * fac, 0.0f, 1.0f), gClamp(float(mB) * fac, 0.0f, 1.0f), gClamp(float(mA) * fac, 0.0f, 1.0f)); }
	inline const RGBAColor	operator / (const float & inF) const		{ float fac = (1.0f / 255.0f) / inF; return RGBAColor(gClamp(float(mR) * fac, 0.0f, 1.0f), gClamp(float(mG) * fac, 0.0f, 1.0f), gClamp(float(mB) * fac, 0.0f, 1.0f), gClamp(float(mA) * fac, 0.0f, 1.0f)); }
	inline RGBAColor&		operator += (const RGBAColor & inRHS)		{ SetComponents((unsigned char)gClamp(int(mR) + int(inRHS.mR), 0, 255), (unsigned char)gClamp(int(mG) + int(inRHS.mG), 0, 255), (unsigned char)gClamp(int(mB) + int(inRHS.mB), 0, 255), (unsigned char)gClamp(int(mA) + int(inRHS.mA), 0, 255)); return *this; }
	inline RGBAColor&		operator -= (const RGBAColor & inRHS)		{ SetComponents((unsigned char)gClamp(int(mR) - int(inRHS.mR), 0, 255), (unsigned char)gClamp(int(mG) - int(inRHS.mG), 0, 255), (unsigned char)gClamp(int(mB) - int(inRHS.mB), 0, 255), (unsigned char)gClamp(int(mA) - int(inRHS.mA), 0, 255)); return *this; }
	inline RGBAColor&		operator *= (const float & inF)				{ float fac = (1.0f / 255.0f) * inF; SetComponentsF(gClamp(float(mR) * fac, 0.0f, 1.0f), gClamp(float(mG) * fac, 0.0f, 1.0f), gClamp(float(mB) * fac, 0.0f, 1.0f), gClamp(float(mA) * fac, 0.0f, 1.0f)); return *this; }
	inline RGBAColor&		operator /= (const float & inF)				{ float fac = (1.0f / 255.0f) / inF; SetComponentsF(gClamp(float(mR) * fac, 0.0f, 1.0f), gClamp(float(mG) * fac, 0.0f, 1.0f), gClamp(float(mB) * fac, 0.0f, 1.0f), gClamp(float(mA) * fac, 0.0f, 1.0f)); return *this; }

	union
	{
		struct
		{
			unsigned char	mB;													///< Blue component
			unsigned char	mG;													///< Green component
			unsigned char	mR;													///< Red component
			unsigned char	mA;													///< Alpha component
		};
		DWORD				mRGBA;												///< RGBA data
	};
};


//---------------------------------------------------------------------------------------------------------------------
// Vertex : custom render vertex
//---------------------------------------------------------------------------------------------------------------------


//
// Vertex
//
struct Vertex
{
	enum
	{
		VERTEX_FORMAT = (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1),
	};

							Vertex() : mPos(0.0f, 0.0f, 0.0f), mColor(0xFFFFFFFF), mUV(0.0f, 0.0f) { }
							Vertex(const Vertex & inOther)				{ mPos = inOther.mPos; mColor = inOther.mColor; mUV = inOther.mUV; }


	inline bool				operator == (const Vertex & inRHS) const	{ return mPos == inRHS.mPos && mColor == inRHS.mColor && mUV == inRHS.mUV; }
	inline bool				operator != (const Vertex & inRHS) const	{ return mPos != inRHS.mPos || mColor != inRHS.mColor || mUV != inRHS.mUV; }

	static void _cdecl		ASConstruct(Vertex & inThis);
	static Vertex& _cdecl	ASAssign(const Vertex & inSource, Vertex & inDest);

	Vector3		mPos;
	RGBAColor	mColor;
	Vector2		mUV;

	static const Vertex sEmpty;
};



//---------------------------------------------------------------------------------------------------------------------
//	Engine registration
//---------------------------------------------------------------------------------------------------------------------

extern void					as_RegisterD3DUtils(asIScriptEngine * outEngine);	// Register all Vector-functionality to AngelScript

#endif

ASD3DUtils.cpp :

#include <stddef.h> // for offsetof()
#include <assert.h>

#include "include/AngelScript.h"

#include "ASArray.h"
#include "ASD3DUtils.h"


const Vector2	Vector2::sZero(0.0f, 0.0f);
const Vector2	Vector2::sOne(1.0f, 1.0f);

const Vector3	Vector3::sZero(0.0f, 0.0f, 0.0f);
const Vector3	Vector3::sOne(1.0f, 1.0f, 1.0f);


//---------------------------------------------------------------------------------------------------------------------
//	Vector2 Implementation
//---------------------------------------------------------------------------------------------------------------------

// Script Construction
void Vector2::ASConstruct(Vector2 & inThis)										{ inThis.x = 0.0f; inThis.y = 0.0f; }

// Script Copy
Vector2& Vector2::ASAssign(const Vector2 & inSource, Vector2 & inDest)			{ inDest = inSource; return inDest; }

// Script Operator Add
Vector2 Vector2::ASOperatorAdd(const Vector2 & inLHS, const Vector2 & inRHS)	{ return inLHS + inRHS; }

// Script Operator Subtract
Vector2 Vector2::ASOperatorSub(const Vector2 & inLHS, const Vector2 & inRHS)	{ return inLHS - inRHS; }

// Script Operator Multiply
Vector2 Vector2::ASOperatorMul(const Vector2 & inLHS, const float inRHS)		{ return inLHS * inRHS; }

// Script Operator Divide
Vector2 Vector2::ASOperatorDiv(const Vector2 & inLHS, const float inRHS)		{ return inRHS == 0.0f ? inLHS : inLHS / inRHS; }

// Script Operator 'Is Equal'
bool Vector2::ASOperatorEqual(const Vector2 & inLHS, const Vector2 & inRHS)		{ return inLHS == inRHS; }

// Script Operator 'Is Not Equal'
bool Vector2::ASOperatorNotEqual(const Vector2 & inLHS, const Vector2 & inRHS)	{ return inLHS != inRHS; }


//---------------------------------------------------------------------------------------------------------------------
//	Vector3 Implementation
//---------------------------------------------------------------------------------------------------------------------

// Script Construction
void Vector3::ASConstruct(Vector3 & inThis)										{ inThis.x = 0.0f; inThis.y = 0.0f;	inThis.z = 0.0f; }

// Script Copy
Vector3 & Vector3::ASAssign(const Vector3 & inSource, Vector3 & inDest)			{ inDest = inSource; return inDest; }

// Script Operator Add
Vector3 Vector3::ASOperatorAdd(const Vector3 & inLHS, const Vector3 & inRHS)	{ return inLHS + inRHS; }

// Script Operator Subtract
Vector3 Vector3::ASOperatorSub(const Vector3 & inLHS, const Vector3 & inRHS)	{ return inLHS - inRHS; }

// Script Operator Multiply
Vector3 Vector3::ASOperatorMul(const Vector3 & inLHS, const float inRHS)		{ return inLHS * inRHS; }

// Script Operator Divide
Vector3 Vector3::ASOperatorDiv(const Vector3 & inLHS, const float inRHS)		{ return inRHS == 0.0f ? inLHS : inLHS / inRHS; }

// Script Operator 'Is Equal'
bool Vector3::ASOperatorEqual(const Vector3 & inLHS, const Vector3 & inRHS)		{ return (inLHS == inRHS); }

// Script Operator 'Is Not Equal'
bool Vector3::ASOperatorNotEqual(const Vector3 & inLHS, const Vector3 & inRHS)	{ return (inLHS != inRHS); }

//---------------------------------------------------------------------------------------------------------------------
//	RGBAColor Implementation
//---------------------------------------------------------------------------------------------------------------------

// Script Construction
void RGBAColor::ASConstruct(RGBAColor & inThis)											{ inThis.mRGBA = 0xFFFFFFFF; }

// Script Copy
RGBAColor & RGBAColor::ASAssign(const RGBAColor & inSource, RGBAColor & inDest)			{ inDest.mRGBA = inSource.mRGBA; return inDest; }

// Script Operator Add
RGBAColor RGBAColor::ASOperatorAdd(const RGBAColor & inLHS, const RGBAColor & inRHS)	{ return inLHS + inRHS; }

// Script Operator Subtract
RGBAColor RGBAColor::ASOperatorSub(const RGBAColor & inLHS, const RGBAColor & inRHS)	{ return inLHS - inRHS; }

// Script Operator Multiply
RGBAColor RGBAColor::ASOperatorMul(const RGBAColor & inLHS, const float inRHS)			{ return inLHS * inRHS; }

// Script Operator Divide
RGBAColor RGBAColor::ASOperatorDiv(const RGBAColor & inLHS, const float inRHS)			{ return inRHS == 0.0f ? inLHS : inLHS / inRHS; }

// Script Operator 'Is Equal'
bool RGBAColor::ASOperatorEqual(const RGBAColor & inLHS, const RGBAColor & inRHS)		{ return inLHS == inRHS; }

// Script Operator 'Is Not Equal'
bool RGBAColor::ASOperatorNotEqual(const RGBAColor & inLHS, const RGBAColor & inRHS)	{ return inLHS != inRHS; }

// Color blending
void RGBAColor::Blend(const RGBAColor & inOther, float inFactor)						{ mR = gClamp(int(float(mR) + inFactor * (float(inOther.mR) - float(mR))), 0, 255); mG = gClamp(int(float(mG) + inFactor * (float(inOther.mG) - float(mG))), 0, 255); mB = gClamp(int(float(mB) + inFactor * (float(inOther.mB) - float(mB))), 0, 255); mA = gClamp(int(float(mA) + inFactor * (float(inOther.mA) - float(mA))), 0, 255); }

//---------------------------------------------------------------------------------------------------------------------
//	Vertex implementation
//---------------------------------------------------------------------------------------------------------------------

const Vertex Vertex::sEmpty;

void	Vertex::ASConstruct(Vertex & inThis)											{ Vector3::ASConstruct(inThis.mPos); RGBAColor::ASConstruct(inThis.mColor); Vector2::ASConstruct(inThis.mUV); }
Vertex& Vertex::ASAssign(const Vertex & inSource, Vertex & inDest)						{ inDest = inSource; return inDest; }



//---------------------------------------------------------------------------------------------------------------------
//	Engine registration
//---------------------------------------------------------------------------------------------------------------------


//
// Register all Vector-functionality to AngelScript
//
void as_RegisterD3DUtils(asIScriptEngine * outEngine)
{
	// stupidity-check
	if (outEngine == NULL) return;

	//
	// Register Vector2
	//
	int	result = outEngine->RegisterObjectType("Vector2", sizeof(Vector2), asOBJ_GUESS); assert(result>=0);
	// Members
	result = outEngine->RegisterObjectProperty("Vector2", "float x", offsetof(Vector2, x)); assert(result>=0);
	result = outEngine->RegisterObjectProperty("Vector2", "float y", offsetof(Vector2, y)); assert(result>=0);
	// Behaviours
	result = outEngine->RegisterTypeBehaviour("Vector2",	asBEHAVE_CONSTRUCT,		"void Construct()", asFUNCTION(Vector2::ASConstruct), asCALL_CDECL_OBJLAST); assert(result>=0);
	result = outEngine->RegisterTypeBehaviour("Vector2",	asBEHAVE_ASSIGNMENT,	"Vector2 &Assign(Vector2 &)", asFUNCTION(Vector2::ASAssign), asCALL_CDECL_OBJLAST); assert(result>=0);
	result = outEngine->RegisterTypeBehaviour(0,			asBEHAVE_ADD,			"Vector2 f(const Vector2&, const Vector2&)", asFUNCTION(Vector2::ASOperatorAdd), asCALL_CDECL); assert(result>=0);
	result = outEngine->RegisterTypeBehaviour(0,			asBEHAVE_SUBTRACT,		"Vector2 f(const Vector2&, const Vector2&)", asFUNCTION(Vector2::ASOperatorSub), asCALL_CDECL); assert(result>=0);
	result = outEngine->RegisterTypeBehaviour(0,			asBEHAVE_MULTIPLY,		"Vector2 f(const Vector2&, const float)", asFUNCTION(Vector2::ASOperatorMul), asCALL_CDECL); assert(result>=0);
	result = outEngine->RegisterTypeBehaviour(0,			asBEHAVE_DIVIDE,		"Vector2 f(const Vector2&, const float)", asFUNCTION(Vector2::ASOperatorDiv), asCALL_CDECL); assert(result>=0);
	result = outEngine->RegisterTypeBehaviour(0,			asBEHAVE_EQUAL,			"bool f(const Vector2&, const Vector2&)", asFUNCTION(Vector2::ASOperatorEqual), asCALL_CDECL); assert(result>=0);
	result = outEngine->RegisterTypeBehaviour(0,			asBEHAVE_NOTEQUAL,		"bool f(const Vector2&, const Vector2&)", asFUNCTION(Vector2::ASOperatorNotEqual), asCALL_CDECL); assert(result>=0);

	// Vector2 methods
	result = outEngine->RegisterObjectMethod("Vector2", "void Set(float, float)", asMETHOD(Vector2, Set), asCALL_THISCALL); assert(result>=0);
	result = outEngine->RegisterObjectMethod("Vector2", "void Add(Vector2 &)", asMETHOD(Vector2, Add), asCALL_THISCALL); assert(result>=0);
	result = outEngine->RegisterObjectMethod("Vector2", "void Sub(Vector2 &)", asMETHOD(Vector2, Sub), asCALL_THISCALL); assert(result>=0);
	result = outEngine->RegisterObjectMethod("Vector2", "void Scale(float)", asMETHOD(Vector2, Scale), asCALL_THISCALL); assert(result>=0);
	result = outEngine->RegisterObjectMethod("Vector2", "void Blend(Vector2 &, float)", asMETHOD(Vector2, Blend), asCALL_THISCALL); assert(result>=0);
	result = outEngine->RegisterObjectMethod("Vector2", "float SquareLength()", asMETHOD(Vector2, SquareLength), asCALL_THISCALL); assert(result>=0);
	result = outEngine->RegisterObjectMethod("Vector2", "float Length()", asMETHOD(Vector2, Length), asCALL_THISCALL); assert(result>=0);
	result = outEngine->RegisterObjectMethod("Vector2", "float Dot(Vector2 &)", asMETHOD(Vector2, Dot), asCALL_THISCALL); assert(result>=0);
	result = outEngine->RegisterObjectMethod("Vector2", "float Cross(Vector2 &)", asMETHOD(Vector2, Cross), asCALL_THISCALL); assert(result>=0);
	result = outEngine->RegisterObjectMethod("Vector2", "void Normalize()", asMETHOD(Vector2, Normalize), asCALL_THISCALL); assert(result>=0);
	result = outEngine->RegisterObjectMethod("Vector2", "Vector2 Normalized()", asMETHOD(Vector2, Normalized), asCALL_THISCALL); assert(result>=0);

	//
	// Register Vector3
	//
	result = outEngine->RegisterObjectType("Vector3", sizeof(Vector3), asOBJ_GUESS); assert(result>=0);
	// Members
	result = outEngine->RegisterObjectProperty("Vector3", "float x", offsetof(Vector3, x)); assert(result>=0);
	result = outEngine->RegisterObjectProperty("Vector3", "float y", offsetof(Vector3, y)); assert(result>=0);
	result = outEngine->RegisterObjectProperty("Vector3", "float z", offsetof(Vector3, z)); assert(result>=0);
	// Behaviours
	result = outEngine->RegisterTypeBehaviour("Vector3",	asBEHAVE_CONSTRUCT,	"void Construct()", asFUNCTION(Vector3::ASConstruct), asCALL_CDECL_OBJLAST); assert(result>=0);
	result = outEngine->RegisterTypeBehaviour("Vector3",	asBEHAVE_ASSIGNMENT,	"Vector3 &Assign(Vector3 &)", asFUNCTION(Vector3::ASAssign), asCALL_CDECL_OBJLAST); assert(result>=0);
	result = outEngine->RegisterTypeBehaviour(0,			asBEHAVE_ADD,			"Vector3 f(const Vector3&, const Vector3&)", asFUNCTION(Vector3::ASOperatorAdd), asCALL_CDECL); assert(result>=0);
	result = outEngine->RegisterTypeBehaviour(0,			asBEHAVE_SUBTRACT,		"Vector3 f(const Vector3&, const Vector3&)", asFUNCTION(Vector3::ASOperatorSub), asCALL_CDECL); assert(result>=0);
	result = outEngine->RegisterTypeBehaviour(0,			asBEHAVE_MULTIPLY,		"Vector3 f(const Vector3&, const float)", asFUNCTION(Vector3::ASOperatorMul), asCALL_CDECL); assert(result>=0);
	result = outEngine->RegisterTypeBehaviour(0,			asBEHAVE_DIVIDE,		"Vector3 f(const Vector3&, const float)", asFUNCTION(Vector3::ASOperatorDiv), asCALL_CDECL); assert(result>=0);
	result = outEngine->RegisterTypeBehaviour(0,			asBEHAVE_EQUAL,			"bool f(const Vector3&, const Vector3&)", asFUNCTION(Vector3::ASOperatorEqual), asCALL_CDECL); assert(result>=0);
	result = outEngine->RegisterTypeBehaviour(0,			asBEHAVE_NOTEQUAL,		"bool f(const Vector3&, const Vector3&)", asFUNCTION(Vector3::ASOperatorNotEqual), asCALL_CDECL); assert(result>=0);

	// Vector3 methods
	result = outEngine->RegisterObjectMethod("Vector3", "void Set(float, float, float)", asMETHOD(Vector3, Set), asCALL_THISCALL); assert(result>=0);
	result = outEngine->RegisterObjectMethod("Vector3", "void Add(Vector3 &)", asMETHOD(Vector3, Add), asCALL_THISCALL); assert(result>=0);
	result = outEngine->RegisterObjectMethod("Vector3", "void Sub(Vector3 &)", asMETHOD(Vector3, Sub), asCALL_THISCALL); assert(result>=0);
	result = outEngine->RegisterObjectMethod("Vector3", "void Scale(float)", asMETHOD(Vector3, Scale), asCALL_THISCALL); assert(result>=0);
	result = outEngine->RegisterObjectMethod("Vector3", "void Blend(Vector3 &, float)", asMETHOD(Vector3, Blend), asCALL_THISCALL); assert(result>=0);

	result = outEngine->RegisterObjectMethod("Vector3", "float SquareLength()", asMETHOD(Vector3, SquareLength), asCALL_THISCALL); assert(result>=0);
	result = outEngine->RegisterObjectMethod("Vector3", "float Length()", asMETHOD(Vector3, Length), asCALL_THISCALL); assert(result>=0);
	result = outEngine->RegisterObjectMethod("Vector3", "float Dot(Vector3 &)", asMETHOD(Vector3, Dot), asCALL_THISCALL); assert(result>=0);
	result = outEngine->RegisterObjectMethod("Vector3", "Vector3 Cross(Vector3 &)", asMETHOD(Vector3, Cross), asCALL_THISCALL); assert(result>=0);
	result = outEngine->RegisterObjectMethod("Vector3", "void Normalize()", asMETHOD(Vector3, Normalize), asCALL_THISCALL); assert(result>=0);
	result = outEngine->RegisterObjectMethod("Vector3", "Vector3 Normalized()", asMETHOD(Vector3, Normalized), asCALL_THISCALL); assert(result>=0);

	//
	// Register Color
	//
	result = outEngine->RegisterObjectType("RGBAColor", sizeof(RGBAColor), asOBJ_GUESS); assert(result>=0);
	// Members
	result = outEngine->RegisterObjectProperty("RGBAColor", "uint8 R", offsetof(RGBAColor, mR)); assert(result>=0);
	result = outEngine->RegisterObjectProperty("RGBAColor", "uint8 G", offsetof(RGBAColor, mG)); assert(result>=0);
	result = outEngine->RegisterObjectProperty("RGBAColor", "uint8 B", offsetof(RGBAColor, mB)); assert(result>=0);
	result = outEngine->RegisterObjectProperty("RGBAColor", "uint8 A", offsetof(RGBAColor, mA)); assert(result>=0);
	// Behaviours
	result = outEngine->RegisterTypeBehaviour("RGBAColor",	asBEHAVE_CONSTRUCT,		"void Construct()", asFUNCTION(RGBAColor::ASConstruct), asCALL_CDECL_OBJLAST); assert(result>=0);
	result = outEngine->RegisterTypeBehaviour("RGBAColor",	asBEHAVE_ASSIGNMENT,	"RGBAColor &Assign(RGBAColor &)", asFUNCTION(RGBAColor::ASAssign), asCALL_CDECL_OBJLAST); assert(result>=0);
	result = outEngine->RegisterTypeBehaviour(0,			asBEHAVE_ADD,			"RGBAColor f(const RGBAColor&, const RGBAColor&)", asFUNCTION(RGBAColor::ASOperatorAdd), asCALL_CDECL); assert(result>=0);
	result = outEngine->RegisterTypeBehaviour(0,			asBEHAVE_SUBTRACT,		"RGBAColor f(const RGBAColor&, const RGBAColor&)", asFUNCTION(RGBAColor::ASOperatorSub), asCALL_CDECL); assert(result>=0);
	result = outEngine->RegisterTypeBehaviour(0,			asBEHAVE_MULTIPLY,		"RGBAColor f(const RGBAColor&, const float)", asFUNCTION(RGBAColor::ASOperatorMul), asCALL_CDECL); assert(result>=0);
	result = outEngine->RegisterTypeBehaviour(0,			asBEHAVE_DIVIDE,		"RGBAColor f(const RGBAColor&, const float)", asFUNCTION(RGBAColor::ASOperatorDiv), asCALL_CDECL); assert(result>=0);
	result = outEngine->RegisterTypeBehaviour(0,			asBEHAVE_EQUAL,			"bool f(const RGBAColor&, const RGBAColor&)", asFUNCTION(RGBAColor::ASOperatorEqual), asCALL_CDECL); assert(result>=0);
	result = outEngine->RegisterTypeBehaviour(0,			asBEHAVE_NOTEQUAL,		"bool f(const RGBAColor&, const RGBAColor&)", asFUNCTION(RGBAColor::ASOperatorNotEqual), asCALL_CDECL); assert(result>=0);

	// Methods
	result = outEngine->RegisterObjectMethod("RGBAColor", "void Set(uint8,uint8,uint8,uint8)", asMETHOD(RGBAColor, SetComponents), asCALL_THISCALL); assert(result>=0);
	result = outEngine->RegisterObjectMethod("RGBAColor", "void Set(float,float,float,float)", asMETHOD(RGBAColor, SetComponentsF), asCALL_THISCALL); assert(result>=0);
	result = outEngine->RegisterObjectMethod("RGBAColor", "void Blend(RGBAColor &, float)", asMETHOD(RGBAColor, Blend), asCALL_THISCALL); assert(result>=0);

	//
	// Register Vertex
	//
	result = outEngine->RegisterObjectType("Vertex", sizeof(Vertex), asOBJ_GUESS); assert(result>=0);

	// Behaviours
	result = outEngine->RegisterTypeBehaviour("Vertex",	asBEHAVE_CONSTRUCT,		"void Construct()",			asFUNCTION(Vertex::ASConstruct), asCALL_CDECL_OBJLAST); assert(result>=0);
	result = outEngine->RegisterTypeBehaviour("Vertex",	asBEHAVE_ASSIGNMENT,	"Vertex &Assign(Vertex &)", asFUNCTION(Vertex::ASAssign), asCALL_CDECL_OBJLAST); assert(result>=0);

	// All of these properties are read and writable (as seen from the last parameter)
	result = outEngine->RegisterObjectProperty("Vertex", "Vector3	Pos", offsetof(Vertex, mPos)); assert(result>=0);
	result = outEngine->RegisterObjectProperty("Vertex", "RGBAColor Color", offsetof(Vertex, mColor)); assert(result>=0);
	result = outEngine->RegisterObjectProperty("Vertex", "Vector2	TexCoord", offsetof(Vertex, mUV)); assert(result>=0);

	gRegisterArray<Vector2>(outEngine,		"Vector2");
	gRegisterArray<Vector3>(outEngine,		"Vector3");
	gRegisterArray<RGBAColor>(outEngine,	"RGBAColor");
	gRegisterArray<Vertex>(outEngine,		"Vertex");
}

ASArray.h :

#ifndef AS_SCRIPT_ARRAY_H
#define AS_SCRIPT_ARRAY_H

#include <string>
#include <memory.h>
#include <assert.h>
#include "include/AngelScript.h"

//---------------------------------------------------------------------------------------------------------------------
//	
//---------------------------------------------------------------------------------------------------------------------

template <typename T> bool gRegisterArray(asIScriptEngine * outEngine, const char * inTypeName)
{
	int result;
	std::string type_name(inTypeName);
	std::string array_name(inTypeName); array_name+="Array";

	// register array-type
	result = outEngine->RegisterObjectType(array_name.c_str(), sizeof(ASArray<T>()), asOBJ_GUESS); assert(result>=0);

	// Behaviours
	result = outEngine->RegisterTypeBehaviour(array_name.c_str(),	asBEHAVE_CONSTRUCT,		"void Construct()", asFUNCTION(ASArray<T>::ASConstruct), asCALL_CDECL_OBJLAST); assert(result>=0);
	result = outEngine->RegisterTypeBehaviour(array_name.c_str(),	asBEHAVE_ASSIGNMENT,	(array_name + " &Assign(" + array_name + "&)").c_str(), asFUNCTION(ASArray<T>::ASAssign), asCALL_CDECL_OBJLAST); assert(result>=0);
	
	result = outEngine->RegisterTypeBehaviour(0,					asBEHAVE_ADD,			(array_name + " f(const " + array_name + "&, const " + array_name + "&)").c_str(), asFUNCTION(ASArray<T>::ASOperatorAddArray), asCALL_CDECL); assert(result>=0);
	result = outEngine->RegisterTypeBehaviour(0,					asBEHAVE_ADD,			(array_name + " f(const " + array_name + "&, const " + type_name + "&)").c_str(), asFUNCTION(ASArray<T>::ASOperatorAddElement), asCALL_CDECL); assert(result>=0);

	result = outEngine->RegisterTypeBehaviour(0,					asBEHAVE_EQUAL,			(std::string("bool f(const ") + array_name + "&, const " + array_name + "&)").c_str(), asFUNCTION(ASArray<T>::ASOperatorEqual), asCALL_CDECL); assert(result>=0);
	result = outEngine->RegisterTypeBehaviour(0,					asBEHAVE_NOTEQUAL,		(std::string("bool f(const ") + array_name + "&, const " + array_name + "&)").c_str(), asFUNCTION(ASArray<T>::ASOperatorNotEqual), asCALL_CDECL); assert(result>=0);

	result = outEngine->RegisterTypeBehaviour(array_name.c_str(),	asBEHAVE_INDEX,			(type_name + std::string("& f(int)")).c_str(), asMETHOD(ASArray<T>, ASIndex), asCALL_THISCALL); assert(result>=0);

	// methods
	result = outEngine->RegisterObjectMethod(array_name.c_str(), "void SetLength(int)",											asMETHOD(ASArray<T>, SetLength), asCALL_THISCALL); assert(result>=0);
	result = outEngine->RegisterObjectMethod(array_name.c_str(), "int GetLength()",												asMETHOD(ASArray<T>, GetLength), asCALL_THISCALL); assert(result>=0);
	
	result = outEngine->RegisterObjectMethod(array_name.c_str(), (std::string("void Add(") + type_name + " &)").c_str(),		asMETHOD(ASArray<T>, ASAddElement), asCALL_THISCALL); assert(result>=0);
	result = outEngine->RegisterObjectMethod(array_name.c_str(), (std::string("void Add(") + array_name + " &)").c_str(),		asMETHOD(ASArray<T>, ASAddArray), asCALL_THISCALL); assert(result>=0);

	result = outEngine->RegisterObjectMethod(array_name.c_str(), "void Remove(int)",											asMETHOD(ASArray<T>, ASRemove), asCALL_THISCALL); assert(result>=0);
	return (result >= 0);
}


template <class T> class ASArray
{
public:
	ASArray();
	ASArray(const ASArray<T> &);
	~ASArray();

	void Allocate(int numElements, bool keepData);
	int  GetCapacity() const;

	void PushLast(const T & element);
	T    PopLast();

	void Remove(int inIndex);

	void SetLength(int numElements);
	int  GetLength() const;

	void Copy(const T*, int count);
	ASArray<T> &operator =(const ASArray<T> &);

	T &operator [](int index) const;
	T *AddressOf();


	inline bool				operator == (const ASArray<T> & inRHS) const	{ return (length == inRHS.length) && (memcmp((void*)array, (void*)inRHS.array, length) == 0); }
	inline bool				operator != (const ASArray<T> & inRHS) const	{ return (length != inRHS.length) || (memcmp((void*)array, (void*)inRHS.array, length) != 0); }
	
	inline const ASArray<T>	operator + (const ASArray<T> & inRHS) const;
	inline const ASArray<T>	operator + (const T & inRHS) const;

	inline ASArray<T>&		operator += (const ASArray<T> & inRHS);



	static void	_cdecl		ASConstruct(ASArray<T> & inThis);
	static ASArray<T> & _cdecl	ASAssign(const ASArray<T> & inSource, ASArray<T> & inDest);
	
	static ASArray<T> _cdecl	ASOperatorAddArray(const ASArray<T> & inLHS, const ASArray<T> & inRHS);
	static ASArray<T> _cdecl	ASOperatorAddElement(const ASArray<T> & inLHS, const T & inRHS);

	static bool _cdecl		ASOperatorEqual(const ASArray<T> & inLHS, const ASArray<T> &inRHS);
	static bool	_cdecl		ASOperatorNotEqual(const ASArray<T> & inLHS, const ASArray<T> &inRHS);

	T*						ASIndex(int inIndex);

	void					ASAddElement(const T & inElement)		{ PushLast(inElement); }
	void					ASAddArray(const ASArray<T> & inArray);
	void					ASRemove(int inIndex);

protected:
	T   *array;
	int  length;
	int  maxLength;
};

// Implementation

template <class T>
T *ASArray<T>::AddressOf()
{
	return array;
}

template <class T>
ASArray<T>::ASArray(void)
{
	array     = 0;
	length    = 0;
	maxLength = 0;
}

template <class T>
ASArray<T>::ASArray(const ASArray<T> &copy)
{
	array     = 0;
	length    = 0;
	maxLength = 0;

	*this = copy;
}

template <class T>
ASArray<T>::~ASArray(void)
{
	if( array )
	{
		delete[] array;
		array = 0;
	}
}

template <class T>
int ASArray<T>::GetLength() const
{
	return length;
}

template <class T>
T &ASArray<T>::operator [](int index) const
{
	assert(index >= 0);
	assert(index < maxLength);

	return array[index];
}

template <class T>
void ASArray<T>::PushLast(const T & element)
{
	if( length == maxLength )
		Allocate(int(maxLength*1.5f) + 1, true);

	array[length++] = element;
}

template <class T>
T ASArray<T>::PopLast()
{
	assert(length > 0);

	return array[--length];
}

template <class T>
void ASArray<T>::Remove(int inIndex)
{
	assert(inIndex >= 0);
	assert(inIndex < maxLength);

	int num = (length - inIndex) - 1;
	if (num > 0)
		memmove((void*) &array[inIndex], (void*) &array[inIndex+1], num);
	length--;
}

template <class T>
void ASArray<T>::Allocate(int numElements, bool keepData)
{
	assert(numElements >= 0);

	T *tmp = new T[numElements];

	for (int i=0; i<numElements; i++)
		T::ASConstruct(tmp);

	if( array )
	{
		if( keepData )
		{
			if( length > numElements )
				length = numElements;

			memcpy(tmp, array, length*sizeof(T));
		}
		else
			length = 0;

		delete[] array;
	}

	array = tmp;
	maxLength = numElements;
}

template <class T>
int ASArray<T>::GetCapacity() const
{
	return maxLength;
}

template <class T>
void ASArray<T>::SetLength(int numElements)
{
	assert(numElements >= 0);

	if( numElements > maxLength )
		Allocate(numElements, true);

	length = numElements;
}

template <class T>
void ASArray<T>::Copy(const T *data, int count)
{
	if( maxLength < count )
		Allocate(count, false);

	memcpy(array, data, count*sizeof(T));
}

template <class T>
ASArray<T> &ASArray<T>::operator =(const ASArray<T> &copy)
{
	Copy(copy.array, copy.length);

	return *this;
}


template <class T>
const ASArray<T> ASArray<T>::operator +(const ASArray<T> & inRHS) const
{
	ASArray<T> result;

	result.Allocate(length + inRHS.length, false);
	memcpy((void *)result.array, (void *)array, length * sizeof(T));
	memcpy((void *)(result.array+length), (void*)inRHS.array, inRHS.length * sizeof(T));
	return result;
}

template <class T>
const ASArray<T> ASArray<T>::operator +(const T & inRHS) const
{
	ASArray<T> result;
	result.Allocate(length + 1, false);
	memcpy((void *)result.array, (void *)array, length * sizeof(T));
	result[length] = inRHS;
	return result;
}

template <class T>
ASArray<T> &ASArray<T>::operator +=(const ASArray<T> & inRHS)
{
	int old_len = length;
	Allocate(old_len + inRHS.length, true);
	memcpy((void *)(array+old_len), (void*)inRHS.array, inRHS.length * sizeof(T));
	return *this;
}




template <class T>
void ASArray<T>::ASConstruct(ASArray<T> & inThis)
{
	inThis.array     = 0;
	inThis.length    = 0;
	inThis.maxLength = 0;
}

template <class T>
ASArray<T> & ASArray<T>::ASAssign(const ASArray<T> & inSource, ASArray<T> & inDest)
{
	inDest = inSource;
	return inDest;
}
	
template <class T>
ASArray<T>	ASArray<T>::ASOperatorAddArray(const ASArray<T> & inLHS, const ASArray<T> & inRHS)
{
	return inLHS + inRHS;
}

template <class T>
ASArray<T>	ASArray<T>::ASOperatorAddElement(const ASArray<T> & inLHS, const T & inRHS)
{
	return inLHS + inRHS;
}

template <class T>
bool ASArray<T>::ASOperatorEqual(const ASArray<T> & inLHS, const ASArray<T> &inRHS)
{
	return inLHS == inRHS;
}

template <class T>
bool ASArray<T>::ASOperatorNotEqual(const ASArray<T> & inLHS, const ASArray<T> &inRHS)
{
	return inLHS != inRHS;
}

template <class T>
T* ASArray<T>::ASIndex(int inIndex)
{
	if ((inIndex >= 0) && (inIndex < GetLength()))
		return &array[inIndex];

	// The script is trying to access memory that isn't 
	// allowed so we'll throw an exception. 
	asIScriptContext *context = asGetActiveContext();
 
	// Should this function be called by the host application directly
	// then there will not be any active context to set the exception on
	if( context )
		context->SetException("Array accessed out of range.");

	return NULL;
}



template <class T>
void ASArray<T>::ASRemove(int inIndex)
{
	if ((inIndex >= 0) && (inIndex < GetLength()))
		Remove(inIndex);
}


template <class T>
void ASArray<T>::ASAddArray(const ASArray<T> & inArray)
{
	(*this) += inArray;
}


#endif

_-=[ "If there's anything more important than my ego around, I want it caught and shot now." ]=--=[ BeatHarness ]=-=[ Guerrilla Games ]=-=[ KillZone ]=-
Advertisement
Very cool Lennart.

Especially the templated array implementation. Can I upload these codes to the site? I think I'll start a new page with add-on codes that can be downloaded separately.

People:

Don't think I'll use Lennart's templated array as an excuse not to include support for native arrays. No, I will implement these as soon as possible, but there are a few other things I want to implement first (like dynamic binding between modules).

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

Quote:Original post by WitchLord
Very cool Lennart.

Especially the templated array implementation. Can I upload these codes to the site?


Ofcourse :)
_-=[ "If there's anything more important than my ego around, I want it caught and shot now." ]=--=[ BeatHarness ]=-=[ Guerrilla Games ]=-=[ KillZone ]=-

This topic is closed to new replies.

Advertisement