begin new serialization framework
also got rid of STL dependency on triangulator
This commit is contained in:
parent
7ebb224ec1
commit
2185c018f6
13 changed files with 729 additions and 206 deletions
|
@ -316,6 +316,11 @@ float _OS::get_time_scale() {
|
||||||
return OS::get_singleton()->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 {
|
enum Weekday {
|
||||||
DAY_SUNDAY,
|
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_system_dir","dir"),&_OS::get_system_dir);
|
||||||
ObjectTypeDB::bind_method(_MD("get_unique_ID"),&_OS::get_unique_ID);
|
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("get_frames_per_second"),&_OS::get_frames_per_second);
|
||||||
|
|
||||||
ObjectTypeDB::bind_method(_MD("print_all_textures_by_size"),&_OS::print_all_textures_by_size);
|
ObjectTypeDB::bind_method(_MD("print_all_textures_by_size"),&_OS::print_all_textures_by_size);
|
||||||
|
|
|
@ -220,6 +220,8 @@ public:
|
||||||
void set_time_scale(float p_scale);
|
void set_time_scale(float p_scale);
|
||||||
float get_time_scale();
|
float get_time_scale();
|
||||||
|
|
||||||
|
bool is_ok_left_and_cancel_right() const;
|
||||||
|
|
||||||
static _OS *get_singleton() { return singleton; }
|
static _OS *get_singleton() { return singleton; }
|
||||||
|
|
||||||
_OS();
|
_OS();
|
||||||
|
|
|
@ -22,9 +22,9 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <algorithm>
|
|
||||||
#include "triangulator.h"
|
#include "triangulator.h"
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
#define TRIANGULATOR_VERTEXTYPE_REGULAR 0
|
#define TRIANGULATOR_VERTEXTYPE_REGULAR 0
|
||||||
#define TRIANGULATOR_VERTEXTYPE_START 1
|
#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
|
//removes holes from inpolys by merging them with non-holes
|
||||||
int TriangulatorPartition::RemoveHoles(list<TriangulatorPoly> *inpolys, list<TriangulatorPoly> *outpolys) {
|
int TriangulatorPartition::RemoveHoles(List<TriangulatorPoly> *inpolys, List<TriangulatorPoly> *outpolys) {
|
||||||
list<TriangulatorPoly> polys;
|
List<TriangulatorPoly> polys;
|
||||||
list<TriangulatorPoly>::iterator holeiter,polyiter,iter,iter2;
|
List<TriangulatorPoly>::Element *holeiter,*polyiter,*iter,*iter2;
|
||||||
long i,i2,holepointindex,polypointindex;
|
long i,i2,holepointindex,polypointindex;
|
||||||
Vector2 holepoint,polypoint,bestpolypoint;
|
Vector2 holepoint,polypoint,bestpolypoint;
|
||||||
Vector2 linep1,linep2;
|
Vector2 linep1,linep2;
|
||||||
|
@ -177,15 +177,15 @@ int TriangulatorPartition::RemoveHoles(list<TriangulatorPoly> *inpolys, list<Tri
|
||||||
|
|
||||||
//check for trivial case (no holes)
|
//check for trivial case (no holes)
|
||||||
hasholes = false;
|
hasholes = false;
|
||||||
for(iter = inpolys->begin(); iter!=inpolys->end(); iter++) {
|
for(iter = inpolys->front(); iter; iter=iter->next()) {
|
||||||
if(iter->IsHole()) {
|
if(iter->get().IsHole()) {
|
||||||
hasholes = true;
|
hasholes = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!hasholes) {
|
if(!hasholes) {
|
||||||
for(iter = inpolys->begin(); iter!=inpolys->end(); iter++) {
|
for(iter = inpolys->front(); iter; iter=iter->next()) {
|
||||||
outpolys->push_back(*iter);
|
outpolys->push_back(iter->get());
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -195,8 +195,8 @@ int TriangulatorPartition::RemoveHoles(list<TriangulatorPoly> *inpolys, list<Tri
|
||||||
while(1) {
|
while(1) {
|
||||||
//find the hole point with the largest x
|
//find the hole point with the largest x
|
||||||
hasholes = false;
|
hasholes = false;
|
||||||
for(iter = polys.begin(); iter!=polys.end(); iter++) {
|
for(iter = polys.front(); iter; iter=iter->next()) {
|
||||||
if(!iter->IsHole()) continue;
|
if(!iter->get().IsHole()) continue;
|
||||||
|
|
||||||
if(!hasholes) {
|
if(!hasholes) {
|
||||||
hasholes = true;
|
hasholes = true;
|
||||||
|
@ -204,38 +204,38 @@ int TriangulatorPartition::RemoveHoles(list<TriangulatorPoly> *inpolys, list<Tri
|
||||||
holepointindex = 0;
|
holepointindex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(i=0; i < iter->GetNumPoints(); i++) {
|
for(i=0; i < iter->get().GetNumPoints(); i++) {
|
||||||
if(iter->GetPoint(i).x > holeiter->GetPoint(holepointindex).x) {
|
if(iter->get().GetPoint(i).x > holeiter->get().GetPoint(holepointindex).x) {
|
||||||
holeiter = iter;
|
holeiter = iter;
|
||||||
holepointindex = i;
|
holepointindex = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!hasholes) break;
|
if(!hasholes) break;
|
||||||
holepoint = holeiter->GetPoint(holepointindex);
|
holepoint = holeiter->get().GetPoint(holepointindex);
|
||||||
|
|
||||||
pointfound = false;
|
pointfound = false;
|
||||||
for(iter = polys.begin(); iter!=polys.end(); iter++) {
|
for(iter = polys.front(); iter; iter=iter->next()) {
|
||||||
if(iter->IsHole()) continue;
|
if(iter->get().IsHole()) continue;
|
||||||
for(i=0; i < iter->GetNumPoints(); i++) {
|
for(i=0; i < iter->get().GetNumPoints(); i++) {
|
||||||
if(iter->GetPoint(i).x <= holepoint.x) continue;
|
if(iter->get().GetPoint(i).x <= holepoint.x) continue;
|
||||||
if(!InCone(iter->GetPoint((i+iter->GetNumPoints()-1)%(iter->GetNumPoints())),
|
if(!InCone(iter->get().GetPoint((i+iter->get().GetNumPoints()-1)%(iter->get().GetNumPoints())),
|
||||||
iter->GetPoint(i),
|
iter->get().GetPoint(i),
|
||||||
iter->GetPoint((i+1)%(iter->GetNumPoints())),
|
iter->get().GetPoint((i+1)%(iter->get().GetNumPoints())),
|
||||||
holepoint))
|
holepoint))
|
||||||
continue;
|
continue;
|
||||||
polypoint = iter->GetPoint(i);
|
polypoint = iter->get().GetPoint(i);
|
||||||
if(pointfound) {
|
if(pointfound) {
|
||||||
v1 = Normalize(polypoint-holepoint);
|
v1 = Normalize(polypoint-holepoint);
|
||||||
v2 = Normalize(bestpolypoint-holepoint);
|
v2 = Normalize(bestpolypoint-holepoint);
|
||||||
if(v2.x > v1.x) continue;
|
if(v2.x > v1.x) continue;
|
||||||
}
|
}
|
||||||
pointvisible = true;
|
pointvisible = true;
|
||||||
for(iter2 = polys.begin(); iter2!=polys.end(); iter2++) {
|
for(iter2 = polys.front(); iter2; iter2=iter2->next()) {
|
||||||
if(iter2->IsHole()) continue;
|
if(iter2->get().IsHole()) continue;
|
||||||
for(i2=0; i2 < iter2->GetNumPoints(); i2++) {
|
for(i2=0; i2 < iter2->get().GetNumPoints(); i2++) {
|
||||||
linep1 = iter2->GetPoint(i2);
|
linep1 = iter2->get().GetPoint(i2);
|
||||||
linep2 = iter2->GetPoint((i2+1)%(iter2->GetNumPoints()));
|
linep2 = iter2->get().GetPoint((i2+1)%(iter2->get().GetNumPoints()));
|
||||||
if(Intersects(holepoint,polypoint,linep1,linep2)) {
|
if(Intersects(holepoint,polypoint,linep1,linep2)) {
|
||||||
pointvisible = false;
|
pointvisible = false;
|
||||||
break;
|
break;
|
||||||
|
@ -254,18 +254,18 @@ int TriangulatorPartition::RemoveHoles(list<TriangulatorPoly> *inpolys, list<Tri
|
||||||
|
|
||||||
if(!pointfound) return 0;
|
if(!pointfound) return 0;
|
||||||
|
|
||||||
newpoly.Init(holeiter->GetNumPoints() + polyiter->GetNumPoints() + 2);
|
newpoly.Init(holeiter->get().GetNumPoints() + polyiter->get().GetNumPoints() + 2);
|
||||||
i2 = 0;
|
i2 = 0;
|
||||||
for(i=0;i<=polypointindex;i++) {
|
for(i=0;i<=polypointindex;i++) {
|
||||||
newpoly[i2] = polyiter->GetPoint(i);
|
newpoly[i2] = polyiter->get().GetPoint(i);
|
||||||
i2++;
|
i2++;
|
||||||
}
|
}
|
||||||
for(i=0;i<=holeiter->GetNumPoints();i++) {
|
for(i=0;i<=holeiter->get().GetNumPoints();i++) {
|
||||||
newpoly[i2] = holeiter->GetPoint((i+holepointindex)%holeiter->GetNumPoints());
|
newpoly[i2] = holeiter->get().GetPoint((i+holepointindex)%holeiter->get().GetNumPoints());
|
||||||
i2++;
|
i2++;
|
||||||
}
|
}
|
||||||
for(i=polypointindex;i<polyiter->GetNumPoints();i++) {
|
for(i=polypointindex;i<polyiter->get().GetNumPoints();i++) {
|
||||||
newpoly[i2] = polyiter->GetPoint(i);
|
newpoly[i2] = polyiter->get().GetPoint(i);
|
||||||
i2++;
|
i2++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -274,8 +274,8 @@ int TriangulatorPartition::RemoveHoles(list<TriangulatorPoly> *inpolys, list<Tri
|
||||||
polys.push_back(newpoly);
|
polys.push_back(newpoly);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(iter = polys.begin(); iter!=polys.end(); iter++) {
|
for(iter = polys.front(); iter; iter=iter->next()) {
|
||||||
outpolys->push_back(*iter);
|
outpolys->push_back(iter->get());
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -366,7 +366,7 @@ void TriangulatorPartition::UpdateVertex(PartitionVertex *v, PartitionVertex *ve
|
||||||
}
|
}
|
||||||
|
|
||||||
//triangulation by ear removal
|
//triangulation by ear removal
|
||||||
int TriangulatorPartition::Triangulate_EC(TriangulatorPoly *poly, list<TriangulatorPoly> *triangles) {
|
int TriangulatorPartition::Triangulate_EC(TriangulatorPoly *poly, List<TriangulatorPoly> *triangles) {
|
||||||
long numvertices;
|
long numvertices;
|
||||||
PartitionVertex *vertices;
|
PartitionVertex *vertices;
|
||||||
PartitionVertex *ear;
|
PartitionVertex *ear;
|
||||||
|
@ -440,20 +440,20 @@ int TriangulatorPartition::Triangulate_EC(TriangulatorPoly *poly, list<Triangula
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int TriangulatorPartition::Triangulate_EC(list<TriangulatorPoly> *inpolys, list<TriangulatorPoly> *triangles) {
|
int TriangulatorPartition::Triangulate_EC(List<TriangulatorPoly> *inpolys, List<TriangulatorPoly> *triangles) {
|
||||||
list<TriangulatorPoly> outpolys;
|
List<TriangulatorPoly> outpolys;
|
||||||
list<TriangulatorPoly>::iterator iter;
|
List<TriangulatorPoly>::Element*iter;
|
||||||
|
|
||||||
if(!RemoveHoles(inpolys,&outpolys)) return 0;
|
if(!RemoveHoles(inpolys,&outpolys)) return 0;
|
||||||
for(iter=outpolys.begin();iter!=outpolys.end();iter++) {
|
for(iter=outpolys.front();iter;iter=iter->next()) {
|
||||||
if(!Triangulate_EC(&(*iter),triangles)) return 0;
|
if(!Triangulate_EC(&(iter->get()),triangles)) return 0;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int TriangulatorPartition::ConvexPartition_HM(TriangulatorPoly *poly, list<TriangulatorPoly> *parts) {
|
int TriangulatorPartition::ConvexPartition_HM(TriangulatorPoly *poly, List<TriangulatorPoly> *parts) {
|
||||||
list<TriangulatorPoly> triangles;
|
List<TriangulatorPoly> triangles;
|
||||||
list<TriangulatorPoly>::iterator iter1,iter2;
|
List<TriangulatorPoly>::Element *iter1,*iter2;
|
||||||
TriangulatorPoly *poly1,*poly2;
|
TriangulatorPoly *poly1,*poly2;
|
||||||
TriangulatorPoly newpoly;
|
TriangulatorPoly newpoly;
|
||||||
Vector2 d1,d2,p1,p2,p3;
|
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;
|
if(!Triangulate_EC(poly,&triangles)) return 0;
|
||||||
|
|
||||||
for(iter1 = triangles.begin(); iter1 != triangles.end(); iter1++) {
|
for(iter1 = triangles.front(); iter1 ; iter1=iter1->next()) {
|
||||||
poly1 = &(*iter1);
|
poly1 = &(iter1->get());
|
||||||
for(i11=0;i11<poly1->GetNumPoints();i11++) {
|
for(i11=0;i11<poly1->GetNumPoints();i11++) {
|
||||||
d1 = poly1->GetPoint(i11);
|
d1 = poly1->GetPoint(i11);
|
||||||
i12 = (i11+1)%(poly1->GetNumPoints());
|
i12 = (i11+1)%(poly1->GetNumPoints());
|
||||||
d2 = poly1->GetPoint(i12);
|
d2 = poly1->GetPoint(i12);
|
||||||
|
|
||||||
isdiagonal = false;
|
isdiagonal = false;
|
||||||
for(iter2 = iter1; iter2 != triangles.end(); iter2++) {
|
for(iter2 = iter1; iter2 ; iter2=iter2->next()) {
|
||||||
if(iter1 == iter2) continue;
|
if(iter1 == iter2) continue;
|
||||||
poly2 = &(*iter2);
|
poly2 = &(iter2->get());
|
||||||
|
|
||||||
for(i21=0;i21<poly2->GetNumPoints();i21++) {
|
for(i21=0;i21<poly2->GetNumPoints();i21++) {
|
||||||
if((d2.x != poly2->GetPoint(i21).x)||(d2.y != poly2->GetPoint(i21).y)) continue;
|
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);
|
triangles.erase(iter2);
|
||||||
*iter1 = newpoly;
|
iter1->get() = newpoly;
|
||||||
poly1 = &(*iter1);
|
poly1 = &(iter1->get());
|
||||||
i11 = -1;
|
i11 = -1;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(iter1 = triangles.begin(); iter1 != triangles.end(); iter1++) {
|
for(iter1 = triangles.front(); iter1 ; iter1=iter1->next()) {
|
||||||
parts->push_back(*iter1);
|
parts->push_back(iter1->get());
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int TriangulatorPartition::ConvexPartition_HM(list<TriangulatorPoly> *inpolys, list<TriangulatorPoly> *parts) {
|
int TriangulatorPartition::ConvexPartition_HM(List<TriangulatorPoly> *inpolys, List<TriangulatorPoly> *parts) {
|
||||||
list<TriangulatorPoly> outpolys;
|
List<TriangulatorPoly> outpolys;
|
||||||
list<TriangulatorPoly>::iterator iter;
|
List<TriangulatorPoly>::Element* iter;
|
||||||
|
|
||||||
if(!RemoveHoles(inpolys,&outpolys)) return 0;
|
if(!RemoveHoles(inpolys,&outpolys)) return 0;
|
||||||
for(iter=outpolys.begin();iter!=outpolys.end();iter++) {
|
for(iter=outpolys.front();iter;iter=iter->next()) {
|
||||||
if(!ConvexPartition_HM(&(*iter),parts)) return 0;
|
if(!ConvexPartition_HM(&(iter->get()),parts)) return 0;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -565,14 +565,14 @@ int TriangulatorPartition::ConvexPartition_HM(list<TriangulatorPoly> *inpolys, l
|
||||||
//minimum-weight polygon triangulation by dynamic programming
|
//minimum-weight polygon triangulation by dynamic programming
|
||||||
//O(n^3) time complexity
|
//O(n^3) time complexity
|
||||||
//O(n^2) space 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;
|
long i,j,k,gap,n;
|
||||||
DPState **dpstates;
|
DPState **dpstates;
|
||||||
Vector2 p1,p2,p3,p4;
|
Vector2 p1,p2,p3,p4;
|
||||||
long bestvertex;
|
long bestvertex;
|
||||||
real_t weight,minweight,d1,d2;
|
real_t weight,minweight,d1,d2;
|
||||||
Diagonal diagonal,newdiagonal;
|
Diagonal diagonal,newdiagonal;
|
||||||
list<Diagonal> diagonals;
|
List<Diagonal> diagonals;
|
||||||
TriangulatorPoly triangle;
|
TriangulatorPoly triangle;
|
||||||
int ret = 1;
|
int ret = 1;
|
||||||
|
|
||||||
|
@ -666,7 +666,7 @@ int TriangulatorPartition::Triangulate_OPT(TriangulatorPoly *poly, list<Triangul
|
||||||
newdiagonal.index2 = n-1;
|
newdiagonal.index2 = n-1;
|
||||||
diagonals.push_back(newdiagonal);
|
diagonals.push_back(newdiagonal);
|
||||||
while(!diagonals.empty()) {
|
while(!diagonals.empty()) {
|
||||||
diagonal = *(diagonals.begin());
|
diagonal = (diagonals.front()->get());
|
||||||
diagonals.pop_front();
|
diagonals.pop_front();
|
||||||
bestvertex = dpstates[diagonal.index2][diagonal.index1].bestvertex;
|
bestvertex = dpstates[diagonal.index2][diagonal.index1].bestvertex;
|
||||||
if(bestvertex == -1) {
|
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) {
|
void TriangulatorPartition::UpdateState(long a, long b, long w, long i, long j, DPState2 **dpstates) {
|
||||||
Diagonal newdiagonal;
|
Diagonal newdiagonal;
|
||||||
list<Diagonal> *pairs;
|
List<Diagonal> *pairs;
|
||||||
long w2;
|
long w2;
|
||||||
|
|
||||||
w2 = dpstates[a][b].weight;
|
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);
|
pairs->push_front(newdiagonal);
|
||||||
dpstates[a][b].weight = w;
|
dpstates[a][b].weight = w;
|
||||||
} else {
|
} else {
|
||||||
if((!pairs->empty())&&(i <= pairs->begin()->index1)) return;
|
if((!pairs->empty())&&(i <= pairs->front()->get().index1)) return;
|
||||||
while((!pairs->empty())&&(pairs->begin()->index2 >= j)) pairs->pop_front();
|
while((!pairs->empty())&&(pairs->front()->get().index2 >= j)) pairs->pop_front();
|
||||||
pairs->push_front(newdiagonal);
|
pairs->push_front(newdiagonal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TriangulatorPartition::TypeA(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates) {
|
void TriangulatorPartition::TypeA(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates) {
|
||||||
list<Diagonal> *pairs;
|
List<Diagonal> *pairs;
|
||||||
list<Diagonal>::iterator iter,lastiter;
|
List<Diagonal>::Element *iter,*lastiter;
|
||||||
long top;
|
long top;
|
||||||
long w;
|
long w;
|
||||||
|
|
||||||
|
@ -733,25 +733,29 @@ void TriangulatorPartition::TypeA(long i, long j, long k, PartitionVertex *verti
|
||||||
}
|
}
|
||||||
if(j-i > 1) {
|
if(j-i > 1) {
|
||||||
pairs = &(dpstates[i][j].pairs);
|
pairs = &(dpstates[i][j].pairs);
|
||||||
iter = pairs->end();
|
iter = NULL;
|
||||||
lastiter = pairs->end();
|
lastiter = NULL;
|
||||||
while(iter!=pairs->begin()) {
|
while(iter!=pairs->front()) {
|
||||||
iter--;
|
if (!iter)
|
||||||
if(!IsReflex(vertices[iter->index2].p,vertices[j].p,vertices[k].p)) lastiter = 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;
|
else break;
|
||||||
}
|
}
|
||||||
if(lastiter == pairs->end()) w++;
|
if(lastiter == NULL) w++;
|
||||||
else {
|
else {
|
||||||
if(IsReflex(vertices[k].p,vertices[i].p,vertices[lastiter->index1].p)) w++;
|
if(IsReflex(vertices[k].p,vertices[i].p,vertices[lastiter->get().index1].p)) w++;
|
||||||
else top = lastiter->index1;
|
else top = lastiter->get().index1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UpdateState(i,k,w,top,j,dpstates);
|
UpdateState(i,k,w,top,j,dpstates);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TriangulatorPartition::TypeB(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates) {
|
void TriangulatorPartition::TypeB(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates) {
|
||||||
list<Diagonal> *pairs;
|
List<Diagonal> *pairs;
|
||||||
list<Diagonal>::iterator iter,lastiter;
|
List<Diagonal>::Element* iter,*lastiter;
|
||||||
long top;
|
long top;
|
||||||
long w;
|
long w;
|
||||||
|
|
||||||
|
@ -766,36 +770,36 @@ void TriangulatorPartition::TypeB(long i, long j, long k, PartitionVertex *verti
|
||||||
if (k-j > 1) {
|
if (k-j > 1) {
|
||||||
pairs = &(dpstates[j][k].pairs);
|
pairs = &(dpstates[j][k].pairs);
|
||||||
|
|
||||||
iter = pairs->begin();
|
iter = pairs->front();
|
||||||
if((!pairs->empty())&&(!IsReflex(vertices[i].p,vertices[j].p,vertices[iter->index1].p))) {
|
if((!pairs->empty())&&(!IsReflex(vertices[i].p,vertices[j].p,vertices[iter->get().index1].p))) {
|
||||||
lastiter = iter;
|
lastiter = iter;
|
||||||
while(iter!=pairs->end()) {
|
while(iter!=NULL) {
|
||||||
if(!IsReflex(vertices[i].p,vertices[j].p,vertices[iter->index1].p)) {
|
if(!IsReflex(vertices[i].p,vertices[j].p,vertices[iter->get().index1].p)) {
|
||||||
lastiter = iter;
|
lastiter = iter;
|
||||||
iter++;
|
iter=iter->next();
|
||||||
}
|
}
|
||||||
else break;
|
else break;
|
||||||
}
|
}
|
||||||
if(IsReflex(vertices[lastiter->index2].p,vertices[k].p,vertices[i].p)) w++;
|
if(IsReflex(vertices[lastiter->get().index2].p,vertices[k].p,vertices[i].p)) w++;
|
||||||
else top = lastiter->index2;
|
else top = lastiter->get().index2;
|
||||||
} else w++;
|
} else w++;
|
||||||
}
|
}
|
||||||
UpdateState(i,k,w,j,top,dpstates);
|
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;
|
Vector2 p1,p2,p3,p4;
|
||||||
PartitionVertex *vertices;
|
PartitionVertex *vertices;
|
||||||
DPState2 **dpstates;
|
DPState2 **dpstates;
|
||||||
long i,j,k,n,gap;
|
long i,j,k,n,gap;
|
||||||
list<Diagonal> diagonals,diagonals2;
|
List<Diagonal> diagonals,diagonals2;
|
||||||
Diagonal diagonal,newdiagonal;
|
Diagonal diagonal,newdiagonal;
|
||||||
list<Diagonal> *pairs,*pairs2;
|
List<Diagonal> *pairs,*pairs2;
|
||||||
list<Diagonal>::iterator iter,iter2;
|
List<Diagonal>::Element* iter,*iter2;
|
||||||
int ret;
|
int ret;
|
||||||
TriangulatorPoly newpoly;
|
TriangulatorPoly newpoly;
|
||||||
list<long> indices;
|
List<long> indices;
|
||||||
list<long>::iterator iiter;
|
List<long>::Element* iiter;
|
||||||
bool ijreal,jkreal;
|
bool ijreal,jkreal;
|
||||||
|
|
||||||
n = poly->GetNumPoints();
|
n = poly->GetNumPoints();
|
||||||
|
@ -903,7 +907,7 @@ int TriangulatorPartition::ConvexPartition_OPT(TriangulatorPoly *poly, list<Tria
|
||||||
newdiagonal.index2 = n-1;
|
newdiagonal.index2 = n-1;
|
||||||
diagonals.push_front(newdiagonal);
|
diagonals.push_front(newdiagonal);
|
||||||
while(!diagonals.empty()) {
|
while(!diagonals.empty()) {
|
||||||
diagonal = *(diagonals.begin());
|
diagonal = (diagonals.front()->get());
|
||||||
diagonals.pop_front();
|
diagonals.pop_front();
|
||||||
if((diagonal.index2 - diagonal.index1) <=1) continue;
|
if((diagonal.index2 - diagonal.index1) <=1) continue;
|
||||||
pairs = &(dpstates[diagonal.index1][diagonal.index2].pairs);
|
pairs = &(dpstates[diagonal.index1][diagonal.index2].pairs);
|
||||||
|
@ -912,23 +916,23 @@ int TriangulatorPartition::ConvexPartition_OPT(TriangulatorPoly *poly, list<Tria
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(!vertices[diagonal.index1].isConvex) {
|
if(!vertices[diagonal.index1].isConvex) {
|
||||||
iter = pairs->end();
|
iter = pairs->back();
|
||||||
iter--;
|
|
||||||
j = iter->index2;
|
j = iter->get().index2;
|
||||||
newdiagonal.index1 = j;
|
newdiagonal.index1 = j;
|
||||||
newdiagonal.index2 = diagonal.index2;
|
newdiagonal.index2 = diagonal.index2;
|
||||||
diagonals.push_front(newdiagonal);
|
diagonals.push_front(newdiagonal);
|
||||||
if((j - diagonal.index1)>1) {
|
if((j - diagonal.index1)>1) {
|
||||||
if(iter->index1 != iter->index2) {
|
if(iter->get().index1 != iter->get().index2) {
|
||||||
pairs2 = &(dpstates[diagonal.index1][j].pairs);
|
pairs2 = &(dpstates[diagonal.index1][j].pairs);
|
||||||
while(1) {
|
while(1) {
|
||||||
if(pairs2->empty()) {
|
if(pairs2->empty()) {
|
||||||
ret = 0;
|
ret = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
iter2 = pairs2->end();
|
iter2 = pairs2->back();
|
||||||
iter2--;
|
|
||||||
if(iter->index1 != iter2->index1) pairs2->pop_back();
|
if(iter->get().index1 != iter2->get().index1) pairs2->pop_back();
|
||||||
else break;
|
else break;
|
||||||
}
|
}
|
||||||
if(ret == 0) break;
|
if(ret == 0) break;
|
||||||
|
@ -938,21 +942,21 @@ int TriangulatorPartition::ConvexPartition_OPT(TriangulatorPoly *poly, list<Tria
|
||||||
diagonals.push_front(newdiagonal);
|
diagonals.push_front(newdiagonal);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
iter = pairs->begin();
|
iter = pairs->front();
|
||||||
j = iter->index1;
|
j = iter->get().index1;
|
||||||
newdiagonal.index1 = diagonal.index1;
|
newdiagonal.index1 = diagonal.index1;
|
||||||
newdiagonal.index2 = j;
|
newdiagonal.index2 = j;
|
||||||
diagonals.push_front(newdiagonal);
|
diagonals.push_front(newdiagonal);
|
||||||
if((diagonal.index2 - j) > 1) {
|
if((diagonal.index2 - j) > 1) {
|
||||||
if(iter->index1 != iter->index2) {
|
if(iter->get().index1 != iter->get().index2) {
|
||||||
pairs2 = &(dpstates[j][diagonal.index2].pairs);
|
pairs2 = &(dpstates[j][diagonal.index2].pairs);
|
||||||
while(1) {
|
while(1) {
|
||||||
if(pairs2->empty()) {
|
if(pairs2->empty()) {
|
||||||
ret = 0;
|
ret = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
iter2 = pairs2->begin();
|
iter2 = pairs2->front();
|
||||||
if(iter->index2 != iter2->index2) pairs2->pop_front();
|
if(iter->get().index2 != iter2->get().index2) pairs2->pop_front();
|
||||||
else break;
|
else break;
|
||||||
}
|
}
|
||||||
if(ret == 0) break;
|
if(ret == 0) break;
|
||||||
|
@ -978,7 +982,7 @@ int TriangulatorPartition::ConvexPartition_OPT(TriangulatorPoly *poly, list<Tria
|
||||||
newdiagonal.index2 = n-1;
|
newdiagonal.index2 = n-1;
|
||||||
diagonals.push_front(newdiagonal);
|
diagonals.push_front(newdiagonal);
|
||||||
while(!diagonals.empty()) {
|
while(!diagonals.empty()) {
|
||||||
diagonal = *(diagonals.begin());
|
diagonal = (diagonals.front())->get();
|
||||||
diagonals.pop_front();
|
diagonals.pop_front();
|
||||||
if((diagonal.index2 - diagonal.index1) <= 1) continue;
|
if((diagonal.index2 - diagonal.index1) <= 1) continue;
|
||||||
|
|
||||||
|
@ -989,21 +993,20 @@ int TriangulatorPartition::ConvexPartition_OPT(TriangulatorPoly *poly, list<Tria
|
||||||
diagonals2.push_front(diagonal);
|
diagonals2.push_front(diagonal);
|
||||||
|
|
||||||
while(!diagonals2.empty()) {
|
while(!diagonals2.empty()) {
|
||||||
diagonal = *(diagonals2.begin());
|
diagonal = (diagonals2.front()->get());
|
||||||
diagonals2.pop_front();
|
diagonals2.pop_front();
|
||||||
if((diagonal.index2 - diagonal.index1) <= 1) continue;
|
if((diagonal.index2 - diagonal.index1) <= 1) continue;
|
||||||
ijreal = true;
|
ijreal = true;
|
||||||
jkreal = true;
|
jkreal = true;
|
||||||
pairs = &(dpstates[diagonal.index1][diagonal.index2].pairs);
|
pairs = &(dpstates[diagonal.index1][diagonal.index2].pairs);
|
||||||
if(!vertices[diagonal.index1].isConvex) {
|
if(!vertices[diagonal.index1].isConvex) {
|
||||||
iter = pairs->end();
|
iter = pairs->back();
|
||||||
iter--;
|
j = iter->get().index2;
|
||||||
j = iter->index2;
|
if(iter->get().index1 != iter->get().index2) ijreal = false;
|
||||||
if(iter->index1 != iter->index2) ijreal = false;
|
|
||||||
} else {
|
} else {
|
||||||
iter = pairs->begin();
|
iter = pairs->front();
|
||||||
j = iter->index1;
|
j = iter->get().index1;
|
||||||
if(iter->index1 != iter->index2) jkreal = false;
|
if(iter->get().index1 != iter->get().index2) jkreal = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
newdiagonal.index1 = diagonal.index1;
|
newdiagonal.index1 = diagonal.index1;
|
||||||
|
@ -1028,8 +1031,8 @@ int TriangulatorPartition::ConvexPartition_OPT(TriangulatorPoly *poly, list<Tria
|
||||||
indices.sort();
|
indices.sort();
|
||||||
newpoly.Init((long)indices.size());
|
newpoly.Init((long)indices.size());
|
||||||
k=0;
|
k=0;
|
||||||
for(iiter = indices.begin();iiter!=indices.end();iiter++) {
|
for(iiter = indices.front();iiter;iiter=iiter->next()) {
|
||||||
newpoly[k] = vertices[*iiter].p;
|
newpoly[k] = vertices[iiter->get()].p;
|
||||||
k++;
|
k++;
|
||||||
}
|
}
|
||||||
parts->push_back(newpoly);
|
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
|
//the algorithm used here is outlined in the book
|
||||||
//"Computational Geometry: Algorithms and Applications"
|
//"Computational Geometry: Algorithms and Applications"
|
||||||
//by Mark de Berg, Otfried Cheong, Marc van Kreveld and Mark Overmars
|
//by Mark de Berg, Otfried Cheong, Marc van Kreveld and Mark Overmars
|
||||||
int TriangulatorPartition::MonotonePartition(list<TriangulatorPoly> *inpolys, list<TriangulatorPoly> *monotonePolys) {
|
int TriangulatorPartition::MonotonePartition(List<TriangulatorPoly> *inpolys, List<TriangulatorPoly> *monotonePolys) {
|
||||||
list<TriangulatorPoly>::iterator iter;
|
List<TriangulatorPoly>::Element *iter;
|
||||||
MonotoneVertex *vertices;
|
MonotoneVertex *vertices;
|
||||||
long i,numvertices,vindex,vindex2,newnumvertices,maxnumvertices;
|
long i,numvertices,vindex,vindex2,newnumvertices,maxnumvertices;
|
||||||
long polystartindex, polyendindex;
|
long polystartindex, polyendindex;
|
||||||
|
@ -1060,8 +1063,8 @@ int TriangulatorPartition::MonotonePartition(list<TriangulatorPoly> *inpolys, li
|
||||||
bool error = false;
|
bool error = false;
|
||||||
|
|
||||||
numvertices = 0;
|
numvertices = 0;
|
||||||
for(iter = inpolys->begin(); iter != inpolys->end(); iter++) {
|
for(iter = inpolys->front(); iter ; iter=iter->next()) {
|
||||||
numvertices += iter->GetNumPoints();
|
numvertices += iter->get().GetNumPoints();
|
||||||
}
|
}
|
||||||
|
|
||||||
maxnumvertices = numvertices*3;
|
maxnumvertices = numvertices*3;
|
||||||
|
@ -1069,8 +1072,8 @@ int TriangulatorPartition::MonotonePartition(list<TriangulatorPoly> *inpolys, li
|
||||||
newnumvertices = numvertices;
|
newnumvertices = numvertices;
|
||||||
|
|
||||||
polystartindex = 0;
|
polystartindex = 0;
|
||||||
for(iter = inpolys->begin(); iter != inpolys->end(); iter++) {
|
for(iter = inpolys->front(); iter ; iter=iter->next()) {
|
||||||
poly = &(*iter);
|
poly = &(iter->get());
|
||||||
polyendindex = polystartindex + poly->GetNumPoints()-1;
|
polyendindex = polystartindex + poly->GetNumPoints()-1;
|
||||||
for(i=0;i<poly->GetNumPoints();i++) {
|
for(i=0;i<poly->GetNumPoints();i++) {
|
||||||
vertices[i+polystartindex].p = poly->GetPoint(i);
|
vertices[i+polystartindex].p = poly->GetPoint(i);
|
||||||
|
@ -1085,7 +1088,9 @@ int TriangulatorPartition::MonotonePartition(list<TriangulatorPoly> *inpolys, li
|
||||||
//construct the priority queue
|
//construct the priority queue
|
||||||
long *priority = new long [numvertices];
|
long *priority = new long [numvertices];
|
||||||
for(i=0;i<numvertices;i++) priority[i] = i;
|
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
|
//determine vertex types
|
||||||
char *vertextypes = new char[maxnumvertices];
|
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
|
//binary search tree that holds edges intersecting the scanline
|
||||||
//note that while set doesn't actually have to be implemented as a tree
|
//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
|
//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
|
//store iterators to the edge tree elements
|
||||||
//this makes deleting existing edges much faster
|
//this makes deleting existing edges much faster
|
||||||
set<ScanLineEdge>::iterator *edgeTreeIterators,edgeIter;
|
Set<ScanLineEdge>::Element **edgeTreeIterators,*edgeIter;
|
||||||
edgeTreeIterators = new set<ScanLineEdge>::iterator[maxnumvertices];
|
edgeTreeIterators = new Set<ScanLineEdge>::Element*[maxnumvertices];
|
||||||
pair<set<ScanLineEdge>::iterator,bool> edgeTreeRet;
|
// Pair<Set<ScanLineEdge>::Element*,bool> edgeTreeRet;
|
||||||
for(i = 0; i<numvertices; i++) edgeTreeIterators[i] = edgeTree.end();
|
for(i = 0; i<numvertices; i++) edgeTreeIterators[i] = NULL;
|
||||||
|
|
||||||
//for each vertex
|
//for each vertex
|
||||||
for(i=0;i<numvertices;i++) {
|
for(i=0;i<numvertices;i++) {
|
||||||
|
@ -1141,8 +1146,7 @@ int TriangulatorPartition::MonotonePartition(list<TriangulatorPoly> *inpolys, li
|
||||||
newedge.p1 = v->p;
|
newedge.p1 = v->p;
|
||||||
newedge.p2 = vertices[v->next].p;
|
newedge.p2 = vertices[v->next].p;
|
||||||
newedge.index = vindex;
|
newedge.index = vindex;
|
||||||
edgeTreeRet = edgeTree.insert(newedge);
|
edgeTreeIterators[vindex] = edgeTree.insert(newedge);
|
||||||
edgeTreeIterators[vindex] = edgeTreeRet.first;
|
|
||||||
helpers[vindex] = vindex;
|
helpers[vindex] = vindex;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1162,24 +1166,24 @@ int TriangulatorPartition::MonotonePartition(list<TriangulatorPoly> *inpolys, li
|
||||||
newedge.p1 = v->p;
|
newedge.p1 = v->p;
|
||||||
newedge.p2 = v->p;
|
newedge.p2 = v->p;
|
||||||
edgeIter = edgeTree.lower_bound(newedge);
|
edgeIter = edgeTree.lower_bound(newedge);
|
||||||
if(edgeIter == edgeTree.begin()) {
|
if(edgeIter == edgeTree.front()) {
|
||||||
error = true;
|
error = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
edgeIter--;
|
edgeIter=edgeIter->prev();
|
||||||
//Insert the diagonal connecting vi to helper(ej) in D.
|
//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);
|
vertextypes, edgeTreeIterators, &edgeTree, helpers);
|
||||||
vindex2 = newnumvertices-2;
|
vindex2 = newnumvertices-2;
|
||||||
v2 = &(vertices[vindex2]);
|
v2 = &(vertices[vindex2]);
|
||||||
//helper(e j)<29>vi
|
//helper(e j)<29>vi
|
||||||
helpers[edgeIter->index] = vindex;
|
helpers[edgeIter->get().index] = vindex;
|
||||||
//Insert ei in T and set helper(ei) to vi.
|
//Insert ei in T and set helper(ei) to vi.
|
||||||
newedge.p1 = v2->p;
|
newedge.p1 = v2->p;
|
||||||
newedge.p2 = vertices[v2->next].p;
|
newedge.p2 = vertices[v2->next].p;
|
||||||
newedge.index = vindex2;
|
newedge.index = vindex2;
|
||||||
edgeTreeRet = edgeTree.insert(newedge);
|
|
||||||
edgeTreeIterators[vindex2] = edgeTreeRet.first;
|
edgeTreeIterators[vindex2] = edgeTree.insert(newedge);
|
||||||
helpers[vindex2] = vindex2;
|
helpers[vindex2] = vindex2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1198,19 +1202,19 @@ int TriangulatorPartition::MonotonePartition(list<TriangulatorPoly> *inpolys, li
|
||||||
newedge.p1 = v->p;
|
newedge.p1 = v->p;
|
||||||
newedge.p2 = v->p;
|
newedge.p2 = v->p;
|
||||||
edgeIter = edgeTree.lower_bound(newedge);
|
edgeIter = edgeTree.lower_bound(newedge);
|
||||||
if(edgeIter == edgeTree.begin()) {
|
if(edgeIter == edgeTree.front()) {
|
||||||
error = true;
|
error = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
edgeIter--;
|
edgeIter=edgeIter->prev();
|
||||||
//if helper(ej) is a merge vertex
|
//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.
|
//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);
|
vertextypes, edgeTreeIterators, &edgeTree, helpers);
|
||||||
}
|
}
|
||||||
//helper(e j)<29>vi
|
//helper(e j)<29>vi
|
||||||
helpers[edgeIter->index] = vindex2;
|
helpers[edgeIter->get().index] = vindex2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TRIANGULATOR_VERTEXTYPE_REGULAR:
|
case TRIANGULATOR_VERTEXTYPE_REGULAR:
|
||||||
|
@ -1230,27 +1234,26 @@ int TriangulatorPartition::MonotonePartition(list<TriangulatorPoly> *inpolys, li
|
||||||
newedge.p1 = v2->p;
|
newedge.p1 = v2->p;
|
||||||
newedge.p2 = vertices[v2->next].p;
|
newedge.p2 = vertices[v2->next].p;
|
||||||
newedge.index = vindex2;
|
newedge.index = vindex2;
|
||||||
edgeTreeRet = edgeTree.insert(newedge);
|
edgeTreeIterators[vindex2] = edgeTree.insert(newedge);
|
||||||
edgeTreeIterators[vindex2] = edgeTreeRet.first;
|
|
||||||
helpers[vindex2] = vindex;
|
helpers[vindex2] = vindex;
|
||||||
} else {
|
} else {
|
||||||
//Search in T to find the edge ej directly left of vi.
|
//Search in T to find the edge ej directly left of vi.
|
||||||
newedge.p1 = v->p;
|
newedge.p1 = v->p;
|
||||||
newedge.p2 = v->p;
|
newedge.p2 = v->p;
|
||||||
edgeIter = edgeTree.lower_bound(newedge);
|
edgeIter = edgeTree.lower_bound(newedge);
|
||||||
if(edgeIter == edgeTree.begin()) {
|
if(edgeIter == edgeTree.front()) {
|
||||||
error = true;
|
error = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
edgeIter--;
|
edgeIter=edgeIter->prev();
|
||||||
//if helper(ej) is a merge vertex
|
//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.
|
//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);
|
vertextypes, edgeTreeIterators, &edgeTree, helpers);
|
||||||
}
|
}
|
||||||
//helper(e j)<29>vi
|
//helper(e j)<29>vi
|
||||||
helpers[edgeIter->index] = vindex;
|
helpers[edgeIter->get().index] = vindex;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1308,8 +1311,8 @@ int TriangulatorPartition::MonotonePartition(list<TriangulatorPoly> *inpolys, li
|
||||||
|
|
||||||
//adds a diagonal to the doubly-connected list of vertices
|
//adds a diagonal to the doubly-connected list of vertices
|
||||||
void TriangulatorPartition::AddDiagonal(MonotoneVertex *vertices, long *numvertices, long index1, long index2,
|
void TriangulatorPartition::AddDiagonal(MonotoneVertex *vertices, long *numvertices, long index1, long index2,
|
||||||
char *vertextypes, set<ScanLineEdge>::iterator *edgeTreeIterators,
|
char *vertextypes, Set<ScanLineEdge>::Element **edgeTreeIterators,
|
||||||
set<ScanLineEdge> *edgeTree, long *helpers)
|
Set<ScanLineEdge> *edgeTree, long *helpers)
|
||||||
{
|
{
|
||||||
long newindex1,newindex2;
|
long newindex1,newindex2;
|
||||||
|
|
||||||
|
@ -1337,13 +1340,13 @@ void TriangulatorPartition::AddDiagonal(MonotoneVertex *vertices, long *numverti
|
||||||
vertextypes[newindex1] = vertextypes[index1];
|
vertextypes[newindex1] = vertextypes[index1];
|
||||||
edgeTreeIterators[newindex1] = edgeTreeIterators[index1];
|
edgeTreeIterators[newindex1] = edgeTreeIterators[index1];
|
||||||
helpers[newindex1] = helpers[index1];
|
helpers[newindex1] = helpers[index1];
|
||||||
if(edgeTreeIterators[newindex1] != edgeTree->end())
|
if(edgeTreeIterators[newindex1] != NULL)
|
||||||
edgeTreeIterators[newindex1]->index = newindex1;
|
edgeTreeIterators[newindex1]->get().index = newindex1;
|
||||||
vertextypes[newindex2] = vertextypes[index2];
|
vertextypes[newindex2] = vertextypes[index2];
|
||||||
edgeTreeIterators[newindex2] = edgeTreeIterators[index2];
|
edgeTreeIterators[newindex2] = edgeTreeIterators[index2];
|
||||||
helpers[newindex2] = helpers[index2];
|
helpers[newindex2] = helpers[index2];
|
||||||
if(edgeTreeIterators[newindex2] != edgeTree->end())
|
if(edgeTreeIterators[newindex2] != NULL)
|
||||||
edgeTreeIterators[newindex2]->index = newindex2;
|
edgeTreeIterators[newindex2]->get().index = newindex2;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TriangulatorPartition::Below(Vector2 &p1, Vector2 &p2) {
|
bool TriangulatorPartition::Below(Vector2 &p1, Vector2 &p2) {
|
||||||
|
@ -1354,8 +1357,12 @@ bool TriangulatorPartition::Below(Vector2 &p1, Vector2 &p2) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//sorts in the falling order of y values, if y is equal, x is used instead
|
//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;
|
if(vertices[index1].p.y > vertices[index2].p.y) return true;
|
||||||
else if(vertices[index1].p.y == vertices[index2].p.y) {
|
else if(vertices[index1].p.y == vertices[index2].p.y) {
|
||||||
if(vertices[index1].p.x > vertices[index2].p.x) return true;
|
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
|
//triangulates monotone polygon
|
||||||
//O(n) time, O(n) space complexity
|
//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;
|
long i,i2,j,topindex,bottomindex,leftindex,rightindex,vindex;
|
||||||
Vector2 *points;
|
Vector2 *points;
|
||||||
long numpoints;
|
long numpoints;
|
||||||
|
@ -1524,19 +1531,19 @@ int TriangulatorPartition::TriangulateMonotone(TriangulatorPoly *inPoly, list<Tr
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int TriangulatorPartition::Triangulate_MONO(list<TriangulatorPoly> *inpolys, list<TriangulatorPoly> *triangles) {
|
int TriangulatorPartition::Triangulate_MONO(List<TriangulatorPoly> *inpolys, List<TriangulatorPoly> *triangles) {
|
||||||
list<TriangulatorPoly> monotone;
|
List<TriangulatorPoly> monotone;
|
||||||
list<TriangulatorPoly>::iterator iter;
|
List<TriangulatorPoly>::Element* iter;
|
||||||
|
|
||||||
if(!MonotonePartition(inpolys,&monotone)) return 0;
|
if(!MonotonePartition(inpolys,&monotone)) return 0;
|
||||||
for(iter = monotone.begin(); iter!=monotone.end();iter++) {
|
for(iter = monotone.front(); iter;iter=iter->next()) {
|
||||||
if(!TriangulateMonotone(&(*iter),triangles)) return 0;
|
if(!TriangulateMonotone(&(iter->get()),triangles)) return 0;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int TriangulatorPartition::Triangulate_MONO(TriangulatorPoly *poly, list<TriangulatorPoly> *triangles) {
|
int TriangulatorPartition::Triangulate_MONO(TriangulatorPoly *poly, List<TriangulatorPoly> *triangles) {
|
||||||
list<TriangulatorPoly> polys;
|
List<TriangulatorPoly> polys;
|
||||||
polys.push_back(*poly);
|
polys.push_back(*poly);
|
||||||
|
|
||||||
return Triangulate_MONO(&polys, triangles);
|
return Triangulate_MONO(&polys, triangles);
|
||||||
|
|
|
@ -22,9 +22,8 @@
|
||||||
#define TRIANGULATOR_H
|
#define TRIANGULATOR_H
|
||||||
|
|
||||||
#include "math_2d.h"
|
#include "math_2d.h"
|
||||||
#include <list>
|
#include "list.h"
|
||||||
#include <set>
|
#include "set.h"
|
||||||
|
|
||||||
//2D point structure
|
//2D point structure
|
||||||
|
|
||||||
|
|
||||||
|
@ -119,11 +118,9 @@ protected:
|
||||||
long next;
|
long next;
|
||||||
};
|
};
|
||||||
|
|
||||||
class VertexSorter{
|
struct VertexSorter{
|
||||||
MonotoneVertex *vertices;
|
mutable MonotoneVertex *vertices;
|
||||||
public:
|
bool operator() (long index1, long index2) const;
|
||||||
VertexSorter(MonotoneVertex *v) : vertices(v) {}
|
|
||||||
bool operator() (long index1, long index2);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Diagonal {
|
struct Diagonal {
|
||||||
|
@ -142,7 +139,7 @@ protected:
|
||||||
struct DPState2 {
|
struct DPState2 {
|
||||||
bool visible;
|
bool visible;
|
||||||
long weight;
|
long weight;
|
||||||
std::list<Diagonal> pairs;
|
List<Diagonal> pairs;
|
||||||
};
|
};
|
||||||
|
|
||||||
//edge that intersects the scanline
|
//edge that intersects the scanline
|
||||||
|
@ -182,11 +179,11 @@ protected:
|
||||||
//helper functions for MonotonePartition
|
//helper functions for MonotonePartition
|
||||||
bool Below(Vector2 &p1, Vector2 &p2);
|
bool Below(Vector2 &p1, Vector2 &p2);
|
||||||
void AddDiagonal(MonotoneVertex *vertices, long *numvertices, long index1, long index2,
|
void AddDiagonal(MonotoneVertex *vertices, long *numvertices, long index1, long index2,
|
||||||
char *vertextypes, std::set<ScanLineEdge>::iterator *edgeTreeIterators,
|
char *vertextypes, Set<ScanLineEdge>::Element **edgeTreeIterators,
|
||||||
std::set<ScanLineEdge> *edgeTree, long *helpers);
|
Set<ScanLineEdge> *edgeTree, long *helpers);
|
||||||
|
|
||||||
//triangulates a monotone polygon, used in Triangulate_MONO
|
//triangulates a monotone polygon, used in Triangulate_MONO
|
||||||
int TriangulateMonotone(TriangulatorPoly *inPoly, std::list<TriangulatorPoly> *triangles);
|
int TriangulateMonotone(TriangulatorPoly *inPoly, List<TriangulatorPoly> *triangles);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -200,7 +197,7 @@ public:
|
||||||
// vertices of all hole polys have to be in clockwise order
|
// vertices of all hole polys have to be in clockwise order
|
||||||
// outpolys : a list of polygons without holes
|
// outpolys : a list of polygons without holes
|
||||||
//returns 1 on success, 0 on failure
|
//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
|
//triangulates a polygon by ear clipping
|
||||||
//time complexity O(n^2), n is the number of vertices
|
//time complexity O(n^2), n is the number of vertices
|
||||||
|
@ -210,7 +207,7 @@ public:
|
||||||
// vertices have to be in counter-clockwise order
|
// vertices have to be in counter-clockwise order
|
||||||
// triangles : a list of triangles (result)
|
// triangles : a list of triangles (result)
|
||||||
//returns 1 on success, 0 on failure
|
//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
|
//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
|
//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
|
// vertices of all hole polys have to be in clockwise order
|
||||||
// triangles : a list of triangles (result)
|
// triangles : a list of triangles (result)
|
||||||
//returns 1 on success, 0 on failure
|
//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
|
//creates an optimal polygon triangulation in terms of minimal edge length
|
||||||
//time complexity: O(n^3), n is the number of vertices
|
//time complexity: O(n^3), n is the number of vertices
|
||||||
|
@ -232,7 +229,7 @@ public:
|
||||||
// vertices have to be in counter-clockwise order
|
// vertices have to be in counter-clockwise order
|
||||||
// triangles : a list of triangles (result)
|
// triangles : a list of triangles (result)
|
||||||
//returns 1 on success, 0 on failure
|
//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
|
//triangulates a polygons by firstly partitioning it into monotone polygons
|
||||||
//time complexity: O(n*log(n)), n is the number of vertices
|
//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
|
// vertices have to be in counter-clockwise order
|
||||||
// triangles : a list of triangles (result)
|
// triangles : a list of triangles (result)
|
||||||
//returns 1 on success, 0 on failure
|
//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
|
//triangulates a list of polygons by firstly partitioning them into monotone polygons
|
||||||
//time complexity: O(n*log(n)), n is the number of vertices
|
//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
|
// vertices of all hole polys have to be in clockwise order
|
||||||
// triangles : a list of triangles (result)
|
// triangles : a list of triangles (result)
|
||||||
//returns 1 on success, 0 on failure
|
//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
|
//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
|
//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
|
// vertices of all hole polys have to be in clockwise order
|
||||||
// monotonePolys : a list of monotone polygons (result)
|
// monotonePolys : a list of monotone polygons (result)
|
||||||
//returns 1 on success, 0 on failure
|
//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
|
//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
|
//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
|
// vertices have to be in counter-clockwise order
|
||||||
// parts : resulting list of convex polygons
|
// parts : resulting list of convex polygons
|
||||||
//returns 1 on success, 0 on failure
|
//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
|
//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
|
//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
|
// vertices of all hole polys have to be in clockwise order
|
||||||
// parts : resulting list of convex polygons
|
// parts : resulting list of convex polygons
|
||||||
//returns 1 on success, 0 on failure
|
//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)
|
//optimal convex partitioning (in terms of number of resulting convex polygons)
|
||||||
//using the Keil-Snoeyink algorithm
|
//using the Keil-Snoeyink algorithm
|
||||||
|
@ -302,7 +299,7 @@ public:
|
||||||
// vertices have to be in counter-clockwise order
|
// vertices have to be in counter-clockwise order
|
||||||
// parts : resulting list of convex polygons
|
// parts : resulting list of convex polygons
|
||||||
//returns 1 on success, 0 on failure
|
//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
core/set.h
37
core/set.h
|
@ -249,6 +249,37 @@ private:
|
||||||
return (node!=_data._nil)?node:NULL;
|
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) {
|
Element *_insert(const T& p_value, bool& r_exists) {
|
||||||
|
|
||||||
|
@ -583,6 +614,12 @@ public:
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Element *lower_bound(const T& p_value) const {
|
||||||
|
|
||||||
|
return _lower_bound(p_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
inline int size() const { return _data.size_cache; }
|
inline int size() const { return _data.size_cache; }
|
||||||
int calculate_depth() const {
|
int calculate_depth() const {
|
||||||
// used for debug mostly
|
// used for debug mostly
|
||||||
|
|
|
@ -2631,8 +2631,13 @@ Variant Variant::call(const StringName& p_method,VARIANT_ARG_DECLARE) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Variant::construct_from_string(const String& p_string,Variant& r_value,ObjectConstruct p_obj_construct,void *p_construct_ud) {
|
||||||
|
|
||||||
String Variant::get_construct_string() const {
|
r_value=Variant();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String Variant::get_construct_string(ObjectDeConstruct p_obj_deconstruct,void *p_deconstruct_ud) const {
|
||||||
|
|
||||||
switch( type ) {
|
switch( type ) {
|
||||||
|
|
||||||
|
@ -2640,7 +2645,7 @@ String Variant::get_construct_string() const {
|
||||||
case BOOL: return _data._bool ? "true" : "false";
|
case BOOL: return _data._bool ? "true" : "false";
|
||||||
case INT: return String::num(_data._int);
|
case INT: return String::num(_data._int);
|
||||||
case REAL: return String::num(_data._real);
|
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 VECTOR2: return "Vector2("+operator Vector2()+")";
|
||||||
case RECT2: return "Rect2("+operator Rect2()+")";
|
case RECT2: return "Rect2("+operator Rect2()+")";
|
||||||
case MATRIX32: return "Matrix32("+operator Matrix32()+")";
|
case MATRIX32: return "Matrix32("+operator Matrix32()+")";
|
||||||
|
@ -2651,7 +2656,7 @@ String Variant::get_construct_string() const {
|
||||||
case QUAT: return "Quat("+operator Quat()+")";
|
case QUAT: return "Quat("+operator Quat()+")";
|
||||||
case MATRIX3: return "Matrix3("+operator Matrix3()+")";
|
case MATRIX3: return "Matrix3("+operator Matrix3()+")";
|
||||||
case TRANSFORM: return "Transform("+operator Transform()+")";
|
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 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 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: {
|
case DICTIONARY: {
|
||||||
|
@ -2667,8 +2672,8 @@ String Variant::get_construct_string() const {
|
||||||
for(List<Variant>::Element *E=keys.front();E;E=E->next()) {
|
for(List<Variant>::Element *E=keys.front();E;E=E->next()) {
|
||||||
|
|
||||||
_VariantStrPair sp;
|
_VariantStrPair sp;
|
||||||
sp.key=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();
|
sp.value=d[E->get()].get_construct_string(p_obj_deconstruct,p_deconstruct_ud);
|
||||||
pairs.push_back(sp);
|
pairs.push_back(sp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2686,50 +2691,50 @@ String Variant::get_construct_string() const {
|
||||||
case VECTOR3_ARRAY: {
|
case VECTOR3_ARRAY: {
|
||||||
|
|
||||||
DVector<Vector3> vec = operator DVector<Vector3>();
|
DVector<Vector3> vec = operator DVector<Vector3>();
|
||||||
String str="[";
|
String str="Vector3Array([";
|
||||||
for(int i=0;i<vec.size();i++) {
|
for(int i=0;i<vec.size();i++) {
|
||||||
|
|
||||||
if (i>0)
|
if (i>0)
|
||||||
str+=", ";
|
str+=", ";
|
||||||
str+=Variant( vec[i] ).get_construct_string();
|
str+=Variant( vec[i] ).get_construct_string();
|
||||||
}
|
}
|
||||||
return str+"]";
|
return str+"])";
|
||||||
} break;
|
} break;
|
||||||
case STRING_ARRAY: {
|
case STRING_ARRAY: {
|
||||||
|
|
||||||
DVector<String> vec = operator DVector<String>();
|
DVector<String> vec = operator DVector<String>();
|
||||||
String str="[";
|
String str="StringArray([";
|
||||||
for(int i=0;i<vec.size();i++) {
|
for(int i=0;i<vec.size();i++) {
|
||||||
|
|
||||||
if (i>0)
|
if (i>0)
|
||||||
str+=", ";
|
str+=", ";
|
||||||
str=str+=Variant( vec[i] ).get_construct_string();
|
str=str+=Variant( vec[i] ).get_construct_string();
|
||||||
}
|
}
|
||||||
return str+"]";
|
return str+"])";
|
||||||
} break;
|
} break;
|
||||||
case INT_ARRAY: {
|
case INT_ARRAY: {
|
||||||
|
|
||||||
DVector<int> vec = operator DVector<int>();
|
DVector<int> vec = operator DVector<int>();
|
||||||
String str="[";
|
String str="IntArray([";
|
||||||
for(int i=0;i<vec.size();i++) {
|
for(int i=0;i<vec.size();i++) {
|
||||||
|
|
||||||
if (i>0)
|
if (i>0)
|
||||||
str+=", ";
|
str+=", ";
|
||||||
str=str+itos(vec[i]);
|
str=str+itos(vec[i]);
|
||||||
}
|
}
|
||||||
return str+"]";
|
return str+"])";
|
||||||
} break;
|
} break;
|
||||||
case REAL_ARRAY: {
|
case REAL_ARRAY: {
|
||||||
|
|
||||||
DVector<real_t> vec = operator DVector<real_t>();
|
DVector<real_t> vec = operator DVector<real_t>();
|
||||||
String str="[";
|
String str="FloatArray([";
|
||||||
for(int i=0;i<vec.size();i++) {
|
for(int i=0;i<vec.size();i++) {
|
||||||
|
|
||||||
if (i>0)
|
if (i>0)
|
||||||
str+=", ";
|
str+=", ";
|
||||||
str=str+rtos(vec[i]);
|
str=str+rtos(vec[i]);
|
||||||
}
|
}
|
||||||
return str+"]";
|
return str+"])";
|
||||||
} break;
|
} break;
|
||||||
case ARRAY: {
|
case ARRAY: {
|
||||||
|
|
||||||
|
@ -2738,16 +2743,20 @@ String Variant::get_construct_string() const {
|
||||||
for (int i=0; i<arr.size(); i++) {
|
for (int i=0; i<arr.size(); i++) {
|
||||||
if (i)
|
if (i)
|
||||||
str+=", ";
|
str+=", ";
|
||||||
str += arr[i].get_construct_string();
|
str += arr[i].get_construct_string(p_obj_deconstruct,p_deconstruct_ud);
|
||||||
};
|
};
|
||||||
return str+"]";
|
return str+"]";
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case OBJECT: {
|
case OBJECT: {
|
||||||
|
|
||||||
if (_get_obj().obj)
|
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()";
|
return _get_obj().obj->get_type()+".new()";
|
||||||
else
|
}
|
||||||
|
} else
|
||||||
return "null";
|
return "null";
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
|
|
|
@ -419,7 +419,11 @@ public:
|
||||||
static bool has_numeric_constant(Variant::Type p_type, const StringName& p_value);
|
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);
|
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
|
void operator=(const Variant& p_variant); // only this is enough for all the other types
|
||||||
Variant(const Variant& p_variant);
|
Variant(const Variant& p_variant);
|
||||||
|
|
433
core/variant_construct_string.cpp
Normal file
433
core/variant_construct_string.cpp
Normal file
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Binary file not shown.
|
@ -89,6 +89,8 @@ const char *GDFunctions::get_func_name(Function p_func) {
|
||||||
"printt",
|
"printt",
|
||||||
"printerr",
|
"printerr",
|
||||||
"printraw",
|
"printraw",
|
||||||
|
"var2str",
|
||||||
|
"str2var",
|
||||||
"range",
|
"range",
|
||||||
"load",
|
"load",
|
||||||
"inst2dict",
|
"inst2dict",
|
||||||
|
@ -577,10 +579,23 @@ void GDFunctions::call(Function p_func,const Variant **p_args,int p_arg_count,Va
|
||||||
r_ret=Variant();
|
r_ret=Variant();
|
||||||
|
|
||||||
} break;
|
} 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: {
|
case GEN_RANGE: {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
switch(p_arg_count) {
|
switch(p_arg_count) {
|
||||||
|
|
||||||
case 0: {
|
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);
|
r_ret = gdscr->_new(NULL,0,r_error);
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
|
@ -1224,6 +1238,18 @@ MethodInfo GDFunctions::get_info(Function p_func) {
|
||||||
return mi;
|
return mi;
|
||||||
|
|
||||||
} break;
|
} 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: {
|
case GEN_RANGE: {
|
||||||
|
|
||||||
MethodInfo mi("range",PropertyInfo(Variant::NIL,"..."));
|
MethodInfo mi("range",PropertyInfo(Variant::NIL,"..."));
|
||||||
|
|
|
@ -85,6 +85,8 @@ public:
|
||||||
TEXT_PRINT_TABBED,
|
TEXT_PRINT_TABBED,
|
||||||
TEXT_PRINTERR,
|
TEXT_PRINTERR,
|
||||||
TEXT_PRINTRAW,
|
TEXT_PRINTRAW,
|
||||||
|
VAR_TO_STR,
|
||||||
|
STR_TO_VAR,
|
||||||
GEN_RANGE,
|
GEN_RANGE,
|
||||||
RESOURCE_LOAD,
|
RESOURCE_LOAD,
|
||||||
INST2DICT,
|
INST2DICT,
|
||||||
|
|
|
@ -1439,7 +1439,6 @@ void OS_Windows::warp_mouse_pos(const Point2& p_to) {
|
||||||
|
|
||||||
SetCursorPos(p.x,p.y);
|
SetCursorPos(p.x,p.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Point2 OS_Windows::get_mouse_pos() const {
|
Point2 OS_Windows::get_mouse_pos() const {
|
||||||
|
|
|
@ -113,7 +113,7 @@ void NavigationPolygon::clear_outlines(){
|
||||||
}
|
}
|
||||||
void NavigationPolygon::make_polygons_from_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);
|
Vector2 outside_point(-1e10,-1e10);
|
||||||
|
|
||||||
|
@ -194,9 +194,9 @@ void NavigationPolygon::make_polygons_from_outlines(){
|
||||||
vertices.resize(0);
|
vertices.resize(0);
|
||||||
|
|
||||||
Map<Vector2,int> points;
|
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;
|
struct Polygon p;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue