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> ©)
{
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.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