Browse Source

Add support for Vector2i, Rect2i and Vector3i to Variant

WARNING: Requires C++17 'guaranteed copy elision' to fix ambiguous
operator problems in Variant.

This was added for this commit (and future C++17 uses) in #36457.
Juan Linietsky 5 years ago
parent
commit
6da0eef9e6

+ 74 - 0
core/io/marshalls.cpp

@@ -186,6 +186,18 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
 			if (r_len)
 				(*r_len) += 4 * 2;
 
+		} break; // 5
+		case Variant::VECTOR2I: {
+
+			ERR_FAIL_COND_V(len < 4 * 2, ERR_INVALID_DATA);
+			Vector2i val;
+			val.x = decode_uint32(&buf[0]);
+			val.y = decode_uint32(&buf[4]);
+			r_variant = val;
+
+			if (r_len)
+				(*r_len) += 4 * 2;
+
 		} break; // 5
 		case Variant::RECT2: {
 
@@ -200,6 +212,20 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
 			if (r_len)
 				(*r_len) += 4 * 4;
 
+		} break;
+		case Variant::RECT2I: {
+
+			ERR_FAIL_COND_V(len < 4 * 4, ERR_INVALID_DATA);
+			Rect2i val;
+			val.position.x = decode_uint32(&buf[0]);
+			val.position.y = decode_uint32(&buf[4]);
+			val.size.x = decode_uint32(&buf[8]);
+			val.size.y = decode_uint32(&buf[12]);
+			r_variant = val;
+
+			if (r_len)
+				(*r_len) += 4 * 4;
+
 		} break;
 		case Variant::VECTOR3: {
 
@@ -213,6 +239,19 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
 			if (r_len)
 				(*r_len) += 4 * 3;
 
+		} break;
+		case Variant::VECTOR3I: {
+
+			ERR_FAIL_COND_V(len < 4 * 3, ERR_INVALID_DATA);
+			Vector3i val;
+			val.x = decode_uint32(&buf[0]);
+			val.y = decode_uint32(&buf[4]);
+			val.z = decode_uint32(&buf[8]);
+			r_variant = val;
+
+			if (r_len)
+				(*r_len) += 4 * 3;
+
 		} break;
 		case Variant::TRANSFORM2D: {
 
@@ -966,6 +1005,17 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
 
 			r_len += 2 * 4;
 
+		} break; // 5
+		case Variant::VECTOR2I: {
+
+			if (buf) {
+				Vector2i v2 = p_variant;
+				encode_uint32(v2.x, &buf[0]);
+				encode_uint32(v2.y, &buf[4]);
+			}
+
+			r_len += 2 * 4;
+
 		} break; // 5
 		case Variant::RECT2: {
 
@@ -978,6 +1028,18 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
 			}
 			r_len += 4 * 4;
 
