Forráskód Böngészése

Exposed math objects construction from an array of float/int and methods to get back the array buffer to the Script API. Enhanced the Attribute Inspector to multi-edit same value at coordinate level for attributes that have multiple coordinates, e.g. Vector3, Color, etc. Different value at coordinate level is non-editable as before.

Wei Tjong Yao 12 éve
szülő
commit
9ed0c43919

+ 123 - 101
Bin/Data/Scripts/Editor/AttributeEditor.as

@@ -149,6 +149,7 @@ UIElement@ CreateNumAttributeEditor(ListView@ list, Array<Serializable@>@ serial
     for (uint i = 0; i < numCoords; ++i)
     {
         LineEdit@ attrEdit = CreateAttributeLineEdit(parent, serializables, index, subIndex);
+        attrEdit.vars["Coordinate"] = i;
         SubscribeToEvent(attrEdit, "TextChanged", "EditAttribute");
         SubscribeToEvent(attrEdit, "TextFinished", "EditAttribute");
     }     
@@ -342,22 +343,22 @@ void LoadAttributeEditor(ListView@ list, Array<Serializable@>@ serializables, bo
     AttributeInfo info = serializables[0].attributeInfos[index];
     bool sameValue = true;
     Variant value = serializables[0].attributes[index];
-    for (uint i = 1; i < serializables.length; ++i)
+    Array<Variant> values;
+    for (uint i = 0; i < serializables.length; ++i)
     {
-        if (serializables[i].attributes[index] != value)
-        {
+        Variant val = serializables[i].attributes[index];
+        if (val != value)
             sameValue = false;
-            break;
-        }
+        values.Push(val);
     }
 
     // Attribute with different values from multiple-select is loaded with default/empty value and non-editable
-    LoadAttributeEditor(parent, value, value.type, info.enumNames, info.defaultValue, editable && sameValue, sameValue);
+    LoadAttributeEditor(parent, value, value.type, info.enumNames, info.defaultValue, editable, sameValue, values);
 
     inLoadAttributeEditor = false;
 }
 
-void LoadAttributeEditor(UIElement@ parent, Variant value, VariantType type, Array<String>@ enumNames, Variant defaultValue, bool editable, bool sameValue = true)
+void LoadAttributeEditor(UIElement@ parent, Variant value, VariantType type, Array<String>@ enumNames, Variant defaultValue, bool editable, bool sameValue, Array<Variant> values)
 {
     uint index = parent.vars["Index"].GetUInt();
 
@@ -376,20 +377,20 @@ void LoadAttributeEditor(UIElement@ parent, Variant value, VariantType type, Arr
     }
     
     if (type == VAR_FLOAT || type == VAR_STRING || type == VAR_BUFFER)
-        SetEditable(SetValue(parent.children[1], value.ToString(), sameValue), editable);
+        SetEditable(SetValue(parent.children[1], value.ToString(), sameValue), editable && sameValue);
     else if (type == VAR_BOOL)
-        SetEditable(SetValue(parent.children[1], value.GetBool(), sameValue), editable);
+        SetEditable(SetValue(parent.children[1], value.GetBool(), sameValue), editable && sameValue);
     else if (type == VAR_INT)
     {
         if (enumNames is null || enumNames.empty)
-            SetEditable(SetValue(parent.children[1], value.ToString(), sameValue), editable);
+            SetEditable(SetValue(parent.children[1], value.ToString(), sameValue), editable && sameValue);
         else
-            SetEditable(SetValue(parent.children[1], value.GetInt(), sameValue), editable);
+            SetEditable(SetValue(parent.children[1], value.GetInt(), sameValue), editable && sameValue);
     }
     else if (type == VAR_RESOURCEREF)
     {
-        SetEditable(SetValue(parent.children[1].children[0], cache.GetResourceName(value.GetResourceRef().id), sameValue), editable);
-        SetEditable(parent.children[1].children[1], editable);  // If editable then can pick
+        SetEditable(SetValue(parent.children[1].children[0], cache.GetResourceName(value.GetResourceRef().id), sameValue), editable && sameValue);
+        SetEditable(parent.children[1].children[1], editable && sameValue);  // If editable then can pick
         SetEditable(parent.children[1].children[2], sameValue); // If same value then can open
     }
     else if (type == VAR_RESOURCEREFLIST)
@@ -401,7 +402,7 @@ void LoadAttributeEditor(UIElement@ parent, Variant value, VariantType type, Arr
             parent = GetAttributeEditorParent(list, index, subIndex);
             if (parent is null)
                 break;
-            SetEditable(SetValue(parent.children[1].children[0], cache.GetResourceName(refList.ids[subIndex]), sameValue), editable);
+            SetEditable(SetValue(parent.children[1].children[0], cache.GetResourceName(refList.ids[subIndex]), sameValue), editable && sameValue);
         }
     }
     else if (type == VAR_VARIANTVECTOR)
@@ -413,7 +414,7 @@ void LoadAttributeEditor(UIElement@ parent, Variant value, VariantType type, Arr
             parent = GetAttributeEditorParent(list, index, i);
             if (parent is null)
                 break;
-            LoadAttributeEditor(parent, vector[i], vector[i].type, null, Variant(), editable, sameValue);
+            LoadAttributeEditor(parent, vector[i], vector[i].type, null, Variant(), editable, sameValue, values);
         }
     }
     else if (type == VAR_VARIANTMAP)
