summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bin/tests/test_math.cpp400
-rw-r--r--core/math/a_star.cpp412
-rw-r--r--core/math/a_star.h92
-rw-r--r--core/object_type_db.cpp174
-rw-r--r--core/object_type_db.h15
-rw-r--r--core/register_core_types.cpp2
-rw-r--r--doc/base/classes.xml3
-rw-r--r--drivers/gles2/rasterizer_gles2.cpp4
-rw-r--r--drivers/gles2/shader_compiler_gles2.cpp1
-rw-r--r--drivers/gles2/shaders/canvas.glsl4
-rw-r--r--drivers/gles2/shaders/material.glsl4
-rw-r--r--drivers/vorbis/SCsub4
-rw-r--r--main/main.cpp5
-rw-r--r--scene/2d/camera_2d.cpp70
-rw-r--r--scene/2d/camera_2d.h5
-rw-r--r--scene/main/canvas_layer.cpp60
-rw-r--r--scene/main/canvas_layer.h8
-rw-r--r--scene/main/viewport.cpp54
-rw-r--r--scene/main/viewport.h2
-rw-r--r--scene/resources/shader_graph.cpp4
-rw-r--r--servers/visual/shader_language.cpp1
-rw-r--r--tools/editor/create_dialog.cpp3
-rw-r--r--tools/editor/editor_node.cpp47
-rw-r--r--tools/editor/editor_node.h9
-rw-r--r--tools/editor/plugins/script_editor_plugin.cpp31
-rw-r--r--tools/editor/plugins/shader_graph_editor_plugin.cpp2
-rw-r--r--tools/editor/project_manager.cpp2
27 files changed, 1338 insertions, 80 deletions
diff --git a/bin/tests/test_math.cpp b/bin/tests/test_math.cpp
index 4b686e8af8..e5667bff64 100644
--- a/bin/tests/test_math.cpp
+++ b/bin/tests/test_math.cpp
@@ -40,12 +40,376 @@
#include "scene/resources/texture.h"
#include "vmap.h"
#include "os/os.h"
+#include "os/file_access.h"
#include "method_ptrcall.h"
namespace TestMath {
+class GetClassAndNamespace {
+
+ String code;
+ int idx;
+ int line;
+ String error_str;
+ bool error;
+ Variant value;
+
+ String class_name;
+
+ enum Token {
+ TK_BRACKET_OPEN,
+ TK_BRACKET_CLOSE,
+ TK_CURLY_BRACKET_OPEN,
+ TK_CURLY_BRACKET_CLOSE,
+ TK_PERIOD,
+ TK_COLON,
+ TK_COMMA,
+ TK_SYMBOL,
+ TK_IDENTIFIER,
+ TK_STRING,
+ TK_NUMBER,
+ TK_EOF,
+ TK_ERROR
+ };
+
+
+ Token get_token() {
+
+ while (true) {
+ switch(code[idx]) {
+
+ case '\n': {
+
+ line++;
+ idx++;
+ break;
+ };
+ case 0: {
+ return TK_EOF;
+
+ } break;
+ case '{': {
+
+ idx++;
+ return TK_CURLY_BRACKET_OPEN;
+ };
+ case '}': {
+
+ idx++;
+ return TK_CURLY_BRACKET_CLOSE;
+ };
+ case '[': {
+
+ idx++;
+ return TK_BRACKET_OPEN;
+ };
+ case ']': {
+
+ idx++;
+ return TK_BRACKET_CLOSE;
+ };
+ case ':': {
+
+ idx++;
+ return TK_COLON;
+ };
+ case ',': {
+
+ idx++;
+ return TK_COMMA;
+ };
+ case '.': {
+
+ idx++;
+ return TK_PERIOD;
+ };
+ case '#': {
+ //compiler directive
+ while(code[idx]!='\n' && code[idx]!=0) {
+ idx++;
+ }
+ continue;
+ } break;
+ case '/': {
+
+
+ switch(code[idx+1]) {
+ case '*': { // block comment
+
+ idx+=2;
+ while(true) {
+ if (code[idx]==0) {
+ error_str="Unterminated comment";
+ error=true;
+ return TK_ERROR;
+ } if (code[idx]=='*' &&code[idx+1]=='/') {
+
+ idx+=2;
+ break;
+ } if (code[idx]=='\n') {
+ line++;
+ }
+
+ idx++;
+ }
+
+ } break;
+ case '/': { // line comment skip
+
+ while(code[idx]!='\n' && code[idx]!=0) {
+ idx++;
+ }
+
+ } break;
+ default: {
+ value="/";
+ idx++;
+ return TK_SYMBOL;
+ }
+
+ }
+
+ continue; // a comment
+ } break;
+ case '\'':
+ case '"': {
+
+ CharType begin_str = code[idx];
+ idx++;
+ String tk_string=String();
+ while(true) {
+ if (code[idx]==0) {
+ error_str="Unterminated String";
+ error=true;
+ return TK_ERROR;
+ } else if (code[idx]==begin_str) {
+ idx++;
+ break;
+ } else if (code[idx]=='\\') {
+ //escaped characters...
+ idx++;
+ CharType next = code[idx];
+ if (next==0) {
+ error_str="Unterminated String";
+ error=true;
+ return TK_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;
+ /* too much, not needed for now
+ case 'u': {
+ //hexnumbarh - oct is deprecated
+
+
+ for(int j=0;j<4;j++) {
+ CharType c = code[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;*/
+ case '\"': res='\"'; break;
+ case '\\': res='\\'; break;
+ //case '/': res='/'; break;
+ default: {
+ res = next;
+ //r_err_str="Invalid escape sequence";
+ //return ERR_PARSE_ERROR;
+ } break;
+ }
+
+ tk_string+=res;
+
+ } else {
+ if (code[idx]=='\n')
+ line++;
+ tk_string+=code[idx];
+ }
+ idx++;
+ }
+
+ value=tk_string;
+
+ return TK_STRING;
+
+ } break;
+ default: {
+
+ if (code[idx]<=32) {
+ idx++;
+ break;
+ }
+
+ if ( (code[idx]>=33 && code[idx]<=47) || (code[idx]>=58 && code[idx]<=64) || (code[idx]>=91 && code[idx]<=96) || (code[idx]>=123 && code[idx]<=127)){
+ value=String::chr(code[idx]);
+ idx++;
+ return TK_SYMBOL;
+ }
+
+ if (code[idx]=='-' || (code[idx]>='0' && code[idx]<='9')) {
+ //a number
+ const CharType *rptr;
+ double number = String::to_double(&code[idx],&rptr);
+ idx+=(rptr - &code[idx]);
+ value=number;
+ return TK_NUMBER;
+
+ } else if ((code[idx]>='A' && code[idx]<='Z') || (code[idx]>='a' && code[idx]<='z') || code[idx]>127) {
+
+ String id;
+
+ while((code[idx]>='A' && code[idx]<='Z') || (code[idx]>='a' && code[idx]<='z') || code[idx]>127) {
+
+ id+=code[idx];
+ idx++;
+ }
+
+ value=id;
+ return TK_IDENTIFIER;
+ } else {
+ error_str="Unexpected character.";
+ error=true;
+ return TK_ERROR;
+ }
+ }
+
+ }
+ }
+ }
+
+public:
+ Error parse(const String& p_code,const String& p_known_class_name=String()) {
+
+ code=p_code;
+ idx=0;
+ line=0;
+ error_str=String();
+ error=false;
+ value=Variant();
+ class_name=String();
+
+ bool use_next_class=false;
+ Token tk = get_token();
+
+ Map<int,String> namespace_stack;
+ int curly_stack=0;
+
+
+ while(!error || tk!=TK_EOF) {
+
+ if (tk==TK_BRACKET_OPEN) {
+ tk = get_token();
+ if (tk==TK_IDENTIFIER && String(value)=="ScriptClass") {
+ if (get_token()==TK_BRACKET_CLOSE) {
+ use_next_class=true;
+ }
+ }
+ } else if (tk==TK_IDENTIFIER && String(value)=="class") {
+ tk = get_token();
+ if (tk==TK_IDENTIFIER) {
+ String name = value;
+ if (use_next_class || p_known_class_name==name) {
+ for (Map<int,String>::Element *E=namespace_stack.front();E;E=E->next()) {
+ class_name+=E->get()+".";
+ }
+ class_name+=String(value);
+ break;
+ }
+ }
+
+ } else if (tk==TK_IDENTIFIER && String(value)=="namespace") {
+ String name;
+ int at_level = curly_stack;
+ while(true) {
+ tk = get_token();
+ if (tk==TK_IDENTIFIER) {
+ name+=String(value);
+ }
+
+ tk = get_token();
+ if (tk==TK_PERIOD) {
+ name+=".";
+ } else if (tk==TK_CURLY_BRACKET_OPEN) {
+ curly_stack++;
+ break;
+ } else {
+ break; //whathever else
+ }
+
+ }
+
+ if (name!=String()) {
+ namespace_stack[at_level]=name;
+ }
+
+ } else if (tk==TK_CURLY_BRACKET_OPEN) {
+ curly_stack++;
+ } else if (tk==TK_CURLY_BRACKET_CLOSE) {
+ curly_stack--;
+ if (namespace_stack.has(curly_stack)) {
+ namespace_stack.erase(curly_stack);
+ }
+ }
+
+ tk = get_token();
+ }
+
+ if (error)
+ return ERR_PARSE_ERROR;
+
+
+
+ return OK;
+
+ }
+
+ String get_error() {
+ return error_str;
+ }
+
+ String get_class() {
+ return class_name;
+ }
+
+};
+
+
void test_vec(Plane p_vec) {
@@ -113,7 +477,41 @@ uint32_t ihash3( uint32_t a)
MainLoop* test() {
- print_line(itos(Math::step_decimals( 0.0001 )));
+
+ List<String> cmdlargs = OS::get_singleton()->get_cmdline_args();
+
+ if (cmdlargs.empty()) {
+ //try editor!
+ return NULL;
+ }
+
+ String test = cmdlargs.back()->get();
+
+ FileAccess *fa = FileAccess::open(test,FileAccess::READ);
+
+ if (!fa) {
+ ERR_EXPLAIN("Could not open file: "+test);
+ ERR_FAIL_V(NULL);
+ }
+
+
+ Vector<uint8_t> buf;
+ int flen = fa->get_len();
+ buf.resize(fa->get_len()+1);
+ fa->get_buffer(&buf[0],flen);
+ buf[flen]=0;
+
+
+ String code;
+ code.parse_utf8((const char*)&buf[0]);
+
+ GetClassAndNamespace getclass;
+ if (getclass.parse(code)) {
+ print_line("Parse error: "+getclass.get_error());
+ } else {
+ print_line("Found class: "+getclass.get_class());
+ }
+
return NULL;
{
diff --git a/core/math/a_star.cpp b/core/math/a_star.cpp
new file mode 100644
index 0000000000..5bbbbdaa5a
--- /dev/null
+++ b/core/math/a_star.cpp
@@ -0,0 +1,412 @@
+#include "a_star.h"
+#include "geometry.h"
+
+
+int AStar::get_available_point_id() const {
+
+ if (points.empty()) {
+ return 1;
+ }
+
+ return points.back()->key()+1;
+}
+
+void AStar::add_point(int p_id, const Vector3 &p_pos, float p_weight_scale) {
+ ERR_FAIL_COND(p_id<0);
+ if (!points.has(p_id)) {
+ Point *pt = memnew( Point );
+ pt->id=p_id;
+ pt->pos=p_pos;
+ pt->weight_scale=p_weight_scale;
+ pt->prev_point=NULL;
+ pt->last_pass=0;
+ points[p_id]=pt;
+ } else {
+ points[p_id]->pos=p_pos;
+ points[p_id]->weight_scale=p_weight_scale;
+ }
+}
+
+Vector3 AStar::get_point_pos(int p_id) const{
+
+ ERR_FAIL_COND_V(!points.has(p_id),Vector3());
+
+ return points[p_id]->pos;
+
+}
+float AStar::get_point_weight_scale(int p_id) const{
+
+ ERR_FAIL_COND_V(!points.has(p_id),0);
+
+ return points[p_id]->weight_scale;
+
+}
+void AStar::remove_point(int p_id){
+
+ ERR_FAIL_COND(!points.has(p_id));
+
+ Point* p = points[p_id];
+
+ for(int i=0;i<p->neighbours.size();i++) {
+
+ Segment s(p_id,p->neighbours[i]->id);
+ segments.erase(s);
+ p->neighbours[i]->neighbours.erase(p);
+ }
+
+ memdelete(p);
+ points.erase(p_id);
+}
+
+void AStar::connect_points(int p_id,int p_with_id){
+
+ ERR_FAIL_COND(!points.has(p_id));
+ ERR_FAIL_COND(!points.has(p_with_id));
+ ERR_FAIL_COND(p_id==p_with_id);
+
+
+ Point* a = points[p_id];
+ Point* b = points[p_with_id];
+ a->neighbours.push_back(b);
+ b->neighbours.push_back(a);
+
+ Segment s(p_id,p_with_id);
+ if (s.from==p_id) {
+ s.from_point=a;
+ s.to_point=b;
+ } else {
+ s.from_point=b;
+ s.to_point=a;
+ }
+
+ segments.insert(s);
+
+
+}
+void AStar::disconnect_points(int p_id,int p_with_id){
+
+ Segment s(p_id,p_with_id);
+ ERR_FAIL_COND(!segments.has(s));
+
+
+ segments.erase(s);
+
+ Point *a = points[p_id];
+ Point *b = points[p_with_id];
+ a->neighbours.erase(b);
+ b->neighbours.erase(a);
+
+}
+bool AStar::are_points_connected(int p_id,int p_with_id) const{
+
+ Segment s(p_id,p_with_id);
+ return segments.has(s);
+}
+
+void AStar::clear(){
+
+ for (const Map<int,Point*>::Element *E=points.front();E;E=E->next()) {
+
+ memdelete(E->get());
+ }
+ segments.clear();
+ points.clear();
+}
+
+
+int AStar::get_closest_point(const Vector3& p_point) const{
+
+ int closest_id=-1;
+ float closest_dist=1e20;
+
+ for (const Map<int,Point*>::Element *E=points.front();E;E=E->next()) {
+
+ float d = p_point.distance_squared_to(E->get()->pos);
+ if (closest_id<0 || d<closest_dist) {
+ closest_dist=d;
+ closest_id=E->key();
+ }
+ }
+
+ return closest_id;
+
+
+}
+Vector3 AStar::get_closest_pos_in_segment(const Vector3& p_point) const {
+
+ float closest_dist = 1e20;
+ bool found=false;
+ Vector3 closest_point;
+
+
+ for (const Set<Segment>::Element *E=segments.front();E;E=E->next()) {
+
+ Vector3 segment[2]={
+ E->get().from_point->pos,
+ E->get().to_point->pos,
+ };
+
+ Vector3 p = Geometry::get_closest_point_to_segment(p_point,segment);
+ float d = p_point.distance_squared_to(p);
+ if (!found || d<closest_dist) {
+
+ closest_point=p;
+ closest_dist=d;
+ found=true;
+ }
+ }
+
+ return closest_point;
+}
+
+bool AStar::_solve(Point* begin_point, Point* end_point) {
+
+ pass++;
+
+ SelfList<Point>::List open_list;
+
+ bool found_route=false;
+
+
+ for(int i=0;i<begin_point->neighbours.size();i++) {
+
+ Point *n = begin_point->neighbours[i];
+ n->prev_point=begin_point;
+ n->distance=n->pos.distance_to(begin_point->pos);
+ n->distance*=n->weight_scale;
+ n->last_pass=pass;
+ open_list.add(&n->list);
+
+ if (end_point==n) {
+ found_route=true;
+ break;
+ }
+ }
+
+ while(!found_route) {
+
+ if (open_list.first()==NULL) {
+ //could not find path sadly
+ break;
+ }
+ //check open list
+
+ SelfList<Point> *least_cost_point=NULL;
+ float least_cost=1e30;
+
+ //this could be faster (cache previous results)
+ for (SelfList<Point> *E=open_list.first();E;E=E->next()) {
+
+ Point *p=E->self();
+
+ float cost=p->distance;
+ cost+=p->pos.distance_to(end_point->pos);
+ cost*=p->weight_scale;
+
+ if (cost<least_cost) {
+
+ least_cost_point=E;
+ least_cost=cost;
+ }
+ }
+
+
+ Point *p=least_cost_point->self();
+ //open the neighbours for search
+ int es = p->neighbours.size();
+
+ for(int i=0;i<es;i++) {
+
+
+ Point* e=p->neighbours[i];
+
+
+ float distance = p->pos.distance_to(e->pos) + p->distance;
+ distance*=e->weight_scale;
+
+
+
+ if (e->last_pass==pass) {
+ //oh this was visited already, can we win the cost?
+
+ if (e->distance>distance) {
+
+ e->prev_point=p;
+ e->distance=distance;
+ }
+ } else {
+ //add to open neighbours
+
+ e->prev_point=p;
+ e->distance=distance;
+ e->last_pass=pass; //mark as used
+ open_list.add(&e->list);
+
+ if (e==end_point) {
+ //oh my reached end! stop algorithm
+ found_route=true;
+ break;
+
+ }
+
+ }
+ }
+
+ if (found_route)
+ break;
+
+ open_list.remove(least_cost_point);
+ }
+
+ //clear the openf list
+ while(open_list.first()) {
+ open_list.remove( open_list.first() );
+ }
+
+ return found_route;
+
+}
+
+DVector<Vector3> AStar::get_point_path(int p_from_id, int p_to_id) {
+
+ ERR_FAIL_COND_V(!points.has(p_from_id),DVector<Vector3>());
+ ERR_FAIL_COND_V(!points.has(p_to_id),DVector<Vector3>());
+
+
+ pass++;
+
+ Point* a = points[p_from_id];
+ Point* b = points[p_to_id];
+
+ if (a==b) {
+ DVector<Vector3> ret;
+ ret.push_back(a->pos);
+ return ret;
+ }
+
+
+ Point *begin_point=a;
+ Point *end_point=b;
+
+ bool found_route=_solve(begin_point,end_point);
+
+ if (!found_route)
+ return DVector<Vector3>();
+
+ //midpoints
+ Point *p=end_point;
+ int pc=1; //begin point
+ while(p!=begin_point) {
+ pc++;
+ p=p->prev_point;
+ }
+
+ DVector<Vector3> path;
+ path.resize(pc);
+
+ {
+ DVector<Vector3>::Write w = path.write();
+
+ Point *p=end_point;
+ int idx=pc-1;
+ while(p!=begin_point) {
+ w[idx--]=p->pos;
+ p=p->prev_point;
+ }
+
+ w[0]=p->pos; //assign first
+
+ }
+
+ return path;
+
+}
+
+
+DVector<int> AStar::get_id_path(int p_from_id, int p_to_id) {
+
+ ERR_FAIL_COND_V(!points.has(p_from_id),DVector<int>());
+ ERR_FAIL_COND_V(!points.has(p_to_id),DVector<int>());
+
+
+ pass++;
+
+ Point* a = points[p_from_id];
+ Point* b = points[p_to_id];
+
+ if (a==b) {
+ DVector<int> ret;
+ ret.push_back(a->id);
+ return ret;
+ }
+
+
+ Point *begin_point=a;
+ Point *end_point=b;
+
+ bool found_route=_solve(begin_point,end_point);
+
+ if (!found_route)
+ return DVector<int>();
+
+ //midpoints
+ Point *p=end_point;
+ int pc=1; //begin point
+ while(p!=begin_point) {
+ pc++;
+ p=p->prev_point;
+ }
+
+ DVector<int> path;
+ path.resize(pc);
+
+ {
+ DVector<int>::Write w = path.write();
+
+ p=end_point;
+ int idx=pc-1;
+ while(p!=begin_point) {
+ w[idx--]=p->id;
+ p=p->prev_point;
+ }
+
+ w[0]=p->id; //assign first
+
+ }
+
+ return path;
+}
+
+void AStar::_bind_methods() {
+
+ ObjectTypeDB::bind_method(_MD("get_available_point_id"),&AStar::get_available_point_id);
+ ObjectTypeDB::bind_method(_MD("add_point","id","pos","weight_scale"),&AStar::add_point,DEFVAL(1.0));
+ ObjectTypeDB::bind_method(_MD("get_point_pos","id"),&AStar::get_point_pos);
+ ObjectTypeDB::bind_method(_MD("get_point_weight_scale","id"),&AStar::get_point_weight_scale);
+ ObjectTypeDB::bind_method(_MD("remove_point","id"),&AStar::remove_point);
+
+ ObjectTypeDB::bind_method(_MD("connect_points","id","to_id"),&AStar::connect_points);
+ ObjectTypeDB::bind_method(_MD("disconnect_points","id","to_id"),&AStar::disconnect_points);
+ ObjectTypeDB::bind_method(_MD("are_points_connected","id","to_id"),&AStar::are_points_connected);
+
+ ObjectTypeDB::bind_method(_MD("clear"),&AStar::clear);
+
+ ObjectTypeDB::bind_method(_MD("get_closest_point","to_pos"),&AStar::get_closest_point);
+ ObjectTypeDB::bind_method(_MD("get_closest_pos_in_segment","to_pos"),&AStar::get_closest_pos_in_segment);
+
+ ObjectTypeDB::bind_method(_MD("get_point_path","from_id","to_id"),&AStar::get_point_path);
+ ObjectTypeDB::bind_method(_MD("get_id_path","from_id","to_id"),&AStar::get_id_path);
+
+}
+
+
+AStar::AStar() {
+
+ pass=1;
+}
+
+
+AStar::~AStar() {
+
+ pass=1;
+}
diff --git a/core/math/a_star.h b/core/math/a_star.h
new file mode 100644
index 0000000000..a0517b5941
--- /dev/null
+++ b/core/math/a_star.h
@@ -0,0 +1,92 @@
+#ifndef ASTAR_H
+#define ASTAR_H
+
+#include "reference.h"
+#include "self_list.h"
+
+class AStar: public Reference {
+
+ OBJ_TYPE(AStar,Reference)
+
+
+ uint64_t pass;
+
+ struct Point {
+
+ SelfList<Point> list;
+
+ int id;
+ Vector3 pos;
+ float weight_scale;
+ uint64_t last_pass;
+
+ Vector<Point*> neighbours;
+
+ //used for pathfinding
+ Point *prev_point;
+ float distance;
+
+ Point() : list(this) {}
+ };
+
+ Map<int,Point*> points;
+
+ struct Segment {
+ union {
+ struct {
+ int32_t from;
+ int32_t to;
+ };
+ uint64_t key;
+ };
+
+ Point *from_point;
+ Point *to_point;
+
+ bool operator<(const Segment& p_s) const { return key<p_s.key; }
+ Segment() { key=0; }
+ Segment(int p_from,int p_to) {
+ if (p_from > p_to) {
+ SWAP(p_from,p_to);
+ }
+
+ from=p_from;
+ to=p_to;
+ }
+ };
+
+
+ Set<Segment> segments;
+
+ bool _solve(Point *begin_point, Point *end_point);
+
+protected:
+
+ static void _bind_methods();
+public:
+
+ int get_available_point_id() const;
+
+ void add_point(int p_id,const Vector3& p_pos,float p_weight_scale=1);
+ Vector3 get_point_pos(int p_id) const;
+ float get_point_weight_scale(int p_id) const;
+ void remove_point(int p_id);
+
+ void connect_points(int p_id,int p_with_id);
+ void disconnect_points(int p_id,int p_with_id);
+ bool are_points_connected(int p_id,int p_with_id) const;
+
+ void clear();
+
+
+ int get_closest_point(const Vector3& p_point) const;
+ Vector3 get_closest_pos_in_segment(const Vector3& p_point) const;
+
+ DVector<Vector3> get_point_path(int p_from_id, int p_to_id);
+ DVector<int> get_id_path(int p_from_id, int p_to_id);
+
+ AStar();
+ ~AStar();
+};
+
+#endif // ASTAR_H
diff --git a/core/object_type_db.cpp b/core/object_type_db.cpp
index aa641923e6..e121dc9e98 100644
--- a/core/object_type_db.cpp
+++ b/core/object_type_db.cpp
@@ -189,6 +189,14 @@ MethodDefinition _MD(const char* p_name,const char *p_arg1,const char *p_arg2,co
#endif
+
+ObjectTypeDB::APIType ObjectTypeDB::current_api=API_CORE;
+
+void ObjectTypeDB::set_current_api(APIType p_api) {
+
+ current_api=p_api;
+}
+
HashMap<StringName,ObjectTypeDB::TypeInfo,StringNameHasher> ObjectTypeDB::types;
HashMap<StringName,StringName,StringNameHasher> ObjectTypeDB::resource_base_extensions;
HashMap<StringName,StringName,StringNameHasher> ObjectTypeDB::compat_types;
@@ -258,6 +266,171 @@ StringName ObjectTypeDB::type_inherits_from(const StringName& p_type) {
return ti->inherits;
}
+ObjectTypeDB::APIType ObjectTypeDB::get_api_type(const StringName &p_type) {
+
+ OBJTYPE_LOCK;
+
+ TypeInfo *ti = types.getptr(p_type);
+ ERR_FAIL_COND_V(!ti,API_NONE);
+ return ti->api;
+}
+
+uint64_t ObjectTypeDB::get_api_hash(APIType p_api) {
+
+#ifdef DEBUG_METHODS_ENABLED
+
+ uint64_t hash = hash_djb2_one_64(HashMapHahserDefault::hash(VERSION_FULL_NAME));
+
+ List<StringName> names;
+
+ const StringName *k=NULL;
+
+ while((k=types.next(k))) {
+
+ names.push_back(*k);
+ }
+ //must be alphabetically sorted for hash to compute
+ names.sort_custom<StringName::AlphCompare>();
+
+ for (List<StringName>::Element *E=names.front();E;E=E->next()) {
+
+ TypeInfo *t = types.getptr(E->get());
+ ERR_FAIL_COND_V(!t,0);
+ if (t->api!=p_api)
+ continue;
+ hash = hash_djb2_one_64(t->name.hash(),hash);
+ hash = hash_djb2_one_64(t->inherits.hash(),hash);
+
+ { //methods
+
+ List<StringName> snames;
+
+ k=NULL;
+
+ while((k=t->method_map.next(k))) {
+
+ snames.push_back(*k);
+ }
+
+ snames.sort_custom<StringName::AlphCompare>();
+
+ for (List<StringName>::Element *F=snames.front();F;F=F->next()) {
+
+ MethodBind *mb = t->method_map[F->get()];
+ hash = hash_djb2_one_64( mb->get_name().hash(), hash);
+ hash = hash_djb2_one_64( mb->get_argument_count(), hash);
+ hash = hash_djb2_one_64( mb->get_argument_type(-1), hash); //return
+
+ for(int i=0;i<mb->get_argument_count();i++) {
+ hash = hash_djb2_one_64( mb->get_argument_info(i).type, hash );
+ hash = hash_djb2_one_64( mb->get_argument_info(i).name.hash(), hash );
+ hash = hash_djb2_one_64( mb->get_argument_info(i).hint, hash );
+ hash = hash_djb2_one_64( mb->get_argument_info(i).hint_string.hash(), hash );
+ }
+
+ hash = hash_djb2_one_64( mb->get_default_argument_count(), hash);
+
+ for(int i=0;i<mb->get_default_argument_count();i++) {
+ //hash should not change, i hope for tis
+ Variant da = mb->get_default_argument(i);
+ hash = hash_djb2_one_64( da.hash(), hash );
+ }
+
+ hash = hash_djb2_one_64( mb->get_hint_flags(), hash);
+
+ }
+ }
+
+
+ { //constants
+
+ List<StringName> snames;
+
+ k=NULL;
+
+ while((k=t->constant_map.next(k))) {
+
+ snames.push_back(*k);
+ }
+
+ snames.sort_custom<StringName::AlphCompare>();
+
+ for (List<StringName>::Element *F=snames.front();F;F=F->next()) {
+
+ hash = hash_djb2_one_64(F->get().hash(), hash);
+ hash = hash_djb2_one_64( t->constant_map[F->get()], hash);
+ }
+ }
+
+
+ { //signals
+
+ List<StringName> snames;
+
+ k=NULL;
+
+ while((k=t->signal_map.next(k))) {
+
+ snames.push_back(*k);
+ }
+
+ snames.sort_custom<StringName::AlphCompare>();
+
+ for (List<StringName>::Element *F=snames.front();F;F=F->next()) {
+
+ MethodInfo &mi = t->signal_map[F->get()];
+ hash = hash_djb2_one_64( F->get().hash(), hash);
+ for(int i=0;i<mi.arguments.size();i++) {
+ hash = hash_djb2_one_64( mi.arguments[i].type, hash);
+ }
+ }
+ }
+
+ { //properties
+
+ List<StringName> snames;
+
+ k=NULL;
+
+ while((k=t->property_setget.next(k))) {
+
+ snames.push_back(*k);
+ }
+
+ snames.sort_custom<StringName::AlphCompare>();
+
+ for (List<StringName>::Element *F=snames.front();F;F=F->next()) {
+
+ PropertySetGet *psg=t->property_setget.getptr(F->get());
+
+ hash = hash_djb2_one_64( F->get().hash(), hash);
+ hash = hash_djb2_one_64( psg->setter.hash(), hash);
+ hash = hash_djb2_one_64( psg->getter.hash(), hash);
+
+ }
+ }
+
+ //property list
+ for (List<PropertyInfo>::Element *F=t->property_list.front();F;F=F->next()) {
+
+ hash = hash_djb2_one_64( F->get().name.hash(), hash);
+ hash = hash_djb2_one_64( F->get().type, hash);
+ hash = hash_djb2_one_64( F->get().hint, hash);
+ hash = hash_djb2_one_64( F->get().hint_string.hash(), hash);
+ hash = hash_djb2_one_64( F->get().usage, hash);
+ }
+
+
+ }
+
+
+ return hash;
+#else
+ return 0;
+#endif
+
+}
+
bool ObjectTypeDB::type_exists(const StringName &p_type) {
OBJTYPE_LOCK;
@@ -309,6 +482,7 @@ void ObjectTypeDB::_add_type2(const StringName& p_type, const StringName& p_inhe
TypeInfo &ti=types[name];
ti.name=name;
ti.inherits=p_inherits;
+ ti.api=current_api;
if (ti.inherits) {
diff --git a/core/object_type_db.h b/core/object_type_db.h
index 725b424c9a..9e9029ff2f 100644
--- a/core/object_type_db.h
+++ b/core/object_type_db.h
@@ -109,7 +109,13 @@ static _FORCE_INLINE_ const char* _MD(const char* m_name, ...) { return m_name;
#endif
class ObjectTypeDB {
-
+public:
+ enum APIType {
+ API_CORE,
+ API_EDITOR,
+ API_NONE
+ };
+public:
struct PropertySetGet {
int index;
@@ -122,6 +128,7 @@ class ObjectTypeDB {
struct TypeInfo {
+ APIType api;
TypeInfo *inherits_ptr;
HashMap<StringName,MethodBind*,StringNameHasher> method_map;
HashMap<StringName,int,StringNameHasher> constant_map;
@@ -161,6 +168,7 @@ class ObjectTypeDB {
#endif
+ static APIType current_api;
static void _add_type2(const StringName& p_type, const StringName& p_inherits);
public:
@@ -236,6 +244,9 @@ public:
static bool is_type(const StringName &p_type,const StringName& p_inherits);
static bool can_instance(const StringName &p_type);
static Object *instance(const StringName &p_type);
+ static APIType get_api_type(const StringName &p_type);
+
+ static uint64_t get_api_hash(APIType p_api);
#if 0
template<class N, class M>
@@ -499,6 +510,8 @@ public:
static void add_compatibility_type(const StringName& p_type,const StringName& p_fallback);
static void init();
+
+ static void set_current_api(APIType p_api);
static void cleanup();
};
diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp
index 3de26573f4..7e4ba039c5 100644
--- a/core/register_core_types.cpp
+++ b/core/register_core_types.cpp
@@ -33,6 +33,7 @@
#include "io/config_file.h"
#include "os/main_loop.h"
#include "io/packet_peer.h"
+#include "math/a_star.h"
#include "globals.h"
#include "object_type_db.h"
#include "geometry.h"
@@ -147,6 +148,7 @@ void register_core_types() {
ObjectTypeDB::register_type<PackedDataContainer>();
ObjectTypeDB::register_virtual_type<PackedDataContainerRef>();
+ ObjectTypeDB::register_type<AStar>();
ip = IP::create();
diff --git a/doc/base/classes.xml b/doc/base/classes.xml
index 916ca09c92..6865bb1378 100644
--- a/doc/base/classes.xml
+++ b/doc/base/classes.xml
@@ -16640,7 +16640,8 @@
<argument index="3" name="duration" type="float" default="0">
</argument>
<description>
- Starts to vibrate the joystick. Joysticks usually come with two rumble motors, a strong and a weak one. weak_magnitude is the strength of the weak motor (between 0 and 1) and strong_magnitude is the strength of the strong motor (between 0 and 1). duration is the duration of the effect in seconds (a duration of 0 will play the vibration indefinitely).
+ Starts to vibrate the joystick. Joysticks usually come with two rumble motors, a strong and a weak one. weak_magnitude is the strength of the weak motor (between 0 and 1) and strong_magnitude is the strength of the strong motor (between 0 and 1). duration is the duration of the effect in seconds (a duration of 0 will try to play the vibration indefinitely).
+ Note that not every hardware is compatible with long effect durations, it is recommended to restart an effect if in need to play it for more than a few seconds.
</description>
</method>
<method name="stop_joy_vibration">
diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp
index 8350fb0674..d5becc0bfc 100644
--- a/drivers/gles2/rasterizer_gles2.cpp
+++ b/drivers/gles2/rasterizer_gles2.cpp
@@ -4666,7 +4666,7 @@ void RasterizerGLES2::_update_shader( Shader* p_shader) const {
enablers.push_back("#define USE_LIGHT_SHADER_CODE\n");
}
if (light_flags.uses_shadow_color) {
- enablers.push_back("#define USE_LIGHT_SHADOW_COLOR\n");
+ enablers.push_back("#define USE_OUTPUT_SHADOW_COLOR\n");
}
if (light_flags.uses_time || fragment_flags.uses_time || vertex_flags.uses_time) {
enablers.push_back("#define USE_TIME\n");
@@ -4709,7 +4709,7 @@ void RasterizerGLES2::_update_shader( Shader* p_shader) const {
enablers.push_back("#define USE_TEXPIXEL_SIZE\n");
}
if (light_flags.uses_shadow_color) {
- enablers.push_back("#define USE_LIGHT_SHADOW_COLOR\n");
+ enablers.push_back("#define USE_OUTPUT_SHADOW_COLOR\n");
}
if (vertex_flags.uses_worldvec) {
diff --git a/drivers/gles2/shader_compiler_gles2.cpp b/drivers/gles2/shader_compiler_gles2.cpp
index 3be0fdab17..d4636ed444 100644
--- a/drivers/gles2/shader_compiler_gles2.cpp
+++ b/drivers/gles2/shader_compiler_gles2.cpp
@@ -904,6 +904,7 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() {
mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["LIGHT_VEC"]="light_vec";
mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["LIGHT_HEIGHT"]="light_height";
mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["LIGHT_COLOR"]="light";
+ mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["LIGHT_SHADOW"]="light_shadow_color";
mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["LIGHT_UV"]="light_uv";
mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["LIGHT"]="light_out";
mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["SHADOW"]="shadow_color";
diff --git a/drivers/gles2/shaders/canvas.glsl b/drivers/gles2/shaders/canvas.glsl
index 285abd30ff..5f4767940d 100644
--- a/drivers/gles2/shaders/canvas.glsl
+++ b/drivers/gles2/shaders/canvas.glsl
@@ -244,7 +244,7 @@ FRAGMENT_SHADER_CODE
vec2 light_uv = light_uv_interp.xy;
vec4 light = texture2D(light_texture,light_uv) * light_color;
-#if defined(USE_LIGHT_SHADOW_COLOR)
+#if defined(USE_OUTPUT_SHADOW_COLOR)
vec4 shadow_color=vec4(0.0,0.0,0.0,0.0);
#endif
@@ -380,7 +380,7 @@ LIGHT_SHADER_CODE
#endif
-#if defined(USE_LIGHT_SHADOW_COLOR)
+#if defined(USE_OUTPUT_SHADOW_COLOR)
color=mix(shadow_color,color,shadow_attenuation);
#else
//color*=shadow_attenuation;
diff --git a/drivers/gles2/shaders/material.glsl b/drivers/gles2/shaders/material.glsl
index fd778f3442..477a451f2f 100644
--- a/drivers/gles2/shaders/material.glsl
+++ b/drivers/gles2/shaders/material.glsl
@@ -1185,7 +1185,7 @@ FRAGMENT_SHADER_CODE
vec3 mdiffuse = diffuse.rgb;
vec3 light;
-#if defined(USE_LIGHT_SHADOW_COLOR)
+#if defined(USE_OUTPUT_SHADOW_COLOR)
vec3 shadow_color=vec3(0.0,0.0,0.0);
#endif
@@ -1209,7 +1209,7 @@ LIGHT_SHADER_CODE
#endif
diffuse.rgb = const_light_mult * ambient_light *diffuse.rgb + light * attenuation * shadow_attenuation;
-#if defined(USE_LIGHT_SHADOW_COLOR)
+#if defined(USE_OUTPUT_SHADOW_COLOR)
diffuse.rgb += light * shadow_color * attenuation * (1.0 - shadow_attenuation);
#endif
diff --git a/drivers/vorbis/SCsub b/drivers/vorbis/SCsub
index 87805cc2d8..4afafcc4ba 100644
--- a/drivers/vorbis/SCsub
+++ b/drivers/vorbis/SCsub
@@ -5,7 +5,7 @@ sources = [
]
sources_lib = [
- "vorbis/analysis.c",
+ #"vorbis/analysis.c",
#"vorbis/barkmel.c",
"vorbis/bitrate.c",
"vorbis/block.c",
@@ -27,7 +27,7 @@ sources_lib = [
"vorbis/smallft.c",
"vorbis/synthesis.c",
#"vorbis/tone.c",
- "vorbis/vorbisenc.c",
+ #"vorbis/vorbisenc.c",
"vorbis/vorbisfile.c",
"vorbis/window.c",
]
diff --git a/main/main.cpp b/main/main.cpp
index ec4386ab20..d2ba38b094 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -994,8 +994,11 @@ Error Main::setup2() {
}
}
#ifdef TOOLS_ENABLED
+ ObjectTypeDB::set_current_api(ObjectTypeDB::API_EDITOR);
EditorNode::register_editor_types();
ObjectTypeDB::register_type<PCKPacker>(); // todo: move somewhere else
+ ObjectTypeDB::set_current_api(ObjectTypeDB::API_CORE);
+
#endif
MAIN_PRINT("Main: Load Scripts, Modules, Drivers");
@@ -1022,6 +1025,8 @@ Error Main::setup2() {
_start_success=true;
locale=String();
+ ObjectTypeDB::set_current_api(ObjectTypeDB::API_NONE); //no more api is registered at this point
+
MAIN_PRINT("Main: Done");
return OK;
diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp
index e576aa10e0..f33faaabd8 100644
--- a/scene/2d/camera_2d.cpp
+++ b/scene/2d/camera_2d.cpp
@@ -44,6 +44,9 @@ void Camera2D::_update_scroll() {
}
if (current) {
+
+ ERR_FAIL_COND( custom_viewport && !ObjectDB::get_instance(custom_viewport_id) );
+
Matrix32 xform = get_camera_transform();
if (viewport) {
@@ -73,8 +76,9 @@ Matrix32 Camera2D::get_camera_transform() {
if (!get_tree())
return Matrix32();
- Size2 screen_size = get_viewport_rect().size;
- screen_size=get_viewport_rect().size;
+ ERR_FAIL_COND_V( custom_viewport && !ObjectDB::get_instance(custom_viewport_id), Matrix32() );
+
+ Size2 screen_size = viewport->get_visible_rect().size;
Point2 new_camera_pos = get_global_transform().get_origin();
@@ -240,14 +244,10 @@ void Camera2D::_notification(int p_what) {
case NOTIFICATION_ENTER_TREE: {
- viewport = NULL;
- Node *n=this;
- while(n){
-
- viewport = n->cast_to<Viewport>();
- if (viewport)
- break;
- n=n->get_parent();
+ if (custom_viewport && ObjectDB::get_instance(custom_viewport_id)) {
+ viewport=custom_viewport;
+ } else {
+ viewport=get_viewport();
}
canvas = get_canvas();
@@ -270,8 +270,8 @@ void Camera2D::_notification(int p_what) {
} break;
case NOTIFICATION_EXIT_TREE: {
- if (is_current()) {
- if (viewport) {
+ if (is_current()) {
+ if (viewport && !(custom_viewport && !ObjectDB::get_instance(custom_viewport_id))) {
viewport->set_canvas_transform( Matrix32() );
}
}
@@ -447,8 +447,10 @@ void Camera2D::reset_smoothing() {
void Camera2D::align() {
- Size2 screen_size = get_viewport_rect().size;
- screen_size=get_viewport_rect().size;
+ ERR_FAIL_COND( custom_viewport && !ObjectDB::get_instance(custom_viewport_id) );
+
+ Size2 screen_size = viewport->get_visible_rect().size;
+
Point2 current_camera_pos = get_global_transform().get_origin();
if (anchor_mode==ANCHOR_MODE_DRAG_CENTER) {
if (h_ofs<0) {
@@ -549,6 +551,42 @@ bool Camera2D::is_follow_smoothing_enabled() const {
return smoothing_enabled;
}
+void Camera2D::set_custom_viewport(Node *p_viewport) {
+ ERR_FAIL_NULL(p_viewport);
+ if (is_inside_tree()) {
+ remove_from_group(group_name);
+ remove_from_group(canvas_group_name);
+ }
+
+ custom_viewport=p_viewport->cast_to<Viewport>();
+
+ if (custom_viewport) {
+ custom_viewport_id=custom_viewport->get_instance_ID();
+ } else {
+ custom_viewport_id=0;
+ }
+
+ if (is_inside_tree()) {
+
+ if (custom_viewport)
+ viewport=custom_viewport;
+ else
+ viewport=get_viewport();
+
+ RID vp = viewport->get_viewport();
+ group_name = "__cameras_"+itos(vp.get_id());
+ canvas_group_name ="__cameras_c"+itos(canvas.get_id());
+ add_to_group(group_name);
+ add_to_group(canvas_group_name);
+ }
+
+}
+
+Node* Camera2D::get_custom_viewport() const {
+
+ return custom_viewport;
+}
+
void Camera2D::_bind_methods() {
@@ -597,6 +635,8 @@ void Camera2D::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_zoom","zoom"),&Camera2D::set_zoom);
ObjectTypeDB::bind_method(_MD("get_zoom"),&Camera2D::get_zoom);
+ ObjectTypeDB::bind_method(_MD("set_custom_viewport","viewport:Viewport"),&Camera2D::set_custom_viewport);
+ ObjectTypeDB::bind_method(_MD("get_custom_viewport:Viewport"),&Camera2D::get_custom_viewport);
ObjectTypeDB::bind_method(_MD("set_follow_smoothing","follow_smoothing"),&Camera2D::set_follow_smoothing);
ObjectTypeDB::bind_method(_MD("get_follow_smoothing"),&Camera2D::get_follow_smoothing);
@@ -662,6 +702,8 @@ Camera2D::Camera2D() {
first=true;
smoothing_enabled=false;
limit_smoothing_enabled=false;
+ custom_viewport=NULL;
+ custom_viewport_id=0;
smoothing=5.0;
zoom = Vector2(1, 1);
diff --git a/scene/2d/camera_2d.h b/scene/2d/camera_2d.h
index 9f3e4254bb..a4d6dc5b96 100644
--- a/scene/2d/camera_2d.h
+++ b/scene/2d/camera_2d.h
@@ -48,6 +48,8 @@ protected:
Point2 smoothed_camera_pos;
bool first;
+ ObjectID custom_viewport_id; // to check validity
+ Viewport *custom_viewport;
Viewport *viewport;
StringName group_name;
@@ -128,6 +130,9 @@ public:
Point2 get_camera_screen_center() const;
+ void set_custom_viewport(Node *p_viewport);
+ Node* get_custom_viewport() const;
+
Vector2 get_camera_pos() const;
void force_update_scroll();
void reset_smoothing();
diff --git a/scene/main/canvas_layer.cpp b/scene/main/canvas_layer.cpp
index c31a57f819..8e238c7d77 100644
--- a/scene/main/canvas_layer.cpp
+++ b/scene/main/canvas_layer.cpp
@@ -168,20 +168,13 @@ void CanvasLayer::_notification(int p_what) {
case NOTIFICATION_ENTER_TREE: {
- Node *n = this;
- vp=NULL;
+ if (custom_viewport && ObjectDB::get_instance(custom_viewport_id)) {
- while(n) {
+ vp=custom_viewport;
+ } else {
+ vp=Node::get_viewport();
- if (n->cast_to<Viewport>()) {
-
- vp = n->cast_to<Viewport>();
- break;
- }
- n=n->get_parent();
}
-
-
ERR_FAIL_COND(!vp);
viewport=vp->get_viewport();
@@ -205,6 +198,7 @@ Size2 CanvasLayer::get_viewport_size() const {
if (!is_inside_tree())
return Size2(1,1);
+
Rect2 r = vp->get_visible_rect();
return r.size;
}
@@ -215,6 +209,43 @@ RID CanvasLayer::get_viewport() const {
return viewport;
}
+void CanvasLayer::set_custom_viewport(Node *p_viewport) {
+ ERR_FAIL_NULL(p_viewport);
+ if (is_inside_tree()) {
+ VisualServer::get_singleton()->viewport_remove_canvas(viewport,canvas->get_canvas());
+ viewport=RID();
+ }
+
+ custom_viewport=p_viewport->cast_to<Viewport>();
+
+ if (custom_viewport) {
+ custom_viewport_id=custom_viewport->get_instance_ID();
+ } else {
+ custom_viewport_id=0;
+ }
+
+ if (is_inside_tree()) {
+
+
+ if (custom_viewport)
+ vp=custom_viewport;
+ else
+ vp=Node::get_viewport();
+
+ viewport = vp->get_viewport();
+
+ VisualServer::get_singleton()->viewport_attach_canvas(viewport,canvas->get_canvas());
+ VisualServer::get_singleton()->viewport_set_canvas_layer(viewport,canvas->get_canvas(),layer);
+ VisualServer::get_singleton()->viewport_set_canvas_transform(viewport,canvas->get_canvas(),transform);
+ }
+
+}
+
+Node* CanvasLayer::get_custom_viewport() const {
+
+ return custom_viewport;
+}
+
void CanvasLayer::_bind_methods() {
@@ -241,8 +272,11 @@ void CanvasLayer::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_scale","scale"),&CanvasLayer::set_scale);
ObjectTypeDB::bind_method(_MD("get_scale"),&CanvasLayer::get_scale);
+ ObjectTypeDB::bind_method(_MD("set_custom_viewport","viewport:Viewport"),&CanvasLayer::set_custom_viewport);
+ ObjectTypeDB::bind_method(_MD("get_custom_viewport:Viewport"),&CanvasLayer::get_custom_viewport);
+
ObjectTypeDB::bind_method(_MD("get_world_2d:World2D"),&CanvasLayer::get_world_2d);
- ObjectTypeDB::bind_method(_MD("get_viewport"),&CanvasLayer::get_viewport);
+// ObjectTypeDB::bind_method(_MD("get_viewport"),&CanvasLayer::get_viewport);
ADD_PROPERTY( PropertyInfo(Variant::INT,"layer",PROPERTY_HINT_RANGE,"-128,128,1"),_SCS("set_layer"),_SCS("get_layer") );
//ADD_PROPERTY( PropertyInfo(Variant::MATRIX32,"transform",PROPERTY_HINT_RANGE),_SCS("set_transform"),_SCS("get_transform") );
@@ -260,4 +294,6 @@ CanvasLayer::CanvasLayer() {
locrotscale_dirty=false;
layer=1;
canvas = Ref<World2D>( memnew(World2D) );
+ custom_viewport=NULL;
+ custom_viewport_id=0;
}
diff --git a/scene/main/canvas_layer.h b/scene/main/canvas_layer.h
index a3e8211a43..6aad90a09d 100644
--- a/scene/main/canvas_layer.h
+++ b/scene/main/canvas_layer.h
@@ -45,6 +45,10 @@ class CanvasLayer : public Node {
int layer;
Matrix32 transform;
Ref<World2D> canvas;
+
+ ObjectID custom_viewport_id; // to check validity
+ Viewport *custom_viewport;
+
RID viewport;
Viewport *vp;
@@ -55,6 +59,7 @@ class CanvasLayer : public Node {
void _update_xform();
void _update_locrotscale();
+
protected:
void _notification(int p_what);
@@ -85,6 +90,9 @@ public:
RID get_viewport() const;
+ void set_custom_viewport(Node *p_viewport);
+ Node* get_custom_viewport() const;
+
CanvasLayer();
};
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 347d72aecd..b22d1fcdf4 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -359,13 +359,7 @@ void Viewport::_notification(int p_what) {
_update_listener_2d();
_update_rect();
- if (world_2d.is_valid()) {
- find_world_2d()->_register_viewport(this,Rect2());
-//best to defer this and not do it here, as it can annoy a lot of setup logic if user
-//adds a node and then moves it, will get enter/exit screen/viewport notifications
-//unnecesarily
-// update_worlds();
- }
+ find_world_2d()->_register_viewport(this,Rect2());
add_to_group("_viewports");
if (get_tree()->is_debugging_collisions_hint()) {
@@ -1001,19 +995,34 @@ bool Viewport::has_transparent_background() const {
return transparent_bg;
}
-#if 0
void Viewport::set_world_2d(const Ref<World2D>& p_world_2d) {
+ if (world_2d==p_world_2d)
+ return;
+
+ if (parent && parent->find_world_2d()==p_world_2d) {
+ WARN_PRINT("Unable to use parent world as world_2d");
+ return;
+ }
+
+ if (is_inside_tree()) {
+ find_world_2d()->_remove_viewport(this);
+ VisualServer::get_singleton()->viewport_remove_canvas(viewport,current_canvas);
+ }
+
+ if (p_world_2d.is_valid())
+ world_2d=p_world_2d;
+ else {
+ WARN_PRINT("Invalid world");
+ world_2d=Ref<World2D>( memnew( World2D ));
+ }
- world_2d=p_world_2d;
_update_listener_2d();
- if (is_inside_scene()) {
- if (current_canvas.is_valid())
- VisualServer::get_singleton()->viewport_remove_canvas(viewport,current_canvas);
+ if (is_inside_tree()) {
current_canvas=find_world_2d()->get_canvas();
VisualServer::get_singleton()->viewport_attach_canvas(viewport,current_canvas);
+ find_world_2d()->_register_viewport(this,Rect2());
}
-
}
Ref<World2D> Viewport::find_world_2d() const{
@@ -1025,13 +1034,6 @@ Ref<World2D> Viewport::find_world_2d() const{
else
return Ref<World2D>();
}
-#endif
-
-Ref<World2D> Viewport::find_world_2d() const{
-
- return world_2d;
-}
-
void Viewport::_propagate_enter_world(Node *p_node) {
@@ -1141,6 +1143,11 @@ Ref<World> Viewport::get_world() const{
return world;
}
+Ref<World2D> Viewport::get_world_2d() const{
+
+ return world_2d;
+}
+
Ref<World> Viewport::find_world() const{
if (own_world.is_valid())
@@ -1303,6 +1310,9 @@ void Viewport::render_target_clear() {
void Viewport::set_render_target_filter(bool p_enable) {
+ if(!render_target)
+ return;
+
render_target_texture->set_flags(p_enable?int(Texture::FLAG_FILTER):int(0));
}
@@ -2587,8 +2597,8 @@ void Viewport::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_rect","rect"), &Viewport::set_rect);
ObjectTypeDB::bind_method(_MD("get_rect"), &Viewport::get_rect);
- //ObjectTypeDB::bind_method(_MD("set_world_2d","world_2d:World2D"), &Viewport::set_world_2d);
- //ObjectTypeDB::bind_method(_MD("get_world_2d:World2D"), &Viewport::get_world_2d);
+ ObjectTypeDB::bind_method(_MD("set_world_2d","world_2d:World2D"), &Viewport::set_world_2d);
+ ObjectTypeDB::bind_method(_MD("get_world_2d:World2D"), &Viewport::get_world_2d);
ObjectTypeDB::bind_method(_MD("find_world_2d:World2D"), &Viewport::find_world_2d);
ObjectTypeDB::bind_method(_MD("set_world","world:World"), &Viewport::set_world);
ObjectTypeDB::bind_method(_MD("get_world:World"), &Viewport::get_world);
diff --git a/scene/main/viewport.h b/scene/main/viewport.h
index 145f642fd3..f657f0507d 100644
--- a/scene/main/viewport.h
+++ b/scene/main/viewport.h
@@ -305,9 +305,11 @@ public:
RID get_viewport() const;
void set_world(const Ref<World>& p_world);
+ void set_world_2d(const Ref<World2D>& p_world_2d);
Ref<World> get_world() const;
Ref<World> find_world() const;
+ Ref<World2D> get_world_2d() const;
Ref<World2D> find_world_2d() const;
diff --git a/scene/resources/shader_graph.cpp b/scene/resources/shader_graph.cpp
index 40ae26ba5d..02faa9425d 100644
--- a/scene/resources/shader_graph.cpp
+++ b/scene/resources/shader_graph.cpp
@@ -1483,6 +1483,8 @@ const ShaderGraph::InOutParamInfo ShaderGraph::inout_param_info[]={
{MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"LightColor","LIGHT_COLOR.rgb","",SLOT_TYPE_VEC,SLOT_IN},
{MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"LightAlpha","LIGHT_COLOR.a","",SLOT_TYPE_SCALAR,SLOT_IN},
{MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"LightHeight","LIGHT_HEIGHT","",SLOT_TYPE_SCALAR,SLOT_IN},
+ {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"ShadowColor","LIGHT_SHADOW.rgb","",SLOT_TYPE_VEC,SLOT_IN},
+ {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"ShadowAlpha","LIGHT_SHADOW.a","",SLOT_TYPE_SCALAR,SLOT_IN},
{MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"TexPixelSize","vec3(TEXTURE_PIXEL_SIZE,0)","",SLOT_TYPE_VEC,SLOT_IN},
{MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"Var1","VAR1.rgb","",SLOT_TYPE_VEC,SLOT_IN},
{MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"Var2","VAR2.rgb","",SLOT_TYPE_VEC,SLOT_IN},
@@ -1490,6 +1492,8 @@ const ShaderGraph::InOutParamInfo ShaderGraph::inout_param_info[]={
//canvas item light out
{MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"LightColor","LIGHT.rgb","",SLOT_TYPE_VEC,SLOT_OUT},
{MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"LightAlpha","LIGHT.a","",SLOT_TYPE_SCALAR,SLOT_OUT},
+ {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"ShadowColor","SHADOW.rgb","",SLOT_TYPE_VEC,SLOT_OUT},
+ {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"ShadowAlpha","SHADOW.a","",SLOT_TYPE_SCALAR,SLOT_OUT},
//end
{MODE_MATERIAL,SHADER_TYPE_FRAGMENT,NULL,NULL,NULL,SLOT_TYPE_SCALAR,SLOT_OUT},
diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp
index 09b3ada509..fdf3cb622d 100644
--- a/servers/visual/shader_language.cpp
+++ b/servers/visual/shader_language.cpp
@@ -1180,6 +1180,7 @@ const ShaderLanguage::BuiltinsDef ShaderLanguage::ci_light_builtins_defs[]={
{ "LIGHT_HEIGHT", TYPE_FLOAT},
{ "LIGHT_COLOR", TYPE_VEC4},
{ "LIGHT_UV", TYPE_VEC2},
+ { "LIGHT_SHADOW", TYPE_VEC4},
{ "LIGHT", TYPE_VEC4},
{ "SHADOW", TYPE_VEC4},
{ "POINT_COORD", TYPE_VEC2},
diff --git a/tools/editor/create_dialog.cpp b/tools/editor/create_dialog.cpp
index 5ff4df90f6..320939cb97 100644
--- a/tools/editor/create_dialog.cpp
+++ b/tools/editor/create_dialog.cpp
@@ -88,6 +88,8 @@ void CreateDialog::popup(bool p_dontclear) {
memdelete(f);
} else {
+#if 0
+// I think this was way too confusing
if (base_type=="Node") {
//harcode some favorites :D
favorite_list.push_back("Panel");
@@ -107,6 +109,7 @@ void CreateDialog::popup(bool p_dontclear) {
favorite_list.push_back("AnimationPlayer");
}
+#endif
}
_update_favorite_list();
diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp
index 65cc383a00..3b1e90a907 100644
--- a/tools/editor/editor_node.cpp
+++ b/tools/editor/editor_node.cpp
@@ -1217,6 +1217,7 @@ void EditorNode::_dialog_action(String p_file) {
//_save_scene(p_file);
_save_scene_with_preview(p_file);
+ _call_build();
_run(true);
}
} break;
@@ -2636,6 +2637,7 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
} break;
case RUN_PLAY: {
_menu_option_confirm(RUN_STOP,true);
+ _call_build();
_run(false);
} break;
@@ -2671,6 +2673,7 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
} break;
case RUN_PLAY_SCENE: {
_menu_option_confirm(RUN_STOP,true);
+ _call_build();
_run(true);
} break;
@@ -2682,6 +2685,7 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
}
if (run_native->is_deploy_debug_remote_enabled()){
_menu_option_confirm(RUN_STOP,true);
+ _call_build();
emit_signal("play_pressed");
editor_run.run_native_notify();
}
@@ -4042,6 +4046,7 @@ void EditorNode::_quick_opened() {
void EditorNode::_quick_run() {
+ _call_build();
_run(false,quick_run->get_selected());
}
@@ -5244,6 +5249,24 @@ void EditorNode::add_plugin_init_callback(EditorPluginInitializeCallback p_callb
EditorPluginInitializeCallback EditorNode::plugin_init_callbacks[EditorNode::MAX_INIT_CALLBACKS];
+int EditorNode::build_callback_count=0;
+
+void EditorNode::add_build_callback(EditorBuildCallback p_callback) {
+
+ ERR_FAIL_COND(build_callback_count==MAX_INIT_CALLBACKS);
+
+ build_callbacks[build_callback_count++]=p_callback;
+}
+
+EditorPluginInitializeCallback EditorNode::build_callbacks[EditorNode::MAX_BUILD_CALLBACKS];
+
+void EditorNode::_call_build() {
+
+ for(int i=0;i<build_callback_count;i++) {
+ build_callbacks[i]();
+ }
+}
+
void EditorNode::_bind_methods() {
@@ -5366,10 +5389,15 @@ EditorNode::EditorNode() {
// load settings
if (!EditorSettings::get_singleton())
EditorSettings::create();
+
+ bool use_single_dock_column = false;
{
int dpi_mode = EditorSettings::get_singleton()->get("global/hidpi_mode");
if (dpi_mode==0) {
- editor_set_scale( OS::get_singleton()->get_screen_dpi(0) > 150 ? 2.0 : 1.0 );
+ editor_set_scale( OS::get_singleton()->get_screen_dpi(0) > 150 && OS::get_singleton()->get_screen_size(OS::get_singleton()->get_current_screen()).x>2000 ? 2.0 : 1.0 );
+
+ use_single_dock_column = OS::get_singleton()->get_screen_size(OS::get_singleton()->get_current_screen()).x<1200;
+
} else if (dpi_mode==1) {
editor_set_scale(0.75);
} else if (dpi_mode==2) {
@@ -5382,7 +5410,6 @@ EditorNode::EditorNode() {
}
-
ResourceLoader::set_abort_on_missing_resources(false);
FileDialog::set_default_show_hidden_files(EditorSettings::get_singleton()->get("file_dialog/show_hidden_files"));
EditorFileDialog::set_default_show_hidden_files(EditorSettings::get_singleton()->get("file_dialog/show_hidden_files"));
@@ -6201,12 +6228,24 @@ EditorNode::EditorNode() {
node_dock = memnew( NodeDock );
//node_dock->set_undoredo(&editor_data.get_undo_redo());
- dock_slot[DOCK_SLOT_RIGHT_BL]->add_child(node_dock);
+ if (use_single_dock_column) {
+ dock_slot[DOCK_SLOT_RIGHT_UL]->add_child(node_dock);
+ } else {
+ dock_slot[DOCK_SLOT_RIGHT_BL]->add_child(node_dock);
+ }
scenes_dock = memnew( FileSystemDock(this) );
scenes_dock->set_name(TTR("FileSystem"));
scenes_dock->set_display_mode(int(EditorSettings::get_singleton()->get("filesystem_dock/display_mode")));
- dock_slot[DOCK_SLOT_LEFT_UR]->add_child(scenes_dock);
+
+ if (use_single_dock_column) {
+ dock_slot[DOCK_SLOT_RIGHT_BL]->add_child(scenes_dock);
+ left_r_vsplit->hide();
+ dock_slot[DOCK_SLOT_LEFT_UR]->hide();
+ dock_slot[DOCK_SLOT_LEFT_BR]->hide();
+ } else {
+ dock_slot[DOCK_SLOT_LEFT_UR]->add_child(scenes_dock);
+ }
//prop_pallete->add_child(scenes_dock);
scenes_dock->connect("open",this,"open_request");
scenes_dock->connect("instance",this,"_instance_request");
diff --git a/tools/editor/editor_node.h b/tools/editor/editor_node.h
index 96242a144d..2fae5daced 100644
--- a/tools/editor/editor_node.h
+++ b/tools/editor/editor_node.h
@@ -95,6 +95,7 @@
typedef void (*EditorNodeInitCallback)();
typedef void (*EditorPluginInitializeCallback)();
+typedef void (*EditorBuildCallback)();
class EditorPluginList;
@@ -580,13 +581,18 @@ private:
void _toggle_distraction_free_mode();
enum {
- MAX_INIT_CALLBACKS=128
+ MAX_INIT_CALLBACKS=128,
+ MAX_BUILD_CALLBACKS=128
};
static int plugin_init_callback_count;
static EditorPluginInitializeCallback plugin_init_callbacks[MAX_INIT_CALLBACKS];
+
+ void _call_build();
+ static int build_callback_count;
+ static EditorBuildCallback build_callbacks[MAX_BUILD_CALLBACKS];
protected:
void _notification(int p_what);
static void _bind_methods();
@@ -754,6 +760,7 @@ public:
void get_singleton(const char* arg1, bool arg2);
static void add_init_callback(EditorNodeInitCallback p_callback) { _init_callbacks.push_back(p_callback); }
+ static void add_build_callback(EditorBuildCallback p_callback);
diff --git a/tools/editor/plugins/script_editor_plugin.cpp b/tools/editor/plugins/script_editor_plugin.cpp
index 522ceba1dc..fd25843de9 100644
--- a/tools/editor/plugins/script_editor_plugin.cpp
+++ b/tools/editor/plugins/script_editor_plugin.cpp
@@ -1362,10 +1362,8 @@ struct _ScriptEditorItemData {
void ScriptEditor::_update_script_colors() {
- bool enabled = EditorSettings::get_singleton()->get("text_editor/script_temperature_enabled");
+ bool script_temperature_enabled = EditorSettings::get_singleton()->get("text_editor/script_temperature_enabled");
bool highlight_current = EditorSettings::get_singleton()->get("text_editor/highlight_current_script");
- if (!enabled)
- return;
int hist_size = EditorSettings::get_singleton()->get("text_editor/script_temperature_history_size");
Color hot_color=EditorSettings::get_singleton()->get("text_editor/script_temperature_hot_color");
@@ -1379,22 +1377,25 @@ void ScriptEditor::_update_script_colors() {
continue;
script_list->set_item_custom_bg_color(i,Color(0,0,0,0));
- if (!n->has_meta("__editor_pass")) {
- continue;
- }
-
- int pass=n->get_meta("__editor_pass");
- int h = edit_pass - pass;
- if (h>hist_size) {
- continue;
- }
- int non_zero_hist_size = ( hist_size == 0 ) ? 1 : hist_size;
- float v = Math::ease((edit_pass-pass)/float(non_zero_hist_size),0.4);
bool current = tab_container->get_current_tab() == c;
if (current && highlight_current) {
script_list->set_item_custom_bg_color(i, EditorSettings::get_singleton()->get("text_editor/current_script_background_color"));
- } else {
+
+ } else if (script_temperature_enabled) {
+
+ if (!n->has_meta("__editor_pass")) {
+ continue;
+ }
+
+ int pass=n->get_meta("__editor_pass");
+ int h = edit_pass - pass;
+ if (h>hist_size) {
+ continue;
+ }
+ int non_zero_hist_size = ( hist_size == 0 ) ? 1 : hist_size;
+ float v = Math::ease((edit_pass-pass)/float(non_zero_hist_size),0.4);
+
script_list->set_item_custom_bg_color(i,hot_color.linear_interpolate(cold_color,v));
}
}
diff --git a/tools/editor/plugins/shader_graph_editor_plugin.cpp b/tools/editor/plugins/shader_graph_editor_plugin.cpp
index aa66a2e0d9..3ab906f84e 100644
--- a/tools/editor/plugins/shader_graph_editor_plugin.cpp
+++ b/tools/editor/plugins/shader_graph_editor_plugin.cpp
@@ -2422,6 +2422,7 @@ void ShaderGraphView::_create_node(int p_id) {
colors.push_back("Color");
colors.push_back("LightColor");
colors.push_back("Light");
+ colors.push_back("ShadowColor");
colors.push_back("Diffuse");
colors.push_back("Specular");
colors.push_back("Emmision");
@@ -2434,6 +2435,7 @@ void ShaderGraphView::_create_node(int p_id) {
reals.push_back("ShadeParam");
reals.push_back("SpecularExp");
reals.push_back("LightAlpha");
+ reals.push_back("ShadowAlpha");
reals.push_back("PointSize");
reals.push_back("Discard");
diff --git a/tools/editor/project_manager.cpp b/tools/editor/project_manager.cpp
index b9691ee7c4..b2eae2f6d1 100644
--- a/tools/editor/project_manager.cpp
+++ b/tools/editor/project_manager.cpp
@@ -1185,7 +1185,7 @@ ProjectManager::ProjectManager() {
{
int dpi_mode = EditorSettings::get_singleton()->get("global/hidpi_mode");
if (dpi_mode==0) {
- editor_set_scale( OS::get_singleton()->get_screen_dpi(0) > 150 ? 2.0 : 1.0 );
+ editor_set_scale( OS::get_singleton()->get_screen_dpi(0) > 150 && OS::get_singleton()->get_screen_size(OS::get_singleton()->get_current_screen()).x>2000 ? 2.0 : 1.0 );
} else if (dpi_mode==1) {
editor_set_scale(0.75);
} else if (dpi_mode==2) {