+		} break;
+		case Variant::RECT2I: {
+
+			if (buf) {
+				Rect2i r2 = p_variant;
+				encode_uint32(r2.position.x, &buf[0]);
+				encode_uint32(r2.position.y, &buf[4]);
+				encode_uint32(r2.size.x, &buf[8]);
+				encode_uint32(r2.size.y, &buf[12]);
+			}
+			r_len += 4 * 4;
+
 		} break;
 		case Variant::VECTOR3: {
 
@@ -990,6 +1052,18 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
 
 			r_len += 3 * 4;
 
+		} break;
+		case Variant::VECTOR3I: {
+
+			if (buf) {
+				Vector3i v3 = p_variant;
+				encode_uint32(v3.x, &buf[0]);
+				encode_uint32(v3.y, &buf[4]);
+				encode_uint32(v3.z, &buf[8]);
+			}
+
+			r_len += 3 * 4;
+
 		} break;
 		case Variant::TRANSFORM2D: {
 

+ 56 - 0
core/io/resource_format_binary.cpp

@@ -76,6 +76,9 @@ enum {
 	VARIANT_CALLABLE = 42,
 	VARIANT_SIGNAL = 43,
 	VARIANT_STRING_NAME = 44,
+	VARIANT_VECTOR2I = 45,
+	VARIANT_RECT2I = 46,
+	VARIANT_VECTOR3I = 47,
 	OBJECT_EMPTY = 0,
 	OBJECT_EXTERNAL_RESOURCE = 1,
 	OBJECT_INTERNAL_RESOURCE = 2,
@@ -158,6 +161,14 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) {
 			v.y = f->get_real();
 			r_v = v;
 
+		} break;
+		case VARIANT_VECTOR2I: {
+
+			Vector2i v;
+			v.x = f->get_32();
+			v.y = f->get_32();
+			r_v = v;
+
 		} break;
 		case VARIANT_RECT2: {
 
@@ -168,6 +179,16 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) {
 			v.size.y = f->get_real();
 			r_v = v;
 
+		} break;
+		case VARIANT_RECT2I: {
+
+			Rect2i v;
+			v.position.x = f->get_32();
+			v.position.y = f->get_32();
+			v.size.x = f->get_32();
+			v.size.y = f->get_32();
+			r_v = v;
+
 		} break;
 		case VARIANT_VECTOR3: {
 
@@ -177,6 +198,14 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) {
 			v.z = f->get_real();
 			r_v = v;
 		} break;
+		case VARIANT_VECTOR3I: {
+
+			Vector3i v;
+			v.x = f->get_32();
+			v.y = f->get_32();
+			v.z = f->get_32();
+			r_v = v;
+		} break;
 		case VARIANT_PLANE: {
 
 			Plane v;
@@ -1292,6 +1321,14 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia
 			f->store_real(val.x);
 			f->store_real(val.y);
 
+		} break;
+		case Variant::VECTOR2I: {
+
+			f->store_32(VARIANT_VECTOR2I);
+			Vector2i val = p_property;
+			f->store_32(val.x);
+			f->store_32(val.y);
+
 		} break;
 		case Variant::RECT2: {
 
@@ -1302,6 +1339,16 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia
 			f->store_real(val.size.x);
 			f->store_real(val.size.y);
 
+		} break;
+		case Variant::RECT2I: {
+
+			f->store_32(VARIANT_RECT2I);
+			Rect2i val = p_property;
+			f->store_32(val.position.x);
+			f->store_32(val.position.y);
+			f->store_32(val.size.x);
+			f->store_32(val.size.y);
+
 		} break;
 		case Variant::VECTOR3: {
 
@@ -1311,6 +1358,15 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia
 			f->store_real(val.y);
 			f->store_real(val.z);
 
+		} break;
+		case Variant::VECTOR3I: {
+
+			f->store_32(VARIANT_VECTOR3I);
+			Vector3i val = p_property;
+			f->store_32(val.x);
+			f->store_32(val.y);
+			f->store_32(val.z);
+
 		} break;
 		case Variant::PLANE: {
 

+ 5 - 0
core/math/rect2.h

@@ -387,6 +387,11 @@ struct Rect2i {
 		size = end - begin;
 	}
 
+	_FORCE_INLINE_ Rect2i abs() const {
+
+		return Rect2i(Point2i(position.x + MIN(size.x, 0), position.y + MIN(size.y, 0)), size.abs());
+	}
+
 	operator String() const { return String(position) + ", " + String(size); }
 
 	operator Rect2() const { return Rect2(position, size); }

+ 6 - 1
core/math/vector2.h

@@ -311,10 +311,15 @@ struct Vector2i {
 	bool operator<(const Vector2i &p_vec2) const { return (x == p_vec2.x) ? (y < p_vec2.y) : (x < p_vec2.x); }
 	bool operator>(const Vector2i &p_vec2) const { return (x == p_vec2.x) ? (y > p_vec2.y) : (x > p_vec2.x); }
 
+	bool operator<=(const Vector2i &p_vec2) const { return x == p_vec2.x ? (y <= p_vec2.y) : (x < p_vec2.x); }
+	bool operator>=(const Vector2i &p_vec2) const { return x == p_vec2.x ? (y >= p_vec2.y) : (x > p_vec2.x); }
+
 	bool operator==(const Vector2i &p_vec2) const;
 	bool operator!=(const Vector2i &p_vec2) const;
 
-	real_t get_aspect() const { return width / (real_t)height; }
+	real_t aspect() const { return width / (real_t)height; }
+	Vector2i sign() const { return Vector2i(SGN(x), SGN(y)); }
+	Vector2i abs() const { return Vector2i(ABS(x), ABS(y)); }
 
 	operator String() const { return String::num(x) + ", " + String::num(y); }
 

+ 298 - 0
core/variant.cpp

@@ -72,10 +72,18 @@ String Variant::get_type_name(Variant::Type p_type) {
 
 			return "Vector2";
 		} break;
+		case VECTOR2I: {
+
+			return "Vector2i";
+		} break;
 		case RECT2: {
 
 			return "Rect2";
 		} break;
+		case RECT2I: {
+
+			return "Rect2i";
+		} break;
 		case TRANSFORM2D: {
 
 			return "Transform2D";
@@ -84,6 +92,10 @@ String Variant::get_type_name(Variant::Type p_type) {
 
 			return "Vector3";
 		} break;
+		case VECTOR3I: {
+
+			return "Vector3i";
+		} break;
 		case PLANE: {
 
 			return "Plane";
@@ -258,6 +270,46 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) {
 
 			invalid_types = invalid;
 		} break;
+		case VECTOR2: {
+
+			static const Type valid[] = {
+				VECTOR2I,
+				NIL,
+			};
+
+			valid_types = valid;
+
+		} break;
+		case VECTOR2I: {
+
+			static const Type valid[] = {
+				VECTOR2,
+				NIL,
+			};
+
+			valid_types = valid;
+
+		} break;
+		case RECT2: {
+
+			static const Type valid[] = {
+				RECT2I,
+				NIL,
+			};
+
+			valid_types = valid;
+
+		} break;
+		case RECT2I: {
+
+			static const Type valid[] = {
+				RECT2,
+				NIL,
+			};
+
+			valid_types = valid;
+
+		} break;
 		case TRANSFORM2D: {
 
 			static const Type valid[] = {
@@ -267,6 +319,27 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) {
 
 			valid_types = valid;
 		} break;
+		case VECTOR3: {
+
+			static const Type valid[] = {
+				VECTOR3I,
+				NIL,
+			};
+
+			valid_types = valid;
+
+		} break;
+		case VECTOR3I: {
+
+			static const Type valid[] = {
+				VECTOR3,
+				NIL,
+			};
+
+			valid_types = valid;
+
+		} break;
+
 		case QUAT: {
 
 			static const Type valid[] = {
@@ -515,6 +588,46 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type
 
 			valid_types = valid;
 		} break;
+		case VECTOR2: {
+
+			static const Type valid[] = {
+				VECTOR2I,
+				NIL,
+			};
+
+			valid_types = valid;
+
+		} break;
+		case VECTOR2I: {
+
+			static const Type valid[] = {
+				VECTOR2,
+				NIL,
+			};
+
+			valid_types = valid;
+
+		} break;
+		case RECT2: {
+
+			static const Type valid[] = {
+				RECT2I,
+				NIL,
+			};
+
+			valid_types = valid;
+
+		} break;
+		case RECT2I: {
+
+			static const Type valid[] = {
+				RECT2,
+				NIL,
+			};
+
+			valid_types = valid;
+
+		} break;
 		case TRANSFORM2D: {
 
 			static const Type valid[] = {
@@ -524,6 +637,27 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type
 
 			valid_types = valid;
 		} break;
+		case VECTOR3: {
+
+			static const Type valid[] = {
+				VECTOR3I,
+				NIL,
+			};
+
+			valid_types = valid;
+
+		} break;
+		case VECTOR3I: {
+
+			static const Type valid[] = {
+				VECTOR3,
+				NIL,
+			};
+
+			valid_types = valid;
+
+		} break;
+
 		case QUAT: {
 
 			static const Type valid[] = {
@@ -764,11 +898,21 @@ bool Variant::is_zero() const {
 
 			return *reinterpret_cast<const Vector2 *>(_data._mem) == Vector2();
 
+		} break;
+		case VECTOR2I: {
+
+			return *reinterpret_cast<const Vector2i *>(_data._mem) == Vector2i();
+
 		} break;
 		case RECT2: {
 
 			return *reinterpret_cast<const Rect2 *>(_data._mem) == Rect2();
 
+		} break;
+		case RECT2I: {
+
+			return *reinterpret_cast<const Rect2i *>(_data._mem) == Rect2i();
+
 		} break;
 		case TRANSFORM2D: {
 
@@ -779,6 +923,11 @@ bool Variant::is_zero() const {
 
 			return *reinterpret_cast<const Vector3 *>(_data._mem) == Vector3();
 
+		} break;
+		case VECTOR3I: {
+
+			return *reinterpret_cast<const Vector3i *>(_data._mem) == Vector3i();
+
 		} break;
 		case PLANE: {
 
@@ -923,16 +1072,31 @@ bool Variant::is_one() const {
 
 			return *reinterpret_cast<const Vector2 *>(_data._mem) == Vector2(1, 1);
 
+		} break;
+		case VECTOR2I: {
+
+			return *reinterpret_cast<const Vector2i *>(_data._mem) == Vector2i(1, 1);
+
 		} break;
 		case RECT2: {
 
 			return *reinterpret_cast<const Rect2 *>(_data._mem) == Rect2(1, 1, 1, 1);
 
+		} break;
+		case RECT2I: {
+
+			return *reinterpret_cast<const Rect2i *>(_data._mem) == Rect2i(1, 1, 1, 1);
+
 		} break;
 		case VECTOR3: {
 
 			return *reinterpret_cast<const Vector3 *>(_data._mem) == Vector3(1, 1, 1);
 
+		} break;
+		case VECTOR3I: {
+
+			return *reinterpret_cast<const Vector3i *>(_data._mem) == Vector3i(1, 1, 1);
+
 		} break;
 		case PLANE: {
 
@@ -1004,10 +1168,18 @@ void Variant::reference(const Variant &p_variant) {
 
 			memnew_placement(_data._mem, Vector2(*reinterpret_cast<const Vector2 *>(p_variant._data._mem)));
 		} break;
+		case VECTOR2I: {
+
+			memnew_placement(_data._mem, Vector2i(*reinterpret_cast<const Vector2i *>(p_variant._data._mem)));
+		} break;
 		case RECT2: {
 
 			memnew_placement(_data._mem, Rect2(*reinterpret_cast<const Rect2 *>(p_variant._data._mem)));
 		} break;
+		case RECT2I: {
+
+			memnew_placement(_data._mem, Rect2i(*reinterpret_cast<const Rect2i *>(p_variant._data._mem)));
+		} break;
 		case TRANSFORM2D: {
 
 			_data._transform2d = memnew(Transform2D(*p_variant._data._transform2d));
@@ -1016,6 +1188,10 @@ void Variant::reference(const Variant &p_variant) {
 
 			memnew_placement(_data._mem, Vector3(*reinterpret_cast<const Vector3 *>(p_variant._data._mem)));
 		} break;
+		case VECTOR3I: {
+
+			memnew_placement(_data._mem, Vector3i(*reinterpret_cast<const Vector3i *>(p_variant._data._mem)));
+		} break;
 		case PLANE: {
 
 			memnew_placement(_data._mem, Plane(*reinterpret_cast<const Plane *>(p_variant._data._mem)));
@@ -1144,8 +1320,11 @@ void Variant::zero() {
 		case INT: this->_data._int = 0; break;
 		case REAL: this->_data._real = 0; break;
 		case VECTOR2: *reinterpret_cast<Vector2 *>(this->_data._mem) = Vector2(); break;
+		case VECTOR2I: *reinterpret_cast<Vector2i *>(this->_data._mem) = Vector2i(); break;
 		case RECT2: *reinterpret_cast<Rect2 *>(this->_data._mem) = Rect2(); break;
+		case RECT2I: *reinterpret_cast<Rect2i *>(this->_data._mem) = Rect2i(); break;
 		case VECTOR3: *reinterpret_cast<Vector3 *>(this->_data._mem) = Vector3(); break;
+		case VECTOR3I: *reinterpret_cast<Vector3i *>(this->_data._mem) = Vector3i(); break;
 		case PLANE: *reinterpret_cast<Plane *>(this->_data._mem) = Plane(); break;
 		case QUAT: *reinterpret_cast<Quat *>(this->_data._mem) = Quat(); break;
 		case COLOR: *reinterpret_cast<Color *>(this->_data._mem) = Color(); break;
@@ -1526,13 +1705,16 @@ String Variant::stringify(List<const void *> &stack) const {
 		case REAL: return rtos(_data._real);
 		case STRING: return *reinterpret_cast<const String *>(_data._mem);
 		case VECTOR2: return "(" + operator Vector2() + ")";
+		case VECTOR2I: return "(" + operator Vector2i() + ")";
 		case RECT2: return "(" + operator Rect2() + ")";
+		case RECT2I: return "(" + operator Rect2i() + ")";
 		case TRANSFORM2D: {
 
 			Transform2D mat32 = operator Transform2D();
 			return "(" + Variant(mat32.elements[0]).operator String() + ", " + Variant(mat32.elements[1]).operator String() + ", " + Variant(mat32.elements[2]).operator String() + ")";
 		} break;
 		case VECTOR3: return "(" + operator Vector3() + ")";
+		case VECTOR3I: return "(" + operator Vector3i() + ")";
 		case PLANE:
 			return operator Plane();
 		//case QUAT:
@@ -1725,28 +1907,78 @@ Variant::operator Vector2() const {
 
 	if (type == VECTOR2)
 		return *reinterpret_cast<const Vector2 *>(_data._mem);
+	else if (type == VECTOR2I)
+		return *reinterpret_cast<const Vector2i *>(_data._mem);
 	else if (type == VECTOR3)
 		return Vector2(reinterpret_cast<const Vector3 *>(_data._mem)->x, reinterpret_cast<const Vector3 *>(_data._mem)->y);
+	else if (type == VECTOR3I)
+		return Vector2(reinterpret_cast<const Vector3i *>(_data._mem)->x, reinterpret_cast<const Vector3i *>(_data._mem)->y);
 	else
 		return Vector2();
 }
+
+Variant::operator Vector2i() const {
+
+	if (type == VECTOR2I)
+		return *reinterpret_cast<const Vector2i *>(_data._mem);
+	else if (type == VECTOR2)
+		return *reinterpret_cast<const Vector2 *>(_data._mem);
+	else if (type == VECTOR3)
+		return Vector2(reinterpret_cast<const Vector3 *>(_data._mem)->x, reinterpret_cast<const Vector3 *>(_data._mem)->y);
+	else if (type == VECTOR3I)
+		return Vector2(reinterpret_cast<const Vector3i *>(_data._mem)->x, reinterpret_cast<const Vector3i *>(_data._mem)->y);
+	else
+		return Vector2i();
+}
+
 Variant::operator Rect2() const {
 
 	if (type == RECT2)
 		return *reinterpret_cast<const Rect2 *>(_data._mem);
+	else if (type == RECT2I)
+		return *reinterpret_cast<const Rect2i *>(_data._mem);
 	else
 		return Rect2();
 }
 
+Variant::operator Rect2i() const {
+
+	if (type == RECT2I)
+		return *reinterpret_cast<const Rect2i *>(_data._mem);
+	else if (type == RECT2)
+		return *reinterpret_cast<const Rect2 *>(_data._mem);
+	else
+		return Rect2i();
+}
+
 Variant::operator Vector3() const {
 
 	if (type == VECTOR3)
 		return *reinterpret_cast<const Vector3 *>(_data._mem);
+	else if (type == VECTOR3I)
+		return *reinterpret_cast<const Vector3i *>(_data._mem);
 	else if (type == VECTOR2)
 		return Vector3(reinterpret_cast<const Vector2 *>(_data._mem)->x, reinterpret_cast<const Vector2 *>(_data._mem)->y, 0.0);
+	else if (type == VECTOR2I)
+		return Vector3(reinterpret_cast<const Vector2i *>(_data._mem)->x, reinterpret_cast<const Vector2i *>(_data._mem)->y, 0.0);
 	else
 		return Vector3();
 }
+
+Variant::operator Vector3i() const {
+
+	if (type == VECTOR3I)
+		return *reinterpret_cast<const Vector3i *>(_data._mem);
+	else if (type == VECTOR3)
+		return *reinterpret_cast<const Vector3 *>(_data._mem);
+	else if (type == VECTOR2)
+		return Vector3i(reinterpret_cast<const Vector2 *>(_data._mem)->x, reinterpret_cast<const Vector2 *>(_data._mem)->y, 0.0);
+	else if (type == VECTOR2I)
+		return Vector3i(reinterpret_cast<const Vector2i *>(_data._mem)->x, reinterpret_cast<const Vector2i *>(_data._mem)->y, 0.0);
+	else
+		return Vector3i();
+}
+
 Variant::operator Plane() const {
 
 	if (type == PLANE)
@@ -2258,17 +2490,36 @@ Variant::Variant(const Vector3 &p_vector3) {
 	type = VECTOR3;
 	memnew_placement(_data._mem, Vector3(p_vector3));
 }
+Variant::Variant(const Vector3i &p_vector3i) {
+
+	type = VECTOR3I;
+	memnew_placement(_data._mem, Vector3i(p_vector3i));
+}
+
 Variant::Variant(const Vector2 &p_vector2) {
 
 	type = VECTOR2;
 	memnew_placement(_data._mem, Vector2(p_vector2));
 }
+
+Variant::Variant(const Vector2i &p_vector2i) {
+
+	type = VECTOR2I;
+	memnew_placement(_data._mem, Vector2i(p_vector2i));
+}
+
 Variant::Variant(const Rect2 &p_rect2) {
 
 	type = RECT2;
 	memnew_placement(_data._mem, Rect2(p_rect2));
 }
 
+Variant::Variant(const Rect2i &p_rect2i) {
+
+	type = RECT2I;
+	memnew_placement(_data._mem, Rect2i(p_rect2i));
+}
+
 Variant::Variant(const Plane &p_plane) {
 
 	type = PLANE;
@@ -2516,10 +2767,18 @@ void Variant::operator=(const Variant &p_variant) {
 
 			*reinterpret_cast<Vector2 *>(_data._mem) = *reinterpret_cast<const Vector2 *>(p_variant._data._mem);
 		} break;
+		case VECTOR2I: {
+
+			*reinterpret_cast<Vector2i *>(_data._mem) = *reinterpret_cast<const Vector2i *>(p_variant._data._mem);
+		} break;
 		case RECT2: {
 
 			*reinterpret_cast<Rect2 *>(_data._mem) = *reinterpret_cast<const Rect2 *>(p_variant._data._mem);
 		} break;
+		case RECT2I: {
+
+			*reinterpret_cast<Rect2i *>(_data._mem) = *reinterpret_cast<const Rect2i *>(p_variant._data._mem);
+		} break;
 		case TRANSFORM2D: {
 
 			*_data._transform2d = *(p_variant._data._transform2d);
@@ -2528,6 +2787,10 @@ void Variant::operator=(const Variant &p_variant) {
 
 			*reinterpret_cast<Vector3 *>(_data._mem) = *reinterpret_cast<const Vector3 *>(p_variant._data._mem);
 		} break;
+		case VECTOR3I: {
+
+			*reinterpret_cast<Vector3i *>(_data._mem) = *reinterpret_cast<const Vector3i *>(p_variant._data._mem);
+		} break;
 		case PLANE: {
 
 			*reinterpret_cast<Plane *>(_data._mem) = *reinterpret_cast<const Plane *>(p_variant._data._mem);
@@ -2690,6 +2953,11 @@ uint32_t Variant::hash() const {
 			uint32_t hash = hash_djb2_one_float(reinterpret_cast<const Vector2 *>(_data._mem)->x);
 			return hash_djb2_one_float(reinterpret_cast<const Vector2 *>(_data._mem)->y, hash);
 		} break;
+		case VECTOR2I: {
+
+			uint32_t hash = hash_djb2_one_32(reinterpret_cast<const Vector2i *>(_data._mem)->x);
+			return hash_djb2_one_32(reinterpret_cast<const Vector2i *>(_data._mem)->y, hash);
+		} break;
 		case RECT2: {
 
 			uint32_t hash = hash_djb2_one_float(reinterpret_cast<const Rect2 *>(_data._mem)->position.x);
@@ -2697,6 +2965,13 @@ uint32_t Variant::hash() const {
 			hash = hash_djb2_one_float(reinterpret_cast<const Rect2 *>(_data._mem)->size.x, hash);
 			return hash_djb2_one_float(reinterpret_cast<const Rect2 *>(_data._mem)->size.y, hash);
 		} break;
+		case RECT2I: {
+
+			uint32_t hash = hash_djb2_one_32(reinterpret_cast<const Rect2i *>(_data._mem)->position.x);
+			hash = hash_djb2_one_32(reinterpret_cast<const Rect2i *>(_data._mem)->position.y, hash);
+			hash = hash_djb2_one_32(reinterpret_cast<const Rect2i *>(_data._mem)->size.x, hash);
+			return hash_djb2_one_32(reinterpret_cast<const Rect2i *>(_data._mem)->size.y, hash);
+		} break;
 		case TRANSFORM2D: {
 
 			uint32_t hash = 5831;
@@ -2715,6 +2990,12 @@ uint32_t Variant::hash() const {
 			hash = hash_djb2_one_float(reinterpret_cast<const Vector3 *>(_data._mem)->y, hash);
 			return hash_djb2_one_float(reinterpret_cast<const Vector3 *>(_data._mem)->z, hash);
 		} break;
+		case VECTOR3I: {
+
+			uint32_t hash = hash_djb2_one_32(reinterpret_cast<const Vector3i *>(_data._mem)->x);
+			hash = hash_djb2_one_32(reinterpret_cast<const Vector3i *>(_data._mem)->y, hash);
+			return hash_djb2_one_32(reinterpret_cast<const Vector3i *>(_data._mem)->z, hash);
+		} break;
 		case PLANE: {
 
 			uint32_t hash = hash_djb2_one_float(reinterpret_cast<const Plane *>(_data._mem)->normal.x);
@@ -2993,6 +3274,11 @@ bool Variant::hash_compare(const Variant &p_variant) const {
 
 			return hash_compare_vector2(*l, *r);
 		} break;
+		case VECTOR2I: {
+			const Vector2i *l = reinterpret_cast<const Vector2i *>(_data._mem);
+			const Vector2i *r = reinterpret_cast<const Vector2i *>(p_variant._data._mem);
+			return *l == *r;
+		} break;
 
 		case RECT2: {
 			const Rect2 *l = reinterpret_cast<const Rect2 *>(_data._mem);
@@ -3001,6 +3287,12 @@ bool Variant::hash_compare(const Variant &p_variant) const {
 			return (hash_compare_vector2(l->position, r->position)) &&
 				   (hash_compare_vector2(l->size, r->size));
 		} break;
+		case RECT2I: {
+			const Rect2i *l = reinterpret_cast<const Rect2i *>(_data._mem);
+			const Rect2i *r = reinterpret_cast<const Rect2i *>(p_variant._data._mem);
+
+			return *l == *r;
+		} break;
 
 		case TRANSFORM2D: {
 			Transform2D *l = _data._transform2d;
@@ -3020,6 +3312,12 @@ bool Variant::hash_compare(const Variant &p_variant) const {
 
 			return hash_compare_vector3(*l, *r);
 		} break;
+		case VECTOR3I: {
+			const Vector3i *l = reinterpret_cast<const Vector3i *>(_data._mem);
+			const Vector3i *r = reinterpret_cast<const Vector3i *>(p_variant._data._mem);
+
+			return *l == *r;
+		} break;
 
 		case PLANE: {
 			const Plane *l = reinterpret_cast<const Plane *>(_data._mem);

+ 10 - 0
core/variant.h

@@ -44,6 +44,7 @@
 #include "core/math/transform.h"
 #include "core/math/transform_2d.h"
 #include "core/math/vector3.h"
+#include "core/math/vector3i.h"
 #include "core/node_path.h"
 #include "core/object_id.h"
 #include "core/rid.h"
@@ -87,8 +88,11 @@ public:
 		// math types
 
 		VECTOR2, // 5
+		VECTOR2I,
 		RECT2,
+		RECT2I,
 		VECTOR3,
+		VECTOR3I,
 		TRANSFORM2D,
 		PLANE,
 		QUAT, // 10
@@ -187,8 +191,11 @@ public:
 	operator String() const;
 	operator StringName() const;
 	operator Vector2() const;
+	operator Vector2i() const;
 	operator Rect2() const;
+	operator Rect2i() const;
 	operator Vector3() const;
+	operator Vector3i() const;
 	operator Plane() const;
 	operator ::AABB() const;
 	operator Quat() const;
@@ -255,8 +262,11 @@ public:
 	Variant(const char *const p_cstring);
 	Variant(const CharType *p_wstring);
 	Variant(const Vector2 &p_vector2);
+	Variant(const Vector2i &p_vector2i);
 	Variant(const Rect2 &p_rect2);
+	Variant(const Rect2i &p_rect2i);
 	Variant(const Vector3 &p_vector3);
+	Variant(const Vector3i &p_vector3i);
 	Variant(const Plane &p_plane);
 	Variant(const ::AABB &p_aabb);
 	Variant(const Quat &p_quat);

+ 95 - 0
core/variant_call.cpp

@@ -383,6 +383,10 @@ struct _VariantCall {
 	VCALL_LOCALMEM1R(Vector2, clamped);
 	VCALL_LOCALMEM0R(Vector2, sign);
 
+	VCALL_LOCALMEM0R(Vector2i, aspect);
+	VCALL_LOCALMEM0R(Vector2i, sign);
+	VCALL_LOCALMEM0R(Vector2i, abs);
+
 	VCALL_LOCALMEM0R(Rect2, get_area);
 	VCALL_LOCALMEM0R(Rect2, has_no_area);
 	VCALL_LOCALMEM1R(Rect2, has_point);
@@ -397,6 +401,19 @@ struct _VariantCall {
 	VCALL_LOCALMEM4R(Rect2, grow_individual);
 	VCALL_LOCALMEM0R(Rect2, abs);
 
+	VCALL_LOCALMEM0R(Rect2i, get_area);
+	VCALL_LOCALMEM0R(Rect2i, has_no_area);
+	VCALL_LOCALMEM1R(Rect2i, has_point);
+	VCALL_LOCALMEM1R(Rect2i, intersects);
+	VCALL_LOCALMEM1R(Rect2i, encloses);
+	VCALL_LOCALMEM1R(Rect2i, clip);
+	VCALL_LOCALMEM1R(Rect2i, merge);
+	VCALL_LOCALMEM1R(Rect2i, expand);
+	VCALL_LOCALMEM1R(Rect2i, grow);
+	VCALL_LOCALMEM2R(Rect2i, grow_margin);
+	VCALL_LOCALMEM4R(Rect2i, grow_individual);
+	VCALL_LOCALMEM0R(Rect2i, abs);
+
 	VCALL_LOCALMEM0R(Vector3, min_axis);
 	VCALL_LOCALMEM0R(Vector3, max_axis);
 	VCALL_LOCALMEM1R(Vector3, distance_to);
@@ -431,6 +448,10 @@ struct _VariantCall {
 	VCALL_LOCALMEM1R(Vector3, reflect);
 	VCALL_LOCALMEM0R(Vector3, sign);
 
+	VCALL_LOCALMEM0R(Vector3i, min_axis);
+	VCALL_LOCALMEM0R(Vector3i, max_axis);
+	VCALL_LOCALMEM0R(Vector3i, sign);
+
 	VCALL_LOCALMEM0R(Plane, normalized);
 	VCALL_LOCALMEM0R(Plane, center);
 	VCALL_LOCALMEM0R(Plane, get_any_point);
@@ -909,6 +930,11 @@ struct _VariantCall {
 		r_ret = Vector2(*p_args[0], *p_args[1]);
 	}
 
+	static void Vector2i_init1(Variant &r_ret, const Variant **p_args) {
+
+		r_ret = Vector2i(*p_args[0], *p_args[1]);
+	}
+
 	static void Rect2_init1(Variant &r_ret, const Variant **p_args) {
 
 		r_ret = Rect2(*p_args[0], *p_args[1]);
@@ -919,6 +945,16 @@ struct _VariantCall {
 		r_ret = Rect2(*p_args[0], *p_args[1], *p_args[2], *p_args[3]);
 	}
 
+	static void Rect2i_init1(Variant &r_ret, const Variant **p_args) {
+
+		r_ret = Rect2i(*p_args[0], *p_args[1]);
+	}
+
+	static void Rect2i_init2(Variant &r_ret, const Variant **p_args) {
+
+		r_ret = Rect2i(*p_args[0], *p_args[1], *p_args[2], *p_args[3]);
+	}
+
 	static void Transform2D_init2(Variant &r_ret, const Variant **p_args) {
 
 		Transform2D m(*p_args[0], *p_args[1]);
@@ -939,6 +975,11 @@ struct _VariantCall {
 		r_ret = Vector3(*p_args[0], *p_args[1], *p_args[2]);
 	}
 
+	static void Vector3i_init1(Variant &r_ret, const Variant **p_args) {
+
+		r_ret = Vector3i(*p_args[0], *p_args[1], *p_args[2]);
+	}
+
 	static void Plane_init1(Variant &r_ret, const Variant **p_args) {
 
 		r_ret = Plane(*p_args[0], *p_args[1], *p_args[2], *p_args[3]);
@@ -1262,8 +1303,13 @@ Variant Variant::construct(const Variant::Type p_type, const Variant **p_args, i
 			case VECTOR2: {
 				return Vector2(*p_args[0]);
 			}
+			case VECTOR2I: {
+				return Vector2i(*p_args[0]);
+			}
 			case RECT2: return (Rect2(*p_args[0]));
+			case RECT2I: return (Rect2i(*p_args[0]));
 			case VECTOR3: return (Vector3(*p_args[0]));
+			case VECTOR3I: return (Vector3i(*p_args[0]));
 			case PLANE: return (Plane(*p_args[0]));
 			case QUAT: return (p_args[0]->operator Quat());
 			case AABB:
@@ -1727,6 +1773,10 @@ void register_variant_methods() {
 	ADDFUNC1R(VECTOR2, VECTOR2, Vector2, clamped, REAL, "length", varray());
 	ADDFUNC0R(VECTOR2, VECTOR2, Vector2, sign, varray());
 
+	ADDFUNC0R(VECTOR2I, REAL, Vector2i, aspect, varray());
+	ADDFUNC0R(VECTOR2I, VECTOR2I, Vector2i, sign, varray());
+	ADDFUNC0R(VECTOR2I, VECTOR2I, Vector2i, abs, varray());
+
 	ADDFUNC0R(RECT2, REAL, Rect2, get_area, varray());
 	ADDFUNC0R(RECT2, BOOL, Rect2, has_no_area, varray());
 	ADDFUNC1R(RECT2, BOOL, Rect2, has_point, VECTOR2, "point", varray());
@@ -1741,6 +1791,19 @@ void register_variant_methods() {
 	ADDFUNC4R(RECT2, RECT2, Rect2, grow_individual, REAL, "left", REAL, "top", REAL, "right", REAL, " bottom", varray());
 	ADDFUNC0R(RECT2, RECT2, Rect2, abs, varray());
 
+	ADDFUNC0R(RECT2I, INT, Rect2i, get_area, varray());
+	ADDFUNC0R(RECT2I, BOOL, Rect2i, has_no_area, varray());
+	ADDFUNC1R(RECT2I, BOOL, Rect2i, has_point, VECTOR2I, "point", varray());
+	ADDFUNC1R(RECT2I, BOOL, Rect2i, intersects, RECT2I, "b", varray());
+	ADDFUNC1R(RECT2I, BOOL, Rect2i, encloses, RECT2I, "b", varray());
+	ADDFUNC1R(RECT2I, RECT2I, Rect2i, clip, RECT2I, "b", varray());
+	ADDFUNC1R(RECT2I, RECT2I, Rect2i, merge, RECT2I, "b", varray());
+	ADDFUNC1R(RECT2I, RECT2I, Rect2i, expand, VECTOR2I, "to", varray());
+	ADDFUNC1R(RECT2I, RECT2I, Rect2i, grow, INT, "by", varray());
+	ADDFUNC2R(RECT2I, RECT2I, Rect2i, grow_margin, INT, "margin", INT, "by", varray());
+	ADDFUNC4R(RECT2I, RECT2I, Rect2i, grow_individual, INT, "left", INT, "top", INT, "right", INT, " bottom", varray());
+	ADDFUNC0R(RECT2I, RECT2I, Rect2i, abs, varray());
+
 	ADDFUNC0R(VECTOR3, INT, Vector3, min_axis, varray());
 	ADDFUNC0R(VECTOR3, INT, Vector3, max_axis, varray());
 	ADDFUNC1R(VECTOR3, REAL, Vector3, angle_to, VECTOR3, "to", varray());
@@ -1775,6 +1838,10 @@ void register_variant_methods() {
 	ADDFUNC1R(VECTOR3, VECTOR3, Vector3, reflect, VECTOR3, "n", varray());
 	ADDFUNC0R(VECTOR3, VECTOR3, Vector3, sign, varray());
 
+	ADDFUNC0R(VECTOR3I, INT, Vector3i, min_axis, varray());
+	ADDFUNC0R(VECTOR3I, INT, Vector3i, max_axis, varray());
+	ADDFUNC0R(VECTOR3I, VECTOR3I, Vector3i, sign, varray());
+
 	ADDFUNC0R(PLANE, PLANE, Plane, normalized, varray());
 	ADDFUNC0R(PLANE, VECTOR3, Plane, center, varray());
 	ADDFUNC0R(PLANE, VECTOR3, Plane, get_any_point, varray());
@@ -2048,14 +2115,19 @@ void register_variant_methods() {
 	/* REGISTER CONSTRUCTORS */
 
 	_VariantCall::add_constructor(_VariantCall::Vector2_init1, Variant::VECTOR2, "x", Variant::REAL, "y", Variant::REAL);
+	_VariantCall::add_constructor(_VariantCall::Vector2i_init1, Variant::VECTOR2I, "x", Variant::INT, "y", Variant::INT);
 
 	_VariantCall::add_constructor(_VariantCall::Rect2_init1, Variant::RECT2, "position", Variant::VECTOR2, "size", Variant::VECTOR2);
 	_VariantCall::add_constructor(_VariantCall::Rect2_init2, Variant::RECT2, "x", Variant::REAL, "y", Variant::REAL, "width", Variant::REAL, "height", Variant::REAL);
 
+	_VariantCall::add_constructor(_VariantCall::Rect2i_init1, Variant::RECT2I, "position", Variant::VECTOR2, "size", Variant::VECTOR2);
+	_VariantCall::add_constructor(_VariantCall::Rect2i_init2, Variant::RECT2I, "x", Variant::INT, "y", Variant::INT, "width", Variant::INT, "height", Variant::INT);
+
 	_VariantCall::add_constructor(_VariantCall::Transform2D_init2, Variant::TRANSFORM2D, "rotation", Variant::REAL, "position", Variant::VECTOR2);
 	_VariantCall::add_constructor(_VariantCall::Transform2D_init3, Variant::TRANSFORM2D, "x_axis", Variant::VECTOR2, "y_axis", Variant::VECTOR2, "origin", Variant::VECTOR2);
 
 	_VariantCall::add_constructor(_VariantCall::Vector3_init1, Variant::VECTOR3, "x", Variant::REAL, "y", Variant::REAL, "z", Variant::REAL);
+	_VariantCall::add_constructor(_VariantCall::Vector3i_init1, Variant::VECTOR3I, "x", Variant::INT, "y", Variant::INT, "z", Variant::INT);
 
 	_VariantCall::add_constructor(_VariantCall::Plane_init1, Variant::PLANE, "a", Variant::REAL, "b", Variant::REAL, "c", Variant::REAL, "d", Variant::REAL);
 	_VariantCall::add_constructor(_VariantCall::Plane_init2, Variant::PLANE, "v1", Variant::VECTOR3, "v2", Variant::VECTOR3, "v3", Variant::VECTOR3);
@@ -2100,9 +2172,25 @@ void register_variant_methods() {
 	_VariantCall::add_variant_constant(Variant::VECTOR3, "FORWARD", Vector3(0, 0, -1));
 	_VariantCall::add_variant_constant(Variant::VECTOR3, "BACK", Vector3(0, 0, 1));
 
+	_VariantCall::add_constant(Variant::VECTOR3I, "AXIS_X", Vector3::AXIS_X);
+	_VariantCall::add_constant(Variant::VECTOR3I, "AXIS_Y", Vector3::AXIS_Y);
+	_VariantCall::add_constant(Variant::VECTOR3I, "AXIS_Z", Vector3::AXIS_Z);
+
+	_VariantCall::add_variant_constant(Variant::VECTOR3I, "ZERO", Vector3i(0, 0, 0));
+	_VariantCall::add_variant_constant(Variant::VECTOR3I, "ONE", Vector3i(1, 1, 1));
+	_VariantCall::add_variant_constant(Variant::VECTOR3I, "LEFT", Vector3i(-1, 0, 0));
+	_VariantCall::add_variant_constant(Variant::VECTOR3I, "RIGHT", Vector3i(1, 0, 0));
+	_VariantCall::add_variant_constant(Variant::VECTOR3I, "UP", Vector3i(0, 1, 0));
+	_VariantCall::add_variant_constant(Variant::VECTOR3I, "DOWN", Vector3i(0, -1, 0));
+	_VariantCall::add_variant_constant(Variant::VECTOR3I, "FORWARD", Vector3i(0, 0, -1));
+	_VariantCall::add_variant_constant(Variant::VECTOR3I, "BACK", Vector3i(0, 0, 1));
+
 	_VariantCall::add_constant(Variant::VECTOR2, "AXIS_X", Vector2::AXIS_X);
 	_VariantCall::add_constant(Variant::VECTOR2, "AXIS_Y", Vector2::AXIS_Y);
 
+	_VariantCall::add_constant(Variant::VECTOR2I, "AXIS_X", Vector2::AXIS_X);
+	_VariantCall::add_constant(Variant::VECTOR2I, "AXIS_Y", Vector2::AXIS_Y);
+
 	_VariantCall::add_variant_constant(Variant::VECTOR2, "ZERO", Vector2(0, 0));
 	_VariantCall::add_variant_constant(Variant::VECTOR2, "ONE", Vector2(1, 1));
 	_VariantCall::add_variant_constant(Variant::VECTOR2, "INF", Vector2(Math_INF, Math_INF));
@@ -2111,6 +2199,13 @@ void register_variant_methods() {
 	_VariantCall::add_variant_constant(Variant::VECTOR2, "UP", Vector2(0, -1));
 	_VariantCall::add_variant_constant(Variant::VECTOR2, "DOWN", Vector2(0, 1));
 
+	_VariantCall::add_variant_constant(Variant::VECTOR2I, "ZERO", Vector2i(0, 0));
+	_VariantCall::add_variant_constant(Variant::VECTOR2I, "ONE", Vector2i(1, 1));
+	_VariantCall::add_variant_constant(Variant::VECTOR2I, "LEFT", Vector2i(-1, 0));
+	_VariantCall::add_variant_constant(Variant::VECTOR2I, "RIGHT", Vector2i(1, 0));
+	_VariantCall::add_variant_constant(Variant::VECTOR2I, "UP", Vector2i(0, -1));
+	_VariantCall::add_variant_constant(Variant::VECTOR2I, "DOWN", Vector2i(0, 1));
+
 	_VariantCall::add_variant_constant(Variant::TRANSFORM2D, "IDENTITY", Transform2D());
 	_VariantCall::add_variant_constant(Variant::TRANSFORM2D, "FLIP_X", Transform2D(-1, 0, 0, 1, 0, 0));
 	_VariantCall::add_variant_constant(Variant::TRANSFORM2D, "FLIP_Y", Transform2D(1, 0, 0, -1, 0, 0));

+ 423 - 8
core/variant_op.cpp

@@ -44,8 +44,11 @@
 	CASE_TYPE(PREFIX, OP, REAL)                 \
 	CASE_TYPE(PREFIX, OP, STRING)               \
 	CASE_TYPE(PREFIX, OP, VECTOR2)              \
+	CASE_TYPE(PREFIX, OP, VECTOR2I)             \
 	CASE_TYPE(PREFIX, OP, RECT2)                \
+	CASE_TYPE(PREFIX, OP, RECT2I)               \
 	CASE_TYPE(PREFIX, OP, VECTOR3)              \
+	CASE_TYPE(PREFIX, OP, VECTOR3I)             \
 	CASE_TYPE(PREFIX, OP, TRANSFORM2D)          \
 	CASE_TYPE(PREFIX, OP, PLANE)                \
 	CASE_TYPE(PREFIX, OP, QUAT)                 \
@@ -80,8 +83,11 @@
 		TYPE(PREFIX, OP, REAL),               \
 		TYPE(PREFIX, OP, STRING),             \
 		TYPE(PREFIX, OP, VECTOR2),            \
+		TYPE(PREFIX, OP, VECTOR2I),            \
 		TYPE(PREFIX, OP, RECT2),              \
+	TYPE(PREFIX, OP, RECT2I),              \
 		TYPE(PREFIX, OP, VECTOR3),            \
+	TYPE(PREFIX, OP, VECTOR3I),            \
 		TYPE(PREFIX, OP, TRANSFORM2D),        \
 		TYPE(PREFIX, OP, PLANE),              \
 		TYPE(PREFIX, OP, QUAT),               \
@@ -228,14 +234,16 @@ bool Variant::booleanize() const {
 		_RETURN(p_a._data.m_type);                              \
 	};
 
-#define DEFAULT_OP_NUM_VEC(m_prefix, m_op_name, m_name, m_op, m_type)                                               \
-	CASE_TYPE(m_prefix, m_op_name, m_name) {                                                                        \
-		if (p_b.type == INT) _RETURN(p_a._data.m_type m_op p_b._data._int);                                         \
-		if (p_b.type == REAL) _RETURN(p_a._data.m_type m_op p_b._data._real);                                       \
-		if (p_b.type == VECTOR2) _RETURN(p_a._data.m_type m_op *reinterpret_cast<const Vector2 *>(p_b._data._mem)); \
-		if (p_b.type == VECTOR3) _RETURN(p_a._data.m_type m_op *reinterpret_cast<const Vector3 *>(p_b._data._mem)); \
-                                                                                                                    \
-		_RETURN_FAIL                                                                                                \
+#define DEFAULT_OP_NUM_VEC(m_prefix, m_op_name, m_name, m_op, m_type)                                                \
+	CASE_TYPE(m_prefix, m_op_name, m_name) {                                                                         \
+		if (p_b.type == INT) _RETURN(p_a._data.m_type m_op p_b._data._int);                                          \
+		if (p_b.type == REAL) _RETURN(p_a._data.m_type m_op p_b._data._real);                                        \
+		if (p_b.type == VECTOR2) _RETURN(p_a._data.m_type m_op *reinterpret_cast<const Vector2 *>(p_b._data._mem));  \
+		if (p_b.type == VECTOR3) _RETURN(p_a._data.m_type m_op *reinterpret_cast<const Vector3 *>(p_b._data._mem));  \
+		if (p_b.type == VECTOR2I) _RETURN(p_a._data.m_type m_op *reinterpret_cast<const Vector2 *>(p_b._data._mem)); \
+		if (p_b.type == VECTOR3I) _RETURN(p_a._data.m_type m_op *reinterpret_cast<const Vector3 *>(p_b._data._mem)); \
+                                                                                                                     \
+		_RETURN_FAIL                                                                                                 \
 	};
 
 #define DEFAULT_OP_STR_REV(m_prefix, m_op_name, m_name, m_op, m_type)                                                                                       \
@@ -491,9 +499,12 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
 			DEFAULT_OP_NUM_NULL(math, OP_EQUAL, REAL, ==, _real);
 			DEFAULT_OP_STR_NULL(math, OP_EQUAL, STRING, ==, String);
 			DEFAULT_OP_LOCALMEM_NULL(math, OP_EQUAL, VECTOR2, ==, Vector2);
+			DEFAULT_OP_LOCALMEM_NULL(math, OP_EQUAL, VECTOR2I, ==, Vector2i);
 			DEFAULT_OP_LOCALMEM_NULL(math, OP_EQUAL, RECT2, ==, Rect2);
+			DEFAULT_OP_LOCALMEM_NULL(math, OP_EQUAL, RECT2I, ==, Rect2i);
 			DEFAULT_OP_PTRREF_NULL(math, OP_EQUAL, TRANSFORM2D, ==, _transform2d);
 			DEFAULT_OP_LOCALMEM_NULL(math, OP_EQUAL, VECTOR3, ==, Vector3);
+			DEFAULT_OP_LOCALMEM_NULL(math, OP_EQUAL, VECTOR3I, ==, Vector3i);
 			DEFAULT_OP_LOCALMEM_NULL(math, OP_EQUAL, PLANE, ==, Plane);
 			DEFAULT_OP_LOCALMEM_NULL(math, OP_EQUAL, QUAT, ==, Quat);
 			DEFAULT_OP_PTRREF_NULL(math, OP_EQUAL, AABB, ==, _aabb);
@@ -585,9 +596,12 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
 			DEFAULT_OP_NUM_NULL(math, OP_NOT_EQUAL, REAL, !=, _real);
 			DEFAULT_OP_STR_NULL(math, OP_NOT_EQUAL, STRING, !=, String);
 			DEFAULT_OP_LOCALMEM_NULL(math, OP_NOT_EQUAL, VECTOR2, !=, Vector2);
+			DEFAULT_OP_LOCALMEM_NULL(math, OP_NOT_EQUAL, VECTOR2I, !=, Vector2i);
 			DEFAULT_OP_LOCALMEM_NULL(math, OP_NOT_EQUAL, RECT2, !=, Rect2);
+			DEFAULT_OP_LOCALMEM_NULL(math, OP_NOT_EQUAL, RECT2I, !=, Rect2i);
 			DEFAULT_OP_PTRREF_NULL(math, OP_NOT_EQUAL, TRANSFORM2D, !=, _transform2d);
 			DEFAULT_OP_LOCALMEM_NULL(math, OP_NOT_EQUAL, VECTOR3, !=, Vector3);
+			DEFAULT_OP_LOCALMEM_NULL(math, OP_NOT_EQUAL, VECTOR3I, !=, Vector3i);
 			DEFAULT_OP_LOCALMEM_NULL(math, OP_NOT_EQUAL, PLANE, !=, Plane);
 			DEFAULT_OP_LOCALMEM_NULL(math, OP_NOT_EQUAL, QUAT, !=, Quat);
 			DEFAULT_OP_PTRREF_NULL(math, OP_NOT_EQUAL, AABB, !=, _aabb);
@@ -653,7 +667,9 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
 			DEFAULT_OP_NUM(math, OP_LESS, REAL, <, _real);
 			DEFAULT_OP_STR(math, OP_LESS, STRING, <, String);
 			DEFAULT_OP_LOCALMEM(math, OP_LESS, VECTOR2, <, Vector2);
+			DEFAULT_OP_LOCALMEM(math, OP_LESS, VECTOR2I, <, Vector2i);
 			DEFAULT_OP_LOCALMEM(math, OP_LESS, VECTOR3, <, Vector3);
+			DEFAULT_OP_LOCALMEM(math, OP_LESS, VECTOR3I, <, Vector3i);
 			DEFAULT_OP_LOCALMEM(math, OP_LESS, _RID, <, RID);
 			DEFAULT_OP_ARRAY_LT(math, OP_LESS, PACKED_BYTE_ARRAY, uint8_t);
 			DEFAULT_OP_ARRAY_LT(math, OP_LESS, PACKED_INT_ARRAY, int);
@@ -665,6 +681,7 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
 
 			CASE_TYPE(math, OP_LESS, NIL)
 			CASE_TYPE(math, OP_LESS, RECT2)
+			CASE_TYPE(math, OP_LESS, RECT2I)
 			CASE_TYPE(math, OP_LESS, TRANSFORM2D)
 			CASE_TYPE(math, OP_LESS, PLANE)
 			CASE_TYPE(math, OP_LESS, QUAT)
@@ -689,12 +706,15 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
 			DEFAULT_OP_NUM(math, OP_LESS_EQUAL, REAL, <=, _real);
 			DEFAULT_OP_STR(math, OP_LESS_EQUAL, STRING, <=, String);
 			DEFAULT_OP_LOCALMEM(math, OP_LESS_EQUAL, VECTOR2, <=, Vector2);
+			DEFAULT_OP_LOCALMEM(math, OP_LESS_EQUAL, VECTOR2I, <=, Vector2i);
 			DEFAULT_OP_LOCALMEM(math, OP_LESS_EQUAL, VECTOR3, <=, Vector3);
+			DEFAULT_OP_LOCALMEM(math, OP_LESS_EQUAL, VECTOR3I, <=, Vector3i);
 			DEFAULT_OP_LOCALMEM(math, OP_LESS_EQUAL, _RID, <=, RID);
 
 			CASE_TYPE(math, OP_LESS_EQUAL, NIL)
 			CASE_TYPE(math, OP_LESS_EQUAL, BOOL)
 			CASE_TYPE(math, OP_LESS_EQUAL, RECT2)
+			CASE_TYPE(math, OP_LESS_EQUAL, RECT2I)
 			CASE_TYPE(math, OP_LESS_EQUAL, TRANSFORM2D)
 			CASE_TYPE(math, OP_LESS_EQUAL, PLANE)
 			CASE_TYPE(math, OP_LESS_EQUAL, QUAT)
@@ -762,7 +782,9 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
 			DEFAULT_OP_NUM(math, OP_GREATER, REAL, >, _real);
 			DEFAULT_OP_STR_REV(math, OP_GREATER, STRING, <, String);
 			DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER, VECTOR2, <, Vector2);
+			DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER, VECTOR2I, <, Vector2i);
 			DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER, VECTOR3, <, Vector3);
+			DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER, VECTOR3I, <, Vector3i);
 			DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER, _RID, <, RID);
 			DEFAULT_OP_ARRAY_GT(math, OP_GREATER, PACKED_BYTE_ARRAY, uint8_t);
 			DEFAULT_OP_ARRAY_GT(math, OP_GREATER, PACKED_INT_ARRAY, int);
@@ -774,6 +796,7 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
 
 			CASE_TYPE(math, OP_GREATER, NIL)
 			CASE_TYPE(math, OP_GREATER, RECT2)
+			CASE_TYPE(math, OP_GREATER, RECT2I)
 			CASE_TYPE(math, OP_GREATER, TRANSFORM2D)
 			CASE_TYPE(math, OP_GREATER, PLANE)
 			CASE_TYPE(math, OP_GREATER, QUAT)
@@ -801,12 +824,15 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
 			DEFAULT_OP_NUM(math, OP_GREATER_EQUAL, REAL, >=, _real);
 			DEFAULT_OP_STR_REV(math, OP_GREATER_EQUAL, STRING, <=, String);
 			DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER_EQUAL, VECTOR2, <=, Vector2);
+			DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER_EQUAL, VECTOR2I, <=, Vector2i);
 			DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER_EQUAL, VECTOR3, <=, Vector3);
+			DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER_EQUAL, VECTOR3I, <=, Vector3i);
 			DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER_EQUAL, _RID, <=, RID);
 
 			CASE_TYPE(math, OP_GREATER_EQUAL, NIL)
 			CASE_TYPE(math, OP_GREATER_EQUAL, BOOL)
 			CASE_TYPE(math, OP_GREATER_EQUAL, RECT2)
+			CASE_TYPE(math, OP_GREATER_EQUAL, RECT2I)
 			CASE_TYPE(math, OP_GREATER_EQUAL, TRANSFORM2D)
 			CASE_TYPE(math, OP_GREATER_EQUAL, PLANE)
 			CASE_TYPE(math, OP_GREATER_EQUAL, QUAT)
@@ -853,7 +879,9 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
 			DEFAULT_OP_NUM(math, OP_ADD, REAL, +, _real);
 			DEFAULT_OP_STR(math, OP_ADD, STRING, +, String);
 			DEFAULT_OP_LOCALMEM(math, OP_ADD, VECTOR2, +, Vector2);
+			DEFAULT_OP_LOCALMEM(math, OP_ADD, VECTOR2I, +, Vector2i);
 			DEFAULT_OP_LOCALMEM(math, OP_ADD, VECTOR3, +, Vector3);
+			DEFAULT_OP_LOCALMEM(math, OP_ADD, VECTOR3I, +, Vector3i);
 			DEFAULT_OP_LOCALMEM(math, OP_ADD, QUAT, +, Quat);
 			DEFAULT_OP_LOCALMEM(math, OP_ADD, COLOR, +, Color);
 
@@ -868,6 +896,7 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
 			CASE_TYPE(math, OP_ADD, NIL)
 			CASE_TYPE(math, OP_ADD, BOOL)
 			CASE_TYPE(math, OP_ADD, RECT2)
+			CASE_TYPE(math, OP_ADD, RECT2I)
 			CASE_TYPE(math, OP_ADD, TRANSFORM2D)
 			CASE_TYPE(math, OP_ADD, PLANE)
 			CASE_TYPE(math, OP_ADD, AABB)
@@ -888,7 +917,9 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
 			DEFAULT_OP_NUM(math, OP_SUBTRACT, INT, -, _int);
 			DEFAULT_OP_NUM(math, OP_SUBTRACT, REAL, -, _real);
 			DEFAULT_OP_LOCALMEM(math, OP_SUBTRACT, VECTOR2, -, Vector2);
+			DEFAULT_OP_LOCALMEM(math, OP_SUBTRACT, VECTOR2I, -, Vector2i);
 			DEFAULT_OP_LOCALMEM(math, OP_SUBTRACT, VECTOR3, -, Vector3);
+			DEFAULT_OP_LOCALMEM(math, OP_SUBTRACT, VECTOR3I, -, Vector3i);
 			DEFAULT_OP_LOCALMEM(math, OP_SUBTRACT, QUAT, -, Quat);
 			DEFAULT_OP_LOCALMEM(math, OP_SUBTRACT, COLOR, -, Color);
 
@@ -896,6 +927,7 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
 			CASE_TYPE(math, OP_SUBTRACT, BOOL)
 			CASE_TYPE(math, OP_SUBTRACT, STRING)
 			CASE_TYPE(math, OP_SUBTRACT, RECT2)
+			CASE_TYPE(math, OP_SUBTRACT, RECT2I)
 			CASE_TYPE(math, OP_SUBTRACT, TRANSFORM2D)
 			CASE_TYPE(math, OP_SUBTRACT, PLANE)
 			CASE_TYPE(math, OP_SUBTRACT, AABB)
@@ -975,13 +1007,16 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
 			DEFAULT_OP_NUM_VEC(math, OP_MULTIPLY, INT, *, _int);
 			DEFAULT_OP_NUM_VEC(math, OP_MULTIPLY, REAL, *, _real);
 			DEFAULT_OP_LOCALMEM_NUM(math, OP_MULTIPLY, VECTOR2, *, Vector2);
+			DEFAULT_OP_LOCALMEM_NUM(math, OP_MULTIPLY, VECTOR2I, *, Vector2i);
 			DEFAULT_OP_LOCALMEM_NUM(math, OP_MULTIPLY, VECTOR3, *, Vector3);
+			DEFAULT_OP_LOCALMEM_NUM(math, OP_MULTIPLY, VECTOR3I, *, Vector3i);
 			DEFAULT_OP_LOCALMEM_NUM(math, OP_MULTIPLY, COLOR, *, Color);
 
 			CASE_TYPE(math, OP_MULTIPLY, NIL)
 			CASE_TYPE(math, OP_MULTIPLY, BOOL)
 			CASE_TYPE(math, OP_MULTIPLY, STRING)
 			CASE_TYPE(math, OP_MULTIPLY, RECT2)
+			CASE_TYPE(math, OP_MULTIPLY, RECT2I)
 			CASE_TYPE(math, OP_MULTIPLY, PLANE)
 			CASE_TYPE(math, OP_MULTIPLY, AABB)
 			CASE_TYPE(math, OP_MULTIPLY, STRING_NAME)
@@ -1019,13 +1054,16 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
 			DEFAULT_OP_NUM_DIV(math, OP_DIVIDE, INT, _int);
 			DEFAULT_OP_NUM_DIV(math, OP_DIVIDE, REAL, _real);
 			DEFAULT_OP_LOCALMEM_NUM(math, OP_DIVIDE, VECTOR2, /, Vector2);
+			DEFAULT_OP_LOCALMEM_NUM(math, OP_DIVIDE, VECTOR2I, /, Vector2i);
 			DEFAULT_OP_LOCALMEM_NUM(math, OP_DIVIDE, VECTOR3, /, Vector3);
+			DEFAULT_OP_LOCALMEM_NUM(math, OP_DIVIDE, VECTOR3I, /, Vector3i);
 			DEFAULT_OP_LOCALMEM_NUM(math, OP_DIVIDE, COLOR, /, Color);
 
 			CASE_TYPE(math, OP_DIVIDE, NIL)
 			CASE_TYPE(math, OP_DIVIDE, BOOL)
 			CASE_TYPE(math, OP_DIVIDE, STRING)
 			CASE_TYPE(math, OP_DIVIDE, RECT2)
+			CASE_TYPE(math, OP_DIVIDE, RECT2I)
 			CASE_TYPE(math, OP_DIVIDE, TRANSFORM2D)
 			CASE_TYPE(math, OP_DIVIDE, PLANE)
 			CASE_TYPE(math, OP_DIVIDE, AABB)
@@ -1054,14 +1092,17 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
 			DEFAULT_OP_NUM_POS(math, OP_POSITIVE, INT, _int);
 			DEFAULT_OP_NUM_POS(math, OP_POSITIVE, REAL, _real);
 			DEFAULT_OP_LOCALMEM_POS(math, OP_POSITIVE, VECTOR3, Vector3);
+			DEFAULT_OP_LOCALMEM_POS(math, OP_POSITIVE, VECTOR3I, Vector3i);
 			DEFAULT_OP_LOCALMEM_POS(math, OP_POSITIVE, PLANE, Plane);
 			DEFAULT_OP_LOCALMEM_POS(math, OP_POSITIVE, QUAT, Quat);
 			DEFAULT_OP_LOCALMEM_POS(math, OP_POSITIVE, VECTOR2, Vector2);
+			DEFAULT_OP_LOCALMEM_POS(math, OP_POSITIVE, VECTOR2I, Vector2i);
 
 			CASE_TYPE(math, OP_POSITIVE, NIL)
 			CASE_TYPE(math, OP_POSITIVE, BOOL)
 			CASE_TYPE(math, OP_POSITIVE, STRING)
 			CASE_TYPE(math, OP_POSITIVE, RECT2)
+			CASE_TYPE(math, OP_POSITIVE, RECT2I)
 			CASE_TYPE(math, OP_POSITIVE, TRANSFORM2D)
 			CASE_TYPE(math, OP_POSITIVE, AABB)
 			CASE_TYPE(math, OP_POSITIVE, BASIS)
@@ -1091,7 +1132,9 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
 			DEFAULT_OP_NUM_NEG(math, OP_NEGATE, REAL, _real);
 
 			DEFAULT_OP_LOCALMEM_NEG(math, OP_NEGATE, VECTOR2, Vector2);
+			DEFAULT_OP_LOCALMEM_NEG(math, OP_NEGATE, VECTOR2I, Vector2i);
 			DEFAULT_OP_LOCALMEM_NEG(math, OP_NEGATE, VECTOR3, Vector3);
+			DEFAULT_OP_LOCALMEM_NEG(math, OP_NEGATE, VECTOR3I, Vector3i);
 			DEFAULT_OP_LOCALMEM_NEG(math, OP_NEGATE, PLANE, Plane);
 			DEFAULT_OP_LOCALMEM_NEG(math, OP_NEGATE, QUAT, Quat);
 			DEFAULT_OP_LOCALMEM_NEG(math, OP_NEGATE, COLOR, Color);
@@ -1100,6 +1143,7 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
 			CASE_TYPE(math, OP_NEGATE, BOOL)
 			CASE_TYPE(math, OP_NEGATE, STRING)
 			CASE_TYPE(math, OP_NEGATE, RECT2)
+			CASE_TYPE(math, OP_NEGATE, RECT2I)
 			CASE_TYPE(math, OP_NEGATE, TRANSFORM2D)
 			CASE_TYPE(math, OP_NEGATE, AABB)
 			CASE_TYPE(math, OP_NEGATE, BASIS)
@@ -1159,8 +1203,11 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
 			CASE_TYPE(math, OP_MODULE, BOOL)
 			CASE_TYPE(math, OP_MODULE, REAL)
 			CASE_TYPE(math, OP_MODULE, VECTOR2)
+			CASE_TYPE(math, OP_MODULE, VECTOR2I)
 			CASE_TYPE(math, OP_MODULE, RECT2)
+			CASE_TYPE(math, OP_MODULE, RECT2I)
 			CASE_TYPE(math, OP_MODULE, VECTOR3)
+			CASE_TYPE(math, OP_MODULE, VECTOR3I)
 			CASE_TYPE(math, OP_MODULE, TRANSFORM2D)
 			CASE_TYPE(math, OP_MODULE, PLANE)
 			CASE_TYPE(math, OP_MODULE, QUAT)
@@ -1327,6 +1374,28 @@ void Variant::set_named(const StringName &p_index, const Variant &p_value, bool
 				}
 			}
 
+		} break;
+		case VECTOR2I: {
+			if (p_value.type == Variant::INT) {
+				Vector2i *v = reinterpret_cast<Vector2i *>(_data._mem);
+				if (p_index == CoreStringNames::singleton->x) {
+					v->x = p_value._data._int;
+					valid = true;
+				} else if (p_index == CoreStringNames::singleton->y) {
+					v->y = p_value._data._int;
+					valid = true;
+				}
+			} else if (p_value.type == Variant::REAL) {
+				Vector2i *v = reinterpret_cast<Vector2i *>(_data._mem);
+				if (p_index == CoreStringNames::singleton->x) {
+					v->x = p_value._data._real;
+					valid = true;
+				} else if (p_index == CoreStringNames::singleton->y) {
+					v->y = p_value._data._real;
+					valid = true;
+				}
+			}
+
 		} break;
 		case RECT2: {
 
@@ -1345,6 +1414,23 @@ void Variant::set_named(const StringName &p_index, const Variant &p_value, bool
 				}
 			}
 		} break;
+		case RECT2I: {
+
+			if (p_value.type == Variant::VECTOR2I) {
+				Rect2i *v = reinterpret_cast<Rect2i *>(_data._mem);
+				//scalar name
+				if (p_index == CoreStringNames::singleton->position) {
+					v->position = *reinterpret_cast<const Vector2i *>(p_value._data._mem);
+					valid = true;
+				} else if (p_index == CoreStringNames::singleton->size) {
+					v->size = *reinterpret_cast<const Vector2i *>(p_value._data._mem);
+					valid = true;
+				} else if (p_index == CoreStringNames::singleton->end) {
+					v->size = *reinterpret_cast<const Vector2i *>(p_value._data._mem) - v->position;
+					valid = true;
+				}
+			}
+		} break;
 		case TRANSFORM2D: {
 
 			if (p_value.type == Variant::VECTOR2) {
@@ -1390,6 +1476,35 @@ void Variant::set_named(const StringName &p_index, const Variant &p_value, bool
 				}
 			}
 
+		} break;
+		case VECTOR3I: {
+
+			if (p_value.type == Variant::INT) {
+				Vector3i *v = reinterpret_cast<Vector3i *>(_data._mem);
+				if (p_index == CoreStringNames::singleton->x) {
+					v->x = p_value._data._int;
+					valid = true;
+				} else if (p_index == CoreStringNames::singleton->y) {
+					v->y = p_value._data._int;
+					valid = true;
+				} else if (p_index == CoreStringNames::singleton->z) {
+					v->z = p_value._data._int;
+					valid = true;
+				}
+			} else if (p_value.type == Variant::REAL) {
+				Vector3i *v = reinterpret_cast<Vector3i *>(_data._mem);
+				if (p_index == CoreStringNames::singleton->x) {
+					v->x = p_value._data._real;
+					valid = true;
+				} else if (p_index == CoreStringNames::singleton->y) {
+					v->y = p_value._data._real;
+					valid = true;
+				} else if (p_index == CoreStringNames::singleton->z) {
+					v->z = p_value._data._real;
+					valid = true;
+				}
+			}
+
 		} break;
 		case PLANE: {
 
@@ -1626,6 +1741,15 @@ Variant Variant::get_named(const StringName &p_index, bool *r_valid) const {
 				return v->y;
 			}
 
+		} break;
+		case VECTOR2I: {
+			const Vector2i *v = reinterpret_cast<const Vector2i *>(_data._mem);
+			if (p_index == CoreStringNames::singleton->x) {
+				return v->x;
+			} else if (p_index == CoreStringNames::singleton->y) {
+				return v->y;
+			}
+
 		} break;
 		case RECT2: {
 
@@ -1639,6 +1763,18 @@ Variant Variant::get_named(const StringName &p_index, bool *r_valid) const {
 				return v->size + v->position;
 			}
 		} break;
+		case RECT2I: {
+
+			const Rect2i *v = reinterpret_cast<const Rect2i *>(_data._mem);
+			//scalar name
+			if (p_index == CoreStringNames::singleton->position) {
+				return v->position;
+			} else if (p_index == CoreStringNames::singleton->size) {
+				return v->size;
+			} else if (p_index == CoreStringNames::singleton->end) {
+				return v->size + v->position;
+			}
+		} break;
 		case TRANSFORM2D: {
 
 			const Transform2D *v = _data._transform2d;
@@ -1662,6 +1798,18 @@ Variant Variant::get_named(const StringName &p_index, bool *r_valid) const {
 				return v->z;
 			}
 
+		} break;
+		case VECTOR3I: {
+
+			const Vector3i *v = reinterpret_cast<const Vector3i *>(_data._mem);
+			if (p_index == CoreStringNames::singleton->x) {
+				return v->x;
+			} else if (p_index == CoreStringNames::singleton->y) {
+				return v->y;
+			} else if (p_index == CoreStringNames::singleton->z) {
+				return v->z;
+			}
+
 		} break;
 		case PLANE: {
 
@@ -1892,6 +2040,41 @@ void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid)
 				}
 			}
 
+		} break; // 5
+		case VECTOR2I: {
+
+			if (p_value.type != Variant::INT && p_value.type != Variant::REAL)
+				return;
+
+			if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::REAL) {
+				// scalar index
+				int idx = p_index;
+
+				if (idx < 0)
+					idx += 2;
+				if (idx >= 0 && idx < 2) {
+
+					Vector2i *v = reinterpret_cast<Vector2i *>(_data._mem);
+					valid = true;
+					(*v)[idx] = p_value;
+					return;
+				}
+			} else if (p_index.get_type() == Variant::STRING) {
+				//scalar name
+
+				const String *str = reinterpret_cast<const String *>(p_index._data._mem);
+				Vector2i *v = reinterpret_cast<Vector2i *>(_data._mem);
+				if (*str == "x") {
+					valid = true;
+					v->x = p_value;
+					return;
+				} else if (*str == "y") {
+					valid = true;
+					v->y = p_value;
+					return;
+				}
+			}
+
 		} break; // 5
 		case RECT2: {
 
@@ -1918,6 +2101,31 @@ void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid)
 				}
 			}
 		} break;
+		case RECT2I: {
+
+			if (p_value.type != Variant::VECTOR2I)
+				return;
+
+			if (p_index.get_type() == Variant::STRING) {
+				//scalar name
+
+				const String *str = reinterpret_cast<const String *>(p_index._data._mem);
+				Rect2i *v = reinterpret_cast<Rect2i *>(_data._mem);
+				if (*str == "position") {
+					valid = true;
+					v->position = p_value;
+					return;
+				} else if (*str == "size") {
+					valid = true;
+					v->size = p_value;
+					return;
+				} else if (*str == "end") {
+					valid = true;
+					v->size = Vector2i(p_value) - v->position;
+					return;
+				}
+			}
+		} break;
 		case TRANSFORM2D: {
 
 			if (p_value.type != Variant::VECTOR2)
@@ -1994,6 +2202,44 @@ void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid)
 				}
 			}
 
+		} break;
+		case VECTOR3I: {
+
+			if (p_value.type != Variant::INT && p_value.type != Variant::REAL)
+				return;
+
+			if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::REAL) {
+				//scalar index
+				int idx = p_index;
+				if (idx < 0)
+					idx += 3;
+				if (idx >= 0 && idx < 3) {
+
+					Vector3i *v = reinterpret_cast<Vector3i *>(_data._mem);
+					valid = true;
+					(*v)[idx] = p_value;
+					return;
+				}
+			} else if (p_index.get_type() == Variant::STRING) {
+
+				//scalar name
+				const String *str = reinterpret_cast<const String *>(p_index._data._mem);
+				Vector3i *v = reinterpret_cast<Vector3i *>(_data._mem);
+				if (*str == "x") {
+					valid = true;
+					v->x = p_value;
+					return;
+				} else if (*str == "y") {
+					valid = true;
+					v->y = p_value;
+					return;
+				} else if (*str == "z") {
+					valid = true;
+					v->z = p_value;
+					return;
+				}
+			}
+
 		} break;
 		case PLANE: {
 
@@ -2355,6 +2601,34 @@ Variant Variant::get(const Variant &p_index, bool *r_valid) const {
 				}
 			}
 
+		} break; // 5
+		case VECTOR2I: {
+
+			if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::REAL) {
+				// scalar index
+				int idx = p_index;
+				if (idx < 0)
+					idx += 2;
+				if (idx >= 0 && idx < 2) {
+
+					const Vector2i *v = reinterpret_cast<const Vector2i *>(_data._mem);
+					valid = true;
+					return (*v)[idx];
+				}
+			} else if (p_index.get_type() == Variant::STRING) {
+				//scalar name
+
+				const String *str = reinterpret_cast<const String *>(p_index._data._mem);
+				const Vector2i *v = reinterpret_cast<const Vector2i *>(_data._mem);
+				if (*str == "x") {
+					valid = true;
+					return v->x;
+				} else if (*str == "y") {
+					valid = true;
+					return v->y;
+				}
+			}
+
 		} break; // 5
 		case RECT2: {
 
@@ -2375,6 +2649,25 @@ Variant Variant::get(const Variant &p_index, bool *r_valid) const {
 				}
 			}
 		} break;
+		case RECT2I: {
+
+			if (p_index.get_type() == Variant::STRING) {
+				//scalar name
+
+				const String *str = reinterpret_cast<const String *>(p_index._data._mem);
+				const Rect2i *v = reinterpret_cast<const Rect2i *>(_data._mem);
+				if (*str == "position") {
+					valid = true;
+					return v->position;
+				} else if (*str == "size") {
+					valid = true;
+					return v->size;
+				} else if (*str == "end") {
+					valid = true;
+					return v->size + v->position;
+				}
+			}
+		} break;
 		case VECTOR3: {
 
 			if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::REAL) {
@@ -2405,6 +2698,37 @@ Variant Variant::get(const Variant &p_index, bool *r_valid) const {
 				}
 			}
 
+		} break;
+		case VECTOR3I: {
+
+			if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::REAL) {
+				//scalar index
+				int idx = p_index;
+				if (idx < 0)
+					idx += 3;
+				if (idx >= 0 && idx < 3) {
+
+					const Vector3i *v = reinterpret_cast<const Vector3i *>(_data._mem);
+					valid = true;
+					return (*v)[idx];
+				}
+			} else if (p_index.get_type() == Variant::STRING) {
+
+				//scalar name
+				const String *str = reinterpret_cast<const String *>(p_index._data._mem);
+				const Vector3i *v = reinterpret_cast<const Vector3i *>(_data._mem);
+				if (*str == "x") {
+					valid = true;
+					return v->x;
+				} else if (*str == "y") {
+					valid = true;
+					return v->y;
+				} else if (*str == "z") {
+					valid = true;
+					return v->z;
+				}
+			}
+
 		} break;
 		case TRANSFORM2D: {
 
@@ -2881,6 +3205,12 @@ void Variant::get_property_list(List<PropertyInfo> *p_list) const {
 			p_list->push_back(PropertyInfo(Variant::REAL, "x"));
 			p_list->push_back(PropertyInfo(Variant::REAL, "y"));
 
+		} break; // 5
+		case VECTOR2I: {
+
+			p_list->push_back(PropertyInfo(Variant::INT, "x"));
+			p_list->push_back(PropertyInfo(Variant::INT, "y"));
+
 		} break; // 5
 		case RECT2: {
 
@@ -2888,6 +3218,13 @@ void Variant::get_property_list(List<PropertyInfo> *p_list) const {
 			p_list->push_back(PropertyInfo(Variant::VECTOR2, "size"));
 			p_list->push_back(PropertyInfo(Variant::VECTOR2, "end"));
 
+		} break;
+		case RECT2I: {
+
+			p_list->push_back(PropertyInfo(Variant::VECTOR2I, "position"));
+			p_list->push_back(PropertyInfo(Variant::VECTOR2I, "size"));
+			p_list->push_back(PropertyInfo(Variant::VECTOR2I, "end"));
+
 		} break;
 		case VECTOR3: {
 
@@ -2895,6 +3232,13 @@ void Variant::get_property_list(List<PropertyInfo> *p_list) const {
 			p_list->push_back(PropertyInfo(Variant::REAL, "y"));
 			p_list->push_back(PropertyInfo(Variant::REAL, "z"));
 
+		} break;
+		case VECTOR3I: {
+
+			p_list->push_back(PropertyInfo(Variant::INT, "x"));
+			p_list->push_back(PropertyInfo(Variant::INT, "y"));
+			p_list->push_back(PropertyInfo(Variant::INT, "z"));
+
 		} break;
 		case TRANSFORM2D: {
 
@@ -3562,16 +3906,50 @@ void Variant::blend(const Variant &a, const Variant &b, float c, Variant &r_dst)
 			r_dst = *reinterpret_cast<const Vector2 *>(a._data._mem) + *reinterpret_cast<const Vector2 *>(b._data._mem) * c;
 		}
 			return;
+		case VECTOR2I: {
+			int32_t vax = reinterpret_cast<const Vector2i *>(a._data._mem)->x;
+			int32_t vbx = reinterpret_cast<const Vector2i *>(b._data._mem)->x;
+			int32_t vay = reinterpret_cast<const Vector2i *>(a._data._mem)->y;
+			int32_t vby = reinterpret_cast<const Vector2i *>(b._data._mem)->y;
+			r_dst = Vector2i(int32_t(vax + vbx * c + 0.5), int32_t(vay + vby * c + 0.5));
+		}
+			return;
 		case RECT2: {
 			const Rect2 *ra = reinterpret_cast<const Rect2 *>(a._data._mem);
 			const Rect2 *rb = reinterpret_cast<const Rect2 *>(b._data._mem);
 			r_dst = Rect2(ra->position + rb->position * c, ra->size + rb->size * c);
 		}
 			return;
+		case RECT2I: {
+			const Rect2i *ra = reinterpret_cast<const Rect2i *>(a._data._mem);
+			const Rect2i *rb = reinterpret_cast<const Rect2i *>(b._data._mem);
+
+			int32_t vax = ra->position.x;
+			int32_t vay = ra->position.y;
+			int32_t vbx = ra->size.x;
+			int32_t vby = ra->size.y;
+			int32_t vcx = rb->position.x;
+			int32_t vcy = rb->position.y;
+			int32_t vdx = rb->size.x;
+			int32_t vdy = rb->size.y;
+
+			r_dst = Rect2i(int32_t(vax + vbx * c + 0.5), int32_t(vay + vby * c + 0.5), int32_t(vcx + vdx * c + 0.5), int32_t(vcy + vdy * c + 0.5));
+		}
+			return;
 		case VECTOR3: {
 			r_dst = *reinterpret_cast<const Vector3 *>(a._data._mem) + *reinterpret_cast<const Vector3 *>(b._data._mem) * c;
 		}
 			return;
+		case VECTOR3I: {
+			int32_t vax = reinterpret_cast<const Vector3i *>(a._data._mem)->x;
+			int32_t vbx = reinterpret_cast<const Vector3i *>(b._data._mem)->x;
+			int32_t vay = reinterpret_cast<const Vector3i *>(a._data._mem)->y;
+			int32_t vby = reinterpret_cast<const Vector3i *>(b._data._mem)->y;
+			int32_t vaz = reinterpret_cast<const Vector3i *>(a._data._mem)->z;
+			int32_t vbz = reinterpret_cast<const Vector3i *>(b._data._mem)->z;
+			r_dst = Vector3i(int32_t(vax + vbx * c + 0.5), int32_t(vay + vby * c + 0.5), int32_t(vaz + vbz * c + 0.5));
+		}
+			return;
 		case AABB: {
 			const ::AABB *ra = reinterpret_cast<const ::AABB *>(a._data._mem);
 			const ::AABB *rb = reinterpret_cast<const ::AABB *>(b._data._mem);
@@ -3688,14 +4066,51 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant &
 			r_dst = reinterpret_cast<const Vector2 *>(a._data._mem)->linear_interpolate(*reinterpret_cast<const Vector2 *>(b._data._mem), c);
 		}
 			return;
+		case VECTOR2I: {
+			int32_t vax = reinterpret_cast<const Vector2i *>(a._data._mem)->x;
+			int32_t vbx = reinterpret_cast<const Vector2i *>(b._data._mem)->x;
+			int32_t vay = reinterpret_cast<const Vector2i *>(a._data._mem)->y;
+			int32_t vby = reinterpret_cast<const Vector2i *>(b._data._mem)->y;
+			r_dst = Vector2i(int32_t(vax + vbx * c + 0.5), int32_t(vay + vby * c + 0.5));
+		}
+			return;
+
 		case RECT2: {
 			r_dst = Rect2(reinterpret_cast<const Rect2 *>(a._data._mem)->position.linear_interpolate(reinterpret_cast<const Rect2 *>(b._data._mem)->position, c), reinterpret_cast<const Rect2 *>(a._data._mem)->size.linear_interpolate(reinterpret_cast<const Rect2 *>(b._data._mem)->size, c));
 		}
 			return;
+		case RECT2I: {
+			const Rect2i *ra = reinterpret_cast<const Rect2i *>(a._data._mem);
+			const Rect2i *rb = reinterpret_cast<const Rect2i *>(b._data._mem);
+
+			int32_t vax = ra->position.x;
+			int32_t vay = ra->position.y;
+			int32_t vbx = ra->size.x;
+			int32_t vby = ra->size.y;
+			int32_t vcx = rb->position.x;
+			int32_t vcy = rb->position.y;
+			int32_t vdx = rb->size.x;
+			int32_t vdy = rb->size.y;
+
+			r_dst = Rect2i(int32_t(vax + vbx * c + 0.5), int32_t(vay + vby * c + 0.5), int32_t(vcx + vdx * c + 0.5), int32_t(vcy + vdy * c + 0.5));
+		}
+			return;
+
 		case VECTOR3: {
 			r_dst = reinterpret_cast<const Vector3 *>(a._data._mem)->linear_interpolate(*reinterpret_cast<const Vector3 *>(b._data._mem), c);
 		}
 			return;
+		case VECTOR3I: {
+			int32_t vax = reinterpret_cast<const Vector3i *>(a._data._mem)->x;
+			int32_t vbx = reinterpret_cast<const Vector3i *>(b._data._mem)->x;
+			int32_t vay = reinterpret_cast<const Vector3i *>(a._data._mem)->y;
+			int32_t vby = reinterpret_cast<const Vector3i *>(b._data._mem)->y;
+			int32_t vaz = reinterpret_cast<const Vector3i *>(a._data._mem)->z;
+			int32_t vbz = reinterpret_cast<const Vector3i *>(b._data._mem)->z;
+			r_dst = Vector3i(int32_t(vax + vbx * c + 0.5), int32_t(vay + vby * c + 0.5), int32_t(vaz + vbz * c + 0.5));
+		}
+			return;
+
 		case TRANSFORM2D: {
 			r_dst = a._data._transform2d->interpolate_with(*b._data._transform2d, c);
 		}

+ 55 - 0
core/variant_parser.cpp

@@ -545,6 +545,19 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
 
 			value = Vector2(args[0], args[1]);
 			return OK;
+		} else if (id == "Vector2i") {
+
+			Vector<int32_t> args;
+			Error err = _parse_construct<int32_t>(p_stream, args, line, r_err_str);
+			if (err)
+				return err;
+
+			if (args.size() != 2) {
+				r_err_str = "Expected 2 arguments for constructor";
+			}
+
+			value = Vector2i(args[0], args[1]);
+			return OK;
 		} else if (id == "Rect2") {
 
 			Vector<float> args;
@@ -558,6 +571,19 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
 
 			value = Rect2(args[0], args[1], args[2], args[3]);
 			return OK;
+		} else if (id == "Rect2i") {
+
+			Vector<int32_t> args;
+			Error err = _parse_construct<int32_t>(p_stream, args, line, r_err_str);
+			if (err)
+				return err;
+
+			if (args.size() != 4) {
+				r_err_str = "Expected 4 arguments for constructor";
+			}
+
+			value = Rect2i(args[0], args[1], args[2], args[3]);
+			return OK;
 		} else if (id == "Vector3") {
 
 			Vector<float> args;
@@ -571,6 +597,19 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
 
 			value = Vector3(args[0], args[1], args[2]);
 			return OK;
+		} else if (id == "Vector3i") {
+
+			Vector<int32_t> args;
+			Error err = _parse_construct<int32_t>(p_stream, args, line, r_err_str);
+			if (err)
+				return err;
+
+			if (args.size() != 3) {
+				r_err_str = "Expected 3 arguments for constructor";
+			}
+
+			value = Vector3i(args[0], args[1], args[2]);
+			return OK;
 		} else if (id == "Transform2D" || id == "Matrix32") { //compatibility
 
 			Vector<float> args;
@@ -1431,17 +1470,33 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
 			Vector2 v = p_variant;
 			p_store_string_func(p_store_string_ud, "Vector2( " + rtosfix(v.x) + ", " + rtosfix(v.y) + " )");
 		} break;
+		case Variant::VECTOR2I: {
+
+			Vector2i v = p_variant;
+			p_store_string_func(p_store_string_ud, "Vector2i( " + itos(v.x) + ", " + itos(v.y) + " )");
+		} break;
 		case Variant::RECT2: {
 
 			Rect2 aabb = p_variant;
 			p_store_string_func(p_store_string_ud, "Rect2( " + rtosfix(aabb.position.x) + ", " + rtosfix(aabb.position.y) + ", " + rtosfix(aabb.size.x) + ", " + rtosfix(aabb.size.y) + " )");
 
+		} break;
+		case Variant::RECT2I: {
+
+			Rect2i aabb = p_variant;
+			p_store_string_func(p_store_string_ud, "Rect2i( " + itos(aabb.position.x) + ", " + itos(aabb.position.y) + ", " + itos(aabb.size.x) + ", " + itos(aabb.size.y) + " )");
+
 		} break;
 		case Variant::VECTOR3: {
 
 			Vector3 v = p_variant;
 			p_store_string_func(p_store_string_ud, "Vector3( " + rtosfix(v.x) + ", " + rtosfix(v.y) + ", " + rtosfix(v.z) + " )");
 		} break;
+		case Variant::VECTOR3I: {
+
+			Vector3i v = p_variant;
+			p_store_string_func(p_store_string_ud, "Vector3i( " + itos(v.x) + ", " + itos(v.y) + ", " + itos(v.z) + " )");
+		} break;
 		case Variant::PLANE: {
 
 			Plane p = p_variant;

+ 1 - 1
modules/gdscript/gdscript_functions.cpp

@@ -365,7 +365,7 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
 					r_ret = ((Vector2)*p_args[0]).linear_interpolate((Vector2)*p_args[1], t);
 				} break;
 				case Variant::VECTOR3: {
-					r_ret = ((Vector3)*p_args[0]).linear_interpolate((Vector3)*p_args[1], t);
+					r_ret = (p_args[0]->operator Vector3()).linear_interpolate(p_args[1]->operator Vector3(), t);
 				} break;
 				case Variant::COLOR: {
 					r_ret = ((Color)*p_args[0]).linear_interpolate((Color)*p_args[1], t);

+ 3 - 0
modules/gdscript/gdscript_tokenizer.cpp

@@ -149,9 +149,12 @@ static const _bit _type_list[] = {
 	{ Variant::REAL, "float" },
 	{ Variant::STRING, "String" },
 	{ Variant::VECTOR2, "Vector2" },
+	{ Variant::VECTOR2I, "Vector2i" },
 	{ Variant::RECT2, "Rect2" },
+	{ Variant::RECT2I, "Rect2i" },
 	{ Variant::TRANSFORM2D, "Transform2D" },
 	{ Variant::VECTOR3, "Vector3" },
+	{ Variant::VECTOR3I, "Vector3i" },
 	{ Variant::AABB, "AABB" },
 	{ Variant::PLANE, "Plane" },
 	{ Variant::QUAT, "Quat" },