@@ -427,21 +428,37 @@ void LoadAttributeEditor(UIElement@ parent, Variant value, VariantType type, Arr
             if (parent is null)
                 break;
             Variant value = map[keys[i]];
-            LoadAttributeEditor(parent, value, value.type, null, Variant(), editable, sameValue);
+            LoadAttributeEditor(parent, value, value.type, null, Variant(), editable, sameValue, values);
         }
     }
     else
     {
-        // Convert Quaternion value to Vector3 value first
-        if (type == VAR_QUATERNION)
-            value = value.GetQuaternion().eulerAngles;
-        Array<String> components = value.ToString().Split(' ');
-        for (uint i = 0; i < components.length; ++i)
-            SetEditable(SetValue(parent.children[i + 1], components[i], sameValue), editable);
+        Array<Array<String> > coordinates;
+        for (uint i = 0; i < values.length; ++i)
+        {
+            Variant value = values[i];
+            
+            // Convert Quaternion value to Vector3 value first
+            if (type == VAR_QUATERNION)
+                value = value.GetQuaternion().eulerAngles;
+            
+            coordinates.Push(value.ToString().Split(' '));
+        }
+        for (uint i = 0; i < coordinates[0].length; ++i)
+        {
+            sameValue = true;
+            String value = coordinates[0][i];
+            for (uint j = 1; j < coordinates.length; ++j)
+            {
+                if (coordinates[j][i] != value)
+                    sameValue = false;
+            }
+            SetEditable(SetValue(parent.children[i + 1], value, sameValue), editable && sameValue);
+        }
     }
 }
 
