summaryrefslogtreecommitdiff
path: root/scene
diff options
context:
space:
mode:
Diffstat (limited to 'scene')
-rw-r--r--scene/3d/navigation.cpp497
-rw-r--r--scene/3d/navigation.h132
-rw-r--r--scene/3d/navigation_agent.cpp5
-rw-r--r--scene/3d/navigation_agent.h10
-rw-r--r--scene/3d/navigation_mesh.cpp237
-rw-r--r--scene/3d/navigation_mesh.h68
-rw-r--r--scene/3d/visual_instance.cpp17
-rw-r--r--scene/3d/visual_instance.h4
-rw-r--r--scene/animation/animation_tree_player.cpp5
-rw-r--r--scene/gui/text_edit.cpp119
-rw-r--r--scene/gui/text_edit.h7
-rw-r--r--scene/main/scene_main_loop.cpp1
-rw-r--r--scene/register_scene_types.cpp6
-rw-r--r--scene/resources/animation.cpp16
-rw-r--r--scene/resources/animation.h4
-rw-r--r--scene/resources/baked_light.cpp161
-rw-r--r--scene/resources/baked_light.h26
17 files changed, 1238 insertions, 77 deletions
diff --git a/scene/3d/navigation.cpp b/scene/3d/navigation.cpp
new file mode 100644
index 0000000000..4b0d233fbe
--- /dev/null
+++ b/scene/3d/navigation.cpp
@@ -0,0 +1,497 @@
+#include "navigation.h"
+
+void Navigation::_navmesh_link(int p_id) {
+
+ ERR_FAIL_COND(!navmesh_map.has(p_id));
+ NavMesh &nm=navmesh_map[p_id];
+ ERR_FAIL_COND(nm.linked);
+
+ print_line("LINK");
+
+ DVector<Vector3> vertices=nm.navmesh->get_vertices();
+ int len = vertices.size();
+ if (len==0)
+ return;
+
+ DVector<Vector3>::Read r=vertices.read();
+
+ for(int i=0;i<nm.navmesh->get_polygon_count();i++) {
+
+ //build
+
+ List<Polygon>::Element *P=nm.polygons.push_back(Polygon());
+ Polygon &p=P->get();
+
+ Vector<int> poly = nm.navmesh->get_polygon(i);
+ int plen=poly.size();
+ const int *indices=poly.ptr();
+ bool valid=true;
+ p.edges.resize(plen);
+
+ Vector3 center;
+
+ for(int j=0;j<plen;j++) {
+
+ int idx = indices[j];
+ if (idx<0 || idx>=len) {
+ valid=false;
+ break;
+ }
+
+ Polygon::Edge e;
+ Vector3 ep=nm.xform.xform(r[idx]);
+ center+=ep;
+ e.point=_get_point(ep);
+ p.edges[j]=e;
+ }
+
+ if (!valid) {
+ nm.polygons.pop_back();
+ ERR_CONTINUE(!valid);
+ continue;
+ }
+
+ p.center=center/plen;
+
+ //connect
+
+ for(int j=0;j<plen;j++) {
+
+ int next = (j+1)%plen;
+ EdgeKey ek(p.edges[j].point,p.edges[next].point);
+
+ Map<EdgeKey,Connection>::Element *C=connections.find(ek);
+ if (!C) {
+
+ Connection c;
+ c.A=&p;
+ c.A_edge=j;
+ c.B=NULL;
+ c.B_edge=-1;
+ connections[ek]=c;
+ } else {
+
+ if (C->get().B!=NULL) {
+ print_line(String()+_get_vertex(ek.a)+" -> "+_get_vertex(ek.b));
+ }
+ ERR_CONTINUE(C->get().B!=NULL); //wut
+
+ C->get().B=&p;
+ C->get().B_edge=j;
+ C->get().A->edges[C->get().A_edge].C=&p;
+ C->get().A->edges[C->get().A_edge].C_edge=j;;
+ p.edges[j].C=C->get().A;
+ p.edges[j].C_edge=C->get().A_edge;
+ //connection successful.
+ }
+ }
+ }
+
+ nm.linked=true;
+
+}
+
+
+void Navigation::_navmesh_unlink(int p_id) {
+
+ ERR_FAIL_COND(!navmesh_map.has(p_id));
+ NavMesh &nm=navmesh_map[p_id];
+ ERR_FAIL_COND(!nm.linked);
+
+ print_line("UNLINK");
+
+ for (List<Polygon>::Element *E=nm.polygons.front();E;E=E->next()) {
+
+
+ Polygon &p=E->get();
+
+ int ec = p.edges.size();
+ Polygon::Edge *edges=p.edges.ptr();
+
+ for(int i=0;i<ec;i++) {
+ int next = (i+1)%ec;
+
+ EdgeKey ek(edges[i].point,edges[next].point);
+ Map<EdgeKey,Connection>::Element *C=connections.find(ek);
+ ERR_CONTINUE(!C);
+ if (C->get().B) {
+ //disconnect
+
+ C->get().B->edges[C->get().B_edge].C=NULL;
+ C->get().B->edges[C->get().B_edge].C_edge=-1;
+ C->get().A->edges[C->get().A_edge].C=NULL;
+ C->get().A->edges[C->get().A_edge].C_edge=-1;
+
+ if (C->get().A==&E->get()) {
+
+ C->get().A=C->get().B;
+ C->get().A_edge=C->get().B_edge;
+ }
+ C->get().B=NULL;
+ C->get().B_edge=-1;
+
+ } else {
+ connections.erase(C);
+ //erase
+ }
+ }
+ }
+
+ nm.polygons.clear();
+
+ nm.linked=false;
+
+
+}
+
+
+int Navigation::navmesh_create(const Ref<NavigationMesh>& p_mesh,const Transform& p_xform) {
+
+ int id = last_id++;
+ NavMesh nm;
+ nm.linked=false;
+ nm.navmesh=p_mesh;
+ nm.xform=p_xform;
+ navmesh_map[id]=nm;
+
+ _navmesh_link(id);
+
+ return id;
+}
+
+void Navigation::navmesh_set_transform(int p_id, const Transform& p_xform){
+
+ ERR_FAIL_COND(!navmesh_map.has(p_id));
+ NavMesh &nm=navmesh_map[p_id];
+ if (nm.xform==p_xform)
+ return; //bleh
+ _navmesh_unlink(p_id);
+ nm.xform=p_xform;
+ _navmesh_link(p_id);
+
+
+
+}
+void Navigation::navmesh_remove(int p_id){
+
+ ERR_FAIL_COND(!navmesh_map.has(p_id));
+ _navmesh_unlink(p_id);
+ navmesh_map.erase(p_id);
+
+}
+
+Vector<Vector3> Navigation::get_simple_path(const Vector3& p_start, const Vector3& p_end) {
+
+
+ Polygon *begin_poly=NULL;
+ Polygon *end_poly=NULL;
+ Vector3 begin_point;
+ Vector3 end_point;
+ float begin_d=1e20;
+ float end_d=1e20;
+
+
+ for (Map<int,NavMesh>::Element*E=navmesh_map.front();E;E=E->next()) {
+
+ if (!E->get().linked)
+ continue;
+ for(List<Polygon>::Element *F=E->get().polygons.front();F;F=F->next()) {
+
+ Polygon &p=F->get();
+ for(int i=2;i<p.edges.size();i++) {
+
+ Face3 f(_get_vertex(p.edges[0].point),_get_vertex(p.edges[i-1].point),_get_vertex(p.edges[i].point));
+ Vector3 spoint = f.get_closest_point_to(p_start);
+ float dpoint = spoint.distance_to(p_start);
+ if (dpoint<begin_d) {
+ begin_d=dpoint;
+ begin_poly=&p;
+ begin_point=spoint;
+ }
+
+ spoint = f.get_closest_point_to(p_end);
+ dpoint = spoint.distance_to(p_end);
+ if (dpoint<end_d) {
+ end_d=dpoint;
+ end_poly=&p;
+ end_point=spoint;
+ }
+ }
+
+ p.prev_edge=-1;
+ }
+ }
+
+ if (!begin_poly || !end_poly) {
+
+ //print_line("No Path Path");
+ return Vector<Vector3>(); //no path
+ }
+
+ if (begin_poly==end_poly) {
+
+ Vector<Vector3> path;
+ path.resize(2);
+ path[0]=begin_point;
+ path[1]=end_point;
+ //print_line("Direct Path");
+ return path;
+ }
+
+
+ bool found_route=false;
+
+ List<Polygon*> open_list;
+
+ for(int i=0;i<begin_poly->edges.size();i++) {
+
+ if (begin_poly->edges[i].C) {
+
+ begin_poly->edges[i].C->prev_edge=begin_poly->edges[i].C_edge;
+ begin_poly->edges[i].C->distance=begin_poly->center.distance_to(begin_poly->edges[i].C->center);
+ open_list.push_back(begin_poly->edges[i].C);
+
+ if (begin_poly->edges[i].C==end_poly) {
+ found_route=true;
+ }
+ }
+ }
+
+
+ while(!found_route) {
+
+ if (open_list.size()==0) {
+ // print_line("NOU OPEN LIST");
+ break;
+ }
+ //check open list
+
+ List<Polygon*>::Element *least_cost_poly=NULL;
+ float least_cost=1e30;
+
+ //this could be faster (cache previous results)
+ for (List<Polygon*>::Element *E=open_list.front();E;E=E->next()) {
+
+ Polygon *p=E->get();
+
+
+ float cost=p->distance;
+ cost+=p->center.distance_to(end_point);
+
+ if (cost<least_cost) {
+
+ least_cost_poly=E;
+ least_cost=cost;
+ }
+ }
+
+
+ Polygon *p=least_cost_poly->get();
+ //open the neighbours for search
+
+ for(int i=0;i<p->edges.size();i++) {
+
+
+ Polygon::Edge &e=p->edges[i];
+
+ if (!e.C)
+ continue;
+
+ float distance = p->center.distance_to(e.C->center) + p->distance;
+
+ if (e.C->prev_edge!=-1) {
+ //oh this was visited already, can we win the cost?
+
+ if (e.C->distance>distance) {
+
+ e.C->prev_edge=e.C_edge;
+ e.C->distance=distance;
+ }
+ } else {
+ //add to open neighbours
+
+ e.C->prev_edge=e.C_edge;
+ e.C->distance=distance;
+ open_list.push_back(e.C);
+
+ if (e.C==end_poly) {
+ //oh my reached end! stop algorithm
+ found_route=true;
+ break;
+
+ }
+
+ }
+ }
+
+ if (found_route)
+ break;
+
+ open_list.erase(least_cost_poly);
+ }
+
+ if (found_route) {
+
+ //use midpoints for now
+ Polygon *p=end_poly;
+ Vector<Vector3> path;
+ path.push_back(end_point);
+ while(true) {
+ int prev = p->prev_edge;
+ int prev_n = (p->prev_edge+1)%p->edges.size();
+ Vector3 point = (_get_vertex(p->edges[prev].point) + _get_vertex(p->edges[prev_n].point))*0.5;
+ path.push_back(point);
+ p = p->edges[prev].C;
+ if (p==begin_poly)
+ break;
+ }
+
+ path.push_back(begin_point);
+
+
+ path.invert();;
+
+ return path;
+ }
+
+
+ return Vector<Vector3>();
+
+}
+
+Vector3 Navigation::get_closest_point_to_segment(const Vector3& p_from,const Vector3& p_to) {
+
+
+ bool use_collision=false;
+ Vector3 closest_point;
+ float closest_point_d=1e20;
+
+ for (Map<int,NavMesh>::Element*E=navmesh_map.front();E;E=E->next()) {
+
+ if (!E->get().linked)
+ continue;
+ for(List<Polygon>::Element *F=E->get().polygons.front();F;F=F->next()) {
+
+ Polygon &p=F->get();
+ for(int i=2;i<p.edges.size();i++) {
+
+ Face3 f(_get_vertex(p.edges[0].point),_get_vertex(p.edges[i-1].point),_get_vertex(p.edges[i].point));
+ Vector3 inters;
+ if (f.intersects_segment(p_from,p_to,&inters)) {
+
+ if (!use_collision) {
+ closest_point=inters;
+ use_collision=true;
+ closest_point_d=p_from.distance_to(inters);
+ } else if (closest_point_d > inters.distance_to(p_from)){
+
+ closest_point=inters;
+ closest_point_d=p_from.distance_to(inters);
+ }
+ }
+ }
+
+ if (!use_collision) {
+
+ for(int i=0;i<p.edges.size();i++) {
+
+ Vector3 a,b;
+
+ Geometry::get_closest_points_between_segments(p_from,p_to,_get_vertex(p.edges[i].point),_get_vertex(p.edges[(i+1)%p.edges.size()].point),a,b);
+
+ float d = a.distance_to(b);
+ if (d<closest_point_d) {
+
+ closest_point_d=d;
+ closest_point=b;
+ }
+
+ }
+ }
+ }
+ }
+
+ return closest_point;
+}
+
+Vector3 Navigation::get_closest_point(const Vector3& p_point) {
+
+ Vector3 closest_point;
+ float closest_point_d=1e20;
+
+ for (Map<int,NavMesh>::Element*E=navmesh_map.front();E;E=E->next()) {
+
+ if (!E->get().linked)
+ continue;
+ for(List<Polygon>::Element *F=E->get().polygons.front();F;F=F->next()) {
+
+ Polygon &p=F->get();
+ for(int i=2;i<p.edges.size();i++) {
+
+ Face3 f(_get_vertex(p.edges[0].point),_get_vertex(p.edges[i-1].point),_get_vertex(p.edges[i].point));
+ Vector3 inters = f.get_closest_point_to(p_point);
+ float d = inters.distance_to(p_point);
+ if (d<closest_point_d) {
+ closest_point=inters;
+ closest_point_d=d;
+ }
+ }
+ }
+ }
+
+ return closest_point;
+
+}
+
+Vector3 Navigation::get_closest_point_normal(const Vector3& p_point){
+
+ Vector3 closest_point;
+ Vector3 closest_normal;
+ float closest_point_d=1e20;
+
+ for (Map<int,NavMesh>::Element*E=navmesh_map.front();E;E=E->next()) {
+
+ if (!E->get().linked)
+ continue;
+ for(List<Polygon>::Element *F=E->get().polygons.front();F;F=F->next()) {
+
+ Polygon &p=F->get();
+ for(int i=2;i<p.edges.size();i++) {
+
+ Face3 f(_get_vertex(p.edges[0].point),_get_vertex(p.edges[i-1].point),_get_vertex(p.edges[i].point));
+ Vector3 inters = f.get_closest_point_to(p_point);
+ float d = inters.distance_to(p_point);
+ if (d<closest_point_d) {
+ closest_point=inters;
+ closest_point_d=d;
+ closest_normal=f.get_plane().normal;
+ }
+ }
+ }
+ }
+
+ return closest_normal;
+
+}
+
+
+void Navigation::_bind_methods() {
+
+ ObjectTypeDB::bind_method(_MD("navmesh_create","mesh:NavigationMesh","xform"),&Navigation::navmesh_create);
+ ObjectTypeDB::bind_method(_MD("navmesh_set_transform","id","xform"),&Navigation::navmesh_set_transform);
+ ObjectTypeDB::bind_method(_MD("navmesh_remove","id"),&Navigation::navmesh_remove);
+
+ ObjectTypeDB::bind_method(_MD("get_simple_path","start","end"),&Navigation::get_simple_path);
+ ObjectTypeDB::bind_method(_MD("get_closest_point_to_segment","start","end"),&Navigation::get_closest_point_to_segment);
+ ObjectTypeDB::bind_method(_MD("get_closest_point","to_point"),&Navigation::get_closest_point);
+ ObjectTypeDB::bind_method(_MD("get_closest_point_normal","to_point"),&Navigation::get_closest_point_normal);
+
+}
+
+Navigation::Navigation() {
+
+ ERR_FAIL_COND( sizeof(Point)!=8 );
+ cell_size=0.01; //one centimeter
+ last_id=1;
+}
+
diff --git a/scene/3d/navigation.h b/scene/3d/navigation.h
new file mode 100644
index 0000000000..40f474858c
--- /dev/null
+++ b/scene/3d/navigation.h
@@ -0,0 +1,132 @@
+#ifndef NAVIGATION_H
+#define NAVIGATION_H
+
+#include "scene/3d/spatial.h"
+#include "scene/3d/navigation_mesh.h"
+
+class Navigation : public Spatial {
+
+ OBJ_TYPE( Navigation, Spatial);
+
+
+ union Point {
+
+ struct {
+ int64_t x:21;
+ int64_t y:22;
+ int64_t z:21;
+ };
+
+ uint64_t key;
+ bool operator<(const Point& p_key) const { return key < p_key.key; }
+ };
+
+
+ struct EdgeKey {
+
+ Point a;
+ Point b;
+
+ bool operator<(const EdgeKey& p_key) const {
+ return (a.key==p_key.a.key)?(b.key<p_key.b.key):(a.key<p_key.a.key);
+ };
+
+ EdgeKey(const Point& p_a=Point(),const Point& p_b=Point()) {
+ a=p_a;
+ b=p_b;
+ if (a.key > b.key) {
+ SWAP(a,b);
+ }
+ }
+ };
+
+
+
+ struct Polygon {
+
+ struct Edge {
+ Point point;
+ Polygon *C; //connection
+ int C_edge;
+ Edge() { C=NULL; C_edge=-1; }
+ };
+
+ Vector<Edge> edges;
+
+ Vector3 center;
+
+ float distance;
+ int prev_edge;
+ };
+
+
+ struct Connection {
+
+ Polygon *A;
+ int A_edge;
+ Polygon *B;
+ int B_edge;
+ Connection() { A=NULL; B=NULL; A_edge=-1; B_edge=-1;}
+ };
+
+ Map<EdgeKey,Connection> connections;
+
+
+ struct NavMesh {
+
+ Transform xform;
+ bool linked;
+ Ref<NavigationMesh> navmesh;
+ List<Polygon> polygons;
+
+ };
+
+
+
+ _FORCE_INLINE_ Point _get_point(const Vector3& p_pos) const {
+
+ int x = int(Math::floor(p_pos.x/cell_size));
+ int y = int(Math::floor(p_pos.y/cell_size));
+ int z = int(Math::floor(p_pos.z/cell_size));
+
+ Point p;
+ p.key=0;
+ p.x=x;
+ p.y=y;
+ p.z=z;
+ return p;
+
+ }
+
+ _FORCE_INLINE_ Vector3 _get_vertex(const Point& p_point) const {
+
+ return Vector3(p_point.x,p_point.y,p_point.z)*cell_size;
+ }
+
+ void _navmesh_link(int p_id);
+ void _navmesh_unlink(int p_id);
+
+ float cell_size;
+ Map<int,NavMesh> navmesh_map;
+ int last_id;
+
+protected:
+
+ static void _bind_methods();
+
+public:
+
+ //API should be as dynamic as possible
+ int navmesh_create(const Ref<NavigationMesh>& p_mesh,const Transform& p_xform);
+ void navmesh_set_transform(int p_id, const Transform& p_xform);
+ void navmesh_remove(int p_id);
+
+ Vector<Vector3> get_simple_path(const Vector3& p_start, const Vector3& p_end);
+ Vector3 get_closest_point_to_segment(const Vector3& p_from,const Vector3& p_to);
+ Vector3 get_closest_point(const Vector3& p_point);
+ Vector3 get_closest_point_normal(const Vector3& p_point);
+
+ Navigation();
+};
+
+#endif // NAVIGATION_H
diff --git a/scene/3d/navigation_agent.cpp b/scene/3d/navigation_agent.cpp
new file mode 100644
index 0000000000..9b304e45ec
--- /dev/null
+++ b/scene/3d/navigation_agent.cpp
@@ -0,0 +1,5 @@
+#include "navigation_agent.h"
+
+NavigationAgent::NavigationAgent()
+{
+}
diff --git a/scene/3d/navigation_agent.h b/scene/3d/navigation_agent.h
new file mode 100644
index 0000000000..baceb693a5
--- /dev/null
+++ b/scene/3d/navigation_agent.h
@@ -0,0 +1,10 @@
+#ifndef NAVIGATION_AGENT_H
+#define NAVIGATION_AGENT_H
+
+class NavigationAgent
+{
+public:
+ NavigationAgent();
+};
+
+#endif // NAVIGATION_AGENT_H
diff --git a/scene/3d/navigation_mesh.cpp b/scene/3d/navigation_mesh.cpp
new file mode 100644
index 0000000000..cf2e22a573
--- /dev/null
+++ b/scene/3d/navigation_mesh.cpp
@@ -0,0 +1,237 @@
+#include "navigation_mesh.h"
+#include "navigation.h"
+
+
+void NavigationMesh::create_from_mesh(const Ref<Mesh>& p_mesh) {
+
+
+ vertices=DVector<Vector3>();
+ clear_polygons();
+
+ for(int i=0;i<p_mesh->get_surface_count();i++) {
+
+ if (p_mesh->surface_get_primitive_type(i)!=Mesh::PRIMITIVE_TRIANGLES)
+ continue;
+ Array arr = p_mesh->surface_get_arrays(i);
+ DVector<Vector3> varr = arr[Mesh::ARRAY_VERTEX];
+ DVector<int> iarr = arr[Mesh::ARRAY_INDEX];
+ if (varr.size()==0 || iarr.size()==0)
+ continue;
+
+ int from = vertices.size();
+ vertices.append_array(varr);
+ int rlen = iarr.size();
+ DVector<int>::Read r = iarr.read();
+
+ for(int j=0;j<rlen;j+=3) {
+ Vector<int> vi;
+ vi.resize(3);
+ vi[0]=r[j+0]+from;
+ vi[1]=r[j+1]+from;
+ vi[2]=r[j+2]+from;
+
+ add_polygon(vi);
+ }
+ }
+}
+
+void NavigationMesh::set_vertices(const DVector<Vector3>& p_vertices) {
+
+ vertices=p_vertices;
+}
+
+DVector<Vector3> NavigationMesh::get_vertices() const{
+
+ return vertices;
+}
+
+
+void NavigationMesh::_set_polygons(const Array& p_array) {
+
+ polygons.resize(p_array.size());
+ for(int i=0;i<p_array.size();i++) {
+ polygons[i].indices=p_array[i];
+ }
+}
+
+Array NavigationMesh::_get_polygons() const {
+
+ Array ret;
+ ret.resize(polygons.size());
+ for(int i=0;i<ret.size();i++) {
+ ret[i]=polygons[i].indices;
+ }
+
+ return ret;
+}
+
+
+void NavigationMesh::add_polygon(const Vector<int>& p_polygon){
+
+ Polygon polygon;
+ polygon.indices=p_polygon;
+ polygons.push_back(polygon);
+
+}
+int NavigationMesh::get_polygon_count() const{
+
+ return polygons.size();
+}
+Vector<int> NavigationMesh::get_polygon(int p_idx){
+
+ ERR_FAIL_INDEX_V(p_idx,polygons.size(),Vector<int>());
+ return polygons[p_idx].indices;
+}
+void NavigationMesh::clear_polygons(){
+
+ polygons.clear();
+}
+
+void NavigationMesh::_bind_methods() {
+
+ ObjectTypeDB::bind_method(_MD("set_vertices","vertices"),&NavigationMesh::set_vertices);
+ ObjectTypeDB::bind_method(_MD("get_vertices"),&NavigationMesh::get_vertices);
+
+ ObjectTypeDB::bind_method(_MD("add_polygon","polygon"),&NavigationMesh::add_polygon);
+ ObjectTypeDB::bind_method(_MD("get_polygon_count"),&NavigationMesh::get_polygon_count);
+ ObjectTypeDB::bind_method(_MD("get_polygon","idx"),&NavigationMesh::get_polygon);
+ ObjectTypeDB::bind_method(_MD("clear_polygons"),&NavigationMesh::clear_polygons);
+
+ ObjectTypeDB::bind_method(_MD("_set_polygons","polygons"),&NavigationMesh::_set_polygons);
+ ObjectTypeDB::bind_method(_MD("_get_polygons"),&NavigationMesh::_get_polygons);
+
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3_ARRAY,"vertices",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("set_vertices"),_SCS("get_vertices"));
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY,"polygons",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_polygons"),_SCS("_get_polygons"));
+}
+
+NavigationMesh::NavigationMesh() {
+
+}
+
+void NavigationMeshInstance::set_enabled(bool p_enabled) {
+
+ if (enabled==p_enabled)
+ return;
+ enabled=p_enabled;
+
+ if (!is_inside_scene())
+ return;
+
+ if (!enabled) {
+
+ if (nav_id!=-1) {
+ navigation->navmesh_remove(nav_id);
+ nav_id=-1;
+ }
+ } else {
+
+ if (navigation) {
+
+ if (navmesh.is_valid()) {
+
+ nav_id = navigation->navmesh_create(navmesh,get_relative_transform(navigation));
+ }
+ }
+
+ }
+
+ update_gizmo();
+}
+
+bool NavigationMeshInstance::is_enabled() const {
+
+
+ return enabled;
+}
+
+
+/////////////////////////////
+
+
+void NavigationMeshInstance::_notification(int p_what) {
+
+
+ switch(p_what) {
+ case NOTIFICATION_ENTER_SCENE: {
+
+ Spatial *c=this;
+ while(c) {
+
+ navigation=c->cast_to<Navigation>();
+ if (navigation) {
+
+ if (enabled && navmesh.is_valid()) {
+
+ nav_id = navigation->navmesh_create(navmesh,get_relative_transform(navigation));
+ }
+ break;
+ }
+
+ c=c->get_parent_spatial();
+ }
+
+ } break;
+ case NOTIFICATION_TRANSFORM_CHANGED: {
+
+ if (navigation && nav_id!=-1) {
+ navigation->navmesh_set_transform(nav_id,get_relative_transform(navigation));
+ }
+
+ } break;
+ case NOTIFICATION_EXIT_SCENE: {
+
+ if (navigation) {
+
+ if (nav_id!=-1) {
+ navigation->navmesh_remove(nav_id);
+ nav_id=-1;
+ }
+ }
+ navigation=NULL;
+ } break;
+ }
+}
+
+
+void NavigationMeshInstance::set_navigation_mesh(const Ref<NavigationMesh>& p_navmesh) {
+
+ if (p_navmesh==navmesh)
+ return;
+
+ if (navigation && nav_id!=-1) {
+ navigation->navmesh_remove(nav_id);
+ nav_id=-1;
+ }
+ navmesh=p_navmesh;
+
+ if (navigation && navmesh.is_valid() && enabled) {
+ nav_id = navigation->navmesh_create(navmesh,get_relative_transform(navigation));
+ }
+ update_gizmo();
+
+}
+
+Ref<NavigationMesh> NavigationMeshInstance::get_navigation_mesh() const{
+
+ return navmesh;
+}
+
+void NavigationMeshInstance::_bind_methods() {
+
+ ObjectTypeDB::bind_method(_MD("set_navigation_mesh","navmesh"),&NavigationMeshInstance::set_navigation_mesh);
+ ObjectTypeDB::bind_method(_MD("get_navigation_mesh"),&NavigationMeshInstance::get_navigation_mesh);
+
+ ObjectTypeDB::bind_method(_MD("set_enabled","enabled"),&NavigationMeshInstance::set_enabled);
+ ObjectTypeDB::bind_method(_MD("is_enabled"),&NavigationMeshInstance::is_enabled);
+
+ ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"navmesh",PROPERTY_HINT_RESOURCE_TYPE,"NavigationMesh"),_SCS("set_navigation_mesh"),_SCS("get_navigation_mesh"));
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"enabled"),_SCS("set_enabled"),_SCS("is_enabled"));
+}
+
+NavigationMeshInstance::NavigationMeshInstance() {
+
+ navigation=NULL;
+ nav_id=-1;
+ enabled=true;
+
+}
diff --git a/scene/3d/navigation_mesh.h b/scene/3d/navigation_mesh.h
new file mode 100644
index 0000000000..fccf405f9d
--- /dev/null
+++ b/scene/3d/navigation_mesh.h
@@ -0,0 +1,68 @@
+#ifndef NAVIGATION_MESH_H
+#define NAVIGATION_MESH_H
+
+#include "scene/3d/spatial.h"
+#include "scene/resources/mesh.h"
+
+
+class NavigationMesh : public Resource {
+
+ OBJ_TYPE( NavigationMesh, Resource );
+
+ DVector<Vector3> vertices;
+ struct Polygon {
+ Vector<int> indices;
+ };
+ Vector<Polygon> polygons;
+
+protected:
+
+ static void _bind_methods();
+
+ void _set_polygons(const Array& p_array);
+ Array _get_polygons() const;
+public:
+
+ void create_from_mesh(const Ref<Mesh>& p_mesh);
+
+ void set_vertices(const DVector<Vector3>& p_vertices);
+ DVector<Vector3> get_vertices() const;
+
+ void add_polygon(const Vector<int>& p_polygon);
+ int get_polygon_count() const;
+ Vector<int> get_polygon(int p_idx);
+ void clear_polygons();
+
+ NavigationMesh();
+};
+
+
+class Navigation;
+
+class NavigationMeshInstance : public Spatial {
+
+ OBJ_TYPE(NavigationMeshInstance,Spatial);
+
+ bool enabled;
+ int nav_id;
+ Navigation *navigation;
+ Ref<NavigationMesh> navmesh;
+protected:
+
+ void _notification(int p_what);
+ static void _bind_methods();
+public:
+
+
+
+ void set_enabled(bool p_enabled);
+ bool is_enabled() const;
+
+ void set_navigation_mesh(const Ref<NavigationMesh>& p_navmesh);
+ Ref<NavigationMesh> get_navigation_mesh() const;
+
+ NavigationMeshInstance();
+};
+
+
+#endif // NAVIGATION_MESH_H
diff --git a/scene/3d/visual_instance.cpp b/scene/3d/visual_instance.cpp
index 625da9b093..d6c46f9bf6 100644
--- a/scene/3d/visual_instance.cpp
+++ b/scene/3d/visual_instance.cpp
@@ -276,6 +276,18 @@ bool GeometryInstance::get_flag(Flags p_flag) const{
}
+void GeometryInstance::set_baked_light_texture_id(int p_id) {
+
+ baked_light_texture_id=p_id;
+ VS::get_singleton()->instance_geometry_set_baked_light_texture_index(get_instance(),baked_light_texture_id);
+
+}
+
+int GeometryInstance::get_baked_light_texture_id() const{
+
+ return baked_light_texture_id;
+}
+
void GeometryInstance::_bind_methods() {
@@ -291,6 +303,9 @@ void GeometryInstance::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_draw_range_end","mode"), &GeometryInstance::set_draw_range_end);
ObjectTypeDB::bind_method(_MD("get_draw_range_end"), &GeometryInstance::get_draw_range_end);
+ ObjectTypeDB::bind_method(_MD("set_baked_light_texture_id","id"), &GeometryInstance::set_baked_light_texture_id);
+ ObjectTypeDB::bind_method(_MD("get_baked_light_texture_id"), &GeometryInstance::get_baked_light_texture_id);
+
ObjectTypeDB::bind_method(_MD("_baked_light_changed"), &GeometryInstance::_baked_light_changed);
ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "geometry/visible"), _SCS("set_flag"), _SCS("get_flag"),FLAG_VISIBLE);
@@ -304,6 +319,7 @@ void GeometryInstance::_bind_methods() {
ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "geometry/depth_scale"), _SCS("set_flag"), _SCS("get_flag"),FLAG_DEPH_SCALE);
ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "geometry/visible_in_all_rooms"), _SCS("set_flag"), _SCS("get_flag"),FLAG_VISIBLE_IN_ALL_ROOMS);
ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "geometry/use_baked_light"), _SCS("set_flag"), _SCS("get_flag"),FLAG_USE_BAKED_LIGHT);
+ ADD_PROPERTY( PropertyInfo( Variant::INT, "geometry/baked_light_tex_id"), _SCS("set_baked_light_texture_id"), _SCS("get_baked_light_texture_id"));
ADD_SIGNAL( MethodInfo("visibility_changed"));
@@ -329,6 +345,7 @@ GeometryInstance::GeometryInstance() {
flags[FLAG_DEPH_SCALE]=false;
flags[FLAG_VISIBLE_IN_ALL_ROOMS]=false;
baked_light_instance=NULL;
+ baked_light_texture_id=0;
}
diff --git a/scene/3d/visual_instance.h b/scene/3d/visual_instance.h
index 1cf96d5d9e..4b4e1e391b 100644
--- a/scene/3d/visual_instance.h
+++ b/scene/3d/visual_instance.h
@@ -106,6 +106,7 @@ private:
float draw_end;
void _find_baked_light();
BakedLightInstance *baked_light_instance;
+ int baked_light_texture_id;
void _baked_light_changed();
protected:
@@ -126,6 +127,9 @@ public:
void set_material_override(const Ref<Material>& p_material);
Ref<Material> get_material_override() const;
+ void set_baked_light_texture_id(int p_id);
+ int get_baked_light_texture_id() const;
+
GeometryInstance();
};
diff --git a/scene/animation/animation_tree_player.cpp b/scene/animation/animation_tree_player.cpp
index bd124746ba..2d1821bc5c 100644
--- a/scene/animation/animation_tree_player.cpp
+++ b/scene/animation/animation_tree_player.cpp
@@ -1046,8 +1046,9 @@ void AnimationTreePlayer::timescale_node_set_scale(const StringName& p_node,floa
void AnimationTreePlayer::timeseek_node_seek(const StringName& p_node,float p_pos) {
-// GET_NODE( NODE_TIMESEEK, TimeSeekNode );
-//hmm
+ GET_NODE( NODE_TIMESEEK, TimeSeekNode );
+ n->seek_pos=p_pos;
+
}
void AnimationTreePlayer::transition_node_set_input_count(const StringName& p_node, int p_inputs) {
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 3566c1bfc4..0b797e7df3 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -1354,13 +1354,13 @@ void TextEdit::_input_event(const InputEvent& p_input_event) {
cursor_set_column(cc);
- } else if (cursor.column==0) {
+ } else if (cursor.column==0) {
if (cursor.line>0) {
cursor_set_line(cursor.line-1);
cursor_set_column(text[cursor.line].length());
}
- } else {
+ } else {
cursor_set_column(cursor_get_column()-1);
}
@@ -1394,13 +1394,13 @@ void TextEdit::_input_event(const InputEvent& p_input_event) {
cursor_set_column(cc);
- } else if (cursor.column==text[cursor.line].length()) {
+ } else if (cursor.column==text[cursor.line].length()) {
if (cursor.line<text.size()-1) {
cursor_set_line(cursor.line+1);
cursor_set_column(0);
}
- } else {
+ } else {
cursor_set_column(cursor_get_column()+1);
}
@@ -1569,19 +1569,35 @@ void TextEdit::_input_event(const InputEvent& p_input_event) {
break;
}
- if (!selection.active)
- break;
+ if (!selection.active){
- String clipboard = _base_get_text(selection.from_line,selection.from_column,selection.to_line,selection.to_column);
- OS::get_singleton()->set_clipboard(clipboard);
+ String clipboard = text[cursor.line];
+ OS::get_singleton()->set_clipboard(clipboard);
+ cursor_set_line(cursor.line);
+ cursor_set_column(0);
+ _remove_text(cursor.line,0,cursor.line,text[cursor.line].length());
- cursor_set_line(selection.from_line);
- cursor_set_column(selection.from_column);
+ backspace_at_cursor();
+ update();
+ cursor_set_line(cursor.line+1);
+ cut_copy_line = true;
- _remove_text(selection.from_line,selection.from_column,selection.to_line,selection.to_column);
- selection.active=false;
- selection.selecting_mode=Selection::MODE_NONE;
- update();
+ }
+ else
+ {
+
+ String clipboard = _base_get_text(selection.from_line,selection.from_column,selection.to_line,selection.to_column);
+ OS::get_singleton()->set_clipboard(clipboard);
+
+ cursor_set_line(selection.from_line);
+ cursor_set_column(selection.from_column);
+
+ _remove_text(selection.from_line,selection.from_column,selection.to_line,selection.to_column);
+ selection.active=false;
+ selection.selecting_mode=Selection::MODE_NONE;
+ update();
+ cut_copy_line = false;
+ }
} break;
case KEY_C: {
@@ -1591,11 +1607,16 @@ void TextEdit::_input_event(const InputEvent& p_input_event) {
break;
}
- if (!selection.active)
- break;
-
- String clipboard = _base_get_text(selection.from_line,selection.from_column,selection.to_line,selection.to_column);
- OS::get_singleton()->set_clipboard(clipboard);
+ if (!selection.active){
+ String clipboard = _base_get_text(cursor.line,0,cursor.line,text[cursor.line].length());
+ OS::get_singleton()->set_clipboard(clipboard);
+ cut_copy_line = true;
+ }
+ else{
+ String clipboard = _base_get_text(selection.from_line,selection.from_column,selection.to_line,selection.to_column);
+ OS::get_singleton()->set_clipboard(clipboard);
+ cut_copy_line = false;
+ }
} break;
case KEY_Z: {
@@ -1625,6 +1646,12 @@ void TextEdit::_input_event(const InputEvent& p_input_event) {
cursor_set_column(selection.from_column);
}
+ else if (cut_copy_line)
+ {
+ cursor_set_column(0);
+ String ins="\n";
+ clipboard += ins;
+ }
_insert_text_at_cursor(clipboard);
@@ -1641,10 +1668,54 @@ void TextEdit::_input_event(const InputEvent& p_input_event) {
} break;
- default: {
-
- scancode_handled=false;
- } break;
+ case KEY_K:{
+ if (!k.mod.command || k.mod.shift || k.mod.alt) {
+ scancode_handled=false;
+ break;
+ }
+ else {
+ if (selection.active) {
+ int ini = selection.from_line;
+ int end = selection.to_line;
+ for (int i=ini; i<= end; i++)
+ {
+ _insert_text(i,0,"#");
+ }
+ }
+ else{
+ _insert_text(cursor.line,0,"#");
+ }
+ update();
+ }
+ break;}
+
+ case KEY_U:{
+ if (!k.mod.command || k.mod.shift || k.mod.alt) {
+ scancode_handled=false;
+ break;
+ }
+ else {
+ if (selection.active) {
+ int ini = selection.from_line;
+ int end = selection.to_line;
+ for (int i=ini; i<= end; i++)
+ {
+ if (text[i][0] == '#')
+ _remove_text(i,0,i,1);
+ }
+ }
+ else{
+ if (text[cursor.line][0] == '#')
+ _remove_text(cursor.line,0,cursor.line,1);
+ }
+ update();
+ }
+ break;}
+
+ default: {
+
+ scancode_handled=false;
+ } break;
}
@@ -3158,7 +3229,7 @@ TextEdit::TextEdit() {
current_op.type=TextOperation::TYPE_NONE;
undo_enabled=true;
- undo_stack_pos=NULL;
+ undo_stack_pos=NULL;
setting_text=false;
last_dblclk=0;
current_op.version=0;
diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h
index 7700bfd4d3..15c289a87e 100644
--- a/scene/gui/text_edit.h
+++ b/scene/gui/text_edit.h
@@ -162,7 +162,7 @@ class TextEdit : public Control {
TextOperation current_op;
List<TextOperation> undo_stack;
- List<TextOperation>::Element *undo_stack_pos;
+ List<TextOperation>::Element *undo_stack_pos;
void _clear_redo();
void _do_text_op(const TextOperation& p_op, bool p_reverse);
@@ -208,6 +208,7 @@ class TextEdit : public Control {
bool line_numbers;
bool auto_brace_completion_enabled;
+ bool cut_copy_line;
uint64_t last_dblclk;
@@ -336,7 +337,7 @@ public:
bool is_selection_active() const;
int get_selection_from_line() const;
- int get_selection_from_column() const;
+ int get_selection_from_column() const;
int get_selection_to_line() const;
int get_selection_to_column() const;
String get_selection_text() const;
@@ -347,7 +348,7 @@ public:
void undo();
void redo();
- void clear_undo_history();
+ void clear_undo_history();
void set_draw_tabs(bool p_draw);
diff --git a/scene/main/scene_main_loop.cpp b/scene/main/scene_main_loop.cpp
index 492c7633c1..1926570885 100644
--- a/scene/main/scene_main_loop.cpp
+++ b/scene/main/scene_main_loop.cpp
@@ -580,6 +580,7 @@ void SceneMainLoop::_notification(int p_notification) {
break;
}
} break;
+ case NOTIFICATION_OS_MEMORY_WARNING:
case NOTIFICATION_WM_FOCUS_IN:
case NOTIFICATION_WM_FOCUS_OUT: {
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index a468f0a379..c7268a6650 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -196,6 +196,9 @@
#include "scene/3d/spatial_sample_player.h"
#include "scene/3d/spatial_stream_player.h"
#include "scene/3d/proximity_group.h"
+#include "scene/3d/navigation_mesh.h"
+#include "scene/3d/navigation.h"
+
#endif
#include "scene/scene_binds.h"
@@ -388,6 +391,9 @@ void register_scene_types() {
ObjectTypeDB::register_type<Particles>();
ObjectTypeDB::register_type<Position3D>();
ObjectTypeDB::register_type<Quad>();
+ ObjectTypeDB::register_type<NavigationMeshInstance>();
+ ObjectTypeDB::register_type<NavigationMesh>();
+ ObjectTypeDB::register_type<Navigation>();
OS::get_singleton()->yield(); //may take time to init
diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp
index 7fa606f5da..67f45ced2b 100644
--- a/scene/resources/animation.cpp
+++ b/scene/resources/animation.cpp
@@ -1716,7 +1716,7 @@ void Animation::clear() {
}
-void Animation::_transform_track_optimize(int p_idx,float p_allowed_err) {
+void Animation::_transform_track_optimize(int p_idx,float p_alowed_linear_err,float p_alowed_angular_err) {
ERR_FAIL_INDEX(p_idx,tracks.size());
ERR_FAIL_COND(tracks[p_idx]->type!=TYPE_TRANSFORM);
@@ -1756,7 +1756,7 @@ void Animation::_transform_track_optimize(int p_idx,float p_allowed_err) {
Vector3 s[2]={ v0, v2 };
real_t d =Geometry::get_closest_point_to_segment(v1,s).distance_to(v1);
- if (d>pd.length()*p_allowed_err) {
+ if (d>pd.length()*p_alowed_linear_err) {
continue; //beyond allowed error for colinearity
}
@@ -1795,7 +1795,7 @@ void Animation::_transform_track_optimize(int p_idx,float p_allowed_err) {
}
real_t err_01 = Math::acos(v01.normalized().dot(v02.normalized()))/Math_PI;
- if (err_01>p_allowed_err) {
+ if (err_01>p_alowed_angular_err) {
//not rotating in the same axis
continue;
}
@@ -1841,7 +1841,7 @@ void Animation::_transform_track_optimize(int p_idx,float p_allowed_err) {
Vector3 s[2]={ v0, v2 };
real_t d =Geometry::get_closest_point_to_segment(v1,s).distance_to(v1);
- if (d>pd.length()*p_allowed_err) {
+ if (d>pd.length()*p_alowed_linear_err) {
continue; //beyond allowed error for colinearity
}
@@ -1866,7 +1866,7 @@ void Animation::_transform_track_optimize(int p_idx,float p_allowed_err) {
if (t[k]==-1)
continue;
- if (Math::abs(lt-t[k])>p_allowed_err) {
+ if (Math::abs(lt-t[k])>p_alowed_linear_err) {
erase=false;
break;
}
@@ -1879,7 +1879,7 @@ void Animation::_transform_track_optimize(int p_idx,float p_allowed_err) {
if (erase) {
- if (Math::abs(lt-c)>p_allowed_err) {
+ if (Math::abs(lt-c)>p_alowed_linear_err) {
//todo, evaluate changing the transition if this fails?
//this could be done as a second pass and would be
//able to optimize more
@@ -1905,7 +1905,7 @@ void Animation::_transform_track_optimize(int p_idx,float p_allowed_err) {
}
-void Animation::optimize(float p_allowed_err) {
+void Animation::optimize(float p_allowed_linear_err,float p_allowed_angular_err) {
int total_tt=0;
@@ -1913,7 +1913,7 @@ void Animation::optimize(float p_allowed_err) {
for(int i=0;i<tracks.size();i++) {
if (tracks[i]->type==TYPE_TRANSFORM)
- _transform_track_optimize(i,p_allowed_err);
+ _transform_track_optimize(i,p_allowed_linear_err,p_allowed_angular_err);
}
diff --git a/scene/resources/animation.h b/scene/resources/animation.h
index 4366bdaca8..4c4e2f0275 100644
--- a/scene/resources/animation.h
+++ b/scene/resources/animation.h
@@ -204,7 +204,7 @@ private:
return idxr;
}
- void _transform_track_optimize(int p_idx,float p_allowed_err=0.05);
+ void _transform_track_optimize(int p_idx, float p_allowed_err=0.05, float p_alowed_angular_err=0.01);
protected:
@@ -271,7 +271,7 @@ public:
void clear();
- void optimize(float p_allowed_err=0.05);
+ void optimize(float p_allowed_linear_err=0.05,float p_allowed_angular_err=0.01);
Animation();
~Animation();
diff --git a/scene/resources/baked_light.cpp b/scene/resources/baked_light.cpp
index 725ac1c946..72eacb51c5 100644
--- a/scene/resources/baked_light.cpp
+++ b/scene/resources/baked_light.cpp
@@ -23,56 +23,79 @@ DVector<uint8_t> BakedLight::get_octree() const {
}
-void BakedLight::_update_lightmaps() {
-
- VS::get_singleton()->baked_light_clear_lightmaps(baked_light);
- for(Map<int,Ref<Texture> >::Element *E=lightmaps.front();E;E=E->next()) {
- VS::get_singleton()->baked_light_add_lightmap(baked_light,E->get()->get_rid(),E->key());
- }
-}
-void BakedLight::add_lightmap(const Ref<Texture> p_texture,int p_id) {
+void BakedLight::add_lightmap(const Ref<Texture> &p_texture,Size2 p_gen_size) {
- ERR_FAIL_COND(!p_texture.is_valid());
- ERR_FAIL_COND(p_id<0);
- lightmaps[p_id]=p_texture;
- VS::get_singleton()->baked_light_add_lightmap(baked_light,p_texture->get_rid(),p_id);
+ LightMap lm;
+ lm.texture=p_texture;
+ lm.gen_size=p_gen_size;
+ lightmaps.push_back(lm);
+ _update_lightmaps();
+ _change_notify();
}
-void BakedLight::erase_lightmap(int p_id) {
+void BakedLight::set_lightmap_gen_size(int p_idx,const Size2& p_size){
- ERR_FAIL_COND(!lightmaps.has(p_id));
- lightmaps.erase(p_id);
+ ERR_FAIL_INDEX(p_idx,lightmaps.size());
+ lightmaps[p_idx].gen_size=p_size;
_update_lightmaps();
}
+Size2 BakedLight::get_lightmap_gen_size(int p_idx) const{
-void BakedLight::get_lightmaps(List<int> *r_lightmaps) {
+ ERR_FAIL_INDEX_V(p_idx,lightmaps.size(),Size2());
+ return lightmaps[p_idx].gen_size;
- for(Map<int,Ref<Texture> >::Element *E=lightmaps.front();E;E=E->next()) {
+}
+void BakedLight::set_lightmap_texture(int p_idx,const Ref<Texture> &p_texture){
- r_lightmaps->push_back(E->key());
- }
+ ERR_FAIL_INDEX(p_idx,lightmaps.size());
+ lightmaps[p_idx].texture=p_texture;
+ _update_lightmaps();
}
+Ref<Texture> BakedLight::get_lightmap_texture(int p_idx) const{
-Ref<Texture> BakedLight::get_lightmap_texture(int p_id) {
+ ERR_FAIL_INDEX_V(p_idx,lightmaps.size(),Ref<Texture>());
+ return lightmaps[p_idx].texture;
- if (!lightmaps.has(p_id))
- return Ref<Texture>();
-
- return lightmaps[p_id];
+}
+void BakedLight::erase_lightmap(int p_idx){
+ ERR_FAIL_INDEX(p_idx,lightmaps.size());
+ lightmaps.remove(p_idx);
+ _update_lightmaps();
+ _change_notify();
}
+int BakedLight::get_lightmaps_count() const{
-void BakedLight::clear_lightmaps() {
+ return lightmaps.size();
+}
+void BakedLight::clear_lightmaps(){
lightmaps.clear();
_update_lightmaps();
+ _change_notify();
+}
+
+
+
+void BakedLight::_update_lightmaps() {
+
+ VS::get_singleton()->baked_light_clear_lightmaps(baked_light);
+ for(int i=0;i<lightmaps.size();i++) {
+
+ RID tid;
+ if (lightmaps[i].texture.is_valid())
+ tid=lightmaps[i].texture->get_rid();
+ VS::get_singleton()->baked_light_add_lightmap(baked_light,tid,i);
+ }
}
+
+
RID BakedLight::get_rid() const {
return baked_light;
@@ -84,12 +107,11 @@ Array BakedLight::_get_lightmap_data() const {
ret.resize(lightmaps.size()*2);
int idx=0;
- for(Map<int,Ref<Texture> >::Element *E=lightmaps.front();E;E=E->next()) {
+ for(int i=0;i<lightmaps.size();i++) {
- ret[idx++]=E->key();
- ret[idx++]=E->get();
+ ret[idx++]=Size2(lightmaps[i].gen_size);
+ ret[idx++]=lightmaps[i].texture;
}
-
return ret;
}
@@ -99,11 +121,13 @@ void BakedLight::_set_lightmap_data(Array p_array){
lightmaps.clear();
for(int i=0;i<p_array.size();i+=2) {
- int id = p_array[i];
+ Size2 size = p_array[i];
Ref<Texture> tex = p_array[i+1];
- ERR_CONTINUE(id<0);
ERR_CONTINUE(tex.is_null());
- lightmaps[id]=tex;
+ LightMap lm;
+ lm.gen_size=size;
+ lm.texture=tex;
+ lightmaps.push_back(lm);
}
_update_lightmaps();
}
@@ -212,6 +236,77 @@ BakedLight::Format BakedLight::get_format() const{
return format;
}
+bool BakedLight::_set(const StringName& p_name, const Variant& p_value) {
+
+ String n = p_name;
+ if (!n.begins_with("lightmap"))
+ return false;
+ int idx = n.get_slice("/",1).to_int();
+ ERR_FAIL_COND_V(idx<0,false);
+ ERR_FAIL_COND_V(idx>lightmaps.size(),false);
+
+ String what = n.get_slice("/",2);
+ Ref<Texture> tex;
+ Size2 gens;
+
+ if (what=="texture")
+ tex=p_value;
+ else if (what=="gen_size")
+ gens=p_value;
+
+ if (idx==lightmaps.size()) {
+ if (tex.is_valid() || gens!=Size2())
+ add_lightmap(tex,gens);
+ } else {
+ if (tex.is_valid())
+ set_lightmap_texture(idx,tex);
+ else if (gens!=Size2())
+ set_lightmap_gen_size(idx,gens);
+ }
+
+
+ return true;
+}
+
+bool BakedLight::_get(const StringName& p_name,Variant &r_ret) const{
+
+ String n = p_name;
+ if (!n.begins_with("lightmap"))
+ return false;
+ int idx = n.get_slice("/",1).to_int();
+ ERR_FAIL_COND_V(idx<0,false);
+ ERR_FAIL_COND_V(idx>lightmaps.size(),false);
+
+ String what = n.get_slice("/",2);
+
+ if (what=="texture") {
+ if (idx==lightmaps.size())
+ r_ret=Ref<Texture>();
+ else
+ r_ret=lightmaps[idx].texture;
+
+ } else if (what=="gen_size") {
+
+ if (idx==lightmaps.size())
+ r_ret=Size2();
+ else
+ r_ret=Size2(lightmaps[idx].gen_size);
+ } else
+ return false;
+
+ return true;
+
+
+}
+void BakedLight::_get_property_list( List<PropertyInfo> *p_list) const{
+
+ for(int i=0;i<=lightmaps.size();i++) {
+
+ p_list->push_back(PropertyInfo(Variant::VECTOR2,"lightmaps/"+itos(i)+"/gen_size",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_EDITOR));
+ p_list->push_back(PropertyInfo(Variant::OBJECT,"lightmaps/"+itos(i)+"/texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture",PROPERTY_USAGE_EDITOR));
+ }
+}
+
void BakedLight::_bind_methods(){
@@ -222,7 +317,7 @@ void BakedLight::_bind_methods(){
ObjectTypeDB::bind_method(_MD("set_octree","octree"),&BakedLight::set_octree);
ObjectTypeDB::bind_method(_MD("get_octree"),&BakedLight::get_octree);
- ObjectTypeDB::bind_method(_MD("add_lightmap","texture:Texture","id"),&BakedLight::add_lightmap);
+ ObjectTypeDB::bind_method(_MD("add_lightmap","texture:Texture","gen_size"),&BakedLight::add_lightmap);
ObjectTypeDB::bind_method(_MD("erase_lightmap","id"),&BakedLight::erase_lightmap);
ObjectTypeDB::bind_method(_MD("clear_lightmaps"),&BakedLight::clear_lightmaps);
diff --git a/scene/resources/baked_light.h b/scene/resources/baked_light.h
index df86f98c08..942f6eab1a 100644
--- a/scene/resources/baked_light.h
+++ b/scene/resources/baked_light.h
@@ -33,7 +33,13 @@ private:
RID baked_light;
Mode mode;
- Map<int,Ref<Texture> > lightmaps;
+ struct LightMap {
+ Size2i gen_size;
+ Ref<Texture> texture;
+ };
+
+
+ Vector< LightMap> lightmaps;
//bake vars
int cell_subdiv;
@@ -54,6 +60,13 @@ private:
Array _get_lightmap_data() const;
void _set_lightmap_data(Array p_array);
+
+protected:
+
+ bool _set(const StringName& p_name, const Variant& p_value);
+ bool _get(const StringName& p_name,Variant &r_ret) const;
+ void _get_property_list( List<PropertyInfo> *p_list) const;
+
static void _bind_methods();
public:
@@ -97,10 +110,13 @@ public:
void set_octree(const DVector<uint8_t>& p_octree);
DVector<uint8_t> get_octree() const;
- void add_lightmap(const Ref<Texture> p_texture,int p_id);
- void erase_lightmap(int p_id);
- void get_lightmaps(List<int> *r_lightmaps);
- Ref<Texture> get_lightmap_texture(int p_id);
+ void add_lightmap(const Ref<Texture> &p_texture,Size2 p_gen_size=Size2(256,256));
+ void set_lightmap_gen_size(int p_idx,const Size2& p_size);
+ Size2 get_lightmap_gen_size(int p_idx) const;
+ void set_lightmap_texture(int p_idx,const Ref<Texture> &p_texture);
+ Ref<Texture> get_lightmap_texture(int p_idx) const;
+ void erase_lightmap(int p_idx);
+ int get_lightmaps_count() const;
void clear_lightmaps();
virtual RID get_rid() const;