Преглед изворни кода

begin new serialization framework

also got rid of STL dependency on triangulator
Juan Linietsky пре 10 година
родитељ
комит
2185c018f6

+ 7 - 0
core/bind/core_bind.cpp

@@ -316,6 +316,11 @@ float _OS::get_time_scale() {
 	return OS::get_singleton()->get_time_scale();
 }
 
+bool _OS::is_ok_left_and_cancel_right() const {
+
+	return OS::get_singleton()->get_swap_ok_cancel();
+}
+
 /*
 enum Weekday {
 	DAY_SUNDAY,
@@ -699,6 +704,8 @@ void _OS::_bind_methods() {
 	ObjectTypeDB::bind_method(_MD("get_system_dir","dir"),&_OS::get_system_dir);
 	ObjectTypeDB::bind_method(_MD("get_unique_ID"),&_OS::get_unique_ID);
 
+	ObjectTypeDB::bind_method(_MD("is_ok_left_and_cancel_right"),&_OS::is_ok_left_and_cancel_right);
+
 	ObjectTypeDB::bind_method(_MD("get_frames_per_second"),&_OS::get_frames_per_second);
 
 	ObjectTypeDB::bind_method(_MD("print_all_textures_by_size"),&_OS::print_all_textures_by_size);

+ 2 - 0
core/bind/core_bind.h

@@ -220,6 +220,8 @@ public:
 	void set_time_scale(float p_scale);
 	float get_time_scale();
 
+	bool is_ok_left_and_cancel_right() const;
+
 	static _OS *get_singleton() { return singleton; }
 
 	_OS();

+ 166 - 159
core/math/triangulator.cpp

@@ -22,9 +22,9 @@
 #include <stdio.h>
 #include <string.h>
 #include <math.h>
-#include <algorithm>
+
 #include "triangulator.h"
-using namespace std;
+
 
 #define TRIANGULATOR_VERTEXTYPE_REGULAR 0
 #define TRIANGULATOR_VERTEXTYPE_START 1
@@ -163,9 +163,9 @@ int TriangulatorPartition::Intersects(Vector2 &p11, Vector2 &p12, Vector2 &p21,
 }
 
 //removes holes from inpolys by merging them with non-holes
-int TriangulatorPartition::RemoveHoles(list<TriangulatorPoly> *inpolys, list<TriangulatorPoly> *outpolys) {
-	list<TriangulatorPoly> polys;
-	list<TriangulatorPoly>::iterator holeiter,polyiter,iter,iter2;
+int TriangulatorPartition::RemoveHoles(List<TriangulatorPoly> *inpolys, List<TriangulatorPoly> *outpolys) {
+	List<TriangulatorPoly> polys;
+	List<TriangulatorPoly>::Element *holeiter,*polyiter,*iter,*iter2;
 	long i,i2,holepointindex,polypointindex;
 	Vector2 holepoint,polypoint,bestpolypoint;
 	Vector2 linep1,linep2;
@@ -177,15 +177,15 @@ int TriangulatorPartition::RemoveHoles(list<TriangulatorPoly> *inpolys, list<Tri
 
 	//check for trivial case (no holes)
 	hasholes = false;
-	for(iter = inpolys->begin(); iter!=inpolys->end(); iter++) {
-		if(iter->IsHole()) {
+	for(iter = inpolys->front(); iter; iter=iter->next()) {
+		if(iter->get().IsHole()) {
 			hasholes = true;
 			break;
 		}
 	}
 	if(!hasholes) {
-		for(iter = inpolys->begin(); iter!=inpolys->end(); iter++) {
-			outpolys->push_back(*iter);
+		for(iter = inpolys->front(); iter; iter=iter->next()) {
+			outpolys->push_back(iter->get());
 		}
 		return 1;
 	}
@@ -195,8 +195,8 @@ int TriangulatorPartition::RemoveHoles(list<TriangulatorPoly> *inpolys, list<Tri
 	while(1) {
 		//find the hole point with the largest x
 		hasholes = false;
-		for(iter = polys.begin(); iter!=polys.end(); iter++) {
-			if(!iter->IsHole()) continue;
+		for(iter = polys.front(); iter; iter=iter->next()) {
+			if(!iter->get().IsHole()) continue;
 
 			if(!hasholes) {
 				hasholes = true;
@@ -204,38 +204,38 @@ int TriangulatorPartition::RemoveHoles(list<TriangulatorPoly> *inpolys, list<Tri
 				holepointindex = 0;
 			}
 
-			for(i=0; i < iter->GetNumPoints(); i++) {
-				if(iter->GetPoint(i).x > holeiter->GetPoint(holepointindex).x) {
+			for(i=0; i < iter->get().GetNumPoints(); i++) {
+				if(iter->get().GetPoint(i).x > holeiter->get().GetPoint(holepointindex).x) {
 					holeiter = iter;
 					holepointindex = i;
 				}
 			}
 		}
 		if(!hasholes) break;
-		holepoint = holeiter->GetPoint(holepointindex);
+		holepoint = holeiter->get().GetPoint(holepointindex);
 
 		pointfound = false;
-		for(iter = polys.begin(); iter!=polys.end(); iter++) {
-			if(iter->IsHole()) continue;
-			for(i=0; i < iter->GetNumPoints(); i++) {
-				if(iter->GetPoint(i).x <= holepoint.x) continue;
-				if(!InCone(iter->GetPoint((i+iter->GetNumPoints()-1)%(iter->GetNumPoints())),
-					   iter->GetPoint(i),
-					   iter->GetPoint((i+1)%(iter->GetNumPoints())),
+		for(iter = polys.front(); iter; iter=iter->next()) {
+			if(iter->get().IsHole()) continue;
+			for(i=0; i < iter->get().GetNumPoints(); i++) {
+				if(iter->get().GetPoint(i).x <= holepoint.x) continue;
+				if(!InCone(iter->get().GetPoint((i+iter->get().GetNumPoints()-1)%(iter->get().GetNumPoints())),
+					   iter->get().GetPoint(i),
+					   iter->get().GetPoint((i+1)%(iter->get().GetNumPoints())),
 					   holepoint))
 					continue;
-				polypoint = iter->GetPoint(i);
+				polypoint = iter->get().GetPoint(i);
 				if(pointfound) {
 					v1 = Normalize(polypoint-holepoint);
 					v2 = Normalize(bestpolypoint-holepoint);
 					if(v2.x > v1.x) continue;
 				}
 				pointvisible = true;
-				for(iter2 = polys.begin(); iter2!=polys.end(); iter2++) {
-					if(iter2->IsHole()) continue;
-					for(i2=0; i2 < iter2->GetNumPoints(); i2++) {
-						linep1 = iter2->GetPoint(i2);
-						linep2 = iter2->GetPoint((i2+1)%(iter2->GetNumPoints()));
+				for(iter2 = polys.front(); iter2; iter2=iter2->next()) {
+					if(iter2->get().IsHole()) continue;
+					for(i2=0; i2 < iter2->get().GetNumPoints(); i2++) {
+						linep1 = iter2->get().GetPoint(i2);
+						linep2 = iter2->get().GetPoint((i2+1)%(iter2->get().GetNumPoints()));
 						if(Intersects(holepoint,polypoint,linep1,linep2)) {
 							pointvisible = false;
 							break;
@@ -254,18 +254,18 @@ int TriangulatorPartition::RemoveHoles(list<TriangulatorPoly> *inpolys, list<Tri
 
 		if(!pointfound) return 0;
 
-		newpoly.Init(holeiter->GetNumPoints() + polyiter->GetNumPoints() + 2);
+		newpoly.Init(holeiter->get().GetNumPoints() + polyiter->get().GetNumPoints() + 2);
 		i2 = 0;
 		for(i=0;i<=polypointindex;i++) {
-			newpoly[i2] = polyiter->GetPoint(i);
+			newpoly[i2] = polyiter->get().GetPoint(i);
 			i2++;
 		}
-		for(i=0;i<=holeiter->GetNumPoints();i++) {
-			newpoly[i2] = holeiter->GetPoint((i+holepointindex)%holeiter->GetNumPoints());
+		for(i=0;i<=holeiter->get().GetNumPoints();i++) {
+			newpoly[i2] = holeiter->get().GetPoint((i+holepointindex)%holeiter->get().GetNumPoints());
 			i2++;
 		}
-		for(i=polypointindex;i<polyiter->GetNumPoints();i++) {
-			newpoly[i2] = polyiter->GetPoint(i);
+		for(i=polypointindex;i<polyiter->get().GetNumPoints();i++) {
+			newpoly[i2] = polyiter->get().GetPoint(i);
 			i2++;
 		}
 
@@ -274,8 +274,8 @@ int TriangulatorPartition::RemoveHoles(list<TriangulatorPoly> *inpolys, list<Tri
 		polys.push_back(newpoly);
 	}
 
-	for(iter = polys.begin(); iter!=polys.end(); iter++) {
-		outpolys->push_back(*iter);
+	for(iter = polys.front(); iter; iter=iter->next()) {
+		outpolys->push_back(iter->get());
 	}
 
 	return 1;
@@ -366,7 +366,7 @@ void TriangulatorPartition::UpdateVertex(PartitionVertex *v, PartitionVertex *ve
 }
 
 //triangulation by ear removal
-int TriangulatorPartition::Triangulate_EC(TriangulatorPoly *poly, list<TriangulatorPoly> *triangles) {
+int TriangulatorPartition::Triangulate_EC(TriangulatorPoly *poly, List<TriangulatorPoly> *triangles) {
 	long numvertices;
 	PartitionVertex *vertices;
 	PartitionVertex *ear;
@@ -440,20 +440,20 @@ int TriangulatorPartition::Triangulate_EC(TriangulatorPoly *poly, list<Triangula
 	return 1;
 }
 
-int TriangulatorPartition::Triangulate_EC(list<TriangulatorPoly> *inpolys, list<TriangulatorPoly> *triangles) {
-	list<TriangulatorPoly> outpolys;
-	list<TriangulatorPoly>::iterator iter;
+int TriangulatorPartition::Triangulate_EC(List<TriangulatorPoly> *inpolys, List<TriangulatorPoly> *triangles) {
+	List<TriangulatorPoly> outpolys;
+	List<TriangulatorPoly>::Element*iter;
 
 	if(!RemoveHoles(inpolys,&outpolys)) return 0;
-	for(iter=outpolys.begin();iter!=outpolys.end();iter++) {
-		if(!Triangulate_EC(&(*iter),triangles)) return 0;
+	for(iter=outpolys.front();iter;iter=iter->next()) {
+		if(!Triangulate_EC(&(iter->get()),triangles)) return 0;
 	}
 	return 1;
 }
 
-int TriangulatorPartition::ConvexPartition_HM(TriangulatorPoly *poly, list<TriangulatorPoly> *parts) {
-	list<TriangulatorPoly> triangles;
-	list<TriangulatorPoly>::iterator iter1,iter2;
+int TriangulatorPartition::ConvexPartition_HM(TriangulatorPoly *poly, List<TriangulatorPoly> *parts) {
+	List<TriangulatorPoly> triangles;
+	List<TriangulatorPoly>::Element *iter1,*iter2;
 	TriangulatorPoly *poly1,*poly2;
 	TriangulatorPoly newpoly;
 	Vector2 d1,d2,p1,p2,p3;
@@ -480,17 +480,17 @@ int TriangulatorPartition::ConvexPartition_HM(TriangulatorPoly *poly, list<Trian
 
 	if(!Triangulate_EC(poly,&triangles)) return 0;
 
-	for(iter1 = triangles.begin(); iter1 != triangles.end(); iter1++) {
-		poly1 = &(*iter1);
+	for(iter1 = triangles.front(); iter1 ; iter1=iter1->next()) {
+		poly1 = &(iter1->get());
 		for(i11=0;i11<poly1->GetNumPoints();i11++) {
 			d1 = poly1->GetPoint(i11);
 			i12 = (i11+1)%(poly1->GetNumPoints());
 			d2 = poly1->GetPoint(i12);
 
 			isdiagonal = false;
-			for(iter2 = iter1; iter2 != triangles.end(); iter2++) {
+			for(iter2 = iter1; iter2 ; iter2=iter2->next()) {
 				if(iter1 == iter2) continue;
-				poly2 = &(*iter2);
+				poly2 = &(iter2->get());
 
 				for(i21=0;i21<poly2->GetNumPoints();i21++) {
 					if((d2.x != poly2->GetPoint(i21).x)||(d2.y != poly2->GetPoint(i21).y)) continue;
@@ -536,28 +536,28 @@ int TriangulatorPartition::ConvexPartition_HM(TriangulatorPoly *poly, list<Trian
 			}
 
 			triangles.erase(iter2);
-			*iter1 = newpoly;
-			poly1 = &(*iter1);
+			iter1->get() = newpoly;
+			poly1 = &(iter1->get());
 			i11 = -1;
 
 			continue;
 		}
 	}
 
-	for(iter1 = triangles.begin(); iter1 != triangles.end(); iter1++) {
-		parts->push_back(*iter1);
+	for(iter1 = triangles.front(); iter1 ; iter1=iter1->next()) {
+		parts->push_back(iter1->get());
 	}
 
 	return 1;
 }
 
-int TriangulatorPartition::ConvexPartition_HM(list<TriangulatorPoly> *inpolys, list<TriangulatorPoly> *parts) {
-	list<TriangulatorPoly> outpolys;
-	list<TriangulatorPoly>::iterator iter;
+int TriangulatorPartition::ConvexPartition_HM(List<TriangulatorPoly> *inpolys, List<TriangulatorPoly> *parts) {
+	List<TriangulatorPoly> outpolys;
+	List<TriangulatorPoly>::Element* iter;
 
 	if(!RemoveHoles(inpolys,&outpolys)) return 0;
-	for(iter=outpolys.begin();iter!=outpolys.end();iter++) {
-		if(!ConvexPartition_HM(&(*iter),parts)) return 0;
+	for(iter=outpolys.front();iter;iter=iter->next()) {
+		if(!ConvexPartition_HM(&(iter->get()),parts)) return 0;
 	}
 	return 1;
 }
@@ -565,14 +565,14 @@ int TriangulatorPartition::ConvexPartition_HM(list<TriangulatorPoly> *inpolys, l
 //minimum-weight polygon triangulation by dynamic programming
 //O(n^3) time complexity
 //O(n^2) space complexity
-int TriangulatorPartition::Triangulate_OPT(TriangulatorPoly *poly, list<TriangulatorPoly> *triangles) {
+int TriangulatorPartition::Triangulate_OPT(TriangulatorPoly *poly, List<TriangulatorPoly> *triangles) {
 	long i,j,k,gap,n;
 	DPState **dpstates;
 	Vector2 p1,p2,p3,p4;
 	long bestvertex;
 	real_t weight,minweight,d1,d2;
 	Diagonal diagonal,newdiagonal;
-	list<Diagonal> diagonals;
+	List<Diagonal> diagonals;
 	TriangulatorPoly triangle;
 	int ret = 1;
 
@@ -666,7 +666,7 @@ int TriangulatorPartition::Triangulate_OPT(TriangulatorPoly *poly, list<Triangul
 	newdiagonal.index2 = n-1;
 	diagonals.push_back(newdiagonal);
 	while(!diagonals.empty()) {
-		diagonal = *(diagonals.begin());
+		diagonal = (diagonals.front()->get());
 		diagonals.pop_front();
 		bestvertex = dpstates[diagonal.index2][diagonal.index1].bestvertex;
 		if(bestvertex == -1) {
@@ -697,7 +697,7 @@ int TriangulatorPartition::Triangulate_OPT(TriangulatorPoly *poly, list<Triangul
 
 void TriangulatorPartition::UpdateState(long a, long b, long w, long i, long j, DPState2 **dpstates) {
 	Diagonal newdiagonal;
-	list<Diagonal> *pairs;
+	List<Diagonal> *pairs;
 	long w2;
 
 	w2 = dpstates[a][b].weight;
@@ -712,15 +712,15 @@ void TriangulatorPartition::UpdateState(long a, long b, long w, long i, long j,
 		pairs->push_front(newdiagonal);
 		dpstates[a][b].weight = w;
 	} else {
-		if((!pairs->empty())&&(i <= pairs->begin()->index1)) return;
-		while((!pairs->empty())&&(pairs->begin()->index2 >= j)) pairs->pop_front();
+		if((!pairs->empty())&&(i <= pairs->front()->get().index1)) return;
+		while((!pairs->empty())&&(pairs->front()->get().index2 >= j)) pairs->pop_front();
 		pairs->push_front(newdiagonal);
 	}
 }
 
 void TriangulatorPartition::TypeA(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates) {
-	list<Diagonal> *pairs;
-	list<Diagonal>::iterator iter,lastiter;
+	List<Diagonal> *pairs;
+	List<Diagonal>::Element *iter,*lastiter;
 	long top;
 	long w;
 
@@ -733,25 +733,29 @@ void TriangulatorPartition::TypeA(long i, long j, long k, PartitionVertex *verti
 	}
 	if(j-i > 1) {
 		pairs = &(dpstates[i][j].pairs);
-		iter = pairs->end();
-		lastiter = pairs->end();
-		while(iter!=pairs->begin()) {
-			iter--;
-			if(!IsReflex(vertices[iter->index2].p,vertices[j].p,vertices[k].p)) lastiter = iter;
+		iter = NULL;
+		lastiter = NULL;
+		while(iter!=pairs->front()) {
+			if (!iter)
+				iter=pairs->back();
+			else
+				iter=iter->prev();
+
+			if(!IsReflex(vertices[iter->get().index2].p,vertices[j].p,vertices[k].p)) lastiter = iter;
 			else break;
 		}
-		if(lastiter == pairs->end()) w++;
+		if(lastiter == NULL) w++;
 		else {
-			if(IsReflex(vertices[k].p,vertices[i].p,vertices[lastiter->index1].p)) w++;
-			else top = lastiter->index1;
+			if(IsReflex(vertices[k].p,vertices[i].p,vertices[lastiter->get().index1].p)) w++;
+			else top = lastiter->get().index1;
 		}
 	}
 	UpdateState(i,k,w,top,j,dpstates);
 }
 
 void TriangulatorPartition::TypeB(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates) {
-	list<Diagonal> *pairs;
-	list<Diagonal>::iterator iter,lastiter;
+	List<Diagonal> *pairs;
+	List<Diagonal>::Element* iter,*lastiter;
 	long top;
 	long w;
 
@@ -766,36 +770,36 @@ void TriangulatorPartition::TypeB(long i, long j, long k, PartitionVertex *verti
 	if (k-j > 1) {
 		pairs = &(dpstates[j][k].pairs);
 
-		iter = pairs->begin();
-		if((!pairs->empty())&&(!IsReflex(vertices[i].p,vertices[j].p,vertices[iter->index1].p))) {
+		iter = pairs->front();
+		if((!pairs->empty())&&(!IsReflex(vertices[i].p,vertices[j].p,vertices[iter->get().index1].p))) {
 			lastiter = iter;
-			while(iter!=pairs->end()) {
-				if(!IsReflex(vertices[i].p,vertices[j].p,vertices[iter->index1].p)) {
+			while(iter!=NULL) {
+				if(!IsReflex(vertices[i].p,vertices[j].p,vertices[iter->get().index1].p)) {
 					lastiter = iter;
-					iter++;
+					iter=iter->next();
 				}
 				else break;
 			}
-			if(IsReflex(vertices[lastiter->index2].p,vertices[k].p,vertices[i].p)) w++;
-			else top = lastiter->index2;
+			if(IsReflex(vertices[lastiter->get().index2].p,vertices[k].p,vertices[i].p)) w++;
+			else top = lastiter->get().index2;
 		} else w++;
 	}
 	UpdateState(i,k,w,j,top,dpstates);
 }
 
-int TriangulatorPartition::ConvexPartition_OPT(TriangulatorPoly *poly, list<TriangulatorPoly> *parts) {
+int TriangulatorPartition::ConvexPartition_OPT(TriangulatorPoly *poly, List<TriangulatorPoly> *parts) {
 	Vector2 p1,p2,p3,p4;
 	PartitionVertex *vertices;
 	DPState2 **dpstates;
 	long i,j,k,n,gap;
-	list<Diagonal> diagonals,diagonals2;
+	List<Diagonal> diagonals,diagonals2;
 	Diagonal diagonal,newdiagonal;
-	list<Diagonal> *pairs,*pairs2;
-	list<Diagonal>::iterator iter,iter2;
+	List<Diagonal> *pairs,*pairs2;
+	List<Diagonal>::Element* iter,*iter2;
 	int ret;
 	TriangulatorPoly newpoly;
-	list<long> indices;
-	list<long>::iterator iiter;
+	List<long> indices;
+	List<long>::Element* iiter;
 	bool ijreal,jkreal;
 
 	n = poly->GetNumPoints();
@@ -903,7 +907,7 @@ int TriangulatorPartition::ConvexPartition_OPT(TriangulatorPoly *poly, list<Tria
 	newdiagonal.index2 = n-1;
 	diagonals.push_front(newdiagonal);
 	while(!diagonals.empty()) {
-		diagonal = *(diagonals.begin());
+		diagonal = (diagonals.front()->get());
 		diagonals.pop_front();
 		if((diagonal.index2 - diagonal.index1) <=1) continue;
 		pairs = &(dpstates[diagonal.index1][diagonal.index2].pairs);
@@ -912,23 +916,23 @@ int TriangulatorPartition::ConvexPartition_OPT(TriangulatorPoly *poly, list<Tria
 			break;
 		}
 		if(!vertices[diagonal.index1].isConvex) {
-			iter = pairs->end();
-			iter--;
-			j = iter->index2;
+			iter = pairs->back();
+
+			j = iter->get().index2;
 			newdiagonal.index1 = j;
 			newdiagonal.index2 = diagonal.index2;
 			diagonals.push_front(newdiagonal);
 			if((j - diagonal.index1)>1) {
-				if(iter->index1 != iter->index2) {
+				if(iter->get().index1 != iter->get().index2) {
 					pairs2 = &(dpstates[diagonal.index1][j].pairs);
 					while(1) {
 						if(pairs2->empty()) {
 							ret = 0;
 							break;
 						}
-						iter2 = pairs2->end();
-						iter2--;
-						if(iter->index1 != iter2->index1) pairs2->pop_back();
+						iter2 = pairs2->back();
+
+						if(iter->get().index1 != iter2->get().index1) pairs2->pop_back();
 						else break;
 					}
 					if(ret == 0) break;
@@ -938,21 +942,21 @@ int TriangulatorPartition::ConvexPartition_OPT(TriangulatorPoly *poly, list<Tria
 				diagonals.push_front(newdiagonal);
 			}
 		} else {
-			iter = pairs->begin();
-			j = iter->index1;
+			iter = pairs->front();
+			j = iter->get().index1;
 			newdiagonal.index1 = diagonal.index1;
 			newdiagonal.index2 = j;
 			diagonals.push_front(newdiagonal);
 			if((diagonal.index2 - j) > 1) {
-				if(iter->index1 != iter->index2) {
+				if(iter->get().index1 != iter->get().index2) {
 					pairs2 = &(dpstates[j][diagonal.index2].pairs);
 					while(1) {
 						if(pairs2->empty()) {
 							ret = 0;
 							break;
 						}
-						iter2 = pairs2->begin();
-						if(iter->index2 != iter2->index2) pairs2->pop_front();
+						iter2 = pairs2->front();
+						if(iter->get().index2 != iter2->get().index2) pairs2->pop_front();
 						else break;
 					}
 					if(ret == 0) break;
@@ -978,7 +982,7 @@ int TriangulatorPartition::ConvexPartition_OPT(TriangulatorPoly *poly, list<Tria
 	newdiagonal.index2 = n-1;
 	diagonals.push_front(newdiagonal);
 	while(!diagonals.empty()) {
-		diagonal = *(diagonals.begin());
+		diagonal = (diagonals.front())->get();
 		diagonals.pop_front();
 		if((diagonal.index2 - diagonal.index1) <= 1) continue;
 
@@ -989,21 +993,20 @@ int TriangulatorPartition::ConvexPartition_OPT(TriangulatorPoly *poly, list<Tria
 		diagonals2.push_front(diagonal);
 
 		while(!diagonals2.empty()) {
-			diagonal = *(diagonals2.begin());
+			diagonal = (diagonals2.front()->get());
 			diagonals2.pop_front();
 			if((diagonal.index2 - diagonal.index1) <= 1) continue;
 			ijreal = true;
 			jkreal = true;
 			pairs = &(dpstates[diagonal.index1][diagonal.index2].pairs);
 			if(!vertices[diagonal.index1].isConvex) {
-				iter = pairs->end();
-				iter--;
-				j = iter->index2;
-				if(iter->index1 != iter->index2) ijreal = false;
+				iter = pairs->back();
+				j = iter->get().index2;
+				if(iter->get().index1 != iter->get().index2) ijreal = false;
 			} else {
-				iter = pairs->begin();
-				j = iter->index1;
-				if(iter->index1 != iter->index2) jkreal = false;
+				iter = pairs->front();
+				j = iter->get().index1;
+				if(iter->get().index1 != iter->get().index2) jkreal = false;
 			}
 
 			newdiagonal.index1 = diagonal.index1;
@@ -1028,8 +1031,8 @@ int TriangulatorPartition::ConvexPartition_OPT(TriangulatorPoly *poly, list<Tria
 		indices.sort();
 		newpoly.Init((long)indices.size());
 		k=0;
-		for(iiter = indices.begin();iiter!=indices.end();iiter++) {
-			newpoly[k] = vertices[*iiter].p;
+		for(iiter = indices.front();iiter;iiter=iiter->next()) {
+			newpoly[k] = vertices[iiter->get()].p;
 			k++;
 		}
 		parts->push_back(newpoly);
@@ -1049,8 +1052,8 @@ int TriangulatorPartition::ConvexPartition_OPT(TriangulatorPoly *poly, list<Tria
 //the algorithm used here is outlined in the book
 //"Computational Geometry: Algorithms and Applications"
 //by Mark de Berg, Otfried Cheong, Marc van Kreveld and Mark Overmars
-int TriangulatorPartition::MonotonePartition(list<TriangulatorPoly> *inpolys, list<TriangulatorPoly> *monotonePolys) {
-	list<TriangulatorPoly>::iterator iter;
+int TriangulatorPartition::MonotonePartition(List<TriangulatorPoly> *inpolys, List<TriangulatorPoly> *monotonePolys) {
+	List<TriangulatorPoly>::Element *iter;
 	MonotoneVertex *vertices;
 	long i,numvertices,vindex,vindex2,newnumvertices,maxnumvertices;
 	long polystartindex, polyendindex;
@@ -1060,8 +1063,8 @@ int TriangulatorPartition::MonotonePartition(list<TriangulatorPoly> *inpolys, li
 	bool error = false;
 
 	numvertices = 0;
-	for(iter = inpolys->begin(); iter != inpolys->end(); iter++) {
-		numvertices += iter->GetNumPoints();
+	for(iter = inpolys->front(); iter ; iter=iter->next()) {
+		numvertices += iter->get().GetNumPoints();
 	}
 
 	maxnumvertices = numvertices*3;
@@ -1069,8 +1072,8 @@ int TriangulatorPartition::MonotonePartition(list<TriangulatorPoly> *inpolys, li
 	newnumvertices = numvertices;
 
 	polystartindex = 0;
-	for(iter = inpolys->begin(); iter != inpolys->end(); iter++) {
-		poly = &(*iter);
+	for(iter = inpolys->front(); iter ; iter=iter->next()) {
+		poly = &(iter->get());
 		polyendindex = polystartindex + poly->GetNumPoints()-1;
 		for(i=0;i<poly->GetNumPoints();i++) {
 			vertices[i+polystartindex].p = poly->GetPoint(i);
@@ -1085,7 +1088,9 @@ int TriangulatorPartition::MonotonePartition(list<TriangulatorPoly> *inpolys, li
 	//construct the priority queue
 	long *priority = new long [numvertices];
 	for(i=0;i<numvertices;i++) priority[i] = i;
-	std::sort(priority,&(priority[numvertices]),VertexSorter(vertices));
+	SortArray<long,VertexSorter> sorter;
+	sorter.compare.vertices=vertices;
+	sorter.sort(priority,numvertices);
 
 	//determine vertex types
 	char *vertextypes = new char[maxnumvertices];
@@ -1118,13 +1123,13 @@ int TriangulatorPartition::MonotonePartition(list<TriangulatorPoly> *inpolys, li
 	//binary search tree that holds edges intersecting the scanline
 	//note that while set doesn't actually have to be implemented as a tree
 	//complexity requirements for operations are the same as for the balanced binary search tree
-	set<ScanLineEdge> edgeTree;
+	Set<ScanLineEdge> edgeTree;
 	//store iterators to the edge tree elements
 	//this makes deleting existing edges much faster
-	set<ScanLineEdge>::iterator *edgeTreeIterators,edgeIter;
-	edgeTreeIterators = new set<ScanLineEdge>::iterator[maxnumvertices];
-	pair<set<ScanLineEdge>::iterator,bool> edgeTreeRet;
-	for(i = 0; i<numvertices; i++) edgeTreeIterators[i] = edgeTree.end();
+	Set<ScanLineEdge>::Element **edgeTreeIterators,*edgeIter;
+	edgeTreeIterators = new Set<ScanLineEdge>::Element*[maxnumvertices];
+//	Pair<Set<ScanLineEdge>::Element*,bool> edgeTreeRet;
+	for(i = 0; i<numvertices; i++) edgeTreeIterators[i] = NULL;
 
 	//for each vertex
 	for(i=0;i<numvertices;i++) {
@@ -1141,8 +1146,7 @@ int TriangulatorPartition::MonotonePartition(list<TriangulatorPoly> *inpolys, li
 				newedge.p1 = v->p;
 				newedge.p2 = vertices[v->next].p;
 				newedge.index = vindex;
-				edgeTreeRet = edgeTree.insert(newedge);
-				edgeTreeIterators[vindex] = edgeTreeRet.first;
+				edgeTreeIterators[vindex] = edgeTree.insert(newedge);
 				helpers[vindex] = vindex;
 				break;
 
@@ -1162,24 +1166,24 @@ int TriangulatorPartition::MonotonePartition(list<TriangulatorPoly> *inpolys, li
 				newedge.p1 = v->p;
 				newedge.p2 = v->p;
 				edgeIter = edgeTree.lower_bound(newedge);
-				if(edgeIter == edgeTree.begin()) {
+				if(edgeIter == edgeTree.front()) {
 					error = true;
 					break;
 				}
-				edgeIter--;
+				edgeIter=edgeIter->prev();
 				//Insert the diagonal connecting vi to helper(ej) in D.
-				AddDiagonal(vertices,&newnumvertices,vindex,helpers[edgeIter->index],
+				AddDiagonal(vertices,&newnumvertices,vindex,helpers[edgeIter->get().index],
 						vertextypes, edgeTreeIterators, &edgeTree, helpers);
 				vindex2 = newnumvertices-2;
 				v2 = &(vertices[vindex2]);
 				//helper(e j)�vi
-				helpers[edgeIter->index] = vindex;
+				helpers[edgeIter->get().index] = vindex;
 				//Insert ei in T and set helper(ei) to vi.
 				newedge.p1 = v2->p;
 				newedge.p2 = vertices[v2->next].p;
 				newedge.index = vindex2;
-				edgeTreeRet = edgeTree.insert(newedge);
-				edgeTreeIterators[vindex2] = edgeTreeRet.first;
+
+				edgeTreeIterators[vindex2] = edgeTree.insert(newedge);
 				helpers[vindex2] = vindex2;
 				break;
 
@@ -1198,19 +1202,19 @@ int TriangulatorPartition::MonotonePartition(list<TriangulatorPoly> *inpolys, li
 				newedge.p1 = v->p;
 				newedge.p2 = v->p;
 				edgeIter = edgeTree.lower_bound(newedge);
-				if(edgeIter == edgeTree.begin()) {
+				if(edgeIter == edgeTree.front()) {
 					error = true;
 					break;
 				}
-				edgeIter--;
+				edgeIter=edgeIter->prev();
 				//if helper(ej) is a merge vertex
-				if(vertextypes[helpers[edgeIter->index]]==TRIANGULATOR_VERTEXTYPE_MERGE) {
+				if(vertextypes[helpers[edgeIter->get().index]]==TRIANGULATOR_VERTEXTYPE_MERGE) {
 					//Insert the diagonal connecting vi to helper(e j) in D.
-					AddDiagonal(vertices,&newnumvertices,vindex2,helpers[edgeIter->index],
+					AddDiagonal(vertices,&newnumvertices,vindex2,helpers[edgeIter->get().index],
 							vertextypes, edgeTreeIterators, &edgeTree, helpers);
 				}
 				//helper(e j)�vi
-				helpers[edgeIter->index] = vindex2;
+				helpers[edgeIter->get().index] = vindex2;
 				break;
 
 			case TRIANGULATOR_VERTEXTYPE_REGULAR:
@@ -1230,27 +1234,26 @@ int TriangulatorPartition::MonotonePartition(list<TriangulatorPoly> *inpolys, li
 					newedge.p1 = v2->p;
 					newedge.p2 = vertices[v2->next].p;
 					newedge.index = vindex2;
-					edgeTreeRet = edgeTree.insert(newedge);
-					edgeTreeIterators[vindex2] = edgeTreeRet.first;
+					edgeTreeIterators[vindex2] = edgeTree.insert(newedge);
 					helpers[vindex2] = vindex;
 				} else {
 					//Search in T to find the edge ej directly left of vi.
 					newedge.p1 = v->p;
 					newedge.p2 = v->p;
 					edgeIter = edgeTree.lower_bound(newedge);
-					if(edgeIter == edgeTree.begin()) {
+					if(edgeIter == edgeTree.front()) {
 						error = true;
 						break;
 					}
-					edgeIter--;
+					edgeIter=edgeIter->prev();
 					//if helper(ej) is a merge vertex
-					if(vertextypes[helpers[edgeIter->index]]==TRIANGULATOR_VERTEXTYPE_MERGE) {
+					if(vertextypes[helpers[edgeIter->get().index]]==TRIANGULATOR_VERTEXTYPE_MERGE) {
 						//Insert the diagonal connecting vi to helper(e j) in D.
-						AddDiagonal(vertices,&newnumvertices,vindex,helpers[edgeIter->index],
+						AddDiagonal(vertices,&newnumvertices,vindex,helpers[edgeIter->get().index],
 								vertextypes, edgeTreeIterators, &edgeTree, helpers);
 					}
 					//helper(e j)�vi
-					helpers[edgeIter->index] = vindex;
+					helpers[edgeIter->get().index] = vindex;
 				}
 				break;
 		}
@@ -1308,8 +1311,8 @@ int TriangulatorPartition::MonotonePartition(list<TriangulatorPoly> *inpolys, li
 
 //adds a diagonal to the doubly-connected list of vertices
 void TriangulatorPartition::AddDiagonal(MonotoneVertex *vertices, long *numvertices, long index1, long index2,
-					char *vertextypes, set<ScanLineEdge>::iterator *edgeTreeIterators,
-					set<ScanLineEdge> *edgeTree, long *helpers)
+					char *vertextypes, Set<ScanLineEdge>::Element **edgeTreeIterators,
+					Set<ScanLineEdge> *edgeTree, long *helpers)
 {
 	long newindex1,newindex2;
 
@@ -1337,13 +1340,13 @@ void TriangulatorPartition::AddDiagonal(MonotoneVertex *vertices, long *numverti
 	vertextypes[newindex1] = vertextypes[index1];
 	edgeTreeIterators[newindex1] = edgeTreeIterators[index1];
 	helpers[newindex1] = helpers[index1];
-	if(edgeTreeIterators[newindex1] != edgeTree->end())
-		edgeTreeIterators[newindex1]->index = newindex1;
+	if(edgeTreeIterators[newindex1] != NULL)
+		edgeTreeIterators[newindex1]->get().index = newindex1;
 	vertextypes[newindex2] = vertextypes[index2];
 	edgeTreeIterators[newindex2] = edgeTreeIterators[index2];
 	helpers[newindex2] = helpers[index2];
-	if(edgeTreeIterators[newindex2] != edgeTree->end())
-		edgeTreeIterators[newindex2]->index = newindex2;
+	if(edgeTreeIterators[newindex2] != NULL)
+		edgeTreeIterators[newindex2]->get().index = newindex2;
 }
 
 bool TriangulatorPartition::Below(Vector2 &p1, Vector2 &p2) {
@@ -1354,8 +1357,12 @@ bool TriangulatorPartition::Below(Vector2 &p1, Vector2 &p2) {
 	return false;
 }
 
+
+
+
+
 //sorts in the falling order of y values, if y is equal, x is used instead
-bool TriangulatorPartition::VertexSorter::operator() (long index1, long index2) {
+bool TriangulatorPartition::VertexSorter::operator() (long index1, long index2) const {
 	if(vertices[index1].p.y > vertices[index2].p.y) return true;
 	else if(vertices[index1].p.y == vertices[index2].p.y) {
 		if(vertices[index1].p.x > vertices[index2].p.x) return true;
@@ -1392,7 +1399,7 @@ bool TriangulatorPartition::ScanLineEdge::operator < (const ScanLineEdge & other
 
 //triangulates monotone polygon
 //O(n) time, O(n) space complexity
-int TriangulatorPartition::TriangulateMonotone(TriangulatorPoly *inPoly, list<TriangulatorPoly> *triangles) {
+int TriangulatorPartition::TriangulateMonotone(TriangulatorPoly *inPoly, List<TriangulatorPoly> *triangles) {
 	long i,i2,j,topindex,bottomindex,leftindex,rightindex,vindex;
 	Vector2 *points;
 	long numpoints;
@@ -1524,19 +1531,19 @@ int TriangulatorPartition::TriangulateMonotone(TriangulatorPoly *inPoly, list<Tr
 	return 1;
 }
 
-int TriangulatorPartition::Triangulate_MONO(list<TriangulatorPoly> *inpolys, list<TriangulatorPoly> *triangles) {
-	list<TriangulatorPoly> monotone;
-	list<TriangulatorPoly>::iterator iter;
+int TriangulatorPartition::Triangulate_MONO(List<TriangulatorPoly> *inpolys, List<TriangulatorPoly> *triangles) {
+	List<TriangulatorPoly> monotone;
+	List<TriangulatorPoly>::Element* iter;
 
 	if(!MonotonePartition(inpolys,&monotone)) return 0;
-	for(iter = monotone.begin(); iter!=monotone.end();iter++) {
-		if(!TriangulateMonotone(&(*iter),triangles)) return 0;
+	for(iter = monotone.front(); iter;iter=iter->next()) {
+		if(!TriangulateMonotone(&(iter->get()),triangles)) return 0;
 	}
 	return 1;
 }
 
-int TriangulatorPartition::Triangulate_MONO(TriangulatorPoly *poly, list<TriangulatorPoly> *triangles) {
-	list<TriangulatorPoly> polys;
+int TriangulatorPartition::Triangulate_MONO(TriangulatorPoly *poly, List<TriangulatorPoly> *triangles) {
+	List<TriangulatorPoly> polys;
 	polys.push_back(*poly);
 
 	return Triangulate_MONO(&polys, triangles);

+ 19 - 22
core/math/triangulator.h

@@ -22,9 +22,8 @@
 #define TRIANGULATOR_H
 
 #include "math_2d.h"
-#include <list>
-#include <set>
-
+#include "list.h"
+#include "set.h"
 //2D point structure
 
 
@@ -119,11 +118,9 @@ protected:
 		long next;
 	};
 
-	class VertexSorter{
-		MonotoneVertex *vertices;
-	public:
-		VertexSorter(MonotoneVertex *v) : vertices(v) {}
-		bool operator() (long index1, long index2);
+	struct VertexSorter{
+		mutable MonotoneVertex *vertices;
+		bool operator() (long index1, long index2) const;
 	};
 
 	struct Diagonal {
@@ -142,7 +139,7 @@ protected:
 	struct DPState2 {
 		bool visible;
 		long weight;
-		std::list<Diagonal> pairs;
+		List<Diagonal> pairs;
 	};
 
 	//edge that intersects the scanline
@@ -182,11 +179,11 @@ protected:
 	//helper functions for MonotonePartition
 	bool Below(Vector2 &p1, Vector2 &p2);
 	void AddDiagonal(MonotoneVertex *vertices, long *numvertices, long index1, long index2,
-			 char *vertextypes, std::set<ScanLineEdge>::iterator *edgeTreeIterators,
-			 std::set<ScanLineEdge> *edgeTree, long *helpers);
+			 char *vertextypes, Set<ScanLineEdge>::Element **edgeTreeIterators,
+			 Set<ScanLineEdge> *edgeTree, long *helpers);
 
 	//triangulates a monotone polygon, used in Triangulate_MONO
-	int TriangulateMonotone(TriangulatorPoly *inPoly, std::list<TriangulatorPoly> *triangles);
+	int TriangulateMonotone(TriangulatorPoly *inPoly, List<TriangulatorPoly> *triangles);
 
 public:
 
@@ -200,7 +197,7 @@ public:
 	//             vertices of all hole polys have to be in clockwise order
 	//   outpolys : a list of polygons without holes
 	//returns 1 on success, 0 on failure
-	int RemoveHoles(std::list<TriangulatorPoly> *inpolys, std::list<TriangulatorPoly> *outpolys);
+	int RemoveHoles(List<TriangulatorPoly> *inpolys, List<TriangulatorPoly> *outpolys);
 
 	//triangulates a polygon by ear clipping
 	//time complexity O(n^2), n is the number of vertices
@@ -210,7 +207,7 @@ public:
 	//          vertices have to be in counter-clockwise order
 	//   triangles : a list of triangles (result)
 	//returns 1 on success, 0 on failure
-	int Triangulate_EC(TriangulatorPoly *poly, std::list<TriangulatorPoly> *triangles);
+	int Triangulate_EC(TriangulatorPoly *poly, List<TriangulatorPoly> *triangles);
 
 	//triangulates a list of polygons that may contain holes by ear clipping algorithm
 	//first calls RemoveHoles to get rid of the holes, and then Triangulate_EC for each resulting polygon
@@ -222,7 +219,7 @@ public:
 	//             vertices of all hole polys have to be in clockwise order
 	//   triangles : a list of triangles (result)
 	//returns 1 on success, 0 on failure
-	int Triangulate_EC(std::list<TriangulatorPoly> *inpolys, std::list<TriangulatorPoly> *triangles);
+	int Triangulate_EC(List<TriangulatorPoly> *inpolys, List<TriangulatorPoly> *triangles);
 
 	//creates an optimal polygon triangulation in terms of minimal edge length
 	//time complexity: O(n^3), n is the number of vertices
@@ -232,7 +229,7 @@ public:
 	//          vertices have to be in counter-clockwise order
 	//   triangles : a list of triangles (result)
 	//returns 1 on success, 0 on failure
-	int Triangulate_OPT(TriangulatorPoly *poly, std::list<TriangulatorPoly> *triangles);
+	int Triangulate_OPT(TriangulatorPoly *poly, List<TriangulatorPoly> *triangles);
 
 	//triangulates a polygons by firstly partitioning it into monotone polygons
 	//time complexity: O(n*log(n)), n is the number of vertices
@@ -242,7 +239,7 @@ public:
 	//          vertices have to be in counter-clockwise order
 	//   triangles : a list of triangles (result)
 	//returns 1 on success, 0 on failure
-	int Triangulate_MONO(TriangulatorPoly *poly, std::list<TriangulatorPoly> *triangles);
+	int Triangulate_MONO(TriangulatorPoly *poly, List<TriangulatorPoly> *triangles);
 
 	//triangulates a list of polygons by firstly partitioning them into monotone polygons
 	//time complexity: O(n*log(n)), n is the number of vertices
@@ -253,7 +250,7 @@ public:
 	//             vertices of all hole polys have to be in clockwise order
 	//   triangles : a list of triangles (result)
 	//returns 1 on success, 0 on failure
-	int Triangulate_MONO(std::list<TriangulatorPoly> *inpolys, std::list<TriangulatorPoly> *triangles);
+	int Triangulate_MONO(List<TriangulatorPoly> *inpolys, List<TriangulatorPoly> *triangles);
 
 	//creates a monotone partition of a list of polygons that can contain holes
 	//time complexity: O(n*log(n)), n is the number of vertices
@@ -264,7 +261,7 @@ public:
 	//             vertices of all hole polys have to be in clockwise order
 	//   monotonePolys : a list of monotone polygons (result)
 	//returns 1 on success, 0 on failure
-	int MonotonePartition(std::list<TriangulatorPoly> *inpolys, std::list<TriangulatorPoly> *monotonePolys);
+	int MonotonePartition(List<TriangulatorPoly> *inpolys, List<TriangulatorPoly> *monotonePolys);
 
 	//partitions a polygon into convex polygons by using Hertel-Mehlhorn algorithm
 	//the algorithm gives at most four times the number of parts as the optimal algorithm
@@ -277,7 +274,7 @@ public:
 	//          vertices have to be in counter-clockwise order
 	//   parts : resulting list of convex polygons
 	//returns 1 on success, 0 on failure
-	int ConvexPartition_HM(TriangulatorPoly *poly, std::list<TriangulatorPoly> *parts);
+	int ConvexPartition_HM(TriangulatorPoly *poly, List<TriangulatorPoly> *parts);
 
 	//partitions a list of polygons into convex parts by using Hertel-Mehlhorn algorithm
 	//the algorithm gives at most four times the number of parts as the optimal algorithm
@@ -291,7 +288,7 @@ public:
 	//             vertices of all hole polys have to be in clockwise order
 	//   parts : resulting list of convex polygons
 	//returns 1 on success, 0 on failure
-	int ConvexPartition_HM(std::list<TriangulatorPoly> *inpolys, std::list<TriangulatorPoly> *parts);
+	int ConvexPartition_HM(List<TriangulatorPoly> *inpolys, List<TriangulatorPoly> *parts);
 
 	//optimal convex partitioning (in terms of number of resulting convex polygons)
 	//using the Keil-Snoeyink algorithm
@@ -302,7 +299,7 @@ public:
 	//          vertices have to be in counter-clockwise order
 	//   parts : resulting list of convex polygons
 	//returns 1 on success, 0 on failure
-	int ConvexPartition_OPT(TriangulatorPoly *poly, std::list<TriangulatorPoly> *parts);
+	int ConvexPartition_OPT(TriangulatorPoly *poly, List<TriangulatorPoly> *parts);
 };
 
 

+ 37 - 0
core/set.h

@@ -249,6 +249,37 @@ private:
 		return (node!=_data._nil)?node:NULL;
 	}
 
+	Element *_lower_bound(const T& p_value) const {
+
+		Element *node = _data._root->left;
+		Element *prev = NULL;
+		C less;
+
+		while(node!=_data._nil) {
+			prev=node;
+
+			if (less(p_value,node->value))
+				node=node->left;
+			else if (less(node->value,p_value))
+				node=node->right;
+			else
+				break; // found
+		}
+
+		if (node==_data._nil) {
+			if (prev==NULL)
+				return NULL;
+			if (less(prev->value,p_value)) {
+
+				prev=prev->_next;
+			}
+
+			return prev;
+
+		} else
+			return node;
+	}
+
 
 	Element *_insert(const T& p_value, bool& r_exists) {
 		
@@ -582,6 +613,12 @@ public:
 		
 		return e;
 	}
+
+	Element *lower_bound(const T& p_value) const {
+
+		return _lower_bound(p_value);
+	}
+
 	
 	inline int size() const { return _data.size_cache; }
 	int calculate_depth() const {

+ 26 - 17
core/variant.cpp

@@ -2631,8 +2631,13 @@ Variant Variant::call(const StringName& p_method,VARIANT_ARG_DECLARE) {
 	return ret;
 }
 
+void Variant::construct_from_string(const String& p_string,Variant& r_value,ObjectConstruct p_obj_construct,void *p_construct_ud) {
+
+	r_value=Variant();
+}
 
-String Variant::get_construct_string() const {
+
+String Variant::get_construct_string(ObjectDeConstruct p_obj_deconstruct,void *p_deconstruct_ud) const {
 
 	switch( type ) {
 
@@ -2640,7 +2645,7 @@ String Variant::get_construct_string() const {
 		case BOOL: return _data._bool ? "true" : "false";
 		case INT: return String::num(_data._int);
 		case REAL: return String::num(_data._real);
-		case STRING: return "\""+*reinterpret_cast<const String*>(_data._mem)+"\"";
+		case STRING: return "\""+reinterpret_cast<const String*>(_data._mem)->c_escape()+"\"";
 		case VECTOR2: return "Vector2("+operator Vector2()+")";
 		case RECT2: return "Rect2("+operator Rect2()+")";
 		case MATRIX32: return "Matrix32("+operator Matrix32()+")";
@@ -2651,7 +2656,7 @@ String Variant::get_construct_string() const {
 		case QUAT: return "Quat("+operator Quat()+")";
 		case MATRIX3: return "Matrix3("+operator Matrix3()+")";
 		case TRANSFORM: return "Transform("+operator Transform()+")";
-		case NODE_PATH: return "@\""+operator NodePath()+"\"";
+		case NODE_PATH: return "@\""+String(operator NodePath()).c_escape()+"\"";
 		case INPUT_EVENT: return "InputEvent()";
 		case COLOR: return "Color("+String::num( operator Color().r)+","+String::num( operator Color().g)+","+String::num( operator Color().b)+","+String::num( operator Color().a)+")" ;
 		case DICTIONARY: {
@@ -2667,8 +2672,8 @@ String Variant::get_construct_string() const {
 			for(List<Variant>::Element *E=keys.front();E;E=E->next()) {
 
 				_VariantStrPair sp;
-				sp.key=E->get().get_construct_string();
-				sp.value=d[E->get()].get_construct_string();
+				sp.key=E->get().get_construct_string(p_obj_deconstruct,p_deconstruct_ud);
+				sp.value=d[E->get()].get_construct_string(p_obj_deconstruct,p_deconstruct_ud);
 				pairs.push_back(sp);
 			}
 
@@ -2686,50 +2691,50 @@ String Variant::get_construct_string() const {
 		case VECTOR3_ARRAY: {
 
 			DVector<Vector3> vec = operator DVector<Vector3>();
-			String str="[";
+			String str="Vector3Array([";
 			for(int i=0;i<vec.size();i++) {
 
 				if (i>0)
 					str+=", ";
 				str+=Variant( vec[i] ).get_construct_string();
 			}
-			return str+"]";
+			return str+"])";
 		} break;
 		case STRING_ARRAY: {
 
 			DVector<String> vec = operator DVector<String>();
-			String str="[";
+			String str="StringArray([";
 			for(int i=0;i<vec.size();i++) {
 
 				if (i>0)
 					str+=", ";
 				str=str+=Variant( vec[i] ).get_construct_string();
 			}
-			return str+"]";
+			return str+"])";
 		} break;
 		case INT_ARRAY: {
 
 			DVector<int> vec = operator DVector<int>();
-			String str="[";
+			String str="IntArray([";
 			for(int i=0;i<vec.size();i++) {
 
 				if (i>0)
 					str+=", ";
 				str=str+itos(vec[i]);
 			}
-			return str+"]";
+			return str+"])";
 		} break;
 		case REAL_ARRAY: {
 
 			DVector<real_t> vec = operator DVector<real_t>();
-			String str="[";
+			String str="FloatArray([";
 			for(int i=0;i<vec.size();i++) {
 
 				if (i>0)
 					str+=", ";
 				str=str+rtos(vec[i]);
 			}
-			return str+"]";
+			return str+"])";
 		} break;
 		case ARRAY: {
 
@@ -2738,16 +2743,20 @@ String Variant::get_construct_string() const {
 			for (int i=0; i<arr.size(); i++) {
 				if (i)
 					str+=", ";
-				str += arr[i].get_construct_string();
+				str += arr[i].get_construct_string(p_obj_deconstruct,p_deconstruct_ud);
 			};
 			return str+"]";
 
 		} break;
 		case OBJECT: {
 
-			if (_get_obj().obj)
-				return _get_obj().obj->get_type()+".new()";
-			else
+			if (_get_obj().obj) {
+				if (p_obj_deconstruct) {
+					return "Object(\""+p_obj_deconstruct(Variant(*this),p_deconstruct_ud).c_escape()+")";
+				} else {
+					return _get_obj().obj->get_type()+".new()";
+				}
+			} else
 				return "null";
 
 		} break;

+ 5 - 1
core/variant.h

@@ -419,7 +419,11 @@ public:
 	static bool has_numeric_constant(Variant::Type p_type, const StringName& p_value);
 	static int get_numeric_constant_value(Variant::Type p_type, const StringName& p_value);
 
-	String get_construct_string() const;
+	typedef String (*ObjectDeConstruct)(const Variant& p_object,void *ud);
+	typedef void (*ObjectConstruct)(const String& p_text,void *ud,Variant& r_value);
+
+	String get_construct_string(ObjectDeConstruct p_obj_deconstruct=NULL,void *p_deconstruct_ud=NULL) const;
+	static void construct_from_string(const String& p_string,Variant& r_value,ObjectConstruct p_obj_construct=NULL,void *p_construct_ud=NULL);
 
 	void operator=(const Variant& p_variant); // only this is enough for all the other types
 	Variant(const Variant& p_variant);

+ 433 - 0
core/variant_construct_string.cpp

@@ -0,0 +1,433 @@
+
+#include "variant.h"
+
+class VariantConstruct {
+
+	enum TokenType {
+		TK_CURLY_BRACKET_OPEN,
+		TK_CURLY_BRACKET_CLOSE,
+		TK_BRACKET_OPEN,
+		TK_BRACKET_CLOSE,
+		TK_IDENTIFIER,
+		TK_STRING,
+		TK_NUMBER,
+		TK_COLON,
+		TK_COMMA,
+		TK_EOF,
+		TK_MAX
+	};
+
+	enum Expecting {
+
+		EXPECT_OBJECT,
+		EXPECT_OBJECT_KEY,
+		EXPECT_COLON,
+		EXPECT_OBJECT_VALUE,
+	};
+
+	struct Token {
+
+		TokenType type;
+		Variant value;
+	};
+
+	static const char * tk_name[TK_MAX];
+
+	static String _print_var(const Variant& p_var);
+
+	static Error _get_token(const CharType *p_str,int &index, int p_len,Token& r_token,int &line,String &r_err_str);
+	static Error _parse_value(Variant &value,Token& token,const CharType *p_str,int &index, int p_len,int &line,String &r_err_str,Variant::ObjectConstruct* p_construct,void* p_ud);
+	static Error _parse_array(Array &array,const CharType *p_str,int &index, int p_len,int &line,String &r_err_str,Variant::ObjectConstruct* p_construct,void* p_ud);
+	static Error _parse_dict(Dictionary &object,const CharType *p_str,int &index, int p_len,int &line,String &r_err_str,Variant::ObjectConstruct* p_construct,void* p_ud);
+
+public:
+
+	static Error parse(const String& p_string,Variant& r_ret,String &r_err_str,int &r_err_line,Variant::ObjectConstruct* p_construct,void* p_ud);
+};
+
+
+const char * VariantConstruct::tk_name[TK_MAX] = {
+	"'{'",
+	"'}'",
+	"'['",
+	"']'",
+	"identifier",
+	"string",
+	"number",
+	"':'",
+	"','",
+	"EOF",
+};
+
+
+
+Error VariantConstruct::_get_token(const CharType *p_str, int &idx, int p_len, Token& r_token,int &line,String &r_err_str) {
+
+	while (true) {
+		switch(p_str[idx]) {
+
+			case '\n': {
+
+				line++;
+				idx++;
+				break;
+			};
+			case 0: {
+				r_token.type=TK_EOF;
+				return OK;
+			} break;
+			case '{': {
+
+				r_token.type=TK_CURLY_BRACKET_OPEN;
+				idx++;
+				return OK;
+			};
+			case '}': {
+
+				r_token.type=TK_CURLY_BRACKET_CLOSE;
+				idx++;
+				return OK;
+			};
+			case '[': {
+
+				r_token.type=TK_BRACKET_OPEN;
+				idx++;
+				return OK;
+			};
+			case ']': {
+
+				r_token.type=TK_BRACKET_CLOSE;
+				idx++;
+				return OK;
+			};
+			case ':': {
+
+				r_token.type=TK_COLON;
+				idx++;
+				return OK;
+			};
+			case ',': {
+
+				r_token.type=TK_COMMA;
+				idx++;
+				return OK;
+			};
+			case '"': {
+
+				idx++;
+				String str;
+				while(true) {
+					if (p_str[idx]==0) {
+						r_err_str="Unterminated String";
+						return ERR_PARSE_ERROR;
+					} else if (p_str[idx]=='"') {
+						idx++;
+						break;
+					} else if (p_str[idx]=='\\') {
+						//escaped characters...
+						idx++;
+						CharType next = p_str[idx];
+						if (next==0) {
+							r_err_str="Unterminated String";
+							return  ERR_PARSE_ERROR;
+						}
+						CharType res=0;
+
+						switch(next) {
+
+							case 'b': res=8; break;
+							case 't': res=9; break;
+							case 'n': res=10; break;
+							case 'f': res=12; break;
+							case 'r': res=13; break;
+							case '\"': res='\"'; break;
+							case '\\': res='\\'; break;
+							case '/': res='/'; break; //wtf
+							case 'u': {
+								//hexnumbarh - oct is deprecated
+
+
+								for(int j=0;j<4;j++) {
+									CharType c = p_str[idx+j+1];
+									if (c==0) {
+										r_err_str="Unterminated String";
+										return ERR_PARSE_ERROR;
+									}
+									if (!((c>='0' && c<='9') || (c>='a' && c<='f') || (c>='A' && c<='F'))) {
+
+										r_err_str="Malformed hex constant in string";
+										return ERR_PARSE_ERROR;
+									}
+									CharType v;
+									if (c>='0' && c<='9') {
+										v=c-'0';
+									} else if (c>='a' && c<='f') {
+										v=c-'a';
+										v+=10;
+									} else if (c>='A' && c<='F') {
+										v=c-'A';
+										v+=10;
+									} else {
+										ERR_PRINT("BUG");
+										v=0;
+									}
+
+									res<<=4;
+									res|=v;
+
+
+								}
+								idx+=4; //will add at the end anyway
+
+
+							} break;
+							default: {
+
+								r_err_str="Invalid escape sequence";
+								return ERR_PARSE_ERROR;
+							} break;
+						}
+
+						str+=res;
+
+					} else {
+						if (p_str[idx]=='\n')
+							line++;
+						str+=p_str[idx];
+					}
+					idx++;
+				}
+
+				r_token.type=TK_STRING;
+				r_token.value=str;
+				return OK;
+
+			} break;
+			default: {
+
+				if (p_str[idx]<=32) {
+					idx++;
+					break;
+				}
+
+				if (p_str[idx]=='-' || (p_str[idx]>='0' && p_str[idx]<='9')) {
+					//a number
+					const CharType *rptr;
+					double number = String::to_double(&p_str[idx],&rptr);
+					idx+=(rptr - &p_str[idx]);
+					r_token.type=TK_NUMBER;
+					r_token.value=number;
+					return OK;
+
+				} else if ((p_str[idx]>='A' && p_str[idx]<='Z') || (p_str[idx]>='a' && p_str[idx]<='z')) {
+
+					String id;
+
+					while((p_str[idx]>='A' && p_str[idx]<='Z') || (p_str[idx]>='a' && p_str[idx]<='z')) {
+
+						id+=p_str[idx];
+						idx++;
+					}
+
+					r_token.type=TK_IDENTIFIER;
+					r_token.value=id;
+					return OK;
+				} else {
+					r_err_str="Unexpected character.";
+					return ERR_PARSE_ERROR;
+				}
+			}
+
+		}
+	}
+
+	return ERR_PARSE_ERROR;
+}
+
+
+
+Error VariantConstruct::_parse_value(Variant &value,Token& token,const CharType *p_str,int &index, int p_len,int &line,String &r_err_str,Variant::ObjectConstruct* p_construct,void* p_ud) {
+
+
+	if (token.type==TK_CURLY_BRACKET_OPEN) {
+
+		Dictionary d;
+		Error err = _parse_dict(d,p_str,index,p_len,line,r_err_str,p_construct,p_ud);
+		if (err)
+			return err;
+		value=d;
+		return OK;
+	} else if (token.type==TK_BRACKET_OPEN) {
+
+		Array a;
+		Error err = _parse_array(a,p_str,index,p_len,line,r_err_str,p_construct,p_ud);
+		if (err)
+			return err;
+		value=a;
+		return OK;
+
+	} else if (token.type==TK_IDENTIFIER) {
+
+		String id = token.value;
+		if (id=="true")
+			value=true;
+		else if (id=="false")
+			value=false;
+		else if (id=="null")
+			value=Variant();
+		else {
+			r_err_str="Expected 'true','false' or 'null', got '"+id+"'.";
+			return ERR_PARSE_ERROR;
+		}
+		return OK;
+
+	} else if (token.type==TK_NUMBER) {
+
+		value=token.value;
+		return OK;
+	} else if (token.type==TK_STRING) {
+
+		value=token.value;
+		return OK;
+	} else {
+		r_err_str="Expected value, got "+String(tk_name[token.type])+".";
+		return ERR_PARSE_ERROR;
+	}
+
+	return ERR_PARSE_ERROR;
+}
+
+
+Error VariantConstruct::_parse_array(Array &array,const CharType *p_str,int &index, int p_len,int &line,String &r_err_str,Variant::ObjectConstruct* p_construct,void* p_ud) {
+
+	Token token;
+	bool need_comma=false;
+
+
+	while(index<p_len) {
+
+		Error err = _get_token(p_str,index,p_len,token,line,r_err_str);
+		if (err!=OK)
+			return err;
+
+		if (token.type==TK_BRACKET_CLOSE) {
+
+			return OK;
+		}
+
+		if (need_comma) {
+
+			if (token.type!=TK_COMMA) {
+
+				r_err_str="Expected ','";
+				return ERR_PARSE_ERROR;
+			} else {
+				need_comma=false;
+				continue;
+			}
+		}
+
+		Variant v;
+		err = _parse_value(v,token,p_str,index,p_len,line,r_err_str,p_construct,p_ud);
+		if (err)
+			return err;
+
+		array.push_back(v);
+		need_comma=true;
+
+	}
+
+	return OK;
+
+}
+
+Error VariantConstruct::_parse_dict(Dictionary &dict,const CharType *p_str,int &index, int p_len,int &line,String &r_err_str,Variant::ObjectConstruct* p_construct,void* p_ud) {
+
+	bool at_key=true;
+	Variant key;
+	Token token;
+	bool need_comma=false;
+
+
+	while(index<p_len) {
+
+
+		if (at_key) {
+
+			Error err = _get_token(p_str,index,p_len,token,line,r_err_str);
+			if (err!=OK)
+				return err;
+
+			if (token.type==TK_CURLY_BRACKET_CLOSE) {
+
+				return OK;
+			}
+
+			if (need_comma) {
+
+				if (token.type!=TK_COMMA) {
+
+					r_err_str="Expected '}' or ','";
+					return ERR_PARSE_ERROR;
+				} else {
+					need_comma=false;
+					continue;
+				}
+			}
+
+			err = _parse_value(key,token,p_str,index,p_len,line,r_err_str,p_construct,p_ud);
+
+
+			if (err!=OK)
+				return err;
+
+			err = _get_token(p_str,index,p_len,token,line,r_err_str);
+
+			if (err!=OK)
+				return err;
+
+			if (token.type!=TK_COLON) {
+
+				r_err_str="Expected ':'";
+				return ERR_PARSE_ERROR;
+			}
+			at_key=false;
+		} else {
+
+
+			Error err = _get_token(p_str,index,p_len,token,line,r_err_str);
+			if (err!=OK)
+				return err;
+
+			Variant v;
+			err = _parse_value(v,token,p_str,index,p_len,line,r_err_str,p_construct,p_ud);
+			if (err)
+				return err;
+			dict[key]=v;
+			need_comma=true;
+			at_key=true;
+		}
+	}
+
+	return OK;
+}
+
+
+Error VariantConstruct::parse(const String& p_string,Variant& r_ret,String &r_err_str,int &r_err_line,Variant::ObjectConstruct* p_construct,void* p_ud) {
+
+
+	const CharType *str = p_string.ptr();
+	int idx = 0;
+	int len = p_string.length();
+	Token token;
+	r_err_line=0;
+	String aux_key;
+
+	Error err = _get_token(str,idx,len,token,r_err_line,r_err_str);
+	if (err)
+		return err;
+
+	return _parse_value(r_ret,token,str,idx,len,r_err_line,r_err_str,p_construct,p_ud);
+}
+
+

BIN
demos/2d/navpoly/navigation.scn


+ 29 - 3
modules/gdscript/gd_functions.cpp

@@ -89,6 +89,8 @@ const char *GDFunctions::get_func_name(Function p_func) {
 		"printt",
 		"printerr",
 		"printraw",
+		"var2str",
+		"str2var",
 		"range",
 		"load",
 		"inst2dict",
@@ -577,10 +579,23 @@ void GDFunctions::call(Function p_func,const Variant **p_args,int p_arg_count,Va
 			r_ret=Variant();
 
 		} break;
+		case VAR_TO_STR: {
+			VALIDATE_ARG_COUNT(1);
+			r_ret=p_args[0]->get_construct_string();
+		} break;
+		case STR_TO_VAR: {
+			VALIDATE_ARG_COUNT(1);
+			if (p_args[0]->get_type()!=Variant::STRING) {
+				r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+				r_error.argument=0;
+				r_error.expected=Variant::STRING;
+				r_ret=Variant();
+				return;
+			}
+			Variant::construct_from_string(*p_args[0],r_ret);
+		} break;
 		case GEN_RANGE: {
 
-
-
 			switch(p_arg_count) {
 
 				case 0: {
@@ -861,7 +876,6 @@ void GDFunctions::call(Function p_func,const Variant **p_args,int p_arg_count,Va
 				}
 			}
 
-
 			r_ret = gdscr->_new(NULL,0,r_error);
 
 		} break;
@@ -1224,6 +1238,18 @@ MethodInfo GDFunctions::get_info(Function p_func) {
 			return mi;
 
 		} break;
+		case VAR_TO_STR: {
+			MethodInfo mi("var2str",PropertyInfo(Variant::NIL,"var"));
+			mi.return_val.type=Variant::STRING;
+			return mi;
+
+		} break;
+		case STR_TO_VAR: {
+
+			MethodInfo mi("str2var:var",PropertyInfo(Variant::STRING,"string"));
+			mi.return_val.type=Variant::NIL;
+			return mi;
+		} break;
 		case GEN_RANGE: {
 
 			MethodInfo mi("range",PropertyInfo(Variant::NIL,"..."));

+ 2 - 0
modules/gdscript/gd_functions.h

@@ -85,6 +85,8 @@ public:
 		TEXT_PRINT_TABBED,
 		TEXT_PRINTERR,
 		TEXT_PRINTRAW,
+		VAR_TO_STR,
+		STR_TO_VAR,
 		GEN_RANGE,
 		RESOURCE_LOAD,
 		INST2DICT,

+ 0 - 1
platform/windows/os_windows.cpp

@@ -1439,7 +1439,6 @@ void OS_Windows::warp_mouse_pos(const Point2& p_to) {
 
 		SetCursorPos(p.x,p.y);
 	}
-
 }
 
 Point2 OS_Windows::get_mouse_pos() const {

+ 3 - 3
scene/2d/navigation_polygon.cpp

@@ -113,7 +113,7 @@ void NavigationPolygon::clear_outlines(){
 }
 void NavigationPolygon::make_polygons_from_outlines(){
 
-	std::list<TriangulatorPoly> in_poly,out_poly;
+	List<TriangulatorPoly> in_poly,out_poly;
 
 	Vector2 outside_point(-1e10,-1e10);
 
@@ -194,9 +194,9 @@ void NavigationPolygon::make_polygons_from_outlines(){
 	vertices.resize(0);
 
 	Map<Vector2,int> points;
-	for(std::list<TriangulatorPoly>::iterator I = out_poly.begin();I!=out_poly.end();I++) {
+	for(List<TriangulatorPoly>::Element*I = out_poly.front();I;I=I->next()) {
 
-		TriangulatorPoly& tp = *I;
+		TriangulatorPoly& tp = I->get();
 
 		struct Polygon p;