-void StoreAttributeEditor(UIElement@ parent, Array<Serializable@>@ serializables, uint index, uint subIndex)
+void StoreAttributeEditor(UIElement@ parent, Array<Serializable@>@ serializables, uint index, uint subIndex, uint coordinate)
 {
     AttributeInfo info = serializables[0].attributeInfos[index];
 
@@ -450,8 +467,9 @@ void StoreAttributeEditor(UIElement@ parent, Array<Serializable@>@ serializables
         for (uint i = 0; i < serializables.length; ++i)
         {
             ResourceRefList refList = serializables[i].attributes[index].GetResourceRefList();
-            Variant newValue = GetEditorValue(parent, VAR_RESOURCEREF, null);
-            ResourceRef ref = newValue.GetResourceRef();
+            Variant[] values(1);
+            GetEditorValue(parent, VAR_RESOURCEREF, null, coordinate, values);
+            ResourceRef ref = values[0].GetResourceRef();
             refList.ids[subIndex] = ref.id;
             serializables[i].attributes[index] = Variant(refList);
         }
@@ -461,8 +479,9 @@ void StoreAttributeEditor(UIElement@ parent, Array<Serializable@>@ serializables
         for (uint i = 0; i < serializables.length; ++i)
         {
             Array<Variant>@ vector = serializables[i].attributes[index].GetVariantVector();
-            Variant newValue = GetEditorValue(parent, vector[subIndex].type, null);
-            vector[subIndex] = newValue;
+            Variant[] values(1);
+            GetEditorValue(parent, vector[subIndex].type, null, coordinate, values);
+            vector[subIndex] = values[0];
             serializables[i].attributes[index] = Variant(vector);
         }
     }
@@ -472,117 +491,121 @@ void StoreAttributeEditor(UIElement@ parent, Array<Serializable@>@ serializables
         {
             VariantMap map = serializables[0].attributes[index].GetVariantMap();
             ShortStringHash key(parent.vars["Key"].GetUInt());
-            Variant newValue = GetEditorValue(parent, map[key].type, null);
-            map[key] = newValue;
+            Variant[] values(1);
+            GetEditorValue(parent, map[key].type, null, coordinate, values);
+            map[key] = values[0];
             serializables[i].attributes[index] = Variant(map);
         }
     }
     else
     {
-        Variant newValue = GetEditorValue(parent, info.type, info.enumNames);
-        for (uint i = 0; i < serializables.length; ++i) {
-            serializables[i].attributes[index] = newValue;
-        }
+        Array<Variant> values;
+        for (uint i = 0; i < serializables.length; ++i)
+            values.Push(serializables[i].attributes[index]);
+        GetEditorValue(parent, info.type, info.enumNames, coordinate, values);
+        for (uint i = 0; i < serializables.length; ++i)
+            serializables[i].attributes[index] = values[i];
     }
 }
 
-Variant GetEditorValue(UIElement@ parent, VariantType type, Array<String>@ enumNames)
+void FillValue(Array<Variant>&inout values, Variant value)
+{
+    for (uint i = 0; i < values.length; ++i)
+        values[i] = value;
+}
+void GetEditorValue(UIElement@ parent, VariantType type, Array<String>@ enumNames, uint coordinate, Array<Variant>&inout values)
 {
+    LineEdit@ attrEdit = parent.children[coordinate + 1];
     if (type == VAR_STRING)
-    {
-        LineEdit@ attrEdit = parent.children[1];
-        return Variant(attrEdit.text.Trimmed());
-    }
-    if (type == VAR_BOOL)
+        FillValue(values, Variant(attrEdit.text.Trimmed()));
+    else if (type == VAR_BOOL)
     {
         CheckBox@ attrEdit = parent.children[1];
-        return Variant(attrEdit.checked);
-    }
-    if (type == VAR_FLOAT)
-    {
-        LineEdit@ attrEdit = parent.children[1];
-        return Variant(attrEdit.text.ToFloat());
+        FillValue(values, Variant(attrEdit.checked));
     }
-    if (type == VAR_VECTOR2)
+    else if (type == VAR_FLOAT)
+        FillValue(values, Variant(attrEdit.text.ToFloat()));
+    else if (type == VAR_VECTOR2)
     {
-        LineEdit@ attrEditX = parent.children[1];
-        LineEdit@ attrEditY = parent.children[2];
-        Vector2 vec(attrEditX.text.ToFloat(), attrEditY.text.ToFloat());
-        return Variant(vec);
+        for (uint i = 0; i < values.length; ++i)
+        {
+            float[] data = values[i].GetVector2().data;
+            data[coordinate] = attrEdit.text.ToFloat();
+            values[i] = Vector2(data);
+        }
     }
-    if (type == VAR_VECTOR3)
+    else if (type == VAR_VECTOR3)
     {
-        LineEdit@ attrEditX = parent.children[1];
-        LineEdit@ attrEditY = parent.children[2];
-        LineEdit@ attrEditZ = parent.children[3];
-        Vector3 vec(attrEditX.text.ToFloat(), attrEditY.text.ToFloat(), attrEditZ.text.ToFloat());
-        return Variant(vec);
+        for (uint i = 0; i < values.length; ++i)
+        {
+            float[] data = values[i].GetVector3().data;
+            data[coordinate] = attrEdit.text.ToFloat();
+            values[i] = Vector3(data);
+        }
     }
-    if (type == VAR_VECTOR4)
+    else if (type == VAR_VECTOR4)
     {
-        LineEdit@ attrEditX = parent.children[1];
-        LineEdit@ attrEditY = parent.children[2];
-        LineEdit@ attrEditZ = parent.children[3];
-        LineEdit@ attrEditW = parent.children[4];
-        Vector4 vec(attrEditX.text.ToFloat(), attrEditY.text.ToFloat(), attrEditZ.text.ToFloat(), attrEditW.text.ToFloat());
-        return Variant(vec);
+        for (uint i = 0; i < values.length; ++i)
+        {
+            float[] data = values[i].GetVector4().data;
+            data[coordinate] = attrEdit.text.ToFloat();
+            values[i] = Vector4(data);
+        }
     }
-    if (type == VAR_COLOR)
+    else if (type == VAR_COLOR)
     {
-        LineEdit@ attrEditR = parent.children[1];
-        LineEdit@ attrEditG = parent.children[2];
-        LineEdit@ attrEditB = parent.children[3];
-        LineEdit@ attrEditA = parent.children[4];
-        Color col(attrEditR.text.ToFloat(), attrEditG.text.ToFloat(), attrEditB.text.ToFloat(), attrEditA.text.ToFloat());
-        return Variant(col);
+        for (uint i = 0; i < values.length; ++i)
+        {
+            float[] data = values[i].GetColor().data;
+            data[coordinate] = attrEdit.text.ToFloat();
+            values[i] = Color(data);
+        }
     }
-    if (type == VAR_QUATERNION)
+    else if (type == VAR_QUATERNION)
     {
-        LineEdit@ attrEditX = parent.children[1];
-        LineEdit@ attrEditY = parent.children[2];
-        LineEdit@ attrEditZ = parent.children[3];
-        Vector3 vec(attrEditX.text.ToFloat(), attrEditY.text.ToFloat(), attrEditZ.text.ToFloat());
-        return Variant(Quaternion(vec));
+        for (uint i = 0; i < values.length; ++i)
+        {
+            float[] data = values[i].GetQuaternion().eulerAngles.data;
+            data[coordinate] = attrEdit.text.ToFloat();
+            values[i] = Quaternion(Vector3(data));
+        }
     }
-    if (type == VAR_INT)
+    else if (type == VAR_INT)
     {
         if (enumNames is null || enumNames.empty)
-        {
-            LineEdit@ attrEdit = parent.children[1];
-            return Variant(attrEdit.text.ToInt());
-        }
+            FillValue(values, Variant(attrEdit.text.ToInt()));
         else
         {
             DropDownList@ attrEdit = parent.children[1];
-            return Variant(attrEdit.selection);
+            FillValue(values, Variant(attrEdit.selection));
         }
     }
-    if (type == VAR_RESOURCEREF)
+    else if (type == VAR_RESOURCEREF)
     {
         LineEdit@ attrEdit = parent.children[0];
         ResourceRef ref;
         ref.id = StringHash(attrEdit.text.Trimmed());
         ref.type = ShortStringHash(attrEdit.vars["Type"].GetUInt());
-        return Variant(ref);
+        FillValue(values, Variant(ref));
     }
-    if (type == VAR_INTVECTOR2)
+    else if (type == VAR_INTVECTOR2)
     {
-        LineEdit@ attrEditX = parent.children[1];
-        LineEdit@ attrEditY = parent.children[2];
-        IntVector2 vec(attrEditX.text.ToInt(), attrEditY.text.ToInt());
-        return Variant(vec);
+        for (uint i = 0; i < values.length; ++i)
+        {
+            int[] data = values[i].GetIntVector2().data;
+            data[coordinate] = attrEdit.text.ToInt();
+            values[i] = IntVector2(data);
+        }
     }
-    if (type == VAR_INTRECT)
+    else if (type == VAR_INTRECT)
     {
-        LineEdit@ attrEditLeft = parent.children[1];
-        LineEdit@ attrEditTop = parent.children[2];
-        LineEdit@ attrEditRight = parent.children[3];
-        LineEdit@ attrEditBottom = parent.children[3];
-        IntRect vec(attrEditLeft.text.ToInt(), attrEditTop.text.ToInt(),
-                       attrEditRight.text.ToInt(), attrEditBottom.text.ToInt());
-        return Variant(vec);
+        for (uint i = 0; i < values.length; ++i)
+        {
+            int[] data = values[i].GetIntRect().data;
+            data[coordinate] = attrEdit.text.ToInt();
+            values[i] = IntRect(data);
+        }
     }
-    return Variant();
 }
 
 void UpdateAttributes(Array<Serializable@>@ serializables, ListView@ list, bool fullUpdate)
@@ -634,9 +657,7 @@ void EditAttribute(StringHash eventType, VariantMap& eventData)
 {
     // Changing elements programmatically may cause events to be sent. Stop possible infinite loop in that case.
     if (inLoadAttributeEditor)
-    {
         return;
-    }
 
     UIElement@ attrEdit = eventData["Element"].GetUIElement();
     UIElement@ parent = attrEdit.parent;
@@ -646,9 +667,10 @@ void EditAttribute(StringHash eventType, VariantMap& eventData)
 
     uint index = attrEdit.vars["Index"].GetUInt();
     uint subIndex = attrEdit.vars["SubIndex"].GetUInt();
+    uint coordinate = attrEdit.vars["Coordinate"].GetUInt();
     bool intermediateEdit = eventType == textChangedEventType;
 
-    StoreAttributeEditor(parent, serializables, index, subIndex);
+    StoreAttributeEditor(parent, serializables, index, subIndex, coordinate);
     for (uint i = 0; i < serializables.length; ++i)
         serializables[i].ApplyAttributes();
 

+ 6 - 0
Docs/ScriptAPI.dox

@@ -321,6 +321,7 @@ Methods:<br>
 - String ToString() const
 
 Properties:<br>
+- int[] data (readonly)
 - int x
 - int y
 
@@ -328,6 +329,7 @@ Properties:<br>
 IntRect
 
 Properties:<br>
+- int[] data (readonly)
 - IntVector2 size (readonly)
 - int width (readonly)
 - int height (readonly)
@@ -349,6 +351,7 @@ Methods:<br>
 - String ToString() const
 
 Properties:<br>
+- float[] data (readonly)
 - float length (readonly)
 - float lengthSquared (readonly)
 - float x
@@ -368,6 +371,7 @@ Methods:<br>
 - String ToString() const
 
 Properties:<br>
+- float[] data (readonly)
 - float length (readonly)
 - float lengthSquared (readonly)
 - float x
@@ -385,6 +389,7 @@ Methods:<br>
 - String ToString() const
 
 Properties:<br>
+- float[] data (readonly)
 - float x
 - float y
 - float z
@@ -661,6 +666,7 @@ Methods:<br>
 - String ToString() const
 
 Properties:<br>
+- float[] data (readonly)
 - Vector3 rgb (readonly)
 - float intensity (readonly)
 - float r

+ 18 - 0
Engine/Engine/APITemplates.h

@@ -101,6 +101,24 @@ template <class T> CScriptArray* VectorToArray(const PODVector<T>& vector, const
         return 0;
 }
 
+/// Template function for data buffer to array conversion.
+template <class T> CScriptArray* BufferToArray(const T* buffer, unsigned size, const char* arrayName)
+{
+    asIScriptContext *context = asGetActiveContext();
+    if (context)
+    {
+        asIObjectType* type = GetScriptContext()->GetSubsystem<Script>()->GetObjectType(arrayName);
+        CScriptArray* arr = new CScriptArray(size, type);
+        
+        for (unsigned i = 0; i < arr->GetSize(); ++i)
+            *(static_cast<T*>(arr->At(i))) = buffer[i];
+        
+        return arr;
+    }
+    else
+        return 0;
+}
+
 /// Template function for Vector to handle array conversion.
 template <class T> CScriptArray* VectorToHandleArray(const Vector<T*>& vector, const char* arrayName)
 {

+ 72 - 0
Engine/Engine/MathAPI.cpp

@@ -124,12 +124,24 @@ static void ConstructIntRectInit(int left, int top, int right, int bottom, IntRe
     new(ptr) IntRect(left, top, right, bottom);
 }
 
+static void ConstructIntRectArrayInit(CScriptArray* data, IntRect* ptr)
+{
+    new(ptr) IntRect((static_cast<int*>(data->At(0))));
+}
+
+static CScriptArray* IntRectData(IntRect* ptr)
+{
+    return BufferToArray<int>(ptr->Data(), 4, "int[]");
+}
+
 static void RegisterIntRect(asIScriptEngine* engine)
 {
     engine->RegisterObjectType("IntRect", sizeof(IntRect), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS_CAK);
     engine->RegisterObjectBehaviour("IntRect", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(ConstructIntRect), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectBehaviour("IntRect", asBEHAVE_CONSTRUCT, "void f(const IntRect&in)", asFUNCTION(ConstructIntRectCopy), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectBehaviour("IntRect", asBEHAVE_CONSTRUCT, "void f(int, int, int, int)", asFUNCTION(ConstructIntRectInit), asCALL_CDECL_OBJLAST);
+    engine->RegisterObjectBehaviour("IntRect", asBEHAVE_CONSTRUCT, "void f(int[]&)", asFUNCTION(ConstructIntRectArrayInit), asCALL_CDECL_OBJLAST);
+    engine->RegisterObjectMethod("IntRect", "int[]& get_data() const", asFUNCTION(IntRectData), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("IntRect", "IntRect& opAssign(const IntRect&in)", asMETHOD(IntRect, operator =), asCALL_THISCALL);
     engine->RegisterObjectMethod("IntRect", "bool opEquals(const IntRect&in) const", asMETHOD(IntRect, operator ==), asCALL_THISCALL);
     engine->RegisterObjectMethod("IntRect", "IntVector2 get_size() const", asMETHOD(IntRect, Size), asCALL_THISCALL);
@@ -157,12 +169,24 @@ static void ConstructIntVector2Init(int x, int y, IntVector2* ptr)
     new(ptr) IntVector2(x, y);
 }
 
+static void ConstructIntVector2ArrayInit(CScriptArray* data, IntVector2* ptr)
+{
+    new(ptr) IntVector2((static_cast<int*>(data->At(0))));
+}
+
+static CScriptArray* IntVector2Data(IntVector2* ptr)
+{
+    return BufferToArray<int>(ptr->Data(), 2, "int[]");
+}
+
 static void RegisterIntVector2(asIScriptEngine* engine)
 {
     engine->RegisterObjectType("IntVector2", sizeof(IntVector2), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS_CAK);
     engine->RegisterObjectBehaviour("IntVector2", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(ConstructIntVector2), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectBehaviour("IntVector2", asBEHAVE_CONSTRUCT, "void f(const IntVector2&in)", asFUNCTION(ConstructIntVector2Copy), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectBehaviour("IntVector2", asBEHAVE_CONSTRUCT, "void f(int, int)", asFUNCTION(ConstructIntVector2Init), asCALL_CDECL_OBJLAST);
+    engine->RegisterObjectBehaviour("IntVector2", asBEHAVE_CONSTRUCT, "void f(int[]&)", asFUNCTION(ConstructIntVector2ArrayInit), asCALL_CDECL_OBJLAST);
+    engine->RegisterObjectMethod("IntVector2", "int[]& get_data() const", asFUNCTION(IntVector2Data), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("IntVector2", "IntVector2& opAssign(const IntVector2&in)", asMETHOD(IntVector2, operator =), asCALL_THISCALL);
     engine->RegisterObjectMethod("IntVector2", "IntVector2& opAddAssign(const IntVector2&in)", asMETHOD(IntVector2, operator +=), asCALL_THISCALL);
     engine->RegisterObjectMethod("IntVector2", "IntVector2& opSubAssign(const IntVector2&in)", asMETHOD(IntVector2, operator -=), asCALL_THISCALL);
@@ -195,12 +219,24 @@ static void ConstructVector2Init(float x, float y, Vector2* ptr)
     new(ptr) Vector2(x, y);
 }
 
+static void ConstructVector2ArrayInit(CScriptArray* data, Vector2* ptr)
+{
+    new(ptr) Vector2((static_cast<float*>(data->At(0))));
+}
+
+static CScriptArray* Vector2Data(Vector2* ptr)
+{
+    return BufferToArray<float>(ptr->Data(), 2, "float[]");
+}
+
 static void RegisterVector2(asIScriptEngine* engine)
 {
     engine->RegisterObjectType("Vector2", sizeof(Vector2), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS_CAK);
     engine->RegisterObjectBehaviour("Vector2", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(ConstructVector2), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectBehaviour("Vector2", asBEHAVE_CONSTRUCT, "void f(const Vector2&in)", asFUNCTION(ConstructVector2Copy), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectBehaviour("Vector2", asBEHAVE_CONSTRUCT, "void f(float, float)", asFUNCTION(ConstructVector2Init), asCALL_CDECL_OBJLAST);
+    engine->RegisterObjectBehaviour("Vector2", asBEHAVE_CONSTRUCT, "void f(float[]&)", asFUNCTION(ConstructVector2ArrayInit), asCALL_CDECL_OBJLAST);
+    engine->RegisterObjectMethod("Vector2", "float[]& get_data() const", asFUNCTION(Vector2Data), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("Vector2", "Vector2& opAssign(const Vector2&in)", asMETHOD(Vector2, operator =), asCALL_THISCALL);
     engine->RegisterObjectMethod("Vector2", "Vector2& opAddAssign(const Vector2&in)", asMETHOD(Vector2, operator +=), asCALL_THISCALL);
     engine->RegisterObjectMethod("Vector2", "Vector2& opSubAssign(const Vector2&in)", asMETHOD(Vector2, operator -=), asCALL_THISCALL);
@@ -245,12 +281,24 @@ static void ConstructVector3Init(float x, float y, float z, Vector3* ptr)
     new(ptr) Vector3(x, y, z);
 }
 
+static void ConstructVector3ArrayInit(CScriptArray* data, Vector3* ptr)
+{
+    new(ptr) Vector3((static_cast<float*>(data->At(0))));
+}
+
+static CScriptArray* Vector3Data(Vector3* ptr)
+{
+    return BufferToArray<float>(ptr->Data(), 3, "float[]");
+}
+
 static void RegisterVector3(asIScriptEngine* engine)
 {
     engine->RegisterObjectType("Vector3", sizeof(Vector3), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS_CAK);
     engine->RegisterObjectBehaviour("Vector3", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(ConstructVector3), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectBehaviour("Vector3", asBEHAVE_CONSTRUCT, "void f(const Vector3&in)", asFUNCTION(ConstructVector3Copy), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectBehaviour("Vector3", asBEHAVE_CONSTRUCT, "void f(float, float, float)", asFUNCTION(ConstructVector3Init), asCALL_CDECL_OBJLAST);
+    engine->RegisterObjectBehaviour("Vector3", asBEHAVE_CONSTRUCT, "void f(float[]&)", asFUNCTION(ConstructVector3ArrayInit), asCALL_CDECL_OBJLAST);
+    engine->RegisterObjectMethod("Vector3", "float[]& get_data() const", asFUNCTION(Vector3Data), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("Vector3", "Vector3& opAssign(const Vector3&in)", asMETHOD(Vector3, operator =), asCALL_THISCALL);
     engine->RegisterObjectMethod("Vector3", "Vector3& opAddAssign(const Vector3&in)", asMETHOD(Vector3, operator +=), asCALL_THISCALL);
     engine->RegisterObjectMethod("Vector3", "Vector3& opSubAssign(const Vector3&in)", asMETHOD(Vector3, operator -=), asCALL_THISCALL);
@@ -302,6 +350,16 @@ static void ConstructVector4InitVector3(const Vector3& vector, float w, Vector4*
     new(ptr) Vector4(vector, w);
 }
 
+static void ConstructVector4ArrayInit(CScriptArray* data, Vector4* ptr)
+{
+    new(ptr) Vector4((static_cast<float*>(data->At(0))));
+}
+
+static CScriptArray* Vector4Data(Vector4* ptr)
+{
+    return BufferToArray<float>(ptr->Data(), 4, "float[]");
+}
+
 static void RegisterVector4(asIScriptEngine* engine)
 {
     engine->RegisterObjectType("Vector4", sizeof(Vector4), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS_CAK);
@@ -309,6 +367,8 @@ static void RegisterVector4(asIScriptEngine* engine)
     engine->RegisterObjectBehaviour("Vector4", asBEHAVE_CONSTRUCT, "void f(const Vector4&in)", asFUNCTION(ConstructVector4Copy), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectBehaviour("Vector4", asBEHAVE_CONSTRUCT, "void f(float, float, float, float)", asFUNCTION(ConstructVector4Init), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectBehaviour("Vector4", asBEHAVE_CONSTRUCT, "void f(const Vector3&in, float)", asFUNCTION(ConstructVector4InitVector3), asCALL_CDECL_OBJLAST);
+    engine->RegisterObjectBehaviour("Vector4", asBEHAVE_CONSTRUCT, "void f(float[]&)", asFUNCTION(ConstructVector4ArrayInit), asCALL_CDECL_OBJLAST);
+    engine->RegisterObjectMethod("Vector4", "float[]& get_data() const", asFUNCTION(Vector4Data), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("Vector4", "Vector4& opAssign(const Vector4&in)", asMETHOD(Vector4, operator =), asCALL_THISCALL);
     engine->RegisterObjectMethod("Vector4", "Vector4& opAddAssign(const Vector4&in)", asMETHOD(Vector4, operator +=), asCALL_THISCALL);
     engine->RegisterObjectMethod("Vector4", "Vector4& opSubAssign(const Vector4&in)", asMETHOD(Vector4, operator -=), asCALL_THISCALL);
@@ -995,6 +1055,16 @@ static void ConstructColorRGB(float r, float g, float b, Color* ptr)
     new(ptr) Color(r, g, b);
 }
 
+static void ConstructColorArrayInit(CScriptArray* data, Color* ptr)
+{
+    new(ptr) Color((static_cast<float*>(data->At(0))));
+}
+
+static CScriptArray* ColorData(Color* ptr)
+{
+    return BufferToArray<float>(ptr->Data(), 4, "float[]");
+}
+
 static void RegisterColor(asIScriptEngine* engine)
 {
     engine->RegisterObjectType("Color", sizeof(Color), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS_CAK);
@@ -1002,6 +1072,8 @@ static void RegisterColor(asIScriptEngine* engine)
     engine->RegisterObjectBehaviour("Color", asBEHAVE_CONSTRUCT, "void f(const Color&in)", asFUNCTION(ConstructColorCopy), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectBehaviour("Color", asBEHAVE_CONSTRUCT, "void f(float, float, float, float)", asFUNCTION(ConstructColorRGBA), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectBehaviour("Color", asBEHAVE_CONSTRUCT, "void f(float, float, float)", asFUNCTION(ConstructColorRGB), asCALL_CDECL_OBJLAST);
+    engine->RegisterObjectBehaviour("Color", asBEHAVE_CONSTRUCT, "void f(float[]&)", asFUNCTION(ConstructColorArrayInit), asCALL_CDECL_OBJLAST);
+    engine->RegisterObjectMethod("Color", "float[]& get_data() const", asFUNCTION(ColorData), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("Color", "Color& opAssign(const Color&in)", asMETHOD(Color, operator =), asCALL_THISCALL);
     engine->RegisterObjectMethod("Color", "Color& opAddAssign(const Color&in)", asMETHOD(Color, operator +=), asCALL_THISCALL);
     engine->RegisterObjectMethod("Color", "bool opEquals(const Color&in) const", asMETHOD(Color, operator ==), asCALL_THISCALL);

+ 10 - 1
Engine/Math/Color.h

@@ -80,7 +80,16 @@ public:
         a_(a)
     {
     }
-    
+
+    /// Construct from a float array.
+    Color(const float* data) :
+        r_(data[0]),
+        g_(data[1]),
+        b_(data[2]),
+        a_(data[3])
+    {
+    }
+
     /// Test for equality with another color.
     bool operator == (const Color& rhs) const { return Equals(r_, rhs.r_) && Equals(g_, rhs.g_) && Equals(b_, rhs.b_) && Equals(a_, rhs.a_); }
     /// Test for inequality with another color.

+ 9 - 0
Engine/Math/Rect.h

@@ -197,6 +197,15 @@ public:
     {
     }
     
+    /// Construct from an int array.
+    IntRect(const int* data) :
+        left_(data[0]),
+        top_(data[1]),
+        right_(data[2]),
+        bottom_(data[3])
+    {
+    }
+
     /// Test for equality with another rect.
     bool operator == (const IntRect& rhs) const { return left_ == rhs.left_ && top_ == rhs.top_ && right_ == rhs.right_ && bottom_ == rhs.bottom_; }
     /// Test for inequality with another rect.

+ 7 - 0
Engine/Math/Vector2.h

@@ -216,6 +216,13 @@ public:
     {
     }
     
+    /// Construct from an int array.
+    IntVector2(const int* data) :
+        x_(data[0]),
+        y_(data[1])
+    {
+    }
+    
     /// Copy-construct from another vector.
     IntVector2(const IntVector2& rhs) :
         x_(rhs.x_),