More 3D Work
-=-=-=-=-=- -ESM Shadow Mapping for softer and less glitchy shadows -HDR Pipeline (convert to Linear on texture import, convert to SRGB at the end) -Fix to xml parse bug
This commit is contained in:
@ -40,7 +40,9 @@ static const char* _light_param_names[VS::LIGHT_PARAM_MAX]={
|
||||
"params/attenuation",
|
||||
"shadow/darkening",
|
||||
"shadow/z_offset",
|
||||
"shadow/z_slope_scale"
|
||||
"shadow/z_slope_scale",
|
||||
"shadow/esm_multiplier",
|
||||
"shadow/blur_passes"
|
||||
};
|
||||
|
||||
void Light::set_parameter(Parameter p_param, float p_value) {
|
||||
@ -479,6 +481,8 @@ void Light::_bind_methods() {
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "shadow/darkening", PROPERTY_HINT_RANGE, "0,64,0.01"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_SHADOW_DARKENING );
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "shadow/z_offset", PROPERTY_HINT_RANGE, "0,128,0.001"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_SHADOW_Z_OFFSET);
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "shadow/z_slope_scale", PROPERTY_HINT_RANGE, "0,128,0.001"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_SHADOW_Z_SLOPE_SCALE);
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "shadow/esm_multiplier", PROPERTY_HINT_RANGE, "1.0,512.0,0.1"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_SHADOW_ESM_MULTIPLIER);
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::INT, "shadow/blur_passes", PROPERTY_HINT_RANGE, "0,4,1"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_SHADOW_BLUR_PASSES);
|
||||
ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "projector",PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_projector"), _SCS("get_projector"));
|
||||
ADD_PROPERTY( PropertyInfo( Variant::INT, "operator",PROPERTY_HINT_ENUM,"Add,Sub"), _SCS("set_operator"), _SCS("get_operator"));
|
||||
|
||||
@ -511,6 +515,8 @@ Light::Light(VisualServer::LightType p_type) {
|
||||
set_parameter(PARAM_SHADOW_DARKENING,0.0);
|
||||
set_parameter(PARAM_SHADOW_Z_OFFSET,0.05);
|
||||
set_parameter(PARAM_SHADOW_Z_SLOPE_SCALE,0);
|
||||
set_parameter(PARAM_SHADOW_ESM_MULTIPLIER,60);
|
||||
set_parameter(PARAM_SHADOW_BLUR_PASSES,1);
|
||||
|
||||
set_color( COLOR_AMBIENT, Color(0,0,0));
|
||||
set_color( COLOR_DIFFUSE, Color(1,1,1));
|
||||
|
||||
@ -53,6 +53,8 @@ public:
|
||||
PARAM_SHADOW_DARKENING=VisualServer::LIGHT_PARAM_SHADOW_DARKENING,
|
||||
PARAM_SHADOW_Z_OFFSET=VisualServer::LIGHT_PARAM_SHADOW_Z_OFFSET,
|
||||
PARAM_SHADOW_Z_SLOPE_SCALE=VisualServer::LIGHT_PARAM_SHADOW_Z_SLOPE_SCALE,
|
||||
PARAM_SHADOW_ESM_MULTIPLIER=VisualServer::LIGHT_PARAM_SHADOW_ESM_MULTIPLIER,
|
||||
PARAM_SHADOW_BLUR_PASSES=VisualServer::LIGHT_PARAM_SHADOW_BLUR_PASSES,
|
||||
PARAM_MAX=VisualServer::LIGHT_PARAM_MAX
|
||||
};
|
||||
|
||||
|
||||
@ -1078,6 +1078,18 @@ void Node::remove_from_group(const StringName& p_identifier) {
|
||||
|
||||
}
|
||||
|
||||
Array Node::_get_groups() const {
|
||||
|
||||
Array groups;
|
||||
List<GroupInfo> gi;
|
||||
get_groups(&gi);
|
||||
for (List<GroupInfo>::Element *E=gi.front();E;E=E->next()) {
|
||||
groups.push_back(E->get().name);
|
||||
}
|
||||
|
||||
return groups;
|
||||
}
|
||||
|
||||
void Node::get_groups(List<GroupInfo> *p_groups) const {
|
||||
|
||||
const StringName *K=NULL;
|
||||
@ -1712,6 +1724,7 @@ void Node::_bind_methods() {
|
||||
ObjectTypeDB::bind_method(_MD("remove_from_group","group"),&Node::remove_from_group);
|
||||
ObjectTypeDB::bind_method(_MD("is_in_group","group"),&Node::is_in_group);
|
||||
ObjectTypeDB::bind_method(_MD("move_child","child_node:Node","to_pos"),&Node::move_child);
|
||||
ObjectTypeDB::bind_method(_MD("get_groups"),&Node::_get_groups);
|
||||
ObjectTypeDB::bind_method(_MD("raise"),&Node::raise);
|
||||
ObjectTypeDB::bind_method(_MD("set_owner","owner:Node"),&Node::set_owner);
|
||||
ObjectTypeDB::bind_method(_MD("get_owner:Node"),&Node::get_owner);
|
||||
|
||||
@ -125,6 +125,7 @@ private:
|
||||
|
||||
void _duplicate_and_reown(Node* p_new_parent, const Map<Node*,Node*>& p_reown_map) const;
|
||||
Array _get_children() const;
|
||||
Array _get_groups() const;
|
||||
|
||||
friend class SceneMainLoop;
|
||||
|
||||
|
||||
@ -140,6 +140,7 @@
|
||||
#include "scene/resources/mesh_library.h"
|
||||
|
||||
#include "scene/resources/image_path_finder.h"
|
||||
#include "scene/resources/polygon_path_finder.h"
|
||||
|
||||
#include "scene/resources/sample.h"
|
||||
#include "scene/audio/sample_player.h"
|
||||
@ -536,6 +537,7 @@ void register_scene_types() {
|
||||
ObjectTypeDB::register_type<StyleBoxImageMask>();
|
||||
ObjectTypeDB::register_type<Theme>();
|
||||
ObjectTypeDB::register_type<ImagePathFinder>();
|
||||
ObjectTypeDB::register_type<PolygonPathFinder>();
|
||||
ObjectTypeDB::register_type<BitMap>();
|
||||
|
||||
OS::get_singleton()->yield(); //may take time to init
|
||||
|
||||
@ -140,8 +140,8 @@ void Environment::_bind_methods() {
|
||||
ADD_PROPERTYI( PropertyInfo(Variant::REAL,"bcs/brightness",PROPERTY_HINT_RANGE,"0.01,8,0.01"),_SCS("fx_set_param"),_SCS("fx_get_param"), FX_PARAM_BCS_BRIGHTNESS);
|
||||
ADD_PROPERTYI( PropertyInfo(Variant::REAL,"bcs/contrast",PROPERTY_HINT_RANGE,"0.01,8,0.01"),_SCS("fx_set_param"),_SCS("fx_get_param"), FX_PARAM_BCS_CONTRAST);
|
||||
ADD_PROPERTYI( PropertyInfo(Variant::REAL,"bcs/saturation",PROPERTY_HINT_RANGE,"0.01,8,0.01"),_SCS("fx_set_param"),_SCS("fx_get_param"), FX_PARAM_BCS_SATURATION);
|
||||
ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"gamma/enabled"),_SCS("set_enable_fx"),_SCS("is_fx_enabled"), FX_GAMMA);
|
||||
ADD_PROPERTYI( PropertyInfo(Variant::REAL,"gamma/gamma",PROPERTY_HINT_EXP_EASING,"0.01,8,0.01"),_SCS("fx_set_param"),_SCS("fx_get_param"), FX_PARAM_GAMMA);
|
||||
ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"srgb/enabled"),_SCS("set_enable_fx"),_SCS("is_fx_enabled"), FX_SRGB);
|
||||
|
||||
|
||||
|
||||
|
||||
@ -194,7 +194,7 @@ void Environment::_bind_methods() {
|
||||
BIND_CONSTANT( FX_HDR );
|
||||
BIND_CONSTANT( FX_FOG );
|
||||
BIND_CONSTANT( FX_BCS);
|
||||
BIND_CONSTANT( FX_GAMMA );
|
||||
BIND_CONSTANT( FX_SRGB );
|
||||
BIND_CONSTANT( FX_MAX );
|
||||
|
||||
|
||||
@ -226,7 +226,6 @@ void Environment::_bind_methods() {
|
||||
BIND_CONSTANT( FX_PARAM_BCS_BRIGHTNESS );
|
||||
BIND_CONSTANT( FX_PARAM_BCS_CONTRAST );
|
||||
BIND_CONSTANT( FX_PARAM_BCS_SATURATION );
|
||||
BIND_CONSTANT( FX_PARAM_GAMMA );
|
||||
BIND_CONSTANT( FX_PARAM_MAX );
|
||||
|
||||
}
|
||||
@ -269,7 +268,7 @@ Environment::Environment() {
|
||||
fx_set_param(FX_PARAM_BCS_BRIGHTNESS,1.0);
|
||||
fx_set_param(FX_PARAM_BCS_CONTRAST,1.0);
|
||||
fx_set_param(FX_PARAM_BCS_SATURATION,1.0);
|
||||
fx_set_param(FX_PARAM_GAMMA,1.0);
|
||||
|
||||
}
|
||||
Environment::~Environment() {
|
||||
|
||||
|
||||
@ -67,7 +67,7 @@ public:
|
||||
FX_HDR=VS::ENV_FX_HDR,
|
||||
FX_FOG=VS::ENV_FX_FOG,
|
||||
FX_BCS=VS::ENV_FX_BCS,
|
||||
FX_GAMMA=VS::ENV_FX_GAMMA,
|
||||
FX_SRGB=VS::ENV_FX_SRGB,
|
||||
FX_MAX=VS::ENV_FX_MAX,
|
||||
};
|
||||
|
||||
@ -102,7 +102,6 @@ public:
|
||||
FX_PARAM_BCS_BRIGHTNESS=VS::ENV_FX_PARAM_BCS_BRIGHTNESS,
|
||||
FX_PARAM_BCS_CONTRAST=VS::ENV_FX_PARAM_BCS_CONTRAST,
|
||||
FX_PARAM_BCS_SATURATION=VS::ENV_FX_PARAM_BCS_SATURATION,
|
||||
FX_PARAM_GAMMA=VS::ENV_FX_PARAM_GAMMA,
|
||||
FX_PARAM_MAX=VS::ENV_FX_PARAM_MAX
|
||||
};
|
||||
private:
|
||||
|
||||
413
scene/resources/polygon_path_finder.cpp
Normal file
413
scene/resources/polygon_path_finder.cpp
Normal file
@ -0,0 +1,413 @@
|
||||
#include "polygon_path_finder.h"
|
||||
#include "geometry.h"
|
||||
|
||||
|
||||
bool PolygonPathFinder::_is_point_inside(const Vector2& p_point) {
|
||||
|
||||
int crosses=0;
|
||||
|
||||
|
||||
for (Set<Edge>::Element *E=edges.front();E;E=E->next()) {
|
||||
|
||||
|
||||
const Edge& e=E->get();
|
||||
|
||||
Vector2 a = points[e.points[0]].pos;
|
||||
Vector2 b = points[e.points[1]].pos;
|
||||
|
||||
|
||||
if (Geometry::segment_intersects_segment_2d(a,b,p_point,outside_point,NULL)) {
|
||||
crosses++;
|
||||
}
|
||||
}
|
||||
|
||||
return crosses&1;
|
||||
}
|
||||
|
||||
void PolygonPathFinder::setup(const Vector<Vector2>& p_points, const Vector<int>& p_connections) {
|
||||
|
||||
|
||||
ERR_FAIL_COND(p_connections.size()&1);
|
||||
|
||||
points.clear();
|
||||
edges.clear();
|
||||
|
||||
//insert points
|
||||
|
||||
int point_count=p_points.size();
|
||||
points.resize(point_count+2);
|
||||
|
||||
for(int i=0;i<p_points.size();i++) {
|
||||
|
||||
points[i].pos=p_points[i];
|
||||
|
||||
outside_point.x = i==0?p_points[0].x:(MAX( p_points[i].x, outside_point.x ));
|
||||
outside_point.y = i==0?p_points[0].y:(MAX( p_points[i].y, outside_point.y ));
|
||||
}
|
||||
|
||||
outside_point.x+=20.451+Math::randf()*10.2039;
|
||||
outside_point.y+=21.193+Math::randf()*12.5412;
|
||||
|
||||
//insert edges (which are also connetions)
|
||||
|
||||
for(int i=0;i<p_connections.size();i+=2) {
|
||||
|
||||
Edge e(p_connections[i],p_connections[i+1]);
|
||||
ERR_FAIL_INDEX(e.points[0],point_count);
|
||||
ERR_FAIL_INDEX(e.points[1],point_count);
|
||||
points[p_connections[i]].connections.insert(p_connections[i+1]);
|
||||
points[p_connections[i+1]].connections.insert(p_connections[i]);
|
||||
edges.insert(e);
|
||||
}
|
||||
|
||||
|
||||
//fill the remaining connections based on visibility
|
||||
|
||||
for(int i=0;i<point_count;i++) {
|
||||
|
||||
for(int j=i+1;j<point_count;j++) {
|
||||
|
||||
if (edges.has(Edge(i,j)))
|
||||
continue; //if in edge ignore
|
||||
|
||||
Vector2 from=points[i].pos;
|
||||
Vector2 to=points[j].pos;
|
||||
|
||||
if (!_is_point_inside(from*0.5+to*0.5)) //connection between points in inside space
|
||||
continue;
|
||||
|
||||
bool valid=true;
|
||||
|
||||
for (Set<Edge>::Element *E=edges.front();E;E=E->next()) {
|
||||
|
||||
const Edge& e=E->get();
|
||||
if (e.points[0]==i || e.points[1]==i || e.points[0]==j || e.points[1]==j )
|
||||
continue;
|
||||
|
||||
|
||||
Vector2 a = points[e.points[0]].pos;
|
||||
Vector2 b = points[e.points[1]].pos;
|
||||
|
||||
|
||||
if (Geometry::segment_intersects_segment_2d(a,b,from,to,NULL)) {
|
||||
valid=false;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (valid) {
|
||||
points[i].connections.insert(j);
|
||||
points[j].connections.insert(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Vector<Vector2> PolygonPathFinder::find_path(const Vector2& p_from, const Vector2& p_to) {
|
||||
|
||||
Vector<Vector2> path;
|
||||
if (!_is_point_inside(p_from))
|
||||
return path;
|
||||
if (!_is_point_inside(p_to))
|
||||
return path;
|
||||
|
||||
//test direct connection
|
||||
{
|
||||
|
||||
bool can_see_eachother=true;
|
||||
|
||||
for (Set<Edge>::Element *E=edges.front();E;E=E->next()) {
|
||||
|
||||
const Edge& e=E->get();
|
||||
Vector2 a = points[e.points[0]].pos;
|
||||
Vector2 b = points[e.points[1]].pos;
|
||||
|
||||
|
||||
if (Geometry::segment_intersects_segment_2d(a,b,p_from,p_to,NULL)) {
|
||||
can_see_eachother=false;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (can_see_eachother) {
|
||||
|
||||
path.push_back(p_from);
|
||||
path.push_back(p_to);
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
//add to graph
|
||||
|
||||
int aidx = points.size()-2;
|
||||
int bidx = points.size()-1;
|
||||
points[aidx].pos=p_from;
|
||||
points[bidx].pos=p_to;
|
||||
points[aidx].distance=0;
|
||||
points[bidx].distance=0;
|
||||
points[aidx].distance=0;
|
||||
points[bidx].distance=0;
|
||||
|
||||
|
||||
for(int i=0;i<points.size()-2;i++) {
|
||||
|
||||
|
||||
bool valid_a=true;
|
||||
bool valid_b=true;
|
||||
points[i].prev=-1;
|
||||
points[i].distance=0;
|
||||
|
||||
for (Set<Edge>::Element *E=edges.front();E;E=E->next()) {
|
||||
|
||||
const Edge& e=E->get();
|
||||
|
||||
if (e.points[0]==i || e.points[1]==i)
|
||||
continue;
|
||||
|
||||
Vector2 a = points[e.points[0]].pos;
|
||||
Vector2 b = points[e.points[1]].pos;
|
||||
|
||||
if (valid_a) {
|
||||
|
||||
if (Geometry::segment_intersects_segment_2d(a,b,p_from,points[i].pos,NULL)) {
|
||||
valid_a=false;
|
||||
}
|
||||
}
|
||||
|
||||
if (valid_b) {
|
||||
|
||||
if (Geometry::segment_intersects_segment_2d(a,b,p_to,points[i].pos,NULL)) {
|
||||
valid_b=false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!valid_a && !valid_b)
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
if (valid_a) {
|
||||
points[i].connections.insert(aidx);
|
||||
points[aidx].connections.insert(i);
|
||||
}
|
||||
|
||||
if (valid_b) {
|
||||
points[i].connections.insert(bidx);
|
||||
points[bidx].connections.insert(i);
|
||||
}
|
||||
|
||||
}
|
||||
//solve graph
|
||||
|
||||
Set<int> open_list;
|
||||
|
||||
points[aidx].distance=0;
|
||||
points[aidx].prev=aidx;
|
||||
for(Set<int>::Element *E=points[aidx].connections.front();E;E=E->next()) {
|
||||
|
||||
open_list.insert(E->get());
|
||||
points[E->get()].distance=p_from.distance_to(points[E->get()].pos);
|
||||
points[E->get()].prev=aidx;
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool found_route=false;
|
||||
|
||||
while(true) {
|
||||
|
||||
if (open_list.size()==0) {
|
||||
break;
|
||||
}
|
||||
//check open list
|
||||
|
||||
int least_cost_point=-1;
|
||||
float least_cost=1e30;
|
||||
|
||||
//this could be faster (cache previous results)
|
||||
for (Set<int>::Element *E=open_list.front();E;E=E->next()) {
|
||||
|
||||
const Point& p =points[E->get()];
|
||||
float cost = p.distance;
|
||||
cost+=p.pos.distance_to(p_to);
|
||||
if (cost<least_cost) {
|
||||
|
||||
least_cost_point=E->get();
|
||||
least_cost=cost;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Point &np = points[least_cost_point];
|
||||
//open the neighbours for search
|
||||
|
||||
for(Set<int>::Element *E=np.connections.front();E;E=E->next()) {
|
||||
|
||||
Point& p =points[E->get()];
|
||||
float distance = np.pos.distance_to(p.pos) + np.distance;
|
||||
|
||||
if (p.prev!=-1) {
|
||||
//oh this was visited already, can we win the cost?
|
||||
|
||||
if (p.distance>distance) {
|
||||
|
||||
p.prev=least_cost_point; //reasign previous
|
||||
p.distance=distance;
|
||||
}
|
||||
} else {
|
||||
//add to open neighbours
|
||||
|
||||
p.prev=least_cost_point;
|
||||
p.distance=distance;
|
||||
open_list.insert(E->get());
|
||||
|
||||
if (E->get()==bidx) {
|
||||
//oh my reached end! stop algorithm
|
||||
found_route=true;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (found_route)
|
||||
break;
|
||||
|
||||
open_list.erase(least_cost_point);
|
||||
}
|
||||
|
||||
if (found_route) {
|
||||
int at = bidx;
|
||||
path.push_back(points[at].pos);
|
||||
do {
|
||||
at=points[at].prev;
|
||||
path.push_back(points[at].pos);
|
||||
} while (at!=aidx);
|
||||
|
||||
path.invert();;
|
||||
}
|
||||
|
||||
for(int i=0;i<points.size()-2;i++) {
|
||||
|
||||
points[i].connections.erase(aidx);
|
||||
points[i].connections.erase(bidx);
|
||||
points[i].prev=-1;
|
||||
points[i].distance=0;
|
||||
}
|
||||
|
||||
points[aidx].connections.clear();
|
||||
points[aidx].prev=-1;
|
||||
points[aidx].distance=0;
|
||||
points[bidx].connections.clear();
|
||||
points[bidx].prev=-1;
|
||||
points[bidx].distance=0;
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
void PolygonPathFinder::_set_data(const Dictionary& p_data) {
|
||||
|
||||
|
||||
ERR_FAIL_COND(!p_data.has("points"));
|
||||
ERR_FAIL_COND(!p_data.has("connections"));
|
||||
ERR_FAIL_COND(!p_data.has("segments"));
|
||||
|
||||
DVector<Vector2> p=p_data["points"];
|
||||
Array c=p_data["connections"];
|
||||
|
||||
ERR_FAIL_COND(c.size()!=p.size());
|
||||
if (c.size())
|
||||
return;
|
||||
|
||||
int pc = p.size();
|
||||
points.resize(pc+2);
|
||||
|
||||
DVector<Vector2>::Read pr=p.read();
|
||||
for(int i=0;i<pc;i++) {
|
||||
points[i].pos=pr[i];
|
||||
DVector<int> con=c[i];
|
||||
DVector<int>::Read cr=con.read();
|
||||
int cc=con.size();
|
||||
for(int j=0;j<cc;j++) {
|
||||
|
||||
points[i].connections.insert(cr[j]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
DVector<int> segs=p_data["segments"];
|
||||
int sc=segs.size();
|
||||
ERR_FAIL_COND(sc&1);
|
||||
DVector<int>::Read sr = segs.read();
|
||||
for(int i=0;i<sc;i+=2) {
|
||||
|
||||
Edge e(sr[i],sr[i+1]);
|
||||
edges.insert(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Dictionary PolygonPathFinder::_get_data() const{
|
||||
|
||||
Dictionary d;
|
||||
DVector<Vector2> p;
|
||||
DVector<int> ind;
|
||||
Array connections;
|
||||
p.resize(points.size()-2);
|
||||
connections.resize(points.size()-2);
|
||||
ind.resize(edges.size()*2);
|
||||
{
|
||||
DVector<Vector2>::Write wp=p.write();
|
||||
for(int i=0;i<points.size()-2;i++) {
|
||||
wp[i]=points[i].pos;
|
||||
DVector<int> c;
|
||||
c.resize(points[i].connections.size());
|
||||
{
|
||||
DVector<int>::Write cw=c.write();
|
||||
int idx=0;
|
||||
for (Set<int>::Element *E=points[i].connections.front();E;E=E->next()) {
|
||||
cw[idx++]=E->get();
|
||||
}
|
||||
}
|
||||
connections[i]=c;
|
||||
}
|
||||
}
|
||||
{
|
||||
|
||||
DVector<int>::Write iw=ind.write();
|
||||
int idx=0;
|
||||
for (Set<Edge>::Element *E=edges.front();E;E=E->next()) {
|
||||
iw[idx++]=E->get().points[0];
|
||||
iw[idx++]=E->get().points[1];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
d["points"]=p;
|
||||
d["connections"]=connections;
|
||||
d["segments"]=ind;
|
||||
|
||||
return d;
|
||||
|
||||
}
|
||||
|
||||
void PolygonPathFinder::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("setup","points","connections"),&PolygonPathFinder::setup);
|
||||
ObjectTypeDB::bind_method(_MD("find_path","from","to"),&PolygonPathFinder::find_path);
|
||||
ObjectTypeDB::bind_method(_MD("_set_data"),&PolygonPathFinder::_set_data);
|
||||
ObjectTypeDB::bind_method(_MD("_get_data"),&PolygonPathFinder::_get_data);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY,"data",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_data"),_SCS("_get_data"));
|
||||
|
||||
}
|
||||
|
||||
PolygonPathFinder::PolygonPathFinder()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
58
scene/resources/polygon_path_finder.h
Normal file
58
scene/resources/polygon_path_finder.h
Normal file
@ -0,0 +1,58 @@
|
||||
#ifndef POLYGON_PATH_FINDER_H
|
||||
#define POLYGON_PATH_FINDER_H
|
||||
|
||||
#include "resource.h"
|
||||
|
||||
class PolygonPathFinder : public Resource {
|
||||
|
||||
OBJ_TYPE(PolygonPathFinder,Resource);
|
||||
|
||||
struct Point {
|
||||
Vector2 pos;
|
||||
Set<int> connections;
|
||||
float distance;
|
||||
int prev;
|
||||
};
|
||||
|
||||
struct Edge {
|
||||
|
||||
int points[2];
|
||||
|
||||
_FORCE_INLINE_ bool operator<(const Edge& p_edge) const {
|
||||
|
||||
if (points[0]==p_edge.points[0])
|
||||
return points[1]<p_edge.points[1];
|
||||
else
|
||||
return points[0]<p_edge.points[0];
|
||||
}
|
||||
|
||||
Edge(int a=0, int b=0) {
|
||||
|
||||
if (a>b) {
|
||||
SWAP(a,b);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Vector2 outside_point;
|
||||
|
||||
Vector<Point> points;
|
||||
Set<Edge> edges;
|
||||
|
||||
bool _is_point_inside(const Vector2& p_point);
|
||||
|
||||
void _set_data(const Dictionary& p_data);
|
||||
Dictionary _get_data() const;
|
||||
protected:
|
||||
|
||||
static void _bind_methods();
|
||||
public:
|
||||
|
||||
|
||||
void setup(const Vector<Vector2>& p_points, const Vector<int>& p_connections);
|
||||
Vector<Vector2> find_path(const Vector2& p_from, const Vector2& p_to);
|
||||
|
||||
PolygonPathFinder();
|
||||
};
|
||||
|
||||
#endif // POLYGON_PATH_FINDER_H
|
||||
Reference in New Issue
Block a user