diff options
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) { |