From bcf27feb980aec593c7cb771984e46113cfad757 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Tue, 16 Dec 2014 22:31:57 -0300 Subject: New Code Completion -=-=-=-=-=-=-=-=-=- -Massive improvement to code completion -Argument hinting for functions If you manage to out-smart the code-completion in a situation where completion should be possible to guess, let me know. Please enter the commit message for your changes. Lines starting --- modules/gdscript/gd_editor.cpp | 1391 ++++++++++++++++++++++++++++++---------- 1 file changed, 1052 insertions(+), 339 deletions(-) (limited to 'modules/gdscript/gd_editor.cpp') diff --git a/modules/gdscript/gd_editor.cpp b/modules/gdscript/gd_editor.cpp index 546fed4e8..7bec0ebd9 100644 --- a/modules/gdscript/gd_editor.cpp +++ b/modules/gdscript/gd_editor.cpp @@ -312,171 +312,277 @@ String GDScriptLanguage::make_function(const String& p_class,const String& p_nam } -static void _parse_native_symbols(const StringName& p_native,bool p_static,List* r_options) { - if (!p_static) { - List methods; - ObjectTypeDB::get_method_list(p_native,&methods); - for(List::Element *E=methods.front();E;E=E->next()) { - if (!E->get().name.begins_with("_")) { - r_options->push_back(E->get().name); - } +struct GDCompletionIdentifier { + + StringName obj_type; + Variant::Type type; + Variant value; //im case there is a value, also return it +}; + + + +static GDCompletionIdentifier _get_type_from_variant(const Variant& p_variant) { + + GDCompletionIdentifier t; + t.type=p_variant.get_type(); + t.value=p_variant; + if (p_variant.get_type()==Variant::OBJECT) { + Object *obj = p_variant; + if (obj) { + //if (obj->cast_to()) { + // t.obj_type=obj->cast_to()->get_name(); + // t.value=Variant(); + //} else { + t.obj_type=obj->get_type(); + //} } } + return t; +} - List constants; - ObjectTypeDB::get_integer_constant_list(p_native,&constants); +static GDCompletionIdentifier _get_type_from_pinfo(const PropertyInfo& p_info) { - for(List::Element *E=constants.front();E;E=E->next()) { - r_options->push_back(E->get()); + GDCompletionIdentifier t; + t.type=p_info.type; + if (p_info.hint==PROPERTY_HINT_RESOURCE_TYPE) { + t.obj_type=p_info.hint_string; } - + return t; } +struct GDCompletionContext { -static bool _parse_script_symbols(const Ref& p_script,bool p_static,List* r_options,List::Element *p_indices); + const GDParser::ClassNode *_class; + const GDParser::FunctionNode *function; + const GDParser::BlockNode *block; + Object* base; + String base_path; +}; -static bool _parse_completion_variant(const Variant& p_var,List* r_options,List::Element *p_indices) { - if (p_indices) { +static Ref _get_parent_class(GDCompletionContext& context) { - bool ok; - Variant si = p_var.get(p_indices->get(),&ok); - if (!ok) - return false; - return _parse_completion_variant(si,r_options,p_indices->next()); - } else { - switch(p_var.get_type()) { + if (context._class->extends_used) { + //do inheritance + String path = context._class->extends_file; + + Ref script; + Ref native; - case Variant::DICTIONARY: { + if (path!="") { + //path (and optionally subclasses) - Dictionary d=p_var; - List vl; - d.get_key_list(&vl); - for (List::Element *E=vl.front();E;E=E->next()) { + if (path.is_rel_path()) { - if (E->get().get_type()==Variant::STRING) - r_options->push_back(E->get()); - } + path=context.base_path.plus_file(path); + } + script = ResourceLoader::load(path); + if (script.is_null()) { + return REF(); + } + if (script->is_valid()) { + + return REF(); + } + //print_line("EXTENDS PATH: "+path+" script is "+itos(script.is_valid())+" indices is "+itos(script->member_indices.size())+" valid? "+itos(script->valid)); + + if (context._class->extends_class.size()) { + for(int i=0;iextends_class.size();i++) { + + String sub = context._class->extends_class[i]; + if (script->get_subclasses().has(sub)) { - List ml; - p_var.get_method_list(&ml); - for(List::Element *E=ml.front();E;E=E->next()) { - r_options->push_back(E->get().name); + script=script->get_subclasses()[sub]; + } else { + + return REF(); + } } + } + + if (script.is_valid()) + return script; - } break; - case Variant::OBJECT: { + } else { + if (context._class->extends_class.size()==0) { + ERR_PRINT("BUG"); + return REF(); + } - Object *o=p_var; - if (o) { - print_line("OBJECT: "+o->get_type()); - if (p_var.is_ref() && o->cast_to()) { + String base=context._class->extends_class[0]; + const GDParser::ClassNode *p = context._class->owner; + Ref base_class; +#if 0 + while(p) { - Ref gds = p_var; - _parse_script_symbols(gds,true,r_options,NULL); - } else if (o->is_type("GDNativeClass")){ + if (p->subclasses.has(base)) { - GDNativeClass *gnc = o->cast_to(); - _parse_native_symbols(gnc->get_name(),false,r_options); + base_class=p->subclasses[base]; + break; + } + p=p->_owner; + } +#endif + if (base_class.is_valid()) { +#if 0 + for(int i=1;iextends_class.size();i++) { + + String subclass=context._class->extends_class[i]; + + if (base_class->subclasses.has(subclass)) { + + base_class=base_class->subclasses[subclass]; } else { - print_line("REGULAR BLEND"); - _parse_native_symbols(o->get_type(),false,r_options); + print_line("Could not find subclass: "+subclass); + return _get_type_from_class(context); //fail please } } - } break; - default: { + script=base_class; +#endif + + } else { + + if (context._class->extends_class.size()>1) { + + return REF(); + - List pi; - p_var.get_property_list(&pi); - for(List::Element *E=pi.front();E;E=E->next()) { - r_options->push_back(E->get().name); } - List cl; + //if not found, try engine classes + if (!GDScriptLanguage::get_singleton()->get_global_map().has(base)) { - p_var.get_numeric_constants_for_type(p_var.get_type(),&cl); - for(List::Element *E=cl.front();E;E=E->next()) { - r_options->push_back(E->get()); + return REF(); } - List ml; - p_var.get_method_list(&ml); - for(List::Element *E=ml.front();E;E=E->next()) { - r_options->push_back(E->get().name); + int base_idx = GDScriptLanguage::get_singleton()->get_global_map()[base]; + native = GDScriptLanguage::get_singleton()->get_global_array()[base_idx]; + if (!native.is_valid()) { + + print_line("Global not a class: '"+base+"'"); + } + return native; + } + - } break; } - return true; } - + return Ref(); } -struct GDCompletionIdentifier { - StringName obj_type; - Variant::Type type; -}; +static GDCompletionIdentifier _get_native_class(GDCompletionContext& context) { + //eeh... + GDCompletionIdentifier id; + id.type=Variant::NIL; -static GDCompletionIdentifier _guess_identifier_type(const GDParser::ClassNode *p_class,int p_line,const StringName& p_identifier); + REF pc = _get_parent_class(context); + if (!pc.is_valid()) { + return id; + } + Ref nc = pc; + Ref s = pc; + if (s.is_null() && nc.is_null()) { + return id; + } + while(!s.is_null()) { + nc=s->get_native(); + s=s->get_base(); + } + if (nc.is_null()) { + return id; + } + + + + id.type=Variant::OBJECT; + if (context.base) + id.value=context.base; + id.obj_type=nc->get_name(); + return id; +} + +static bool _guess_identifier_type(GDCompletionContext& context,int p_line,const StringName& p_identifier,GDCompletionIdentifier &r_type); -static bool _guess_identifier_type_in_expression(const GDParser::ClassNode *p_class,const GDParser::Node *p_node,int p_line,GDCompletionIdentifier &r_type) { + +static bool _guess_expression_type(GDCompletionContext& context,const GDParser::Node* p_node,int p_line,GDCompletionIdentifier &r_type) { if (p_node->type==GDParser::Node::TYPE_CONSTANT) { const GDParser::ConstantNode *cn=static_cast(p_node); - r_type.type=cn->value.get_type(); - if (r_type.type==Variant::OBJECT) { - Object *obj = cn->value; - if (obj) { - r_type.obj_type=obj->get_type(); - } - } + r_type=_get_type_from_variant(cn->value); return true; } else if (p_node->type==GDParser::Node::TYPE_DICTIONARY) { r_type.type=Variant::DICTIONARY; + + + //what the heck, fill it anyway + const GDParser::DictionaryNode *an = static_cast(p_node); + Dictionary d; + for(int i=0;ielements.size();i++) { + GDCompletionIdentifier k; + if (_guess_expression_type(context,an->elements[i].key,p_line,k) && k.value.get_type()!=Variant::NIL) { + GDCompletionIdentifier v; + if (_guess_expression_type(context,an->elements[i].value,p_line,v)) { + d[k.value]=v.value; + } + + } + } + r_type.value=d; return true; } else if (p_node->type==GDParser::Node::TYPE_ARRAY) { r_type.type=Variant::ARRAY; + //what the heck, fill it anyway + const GDParser::ArrayNode *an = static_cast(p_node); + Array arr; + arr.resize(an->elements.size()); + for(int i=0;ielements.size();i++) { + GDCompletionIdentifier ci; + if (_guess_expression_type(context,an->elements[i],p_line,ci)) { + arr[i]=ci.value; + } + } + r_type.value=arr; return true; } else if (p_node->type==GDParser::Node::TYPE_BUILT_IN_FUNCTION) { MethodInfo mi = GDFunctions::get_info(static_cast(p_node)->function); - r_type.type=mi.return_val.type; - if (mi.return_val.hint==PROPERTY_HINT_RESOURCE_TYPE) { - r_type.obj_type=mi.return_val.hint_string; - } + r_type=_get_type_from_pinfo(mi.return_val); + return true; } else if (p_node->type==GDParser::Node::TYPE_IDENTIFIER) { - - r_type=_guess_identifier_type(p_class,p_line,static_cast(p_node)->name); - return true; + return _guess_identifier_type(context,p_line-1,static_cast(p_node)->name,r_type); } else if (p_node->type==GDParser::Node::TYPE_SELF) { //eeh... - return false; + + r_type=_get_native_class(context); + return r_type.type!=Variant::NIL; } else if (p_node->type==GDParser::Node::TYPE_OPERATOR) { + + const GDParser::OperatorNode *op = static_cast(p_node); if (op->op==GDParser::OperatorNode::OP_CALL) { - if (op->arguments[0]->type==GDParser::Node::TYPE_TYPE) { const GDParser::TypeNode *tn = static_cast(op->arguments[0]); @@ -486,25 +592,76 @@ static bool _guess_identifier_type_in_expression(const GDParser::ClassNode *p_cl const GDParser::BuiltInFunctionNode *bin = static_cast(op->arguments[0]); - return _guess_identifier_type_in_expression(p_class,bin,p_line,r_type); + return _guess_expression_type(context,bin,p_line,r_type); } else if (op->arguments.size()>1 && op->arguments[1]->type==GDParser::Node::TYPE_IDENTIFIER) { + GDCompletionIdentifier base; - if (!_guess_identifier_type_in_expression(p_class,op->arguments[0],p_line,base)) + if (!_guess_expression_type(context,op->arguments[0],p_line,base)) return false; - StringName id = static_cast(p_node)->name; + + StringName id = static_cast(op->arguments[1])->name; + if (base.type==Variant::OBJECT) { + if (ObjectTypeDB::has_method(base.obj_type,id)) { + #ifdef TOOLS_ENABLED MethodBind *mb = ObjectTypeDB::get_method(base.obj_type,id); PropertyInfo pi = mb->get_argument_info(-1); + //try calling the function if constant and all args are constant, should not crash.. + Object *baseptr = base.value; + + if (baseptr && mb->is_const() && pi.type==Variant::OBJECT) { + bool all_valid=true; + Vector args; + for(int i=2;iarguments.size();i++) { + GDCompletionIdentifier arg; + + if (_guess_expression_type(context,op->arguments[i],p_line,arg)) { + if (arg.value.get_type()!=Variant::NIL && arg.value.get_type()!=Variant::OBJECT) { // calling with object seems dangerous, i don' t know + args.push_back(arg.value); + } else { + all_valid=false; + break; + } + } else { + all_valid=false; + } + } + if (all_valid) { + Vector argptr; + for(int i=0;icall(baseptr,argptr.ptr(),argptr.size(),ce); + + + if (ce.error==Variant::CallError::CALL_OK && ret.get_type()!=Variant::NIL) { + + if (ret.get_type()!=Variant::OBJECT || ret.operator Object*()!=NULL) { + + r_type=_get_type_from_variant(ret); + return true; + } + } + + } + } + r_type.type=pi.type; if (pi.hint==PROPERTY_HINT_RESOURCE_TYPE) { r_type.obj_type=pi.hint_string; } + + + + return true; #else return false; #endif @@ -534,49 +691,157 @@ static bool _guess_identifier_type_in_expression(const GDParser::ClassNode *p_cl } + } else if (op->op==GDParser::OperatorNode::OP_INDEX || op->op==GDParser::OperatorNode::OP_INDEX_NAMED) { + + GDCompletionIdentifier p1; + GDCompletionIdentifier p2; + + + + if (op->op==GDParser::OperatorNode::OP_INDEX_NAMED) { + + if (op->arguments[1]->type==GDParser::Node::TYPE_IDENTIFIER) { + String id = static_cast(op->arguments[1])->name; + p2.type=Variant::STRING; + p2.value=id; + } + + } else { + if (op->arguments[1]) { + if (!_guess_expression_type(context,op->arguments[1],p_line,p2)) { + + return false; + } + } + } + + if (op->arguments[0]->type==GDParser::Node::TYPE_ARRAY) { + + const GDParser::ArrayNode *an = static_cast(op->arguments[0]); + if (p2.value.is_num()) { + int index = p2.value; + if (index<0 || index>=an->elements.size()) + return false; + return _guess_expression_type(context,an->elements[index],p_line,r_type); + } + + } else if (op->arguments[0]->type==GDParser::Node::TYPE_DICTIONARY) { + + const GDParser::DictionaryNode *dn = static_cast(op->arguments[0]); + + if (p2.value.get_type()==Variant::NIL) + return false; + + for(int i=0;ielements.size();i++) { + + GDCompletionIdentifier k; + + if (!_guess_expression_type(context,dn->elements[i].key,p_line,k)) { + + return false; + } + + if (k.value.get_type()==Variant::NIL) + return false; + + if (k.value==p2.value) { + + return _guess_expression_type(context,dn->elements[i].value,p_line,r_type); + } + } + + } else { + + if (op->arguments[0]) { + if (!_guess_expression_type(context,op->arguments[0],p_line,p1)) { + + return false; + } + + } + + if (p1.value.get_type()==Variant::OBJECT) { + //?? + } else if (p1.value.get_type()!=Variant::NIL) { + + bool valid; + Variant ret = p1.value.get(p2.value,&valid); + if (valid) { + r_type=_get_type_from_variant(ret); + return true; + } + + } else { + if (p1.type!=Variant::NIL) { + Variant::CallError ce; + Variant base = Variant::construct(p1.type,NULL,0,ce); + bool valid; + Variant ret = base.get(p2.value,&valid); + if (valid) { + r_type=_get_type_from_variant(ret); + return true; + } + } + } + } + } else { + Variant::Operator vop = Variant::OP_MAX; switch(op->op) { - case GDParser::OperatorNode::OP_ASSIGN_ADD: vop=Variant::OP_ADD; break; - case GDParser::OperatorNode::OP_ASSIGN_SUB: vop=Variant::OP_SUBSTRACT; break; - case GDParser::OperatorNode::OP_ASSIGN_MUL: vop=Variant::OP_MULTIPLY; break; - case GDParser::OperatorNode::OP_ASSIGN_DIV: vop=Variant::OP_DIVIDE; break; - case GDParser::OperatorNode::OP_ASSIGN_MOD: vop=Variant::OP_MODULE; break; - case GDParser::OperatorNode::OP_ASSIGN_SHIFT_LEFT: vop=Variant::OP_SHIFT_LEFT; break; - case GDParser::OperatorNode::OP_ASSIGN_SHIFT_RIGHT: vop=Variant::OP_SHIFT_RIGHT; break; - case GDParser::OperatorNode::OP_ASSIGN_BIT_AND: vop=Variant::OP_BIT_AND; break; - case GDParser::OperatorNode::OP_ASSIGN_BIT_OR: vop=Variant::OP_BIT_OR; break; - case GDParser::OperatorNode::OP_ASSIGN_BIT_XOR: vop=Variant::OP_BIT_XOR; break; + case GDParser::OperatorNode::OP_ADD: vop=Variant::OP_ADD; break; + case GDParser::OperatorNode::OP_SUB: vop=Variant::OP_SUBSTRACT; break; + case GDParser::OperatorNode::OP_MUL: vop=Variant::OP_MULTIPLY; break; + case GDParser::OperatorNode::OP_DIV: vop=Variant::OP_DIVIDE; break; + case GDParser::OperatorNode::OP_MOD: vop=Variant::OP_MODULE; break; + case GDParser::OperatorNode::OP_SHIFT_LEFT: vop=Variant::OP_SHIFT_LEFT; break; + case GDParser::OperatorNode::OP_SHIFT_RIGHT: vop=Variant::OP_SHIFT_RIGHT; break; + case GDParser::OperatorNode::OP_BIT_AND: vop=Variant::OP_BIT_AND; break; + case GDParser::OperatorNode::OP_BIT_OR: vop=Variant::OP_BIT_OR; break; + case GDParser::OperatorNode::OP_BIT_XOR: vop=Variant::OP_BIT_XOR; break; default:{} } + + if (vop==Variant::OP_MAX) return false; + + GDCompletionIdentifier p1; GDCompletionIdentifier p2; if (op->arguments[0]) { - if (!_guess_identifier_type_in_expression(p_class,op->arguments[0],p_line,p1)) + if (!_guess_expression_type(context,op->arguments[0],p_line,p1)) { + return false; + } + } if (op->arguments.size()>1) { - if (!_guess_identifier_type_in_expression(p_class,op->arguments[1],p_line,p2)) + if (!_guess_expression_type(context,op->arguments[1],p_line,p2)) { + return false; + } } Variant::CallError ce; - Variant v1 = Variant::construct(p1.type,NULL,0,ce); - Variant v2 = Variant::construct(p2.type,NULL,0,ce); + bool v1_use_value = p1.value.get_type()!=Variant::NIL && p1.value.get_type()!=Variant::OBJECT; + Variant v1 = (v1_use_value)?p1.value:Variant::construct(p1.type,NULL,0,ce); + bool v2_use_value = p2.value.get_type()!=Variant::NIL && p2.value.get_type()!=Variant::OBJECT; + Variant v2 = (v2_use_value)?p2.value:Variant::construct(p2.type,NULL,0,ce); // avoid potential invalid ops if ((vop==Variant::OP_DIVIDE || vop==Variant::OP_MODULE) && v2.get_type()==Variant::INT) { v2=1; + v2_use_value=false; } if (vop==Variant::OP_DIVIDE && v2.get_type()==Variant::REAL) { v2=1.0; + v2_use_value=false; } Variant r; @@ -585,6 +850,9 @@ static bool _guess_identifier_type_in_expression(const GDParser::ClassNode *p_cl if (!valid) return false; r_type.type=r.get_type(); + if (v1_use_value && v2_use_value) + r_type.value=r; + return true; } @@ -594,46 +862,42 @@ static bool _guess_identifier_type_in_expression(const GDParser::ClassNode *p_cl return false; } -static bool _guess_identifier_type_in_block(const GDParser::ClassNode *p_class,const GDParser::BlockNode *p_block,int p_line,const StringName& p_identifier,GDCompletionIdentifier &r_type) { - - - for(int i=0;isub_blocks.size();i++) { - //parse inner first - if (p_line>=p_block->sub_blocks[i]->line && (p_line<=p_block->sub_blocks[i]->end_line || p_block->sub_blocks[i]->end_line==-1)) { - if (_guess_identifier_type_in_block(p_class,p_block->sub_blocks[i],p_line,p_identifier,r_type)) - return true; - } - } +static bool _guess_identifier_type_in_block(GDCompletionContext& context,int p_line,const StringName& p_identifier,GDCompletionIdentifier &r_type) { const GDParser::Node *last_assign=NULL; int last_assign_line=-1; - for (int i=0;istatements.size();i++) { + for (int i=0;istatements.size();i++) { - if (p_block->statements[i]->line>p_line) - break; + if (context.block->statements[i]->line>p_line) + continue; - if (p_block->statements[i]->type==GDParser::BlockNode::TYPE_LOCAL_VAR) { + if (context.block->statements[i]->type==GDParser::BlockNode::TYPE_LOCAL_VAR) { + + const GDParser::LocalVarNode *lv=static_cast(context.block->statements[i]); - const GDParser::LocalVarNode *lv=static_cast(p_block->statements[i]); if (lv->assign && lv->name==p_identifier) { + last_assign=lv->assign; - last_assign_line=p_block->statements[i]->line; + last_assign_line=context.block->statements[i]->line; } } - if (p_block->statements[i]->type==GDParser::BlockNode::TYPE_OPERATOR) { - const GDParser::OperatorNode *op = static_cast(p_block->statements[i]); + if (context.block->statements[i]->type==GDParser::BlockNode::TYPE_OPERATOR) { + const GDParser::OperatorNode *op = static_cast(context.block->statements[i]); if (op->op==GDParser::OperatorNode::OP_ASSIGN) { if (op->arguments.size() && op->arguments[0]->type==GDParser::Node::TYPE_IDENTIFIER) { + const GDParser::IdentifierNode *id = static_cast(op->arguments[0]); + if (id->name==p_identifier) { + last_assign=op->arguments[1]; - last_assign_line=p_block->statements[i]->line; + last_assign_line=context.block->statements[i]->line; } } } @@ -642,382 +906,830 @@ static bool _guess_identifier_type_in_block(const GDParser::ClassNode *p_class,c //use the last assignment, (then backwards?) if (last_assign) { - return _guess_identifier_type_in_expression(p_class,last_assign,last_assign_line-1,r_type); + + return _guess_expression_type(context,last_assign,last_assign_line,r_type); } + return false; } -static GDCompletionIdentifier _guess_identifier_type(const GDParser::ClassNode *p_class,int p_line,const StringName& p_identifier) { - - - return GDCompletionIdentifier(); -} +static bool _guess_identifier_type(GDCompletionContext& context,int p_line,const StringName& p_identifier,GDCompletionIdentifier &r_type) { -static void _parse_expression_node(const GDParser::ClassNode *p_class,const GDParser::Node *p_node,int p_line,List* r_options,List::Element *p_indices) { + //go to block first + const GDParser::BlockNode *block=context.block; - if (p_node->type==GDParser::Node::TYPE_CONSTANT) { + while(block) { - const GDParser::ConstantNode *cn=static_cast(p_node); - _parse_completion_variant(cn->value,r_options,p_indices?p_indices->next():NULL); - } else if (p_node->type==GDParser::Node::TYPE_DICTIONARY) { + GDCompletionContext c = context; + c.block=block; - const GDParser::DictionaryNode *dn=static_cast(p_node); - for (int i=0;ielements.size();i++) { + if (_guess_identifier_type_in_block(c,p_line,p_identifier,r_type)) { + return true; + } - if (dn->elements[i].key->type==GDParser::Node::TYPE_CONSTANT) { + block=block->parent_block; + } - const GDParser::ConstantNode *cn=static_cast(dn->elements[i].key); - if (cn->value.get_type()==Variant::STRING) { + //TODO guess identifier type of arguments (ONLY if this is a virtual function) + if (context.function && context.function->name!=StringName()) { - String str=cn->value; - if (p_indices) { + int argindex = -1; - if (str==p_indices->get()) { - _parse_expression_node(p_class,dn->elements[i].value,p_line,r_options,p_indices->next()); - return; - } + for(int i=0;iarguments.size();i++) { - } else { - r_options->push_back(str); - } - } + if (context.function->arguments[i]==p_identifier) { + argindex=i; + break; } + } - } else if (p_node->type==GDParser::Node::TYPE_BUILT_IN_FUNCTION) { - MethodInfo mi = GDFunctions::get_info(static_cast(p_node)->function); + if (argindex!=-1) { + GDCompletionIdentifier id =_get_native_class(context); + if (id.type==Variant::OBJECT && id.obj_type!=StringName()) { + //this kinda sucks but meh - Variant::CallError ce; - _parse_completion_variant(Variant::construct(mi.return_val.type,NULL,0,ce),r_options,p_indices?p_indices->next():NULL); - } else if (p_node->type==GDParser::Node::TYPE_IDENTIFIER) { + List vmethods; + ObjectTypeDB::get_virtual_methods(id.obj_type,&vmethods); + for (List::Element *E=vmethods.front();E;E=E->next()) { - //GDCompletionIdentifier idt = _guess_identifier_type(p_class,p_line-1,static_cast(p_node)->name); - //Variant::CallError ce; - //_parse_completion_variant(Variant::construct(mi.return_val.type,NULL,0,ce),r_options,p_indices?p_indices->next():NULL); - } -} -static bool _parse_completion_block(const GDParser::ClassNode *p_class,const GDParser::BlockNode *p_block,int p_line,List* r_options,List::Element *p_indices) { + if (E->get().name==context.function->name && argindexget().arguments.size()) { - print_line("COMPLETION BLOCK "+itos(p_block->line)+" -> "+itos(p_block->end_line)); + PropertyInfo arg=E->get().arguments[argindex]; - for(int i=0;isub_blocks.size();i++) { - //parse inner first - if (p_line>=p_block->sub_blocks[i]->line && (p_line<=p_block->sub_blocks[i]->end_line || p_block->sub_blocks[i]->end_line==-1)) { - if (_parse_completion_block(p_class,p_block->sub_blocks[i],p_line,r_options,p_indices)) - return true; + int scp = arg.name.find(":"); + if (scp!=-1) { + + + r_type.type=Variant::OBJECT; + r_type.obj_type=arg.name.substr(scp+1,arg.name.length()); + return true; + + } else { + + r_type.type=arg.type; + if (arg.hint==PROPERTY_HINT_RESOURCE_TYPE) + r_type.obj_type=arg.hint_string; + return true; + } + } + } + } } } - if (p_indices) { + //guess type in constant - //parse indices in expressions :| + for(int i=0;iconstant_expressions.size();i++) { - const GDParser::Node *last_assign=NULL; - int last_assign_line=-1; + if (context._class->constant_expressions[i].identifier==p_identifier) { + + ERR_FAIL_COND_V( context._class->constant_expressions[i].expression->type!=GDParser::Node::TYPE_CONSTANT, false ); + r_type=_get_type_from_variant(static_cast(context._class->constant_expressions[i].expression)->value ); + return true; + } + } - for (int i=0;istatements.size();i++) { + if (context.function && !context.function->_static) { - if (p_block->statements[i]->line>p_line) - break; + for(int i=0;ivariables.size();i++) { + if (context._class->variables[i].identifier==p_identifier) { - if (p_block->statements[i]->type==GDParser::BlockNode::TYPE_LOCAL_VAR) { + if (context._class->variables[i]._export.type!=Variant::NIL) { - const GDParser::LocalVarNode *lv=static_cast(p_block->statements[i]); - if (lv->assign && String(lv->name)==p_indices->get()) { - last_assign=lv->assign; - last_assign_line=p_block->statements[i]->line; + r_type=_get_type_from_pinfo(context._class->variables[i]._export); + return true; + } else if (context._class->variables[i].expression) { + return _guess_expression_type(context,context._class->variables[i].expression,context._class->variables[i].line,r_type); } } } + } - //use the last assignment, (then backwards?) - if (last_assign) { - _parse_expression_node(p_class,last_assign,last_assign_line,r_options,p_indices->next()); - return true; - } + //globals - } else { - //no indices, just add all variables and continue - for(int i=0;ivariables.size();i++) { - //parse variables second - if (p_line>=p_block->variable_lines[i]) { - r_options->push_back(p_block->variables[i]); - } else break; + for(Map::Element *E=GDScriptLanguage::get_singleton()->get_global_map().front();E;E=E->next()) { + if (E->key()==p_identifier) { + r_type=_get_type_from_variant(GDScriptLanguage::get_singleton()->get_global_array()[E->get()]); + return true; } - } + } return false; } -static bool _parse_script_symbols(const Ref& p_script,bool p_static,List* r_options,List::Element *p_indices) { +static void _find_identifiers_in_block(GDCompletionContext& context,int p_line,bool p_only_functions,Set& result) { - //for (Map >::Element ? + if (p_only_functions) + return; - if (!p_static && !p_indices) { - for(const Set::Element *E=p_script->get_members().front();E;E=E->next()) { + for (int i=0;istatements.size();i++) { - r_options->push_back(E->get()); + if (context.block->statements[i]->line>p_line) + continue; + + + if (context.block->statements[i]->type==GDParser::BlockNode::TYPE_LOCAL_VAR) { + + const GDParser::LocalVarNode *lv=static_cast(context.block->statements[i]); + result.insert(lv->name.operator String()); } } +} - for (const Map::Element *E=p_script->get_constants().front();E;E=E->next()) { +static void _find_identifiers_in_class(GDCompletionContext& context,bool p_static,bool p_only_functions,Set& result) { - if( p_indices) { - if (p_indices->get()==String(E->get())) { - _parse_completion_variant(E->get(),r_options,p_indices->next()); - return true; - } - } else { - r_options->push_back(E->key()); + if (!p_static && !p_only_functions) { + + for(int i=0;ivariables.size();i++) { + result.insert(context._class->variables[i].identifier); } } + if (!p_only_functions) { - if (!p_indices){ - for (const Map::Element *E=p_script->get_member_functions().front();E;E=E->next()) { + for(int i=0;iconstant_expressions.size();i++) { + result.insert(context._class->constant_expressions[i].identifier); + } - if (E->get().is_static() || !p_static) - r_options->push_back(E->key()); + for(int i=0;isubclasses.size();i++) { + result.insert(context._class->subclasses[i]->name); } + } - if (p_script->get_base().is_valid()){ - if (_parse_script_symbols(p_script->get_base(),p_static,r_options,p_indices)) - return true; - } else if (p_script->get_native().is_valid() && !p_indices) { - _parse_native_symbols(p_script->get_native()->get_name(),p_static,r_options); + for(int i=0;istatic_functions.size();i++) { + if (context._class->static_functions[i]->arguments.size()) + result.insert(context._class->static_functions[i]->name.operator String()+"("); + else + result.insert(context._class->static_functions[i]->name.operator String()+"()"); } - return false; -} + if (!p_static) { + for(int i=0;ifunctions.size();i++) { + if (context._class->functions[i]->arguments.size()) + result.insert(context._class->functions[i]->name.operator String()+"("); + else + result.insert(context._class->functions[i]->name.operator String()+"()"); + } + } -static bool _parse_completion_class(const String& p_base_path,const GDParser::ClassNode *p_class,int p_line,List* r_options,List::Element *p_indices) { + Ref base = _get_parent_class(context); - //checks known classes or built-in types for completion + while(true) { - if (p_indices && !p_indices->next()) { - //built-in types do not have sub-classes, try these first if no sub-indices exist. - static const char*_type_names[Variant::VARIANT_MAX]={ - "null","bool","int","float","String","Vector2","Rect2","Vector3","Matrix32","Plane","Quat","AABB","Matrix3","Trasnform", - "Color","Image","NodePath","RID","Object","InputEvent","Dictionary","Array","RawArray","IntArray","FloatArray","StringArray", - "Vector2Array","Vector3Array","ColorArray"}; + Ref script = base; + Ref nc = base; + if (script.is_valid()) { - for(int i=0;i::Element *E=script->get_members().front();E;E=E->next()) { + result.insert(E->get().operator String()); + } + } - if (p_indices->get()==_type_names[i]) { + if (!p_only_functions) { + for (const Map::Element *E=script->get_constants().front();E;E=E->next()) { + result.insert(E->key().operator String()); + } + } - List ic; + for (const Map::Element *E=script->get_member_functions().front();E;E=E->next()) { + if (!p_static || E->get().is_static()) { + if (E->get().get_argument_count()) + result.insert(E->key().operator String()+"("); + else + result.insert(E->key().operator String()+"()"); + } + } - Variant::get_numeric_constants_for_type(Variant::Type(i),&ic); - for(List::Element *E=ic.front();E;E=E->next()) { - r_options->push_back(E->get()); + if (!p_only_functions) { + for (const Map >::Element *E=script->get_subclasses().front();E;E=E->next()) { + result.insert(E->key().operator String()); } - return true; } - } + + base=script->get_base(); + if (base.is_null()) + base=script->get_native(); + } else if (nc.is_valid()) { + + if (!p_only_functions) { + + StringName type = nc->get_name(); + List constants; + ObjectTypeDB::get_integer_constant_list(type,&constants); + for(List::Element *E=constants.front();E;E=E->next()) { + result.insert(E->get()); + } + + List methods; + ObjectTypeDB::get_method_list(type,&methods); + for(List::Element *E=methods.front();E;E=E->next()) { + if (E->get().arguments.size()) + result.insert(E->get().name+"("); + else + result.insert(E->get().name+"()"); + } + } + break; + } else + break; + } - // check the sub-classes of current class +} - for(int i=0;isubclasses.size();i++) { +static void _find_identifiers(GDCompletionContext& context,int p_line,bool p_only_functions,Set& result) { - if (p_line>=p_class->subclasses[i]->line && (p_line<=p_class->subclasses[i]->end_line || p_class->subclasses[i]->end_line==-1)) { - // if OK in sub-classes, try completing the sub-class - if (_parse_completion_class(p_base_path,p_class->subclasses[i],p_line,r_options,p_indices)) - return true; - } + const GDParser::BlockNode *block=context.block; + + while(block) { + + GDCompletionContext c = context; + c.block=block; + + _find_identifiers_in_block(c,p_line,p_only_functions,result); + block=block->parent_block; } - bool in_static_func=false; + const GDParser::ClassNode *clss=context._class; + + bool _static=context.function->_static; - for(int i=0;ifunctions.size();i++) { + while(clss) { + GDCompletionContext c = context; + c._class=clss; + c.block=NULL; + c.function=NULL; + _find_identifiers_in_class(c,_static,p_only_functions,result); + clss=clss->owner; + } - const GDParser::FunctionNode *fu = p_class->functions[i]; + for(int i=0;i=fu->body->line && (p_line<=fu->body->end_line || fu->body->end_line==-1)) { - //if in function, first block stuff from outer to inner - if (_parse_completion_block(p_class,fu->body,p_line,r_options,p_indices)) - return true; - //then function arguments - if (!p_indices) { - for(int j=0;jarguments.size();j++) { + result.insert(GDFunctions::get_func_name(GDFunctions::Function(i))); + } + + for(const Map::Element *E=GDScriptLanguage::get_singleton()->get_global_map().front();E;E=E->next()) { + result.insert(E->key().operator String()); + } +} + + +static String _get_visual_datatype(const PropertyInfo& p_info) { + + String n = p_info.name; + int idx = n.find(":"); + if (idx!=-1) { + return n.substr(idx+1,n.length()); + } + + if (p_info.type==Variant::OBJECT && p_info.hint==PROPERTY_HINT_RESOURCE_TYPE) + return p_info.hint_string; + if (p_info.type==Variant::NIL) + return "void"; + + return Variant::get_type_name(p_info.type); +} + +static void _make_function_hint(const GDParser::FunctionNode* p_func,int p_argidx,String& arghint) { + + arghint="func "+p_func->name+"("; + for (int i=0;iarguments.size();i++) { + if (i>0) + arghint+=", "; + else + arghint+=" "; + + if (i==p_argidx) { + arghint+=String::chr(0xFFFF); + } + arghint+=p_func->arguments[i].operator String(); + int deffrom = p_func->arguments.size()-p_func->default_values.size(); + + if (i>=deffrom) { + int defidx = deffrom-i; + + if (defidx>=0 && defidxdefault_values.size()) { + + if (p_func->default_values[defidx]->type==GDParser::Node::TYPE_OPERATOR) { + + const GDParser::OperatorNode *op=static_cast(p_func->default_values[defidx]); + if (op->op==GDParser::OperatorNode::OP_ASSIGN) { + const GDParser::ConstantNode *cn=static_cast(op->arguments[1]); + arghint+="="+cn->value.get_construct_string(); + + } + } else { - r_options->push_back(fu->arguments[j]); } } } + if (i==p_argidx) { + arghint+=String::chr(0xFFFF); + } } + if (p_func->arguments.size()>0) + arghint+=" "; + arghint+=")"; +} - for(int i=0;istatic_functions.size();i++) { - const GDParser::FunctionNode *fu = p_class->static_functions[i]; +static void _find_type_arguments(const GDParser::Node*p_node,int p_line,const StringName& p_method,const GDCompletionIdentifier& id, int p_argidx, Set& result, String& arghint) { - if (p_line>=fu->body->line && (p_line<=fu->body->end_line || fu->body->end_line==-1)) { - //if in function, first block stuff from outer to inne - if (_parse_completion_block(p_class,fu->body,p_line,r_options,p_indices)) - return true; - //then function arguments - if (!p_indices) { - for(int j=0;jarguments.size();j++) { + if (id.type==Variant::OBJECT && id.obj_type!=StringName()) { + + + MethodBind *m = ObjectTypeDB::get_method(id.obj_type,p_method); + if (!m) + return; - r_options->push_back(fu->arguments[j]); + if (p_method.operator String()=="connect") { + + + if (p_argidx==0) { + List sigs; + ObjectTypeDB::get_signal_list(id.obj_type,&sigs); + for (List::Element *E=sigs.front();E;E=E->next()) { + result.insert("\""+E->get().name+"\""); } } + /*if (p_argidx==2) { - in_static_func=true; - } + ERR_FAIL_COND(p_node->type!=GDParser::Node::TYPE_OPERATOR); + const GDParser::OperatorNode *op=static_cast(p_node); + if (op->arguments.size()>) - } + }*/ + } else { + Object *obj=id.value; + if (obj) { + List options; + obj->get_argument_options(p_method,p_argidx,&options); + for(List::Element *E=options.front();E;E=E->next()) { - //add all local names - if (!p_indices) { + result.insert(E->get()); + } + } - if (!in_static_func) { + } - for(int i=0;ivariables.size();i++) { + arghint = _get_visual_datatype(m->get_argument_info(-1))+" "+p_method.operator String()+String("("); + for(int i=0;iget_argument_count();i++) { + if (i>0) + arghint+=", "; + else + arghint+=" "; - r_options->push_back(p_class->variables[i].identifier); + if (i==p_argidx) { + arghint+=String::chr(0xFFFF); } - } + String n = m->get_argument_info(i).name; + int dp = n.find(":"); + if (dp!=-1) + n=n.substr(0,dp); + arghint+=_get_visual_datatype(m->get_argument_info(i))+" "+n; + int deffrom = m->get_argument_count()-m->get_default_argument_count(); - for(int i=0;iconstant_expressions.size();i++) { - r_options->push_back(p_class->constant_expressions[i].identifier); - } + if (i>=deffrom) { + int defidx = i-deffrom; - if (!in_static_func) { - for(int i=0;ifunctions.size();i++) { + if (defidx>=0 && defidxget_default_argument_count()) { + Variant v= m->get_default_argument(i); + arghint+="="+v.get_construct_string(); + } + } - r_options->push_back(p_class->functions[i]->name); + if (i==p_argidx) { + arghint+=String::chr(0xFFFF); } + } + if (m->get_argument_count()>0) + arghint+=" "; - for(int i=0;istatic_functions.size();i++) { - r_options->push_back(p_class->static_functions[i]->name); - } + arghint+=")"; + } +} - if (p_class->extends_used) { - //do inheritance - String path = p_class->extends_file; +static void _find_call_arguments(GDCompletionContext& context,const GDParser::Node* p_node, int p_line,int p_argidx, Set& result, String& arghint) { - Ref script; - Ref native; - if (path!="") { - //path (and optionally subclasses) - script = ResourceLoader::load(path); - if (script.is_null()) { - return false; + if (!p_node || p_node->type!=GDParser::Node::TYPE_OPERATOR) { + + return; + } + + const GDParser::OperatorNode *op = static_cast(p_node); + + if (op->op!=GDParser::OperatorNode::OP_CALL) { + + return; + } + + if (op->arguments[0]->type==GDParser::Node::TYPE_BUILT_IN_FUNCTION) { + //complete built-in function + const GDParser::BuiltInFunctionNode *fn = static_cast(op->arguments[0]); + MethodInfo mi = GDFunctions::get_info(fn->function); + + arghint = _get_visual_datatype(mi.return_val)+" "+GDFunctions::get_func_name(fn->function)+String("("); + for(int i=0;i0) + arghint+=", "; + else + arghint+=" "; + if (i==p_argidx) { + arghint+=String::chr(0xFFFF); + } + arghint+=_get_visual_datatype(mi.arguments[i])+" "+mi.arguments[i].name; + if (i==p_argidx) { + arghint+=String::chr(0xFFFF); } - if (p_class->extends_class.size()) { + } + if (mi.arguments.size()>0) + arghint+=" "; + arghint+=")"; + + } else if (op->arguments[0]->type==GDParser::Node::TYPE_TYPE) { + //complete built-in function + const GDParser::TypeNode *tn = static_cast(op->arguments[0]); + + List mil; + Variant::get_constructor_list(tn->vtype,&mil); + + for(List::Element *E=mil.front();E;E=E->next()) { + + MethodInfo mi = E->get(); + if (mi.arguments.size()==0) + continue; + if (E->prev()) + arghint+="\n"; + arghint += Variant::get_type_name(tn->vtype)+" "+Variant::get_type_name(tn->vtype)+String("("); + for(int i=0;i0) + arghint+=", "; + else + arghint+=" "; + if (i==p_argidx) { + arghint+=String::chr(0xFFFF); + } + arghint+=_get_visual_datatype(mi.arguments[i])+" "+mi.arguments[i].name; + if (i==p_argidx) { + arghint+=String::chr(0xFFFF); + } - for(int i=0;iextends_class.size();i++) { + } + if (mi.arguments.size()>0) + arghint+=" "; + arghint+=")"; + } - String sub = p_class->extends_class[i]; - if (script->get_subclasses().has(sub)) { + } else if (op->arguments.size()>=2 && op->arguments[1]->type==GDParser::Node::TYPE_IDENTIFIER) { + //make sure identifier exists... - script=script->get_subclasses()[sub]; - } else { + const GDParser::IdentifierNode *id=static_cast(op->arguments[1]); - return false; + if (op->arguments[0]->type==GDParser::Node::TYPE_SELF) { + //self, look up + + for(int i=0;istatic_functions.size();i++) { + if (context._class->static_functions[i]->name==id->name) { + _make_function_hint(context._class->static_functions[i],p_argidx,arghint); + return; + } + } + + if (context.function && !context.function->_static) { + + for(int i=0;ifunctions.size();i++) { + if (context._class->functions[i]->name==id->name) { + _make_function_hint(context._class->functions[i],p_argidx,arghint); + return; } } } - } else { + Ref base = _get_parent_class(context); - ERR_FAIL_COND_V(p_class->extends_class.size()==0,false); - //look around for the subclasses + while(true) { - String base=p_class->extends_class[0]; - Ref base_class; -#if 0 - while(p) { + Ref script = base; + Ref nc = base; + if (script.is_valid()) { - if (p->subclasses.has(base)) { - base_class=p->subclasses[base]; + for (const Map::Element *E=script->get_member_functions().front();E;E=E->next()) { + + if (E->key()==id->name) { + + if (context.function && context.function->_static && !E->get().is_static()) + continue; + + + arghint = "func "+id->name.operator String()+String("("); + for(int i=0;iget().get_argument_count();i++) { + if (i>0) + arghint+=", "; + else + arghint+=" "; + if (i==p_argidx) { + arghint+=String::chr(0xFFFF); + } + arghint+=E->get().get_argument_name(i); + int deffrom = E->get().get_argument_count()-E->get().get_default_argument_count(); + if (i>=deffrom) { + int defidx = deffrom-i; + if (defidx>=0 && defidxget().get_default_argument_count()) { + arghint+="="+E->get().get_default_argument(defidx).get_construct_string(); + } + } + if (i==p_argidx) { + arghint+=String::chr(0xFFFF); + } + + } + if (E->get().get_argument_count()>0) + arghint+=" "; + arghint+=")"; + return; + } + } + + base=script->get_base(); + if (base.is_null()) + base=script->get_native(); + } else if (nc.is_valid()) { + + if (context.function && !context.function->_static) { + + GDCompletionIdentifier ci; + ci.type=Variant::OBJECT; + ci.obj_type=nc->get_name(); + if (!context._class->owner) + ci.value=context.base; + + _find_type_arguments(p_node,p_line,id->name,ci,p_argidx,result,arghint); + //guess type.. + /* + List methods; + ObjectTypeDB::get_method_list(type,&methods); + for(List::Element *E=methods.front();E;E=E->next()) { + //if (E->get().arguments.size()) + // result.insert(E->get().name+"("); + //else + // result.insert(E->get().name+"()"); + }*/ + } break; - } - p=p->_owner; + } else + break; + } + } else { - if (base_class.is_valid()) { - for(int i=1;iextends_class.size();i++) { + GDCompletionIdentifier ci; + if (_guess_expression_type(context,op->arguments[0],p_line,ci)) { - String subclass=p_class->extends_class[i]; + _find_type_arguments(p_node,p_line,id->name,ci,p_argidx,result,arghint); + return; + } - if (base_class->subclasses.has(subclass)) { + } - base_class=base_class->subclasses[subclass]; - } else { + } +#if 0 + bool _static=context.function->_static; - _set_error("Could not find subclass: "+subclass,p_class); - return ERR_FILE_NOT_FOUND; - } - } - } else { -#endif - if (p_class->extends_class.size()>1) { - return false; + for(int i=0;istatic_functions.size();i++) { + if (context._class->static_functions[i]->arguments.size()) + result.insert(context._class->static_functions[i]->name.operator String()+"("); + else + result.insert(context._class->static_functions[i]->name.operator String()+"()"); + } + + if (!p_static) { + + for(int i=0;ifunctions.size();i++) { + if (context._class->functions[i]->arguments.size()) + result.insert(context._class->functions[i]->name.operator String()+"("); + else + result.insert(context._class->functions[i]->name.operator String()+"()"); + } + } + + Ref base = _get_parent_class(context); + + while(true) { + + Ref script = base; + Ref nc = base; + if (script.is_valid()) { + if (!p_static && !p_only_functions) { + for (const Set::Element *E=script->get_members().front();E;E=E->next()) { + result.insert(E->get().operator String()); } - //if not found, try engine classes - if (!GDScriptLanguage::get_singleton()->get_global_map().has(base)) { - return false; + } + + if (!p_only_functions) { + for (const Map::Element *E=script->get_constants().front();E;E=E->next()) { + result.insert(E->key().operator String()); } + } - int base_idx = GDScriptLanguage::get_singleton()->get_global_map()[base]; - native = GDScriptLanguage::get_singleton()->get_global_array()[base_idx]; - if (!native.is_valid()) { - return false; + for (const Map::Element *E=script->get_member_functions().front();E;E=E->next()) { + if (!p_static || E->get().is_static()) { + if (E->get().get_argument_count()) + result.insert(E->key().operator String()+"("); + else + result.insert(E->key().operator String()+"()"); } -#if 0 } -#endif - } + if (!p_only_functions) { + for (const Map >::Element *E=script->get_subclasses().front();E;E=E->next()) { + result.insert(E->key().operator String()); + } + } - if (script.is_valid()) { - if (_parse_script_symbols(script,in_static_func,r_options,p_indices)) - return true; + base=script->get_base(); + if (base.is_null()) + base=script->get_native(); + } else if (nc.is_valid()) { - } else if (native.is_valid() && !p_indices) { + if (!p_only_functions) { + + StringName type = nc->get_name(); + List constants; + ObjectTypeDB::get_integer_constant_list(type,&constants); + for(List::Element *E=constants.front();E;E=E->next()) { + result.insert(E->get()); + } + + List methods; + ObjectTypeDB::get_method_list(type,&methods); + for(List::Element *E=methods.front();E;E=E->next()) { + if (E->get().arguments.size()) + result.insert(E->get().name+"("); + else + result.insert(E->get().name+"()"); + } + } + break; + } else + break; - _parse_native_symbols(native->get_name(),in_static_func,r_options); - } } - return false; + for(int i=0;i* r_options) { +} +Error GDScriptLanguage::complete_code(const String& p_code, const String& p_base_path, Object*p_owner, List* r_options, String &r_call_hint) { +/* bugs: + a[0]. does not work + functions should end in ( + when completing virtuals, ask for full back + */ + //print_line( p_code.replace(String::chr(0xFFFF),"")); GDParser p; Error err = p.parse(p_code,p_base_path); + bool isfunction=false; + Set options; + + GDCompletionContext context; + context._class=p.get_completion_class(); + context.block=p.get_completion_block(); + context.function=p.get_completion_function(); + context.base=p_owner; + context.base_path=p_base_path; + + switch(p.get_completion_type()) { + + case GDParser::COMPLETION_NONE: { + print_line("No completion"); + } break; + case GDParser::COMPLETION_BUILT_IN_TYPE_CONSTANT: { + print_line("Built in type constant"); + List constants; + Variant::get_numeric_constants_for_type(p.get_completion_built_in_constant(),&constants); + for(List::Element *E=constants.front();E;E=E->next()) { + options.insert(E->get().operator String()); + } + + + } break; + case GDParser::COMPLETION_FUNCTION: + isfunction=true; + case GDParser::COMPLETION_IDENTIFIER: { + + _find_identifiers(context,p.get_completion_line(),isfunction,options); + } break; + case GDParser::COMPLETION_PARENT_FUNCTION: { + print_line("parent function"); + + } break; + case GDParser::COMPLETION_METHOD: + isfunction=true; + case GDParser::COMPLETION_INDEX: { + + print_line("index"); + const GDParser::Node *node = p.get_completion_node(); + if (node->type!=GDParser::Node::TYPE_OPERATOR) + break; + + + + + GDCompletionIdentifier t; + if (_guess_expression_type(context,static_cast(node)->arguments[0],p.get_completion_line(),t)) { + + if (t.type==Variant::OBJECT && t.obj_type!=StringName()) { + if (!isfunction) { + ObjectTypeDB::get_integer_constant_list(t.obj_type,r_options); + } + List mi; + ObjectTypeDB::get_method_list(t.obj_type,&mi); + for (List::Element *E=mi.front();E;E=E->next()) { + + if (E->get().arguments.size()) + options.insert(E->get().name+"("); + else + options.insert(E->get().name+"()"); + + } + } else { + if (t.value.get_type()==Variant::NIL) { + Variant::CallError ce; + t.value=Variant::construct(t.type,NULL,0,ce); + } + + if (!isfunction) { + List pl; + t.value.get_property_list(&pl); + for (List::Element *E=pl.front();E;E=E->next()) { + + if (E->get().name.find("/")==-1) + options.insert(E->get().name); + } + } + + List mi; + t.value.get_method_list(&mi); + for (List::Element *E=mi.front();E;E=E->next()) { + if (E->get().arguments.size()) + options.insert(E->get().name+"("); + else + options.insert(E->get().name+"()"); + + } + } + } + + + + } break; + case GDParser::COMPLETION_CALL_ARGUMENTS: { + + _find_call_arguments(context,p.get_completion_node(),p.get_completion_line(),p.get_completion_argument_index(),options,r_call_hint); + } break; + + + } + + + for(Set::Element *E=options.front();E;E=E->next()) { + r_options->push_back(E->get()); + } +#if 0 // don't care much about error I guess const GDParser::Node* root = p.get_parse_tree(); ERR_FAIL_COND_V(root->type!=GDParser::Node::TYPE_CLASS,ERR_INVALID_DATA); @@ -1050,10 +1762,11 @@ Error GDScriptLanguage::complete_keyword(const String& p_code, int p_line, const r_options->push_back(E->key()); } } - +#endif return OK; } + void GDScriptLanguage::auto_indent_code(String& p_code,int p_from_line,int p_to_line) const { -- cgit v1.2.3-70-g09d2 From 2dd302ff906285c5fdcb5f7bc822eb786870327a Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Tue, 16 Dec 2014 23:17:35 -0300 Subject: -fix compilation issue -fix missing built-ins in completion -fix parse error --- modules/gdscript/gd_editor.cpp | 52 ++++++++++++++++-------------------------- modules/gdscript/gd_parser.cpp | 2 +- 2 files changed, 21 insertions(+), 33 deletions(-) (limited to 'modules/gdscript/gd_editor.cpp') diff --git a/modules/gdscript/gd_editor.cpp b/modules/gdscript/gd_editor.cpp index 7bec0ebd9..41caaa0dd 100644 --- a/modules/gdscript/gd_editor.cpp +++ b/modules/gdscript/gd_editor.cpp @@ -312,6 +312,7 @@ String GDScriptLanguage::make_function(const String& p_class,const String& p_nam } +#if defined(DEBUG_METHODS_ENABLED) && defined(TOOLS_ENABLED) struct GDCompletionIdentifier { @@ -1011,7 +1012,7 @@ static bool _guess_identifier_type(GDCompletionContext& context,int p_line,const } } - //globals + for(Map::Element *E=GDScriptLanguage::get_singleton()->get_global_map().front();E;E=E->next()) { if (E->key()==p_identifier) { @@ -1081,6 +1082,8 @@ static void _find_identifiers_in_class(GDCompletionContext& context,bool p_stati } } + //globals + Ref base = _get_parent_class(context); while(true) { @@ -1178,6 +1181,15 @@ static void _find_identifiers(GDCompletionContext& context,int p_line,bool p_onl result.insert(GDFunctions::get_func_name(GDFunctions::Function(i))); } + static const char*_type_names[Variant::VARIANT_MAX]={ + "null","bool","int","float","String","Vector2","Rect2","Vector3","Matrix32","Plane","Quat","AABB","Matrix3","Trasnform", + "Color","Image","NodePath","RID","Object","InputEvent","Dictionary","Array","RawArray","IntArray","FloatArray","StringArray", + "Vector2Array","Vector3Array","ColorArray"}; + + for(int i=0;i::Element *E=GDScriptLanguage::get_singleton()->get_global_map().front();E;E=E->next()) { result.insert(E->key().operator String()); } @@ -1286,6 +1298,7 @@ static void _find_type_arguments(const GDParser::Node*p_node,int p_line,const St } arghint = _get_visual_datatype(m->get_argument_info(-1))+" "+p_method.operator String()+String("("); + for(int i=0;iget_argument_count();i++) { if (i>0) arghint+=", "; @@ -1729,43 +1742,18 @@ Error GDScriptLanguage::complete_code(const String& p_code, const String& p_base for(Set::Element *E=options.front();E;E=E->next()) { r_options->push_back(E->get()); } -#if 0 - // don't care much about error I guess - const GDParser::Node* root = p.get_parse_tree(); - ERR_FAIL_COND_V(root->type!=GDParser::Node::TYPE_CLASS,ERR_INVALID_DATA); - - print_line("BASE: "+p_base); - const GDParser::ClassNode *cl = static_cast(root); - - List indices; - Vector spl = p_base.split("."); - - for(int i=0;i::Element *E=globals.front();E;E=E->next()) { - if (!indices.empty()) { - if (String(E->key())==indices.front()->get()) { + return OK; +} - _parse_completion_variant(global_array[E->get()],r_options,indices.front()->next()); +#else - return OK; - } - } else { - r_options->push_back(E->key()); - } - } -#endif +Error GDScriptLanguage::complete_code(const String& p_code, const String& p_base_path, Object*p_owner, List* r_options, String &r_call_hint) { return OK; } +#endif + void GDScriptLanguage::auto_indent_code(String& p_code,int p_from_line,int p_to_line) const { diff --git a/modules/gdscript/gd_parser.cpp b/modules/gdscript/gd_parser.cpp index 1c46a2f4f..f727512ff 100644 --- a/modules/gdscript/gd_parser.cpp +++ b/modules/gdscript/gd_parser.cpp @@ -374,7 +374,7 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_ completion_built_in_constant=bi_type; } - if (identifier!=StringName()) { + if (identifier==StringName()) { _set_error("Built-in type constant expected after '.'"); return NULL; -- cgit v1.2.3-70-g09d2 From fd4648c081afa565cb20c923c4e3c94d88e71e4f Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Tue, 16 Dec 2014 23:46:55 -0300 Subject: -fixed crash reported by n-pigeon --- modules/gdscript/gd_editor.cpp | 2 +- modules/gdscript/gd_parser.cpp | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'modules/gdscript/gd_editor.cpp') diff --git a/modules/gdscript/gd_editor.cpp b/modules/gdscript/gd_editor.cpp index 41caaa0dd..09f193706 100644 --- a/modules/gdscript/gd_editor.cpp +++ b/modules/gdscript/gd_editor.cpp @@ -1165,7 +1165,7 @@ static void _find_identifiers(GDCompletionContext& context,int p_line,bool p_onl const GDParser::ClassNode *clss=context._class; - bool _static=context.function->_static; + bool _static=context.function && context.function->_static; while(clss) { GDCompletionContext c = context; diff --git a/modules/gdscript/gd_parser.cpp b/modules/gdscript/gd_parser.cpp index f727512ff..f79f3ee44 100644 --- a/modules/gdscript/gd_parser.cpp +++ b/modules/gdscript/gd_parser.cpp @@ -2757,6 +2757,9 @@ Error GDParser::parse_bytecode(const Vector &p_bytecode,const String& p completion_class=NULL; completion_function=NULL; completion_block=NULL; + current_block=NULL; + current_class=NULL; + current_function=NULL; self_path=p_self_path; GDTokenizerBuffer *tb = memnew( GDTokenizerBuffer ); @@ -2776,6 +2779,10 @@ Error GDParser::parse(const String& p_code, const String& p_base_path, bool p_ju completion_class=NULL; completion_function=NULL; completion_block=NULL; + current_block=NULL; + current_class=NULL; + + current_function=NULL; self_path=p_self_path; GDTokenizerText *tt = memnew( GDTokenizerText ); @@ -2811,6 +2818,10 @@ void GDParser::clear() { completion_class=NULL; completion_function=NULL; completion_block=NULL; + current_block=NULL; + current_class=NULL; + + current_function=NULL; validating=false; error_set=false; -- cgit v1.2.3-70-g09d2 From 9f5bbfc322640c33c4accde98ffaee92a7b62cab Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Thu, 18 Dec 2014 00:56:33 -0300 Subject: -improved completion options for InputEvent, shows all event types now --- core/object_type_db.cpp | 17 +++++++- core/object_type_db.h | 2 +- modules/gdscript/gd_editor.cpp | 95 +++++++++++++++++++++++++++++++----------- scene/gui/text_edit.cpp | 12 +++++- 4 files changed, 98 insertions(+), 28 deletions(-) (limited to 'modules/gdscript/gd_editor.cpp') diff --git a/core/object_type_db.cpp b/core/object_type_db.cpp index 62244cbd4..efd92542c 100644 --- a/core/object_type_db.cpp +++ b/core/object_type_db.cpp @@ -805,12 +805,25 @@ void ObjectTypeDB::add_virtual_method(const StringName& p_type,const MethodInfo& } -void ObjectTypeDB::get_virtual_methods(const StringName& p_type,List * p_methods ) { +void ObjectTypeDB::get_virtual_methods(const StringName& p_type, List * p_methods , bool p_no_inheritance) { ERR_FAIL_COND(!types.has(p_type)); #ifdef DEBUG_METHODS_ENABLED - *p_methods=types[p_type].virtual_methods; + + TypeInfo *type=types.getptr(p_type); + TypeInfo *check=type; + while(check) { + + for(List::Element *E=check->virtual_methods.front();E;E=E->next()) { + p_methods->push_back(E->get()); + } + + if (p_no_inheritance) + return; + check=check->inherits_ptr; + } + #endif } diff --git a/core/object_type_db.h b/core/object_type_db.h index ae0644f9b..f2ff194e2 100644 --- a/core/object_type_db.h +++ b/core/object_type_db.h @@ -468,7 +468,7 @@ public: static MethodBind *get_method(StringName p_type, StringName p_name); static void add_virtual_method(const StringName& p_type,const MethodInfo& p_method ); - static void get_virtual_methods(const StringName& p_type,List * p_methods ); + static void get_virtual_methods(const StringName& p_type,List * p_methods,bool p_no_inheritance=false ); static void bind_integer_constant(const StringName& p_type, const StringName &p_name, int p_constant); static void get_integer_constant_list(const StringName& p_type, List *p_constants, bool p_no_inheritance=false); diff --git a/modules/gdscript/gd_editor.cpp b/modules/gdscript/gd_editor.cpp index 09f193706..f47b147db 100644 --- a/modules/gdscript/gd_editor.cpp +++ b/modules/gdscript/gd_editor.cpp @@ -1625,12 +1625,6 @@ static void _find_call_arguments(GDCompletionContext& context,const GDParser::No } Error GDScriptLanguage::complete_code(const String& p_code, const String& p_base_path, Object*p_owner, List* r_options, String &r_call_hint) { -/* bugs: - a[0]. does not work - functions should end in ( - when completing virtuals, ask for full back - - */ //print_line( p_code.replace(String::chr(0xFFFF),"")); GDParser p; @@ -1700,29 +1694,82 @@ Error GDScriptLanguage::complete_code(const String& p_code, const String& p_base } } else { - if (t.value.get_type()==Variant::NIL) { - Variant::CallError ce; - t.value=Variant::construct(t.type,NULL,0,ce); - } - if (!isfunction) { - List pl; - t.value.get_property_list(&pl); - for (List::Element *E=pl.front();E;E=E->next()) { + if (t.type==Variant::INPUT_EVENT) { + + //this is hardcoded otherwise it's not obvious + Set exclude; + + for(int i=0;ipush_back(evnames[i]); + + Variant v = ie; + + if (i==0) { + List mi; + v.get_method_list(&mi); + for (List::Element *E=mi.front();E;E=E->next()) { + r_options->push_back(E->get().name+"("); + + } + + } + + List pi; + v.get_property_list(&pi); + + for (List::Element *E=pi.front();E;E=E->next()) { + + if (i==0) + exclude.insert(E->get().name); + else if (exclude.has(E->get().name)) + continue; - if (E->get().name.find("/")==-1) - options.insert(E->get().name); + r_options->push_back(E->get().name); + } + } + return OK; + } else { + if (t.value.get_type()==Variant::NIL) { + Variant::CallError ce; + t.value=Variant::construct(t.type,NULL,0,ce); } - } - List mi; - t.value.get_method_list(&mi); - for (List::Element *E=mi.front();E;E=E->next()) { - if (E->get().arguments.size()) - options.insert(E->get().name+"("); - else - options.insert(E->get().name+"()"); + if (!isfunction) { + List pl; + t.value.get_property_list(&pl); + for (List::Element *E=pl.front();E;E=E->next()) { + + if (E->get().name.find("/")==-1) + options.insert(E->get().name); + } + } + + List mi; + t.value.get_method_list(&mi); + for (List::Element *E=mi.front();E;E=E->next()) { + if (E->get().arguments.size()) + options.insert(E->get().name+"("); + else + options.insert(E->get().name+"()"); + + } } } } diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 67d786cf4..a8cdfe906 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -793,6 +793,7 @@ void TextEdit::_notification(int p_what) { int maxlines = get_constant("completion_lines"); int cmax_width = get_constant("completion_max_width")*cache.font->get_char_size('x').x; Color existing = get_color("completion_existing"); + existing.a=0.2; int scrollw = get_constant("completion_scroll_width"); Color scrollc = get_color("completion_scroll_color"); @@ -841,11 +842,20 @@ void TextEdit::_notification(int p_what) { draw_rect(Rect2(completion_rect.pos,Size2(nofs,completion_rect.size.height)),existing); + + + for(int i=0;i= completion_options.size()); - draw_string(cache.font,Point2(completion_rect.pos.x,completion_rect.pos.y+i*get_row_height()+cache.font->get_ascent()),completion_options[l],cache.font_color,completion_rect.size.width); + Color text_color = cache.font_color; + for(int j=0;jget_ascent()),completion_options[l],text_color,completion_rect.size.width); } if (scrollw) { -- cgit v1.2.3-70-g09d2 From a36a774897ae191ebb90ba803bac7f919e92bd6c Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Sat, 20 Dec 2014 15:30:06 -0300 Subject: Fixes -=-=-= -Added missing quaternion constructor -code completion fixes -winrt fixes --- core/bind/core_bind.cpp | 6 +- core/bind/core_bind.h | 2 +- core/math/math_funcs.h | 2 +- core/register_core_types.cpp | 1 + core/variant_call.cpp | 6 + drivers/png/pngpriv.h | 6 +- drivers/vorbis/os.h | 2 +- modules/gdscript/gd_editor.cpp | 65 +++++++-- modules/gdscript/gd_script.cpp | 1 + platform/winrt/app.cpp | 25 +++- platform/winrt/detect.py | 102 ++++++++++--- platform/winrt/gl_context_egl.cpp | 28 +++- platform/winrt/gl_context_egl.h | 1 + platform/winrt/include/EGL/eglext.h | 21 ++- platform/winrt/include/EGL/eglplatform.h | 4 +- platform/winrt/include/GLSLANG/ShaderLang.h | 216 ++++++++-------------------- platform/winrt/include/GLSLANG/ShaderVars.h | 93 +++++++++--- platform/winrt/os_winrt.cpp | 9 ++ platform/winrt/os_winrt.h | 1 + scene/2d/collision_polygon_2d.cpp | 22 ++- scene/2d/collision_polygon_2d.h | 4 + scene/2d/physics_body_2d.cpp | 5 +- scene/3d/physics_body.cpp | 7 + 23 files changed, 396 insertions(+), 233 deletions(-) (limited to 'modules/gdscript/gd_editor.cpp') diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp index ef943b2f7..cc07a4836 100644 --- a/core/bind/core_bind.cpp +++ b/core/bind/core_bind.cpp @@ -12,9 +12,9 @@ Ref _ResourceLoader::load_interactive(const String& p return ResourceLoader::load_interactive(p_path,p_type_hint); } -RES _ResourceLoader::load(const String &p_path,const String& p_type_hint) { +RES _ResourceLoader::load(const String &p_path,const String& p_type_hint, bool p_no_cache) { - RES ret = ResourceLoader::load(p_path,p_type_hint); + RES ret = ResourceLoader::load(p_path,p_type_hint, p_no_cache); return ret; } @@ -59,7 +59,7 @@ void _ResourceLoader::_bind_methods() { ObjectTypeDB::bind_method(_MD("load_interactive:ResourceInteractiveLoader","path","type_hint"),&_ResourceLoader::load_interactive,DEFVAL("")); - ObjectTypeDB::bind_method(_MD("load:Resource","path","type_hint"),&_ResourceLoader::load,DEFVAL("")); + ObjectTypeDB::bind_method(_MD("load:Resource","path","type_hint", "p_no_cache"),&_ResourceLoader::load,DEFVAL(""), DEFVAL(false)); ObjectTypeDB::bind_method(_MD("get_recognized_extensions_for_type","type"),&_ResourceLoader::get_recognized_extensions_for_type); ObjectTypeDB::bind_method(_MD("set_abort_on_missing_resources","abort"),&_ResourceLoader::set_abort_on_missing_resources); ObjectTypeDB::bind_method(_MD("get_dependencies"),&_ResourceLoader::get_dependencies); diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h index a76b4aa81..12a4ae86e 100644 --- a/core/bind/core_bind.h +++ b/core/bind/core_bind.h @@ -21,7 +21,7 @@ public: static _ResourceLoader *get_singleton() { return singleton; } Ref load_interactive(const String& p_path,const String& p_type_hint=""); - RES load(const String &p_path,const String& p_type_hint=""); + RES load(const String &p_path,const String& p_type_hint="", bool p_no_cache = false); DVector get_recognized_extensions_for_type(const String& p_type); void set_abort_on_missing_resources(bool p_abort); StringArray get_dependencies(const String& p_path); diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h index 28a841332..6d43ed8e6 100644 --- a/core/math/math_funcs.h +++ b/core/math/math_funcs.h @@ -136,7 +136,7 @@ public: static int b; -#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0603 // windows 8? +#if (defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0603) || WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP // windows 8 phone? b = (int)((a>0.0f) ? (a + 0.5f):(a -0.5f)); #elif defined(_MSC_VER) && _MSC_VER < 1800 diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp index 2f16e31de..4935136ee 100644 --- a/core/register_core_types.cpp +++ b/core/register_core_types.cpp @@ -110,6 +110,7 @@ void register_core_types() { ObjectTypeDB::register_type(); + ObjectTypeDB::register_type(); ObjectTypeDB::register_type(); ObjectTypeDB::register_type(); ObjectTypeDB::register_type(); diff --git a/core/variant_call.cpp b/core/variant_call.cpp index 93a9e6475..3f2800494 100644 --- a/core/variant_call.cpp +++ b/core/variant_call.cpp @@ -757,6 +757,11 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var r_ret=Quat(*p_args[0],*p_args[1],*p_args[2],*p_args[3]); } + static void Quat_init2(Variant& r_ret,const Variant** p_args) { + + r_ret=Quat(((Vector3)(*p_args[0])),((float)(*p_args[1]))); + } + static void Color_init1(Variant& r_ret,const Variant** p_args) { r_ret=Color(*p_args[0],*p_args[1],*p_args[2],*p_args[3]); @@ -1509,6 +1514,7 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl _VariantCall::add_constructor(_VariantCall::Plane_init3,Variant::PLANE,"normal",Variant::VECTOR3,"d",Variant::REAL); _VariantCall::add_constructor(_VariantCall::Quat_init1,Variant::QUAT,"x",Variant::REAL,"y",Variant::REAL,"z",Variant::REAL,"w",Variant::REAL); + _VariantCall::add_constructor(_VariantCall::Quat_init2,Variant::QUAT,"axis",Variant::VECTOR3,"angle",Variant::REAL); _VariantCall::add_constructor(_VariantCall::Color_init1,Variant::COLOR,"r",Variant::REAL,"g",Variant::REAL,"b",Variant::REAL,"a",Variant::REAL); _VariantCall::add_constructor(_VariantCall::Color_init2,Variant::COLOR,"r",Variant::REAL,"g",Variant::REAL,"b",Variant::REAL); diff --git a/drivers/png/pngpriv.h b/drivers/png/pngpriv.h index 67e486c57..56532f4ee 100644 --- a/drivers/png/pngpriv.h +++ b/drivers/png/pngpriv.h @@ -341,7 +341,11 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp; # ifdef _WINDOWS_ /* Favor Windows over C runtime fns */ # define CVT_PTR(ptr) (ptr) # define CVT_PTR_NOCHECK(ptr) (ptr) -# define png_strlen lstrlenA +# ifdef WINRT_ENABLED +# define png_strlen strlen +# else +# define png_strlen lstrlenA +# endif # define png_memcmp memcmp # define png_memcpy CopyMemory # define png_memset memset diff --git a/drivers/vorbis/os.h b/drivers/vorbis/os.h index 276b4decc..3df1d194e 100644 --- a/drivers/vorbis/os.h +++ b/drivers/vorbis/os.h @@ -120,7 +120,7 @@ static inline int vorbis_ftoi(double f){ /* yes, double! Otherwise, /* MSVC inline assembly. 32 bit only; inline ASM isn't implemented in the * 64 bit compiler */ -#if defined(_MSC_VER) && !defined(_WIN64) && !defined(_WIN32_WCE) +#if defined(_MSC_VER) && !defined(_WIN64) && !defined(_WIN32_WCE) && !defined(WINDOWSPHONE_ENABLED) # define VORBIS_FPU_CONTROL typedef ogg_int16_t vorbis_fpu_control; diff --git a/modules/gdscript/gd_editor.cpp b/modules/gdscript/gd_editor.cpp index 09f193706..24a5a7e1f 100644 --- a/modules/gdscript/gd_editor.cpp +++ b/modules/gdscript/gd_editor.cpp @@ -606,6 +606,16 @@ static bool _guess_expression_type(GDCompletionContext& context,const GDParser:: if (base.type==Variant::OBJECT) { + if (id.operator String()=="new" && base.value.get_type()==Variant::OBJECT) { + Object *obj = base.value; + if (obj && obj->cast_to()) { + GDNativeClass *gdnc = obj->cast_to(); + r_type.type=Variant::OBJECT; + r_type.value=Variant(); + r_type.obj_type=gdnc->get_name(); + return true; + } + } if (ObjectTypeDB::has_method(base.obj_type,id)) { @@ -677,7 +687,8 @@ static bool _guess_expression_type(GDCompletionContext& context,const GDParser:: v.get_method_list(&mi); for (List::Element *E=mi.front();E;E=E->next()) { - if (E->get().name==id.operator String()) { + if (!E->get().name.begins_with("_") && E->get().name==id.operator String()) { + MethodInfo mi = E->get(); r_type.type=mi.return_val.type; @@ -934,7 +945,7 @@ static bool _guess_identifier_type(GDCompletionContext& context,int p_line,const block=block->parent_block; } - //TODO guess identifier type of arguments (ONLY if this is a virtual function) + //guess from argument if virtual if (context.function && context.function->name!=StringName()) { int argindex = -1; @@ -995,7 +1006,7 @@ static bool _guess_identifier_type(GDCompletionContext& context,int p_line,const } } - if (context.function && !context.function->_static) { + if (!(context.function && context.function->_static)) { for(int i=0;ivariables.size();i++) { @@ -1136,6 +1147,8 @@ static void _find_identifiers_in_class(GDCompletionContext& context,bool p_stati List methods; ObjectTypeDB::get_method_list(type,&methods); for(List::Element *E=methods.front();E;E=E->next()) { + if (E->get().name.begins_with("_")) + continue; if (E->get().arguments.size()) result.insert(E->get().name+"("); else @@ -1196,7 +1209,7 @@ static void _find_identifiers(GDCompletionContext& context,int p_line,bool p_onl } -static String _get_visual_datatype(const PropertyInfo& p_info) { +static String _get_visual_datatype(const PropertyInfo& p_info,bool p_isarg=true) { String n = p_info.name; int idx = n.find(":"); @@ -1206,8 +1219,12 @@ static String _get_visual_datatype(const PropertyInfo& p_info) { if (p_info.type==Variant::OBJECT && p_info.hint==PROPERTY_HINT_RESOURCE_TYPE) return p_info.hint_string; - if (p_info.type==Variant::NIL) - return "void"; + if (p_info.type==Variant::NIL) { + if (p_isarg) + return "var"; + else + return "void"; + } return Variant::get_type_name(p_info.type); } @@ -1297,7 +1314,7 @@ static void _find_type_arguments(const GDParser::Node*p_node,int p_line,const St } - arghint = _get_visual_datatype(m->get_argument_info(-1))+" "+p_method.operator String()+String("("); + arghint = _get_visual_datatype(m->get_argument_info(-1),false)+" "+p_method.operator String()+String("("); for(int i=0;iget_argument_count();i++) { if (i>0) @@ -1361,7 +1378,7 @@ static void _find_call_arguments(GDCompletionContext& context,const GDParser::No const GDParser::BuiltInFunctionNode *fn = static_cast(op->arguments[0]); MethodInfo mi = GDFunctions::get_info(fn->function); - arghint = _get_visual_datatype(mi.return_val)+" "+GDFunctions::get_func_name(fn->function)+String("("); + arghint = _get_visual_datatype(mi.return_val,false)+" "+GDFunctions::get_func_name(fn->function)+String("("); for(int i=0;i0) arghint+=", "; @@ -1674,7 +1691,6 @@ Error GDScriptLanguage::complete_code(const String& p_code, const String& p_base isfunction=true; case GDParser::COMPLETION_INDEX: { - print_line("index"); const GDParser::Node *node = p.get_completion_node(); if (node->type!=GDParser::Node::TYPE_OPERATOR) break; @@ -1686,6 +1702,32 @@ Error GDScriptLanguage::complete_code(const String& p_code, const String& p_base if (_guess_expression_type(context,static_cast(node)->arguments[0],p.get_completion_line(),t)) { if (t.type==Variant::OBJECT && t.obj_type!=StringName()) { + + + if (t.value.get_type()) { + Object *obj=t.value; + if (obj) { + GDScript *scr = obj->cast_to(); + while (scr) { + + if (!isfunction) { + for (const Map::Element *E=scr->get_constants().front();E;E=E->next()) { + options.insert(E->key()); + } + } + for (const Map::Element *E=scr->get_member_functions().front();E;E=E->next()) { + options.insert(E->key()); + } + + if (scr->get_base().is_valid()) + scr=scr->get_base().ptr(); + else + scr=NULL; + } + } + } + + if (!isfunction) { ObjectTypeDB::get_integer_constant_list(t.obj_type,r_options); } @@ -1693,6 +1735,9 @@ Error GDScriptLanguage::complete_code(const String& p_code, const String& p_base ObjectTypeDB::get_method_list(t.obj_type,&mi); for (List::Element *E=mi.front();E;E=E->next()) { + if (E->get().name.begins_with("_")) + continue; + if (E->get().arguments.size()) options.insert(E->get().name+"("); else @@ -1700,6 +1745,7 @@ Error GDScriptLanguage::complete_code(const String& p_code, const String& p_base } } else { + if (t.value.get_type()==Variant::NIL) { Variant::CallError ce; t.value=Variant::construct(t.type,NULL,0,ce); @@ -1728,7 +1774,6 @@ Error GDScriptLanguage::complete_code(const String& p_code, const String& p_base } - } break; case GDParser::COMPLETION_CALL_ARGUMENTS: { diff --git a/modules/gdscript/gd_script.cpp b/modules/gdscript/gd_script.cpp index 97d97f1ef..3f7a6b000 100644 --- a/modules/gdscript/gd_script.cpp +++ b/modules/gdscript/gd_script.cpp @@ -1756,6 +1756,7 @@ bool GDScript::_update_exports() { return changed; #endif + return false; } void GDScript::update_exports() { diff --git a/platform/winrt/app.cpp b/platform/winrt/app.cpp index f7fe91188..662229b04 100644 --- a/platform/winrt/app.cpp +++ b/platform/winrt/app.cpp @@ -178,7 +178,7 @@ static Windows::Foundation::Point _get_pixel_position(CoreWindow^ window, Window // Compute coordinates normalized from 0..1. // If the coordinates need to be sized to the SDL window, // we'll do that after. - #if WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP + #if 1 || WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP outputPosition.X = rawPosition.X / window->Bounds.Width; outputPosition.Y = rawPosition.Y / window->Bounds.Height; #else @@ -357,16 +357,29 @@ void App::OnWindowSizeChanged(CoreWindow^ sender, WindowSizeChangedEventArgs^ ar // On Windows Phone 8.1, the window size changes when the device is rotated. // The default framebuffer will not be automatically resized when this occurs. // It is therefore up to the app to handle rotation-specific logic in its rendering code. + //os->screen_size_changed(); + UpdateWindowSize(args->Size); #endif } void App::UpdateWindowSize(Size size) { - /* - DisplayInformation^ currentDisplayInformation = DisplayInformation::GetForCurrentView(); - Size pixelSize(ConvertDipsToPixels(size.Width, currentDisplayInformation->LogicalDpi), ConvertDipsToPixels(size.Height, currentDisplayInformation->LogicalDpi)); - + float dpi; +#if (WINAPI_FAMILY == WINAPI_FAMILY_PC_APP) + DisplayInformation^ currentDisplayInformation = DisplayInformation::GetForCurrentView(); + dpi = currentDisplayInformation->LogicalDpi; +#else if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) + dpi = DisplayProperties::LogicalDpi; +#endif + Size pixelSize(ConvertDipsToPixels(size.Width, dpi), ConvertDipsToPixels(size.Height, dpi)); + mWindowWidth = static_cast(pixelSize.Width); mWindowHeight = static_cast(pixelSize.Height); - */ + + OS::VideoMode vm; + vm.width = mWindowWidth; + vm.height = mWindowHeight; + vm.fullscreen = true; + vm.resizable = false; + os->set_video_mode(vm); } diff --git a/platform/winrt/detect.py b/platform/winrt/detect.py index dd9d1877e..d97d974a1 100644 --- a/platform/winrt/detect.py +++ b/platform/winrt/detect.py @@ -30,38 +30,99 @@ def get_flags(): def configure(env): env.Append(CPPPATH=['#platform/winrt', '#platform/winrt/include']) + arch = "" - env.Append(LINKFLAGS=['/MANIFEST:NO', '/NXCOMPAT', '/DYNAMICBASE', "kernel32.lib", '/MACHINE:X64', '/WINMD', '/APPCONTAINER', '/MANIFESTUAC:NO', '/ERRORREPORT:PROMPT', '/NOLOGO', '/TLBID:1']) + if os.getenv('PLATFORM') == "ARM": - env.Append(LIBPATH=['#platform/winrt/x64/lib']) + # compiler commandline + # debug: /Yu"pch.h" /MP /GS /analyze- /W3 /wd"4453" /wd"28204" /Zc:wchar_t /I"C:\Users\ariel\Documents\Visual Studio 2013\Projects\App2\App2\App2.WindowsPhone\" /I"Generated Files\" /I"ARM\Debug\" /I"C:\Users\ariel\Documents\Visual Studio 2013\Projects\App2\App2\App2.Shared\" /ZW:nostdlib /Zi /Gm- /Od /sdl /Fd"ARM\Debug\vc120.pdb" /fp:precise /D "PSAPI_VERSION=2" /D "WINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP" /D "_UITHREADCTXT_SUPPORT=0" /D "_UNICODE" /D "UNICODE" /D "_DEBUG" /errorReport:prompt /WX- /Zc:forScope /RTC1 /ZW /Gd /Oy- /MDd /Fa"ARM\Debug\" /EHsc /nologo /Fo"ARM\Debug\" /Fp"ARM\Debug\App2.WindowsPhone.pch" + # release: /Yu"pch.h" /MP /GS /GL /analyze- /W3 /wd"4453" /wd"28204" /Gy /Zc:wchar_t /I"C:\Users\ariel\Documents\Visual Studio 2013\Projects\App2\App2\App2.WindowsPhone\" /I"Generated Files\" /I"ARM\Release\" /I"C:\Users\ariel\Documents\Visual Studio 2013\Projects\App2\App2\App2.Shared\" /ZW:nostdlib /Zi /Gm- /O2 /sdl /Fd"ARM\Release\vc120.pdb" /fp:precise /D "PSAPI_VERSION=2" /D "WINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP" /D "_UITHREADCTXT_SUPPORT=0" /D "_UNICODE" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /ZW /Gd /Oy- /Oi /MD /Fa"ARM\Release\" /EHsc /nologo /Fo"ARM\Release\" /Fp"ARM\Release\App2.WindowsPhone.pch" + # linker commandline + # debug: /OUT:"C:\Users\ariel\Documents\Visual Studio 2013\Projects\App2\ARM\Debug\App2.WindowsPhone\App2.WindowsPhone.exe" /MANIFEST:NO /NXCOMPAT /PDB:"C:\Users\ariel\Documents\Visual Studio 2013\Projects\App2\ARM\Debug\App2.WindowsPhone\App2.WindowsPhone.pdb" /DYNAMICBASE "WindowsPhoneCore.lib" "RuntimeObject.lib" "PhoneAppModelHost.lib" /DEBUG /MACHINE:ARM /NODEFAULTLIB:"kernel32.lib" /NODEFAULTLIB:"ole32.lib" /WINMD /APPCONTAINER /INCREMENTAL /PGD:"C:\Users\ariel\Documents\Visual Studio 2013\Projects\App2\ARM\Debug\App2.WindowsPhone\App2.WindowsPhone.pgd" /WINMDFILE:"C:\Users\ariel\Documents\Visual Studio 2013\Projects\App2\ARM\Debug\App2.WindowsPhone\App2.winmd" /SUBSYSTEM:WINDOWS /MANIFESTUAC:NO /ManifestFile:"ARM\Debug\App2.WindowsPhone.exe.intermediate.manifest" /ERRORREPORT:PROMPT /NOLOGO /TLBID:1 + # release: /OUT:"C:\Users\ariel\Documents\Visual Studio 2013\Projects\App2\ARM\Release\App2.WindowsPhone\App2.WindowsPhone.exe" /MANIFEST:NO /LTCG /NXCOMPAT /PDB:"C:\Users\ariel\Documents\Visual Studio 2013\Projects\App2\ARM\Release\App2.WindowsPhone\App2.WindowsPhone.pdb" /DYNAMICBASE "WindowsPhoneCore.lib" "RuntimeObject.lib" "PhoneAppModelHost.lib" /DEBUG /MACHINE:ARM /NODEFAULTLIB:"kernel32.lib" /NODEFAULTLIB:"ole32.lib" /WINMD /APPCONTAINER /OPT:REF /PGD:"C:\Users\ariel\Documents\Visual Studio 2013\Projects\App2\ARM\Release\App2.WindowsPhone\App2.WindowsPhone.pgd" /WINMDFILE:"C:\Users\ariel\Documents\Visual Studio 2013\Projects\App2\ARM\Release\App2.WindowsPhone\App2.winmd" /SUBSYSTEM:WINDOWS /MANIFESTUAC:NO /ManifestFile:"ARM\Release\App2.WindowsPhone.exe.intermediate.manifest" /OPT:ICF /ERRORREPORT:PROMPT /NOLOGO /TLBID:1 - if (env["target"]=="release"): + arch = "arm" - env.Append(CCFLAGS=['/O2']) - env.Append(LINKFLAGS=['/SUBSYSTEM:WINDOWS']) - env.Append(LINKFLAGS=['/ENTRY:mainCRTStartup']) + env.Append(LINKFLAGS=['/INCREMENTAL:NO', '/MANIFEST:NO', '/NXCOMPAT', '/DYNAMICBASE', "WindowsPhoneCore.lib", "RuntimeObject.lib", "PhoneAppModelHost.lib", "/DEBUG", "/MACHINE:ARM", '/NODEFAULTLIB:"kernel32.lib"', '/NODEFAULTLIB:"ole32.lib"', '/WINMD', '/APPCONTAINER', '/MANIFESTUAC:NO', '/ERRORREPORT:PROMPT', '/NOLOGO', '/TLBID:1']) + env.Append(LIBPATH=['#platform/winrt/ARM/lib']) - elif (env["target"]=="test"): + env.Append(CCFLAGS=string.split('/MP /GS /wd"4453" /wd"28204" /analyze- /Zc:wchar_t /Zi /Gm- /Od /fp:precise /fp:precise /D "PSAPI_VERSION=2" /D "WINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP" /DWINDOWSPHONE_ENABLED /D "_UITHREADCTXT_SUPPORT=0" /D "_UNICODE" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /Gd /Oy- /Oi /MD /RTC1 /Gd /EHsc /nologo')) + env.Append(CXXFLAGS=string.split('/ZW')) - env.Append(CCFLAGS=['/O2','/DDEBUG_ENABLED','/DD3D_DEBUG_INFO']) - env.Append(LINKFLAGS=['/SUBSYSTEM:CONSOLE']) + if (env["target"]=="release"): - elif (env["target"]=="debug"): + env.Append(CCFLAGS=['/O2']) + env.Append(LINKFLAGS=['/SUBSYSTEM:WINDOWS']) - env.Append(CCFLAGS=['/Zi','/DDEBUG_ENABLED','/DD3D_DEBUG_INFO']) - env.Append(LINKFLAGS=['/SUBSYSTEM:CONSOLE']) - env.Append(LINKFLAGS=['/DEBUG', '/D_DEBUG']) + elif (env["target"]=="test"): - elif (env["target"]=="profile"): + env.Append(CCFLAGS=['/O2','/DDEBUG_ENABLED','/DD3D_DEBUG_INFO']) + env.Append(LINKFLAGS=['/SUBSYSTEM:CONSOLE']) - env.Append(CCFLAGS=['-g','-pg']) - env.Append(LINKFLAGS=['-pg']) + elif (env["target"]=="debug"): + env.Append(CCFLAGS=['/Zi','/DDEBUG_ENABLED','/DD3D_DEBUG_INFO']) + env.Append(LINKFLAGS=['/SUBSYSTEM:CONSOLE']) + env.Append(LINKFLAGS=['/DEBUG', '/D_DEBUG']) + + elif (env["target"]=="profile"): + + env.Append(CCFLAGS=['-g','-pg']) + env.Append(LINKFLAGS=['-pg']) + + + env['ENV'] = os.environ; + # fix environment for windows phone 8.1 + env['ENV']['WINDOWSPHONEKITDIR'] = env['ENV']['WINDOWSPHONEKITDIR'].replace("8.0", "8.1") # wtf + env['ENV']['INCLUDE'] = env['ENV']['INCLUDE'].replace("8.0", "8.1") + env['ENV']['LIB'] = env['ENV']['LIB'].replace("8.0", "8.1") + env['ENV']['PATH'] = env['ENV']['PATH'].replace("8.0", "8.1") + env['ENV']['LIBPATH'] = env['ENV']['LIBPATH'].replace("8.0\\Windows Metadata", "8.1\\References\\CommonConfiguration\\Neutral") + + else: + + arch = "x64" + env.Append(LINKFLAGS=['/MANIFEST:NO', '/NXCOMPAT', '/DYNAMICBASE', "kernel32.lib", '/MACHINE:X64', '/WINMD', '/APPCONTAINER', '/MANIFESTUAC:NO', '/ERRORREPORT:PROMPT', '/NOLOGO', '/TLBID:1']) + + env.Append(LIBPATH=['#platform/winrt/x64/lib']) + + + if (env["target"]=="release"): + + env.Append(CCFLAGS=['/O2']) + env.Append(LINKFLAGS=['/SUBSYSTEM:WINDOWS']) + env.Append(LINKFLAGS=['/ENTRY:mainCRTStartup']) + + elif (env["target"]=="test"): + + env.Append(CCFLAGS=['/O2','/DDEBUG_ENABLED','/DD3D_DEBUG_INFO']) + env.Append(LINKFLAGS=['/SUBSYSTEM:CONSOLE']) + + elif (env["target"]=="debug"): + + env.Append(CCFLAGS=['/Zi','/DDEBUG_ENABLED','/DD3D_DEBUG_INFO']) + env.Append(LINKFLAGS=['/SUBSYSTEM:CONSOLE']) + env.Append(LINKFLAGS=['/DEBUG', '/D_DEBUG']) + + elif (env["target"]=="profile"): + + env.Append(CCFLAGS=['-g','-pg']) + env.Append(LINKFLAGS=['-pg']) + + + env.Append(CCFLAGS=string.split('/MP /GS /wd"4453" /wd"28204" /Zc:wchar_t /Gm- /Od /fp:precise /D "_UNICODE" /D "UNICODE" /D "WINAPI_FAMILY=WINAPI_FAMILY_APP" /errorReport:prompt /WX- /Zc:forScope /RTC1 /Gd /MDd /EHsc /nologo')) + env.Append(CXXFLAGS=string.split('/ZW')) + env.Append(CCFLAGS=['/AI', os.environ['VCINSTALLDIR']+'\\vcpackages', '/AI', os.environ['WINDOWSSDKDIR']+'\\References\\CommonConfiguration\\Neutral']) + env.Append(CCFLAGS=['/DWINAPI_FAMILY=WINAPI_FAMILY_APP', '/D_WIN32_WINNT=0x0603', '/DNTDDI_VERSION=0x06030000']) + + env['ENV'] = os.environ; + + + env["PROGSUFFIX"]="."+arch+env["PROGSUFFIX"] + env["OBJSUFFIX"]="."+arch+env["OBJSUFFIX"] + env["LIBSUFFIX"]="."+arch+env["LIBSUFFIX"] - env.Append(CCFLAGS=string.split('/MP /GS /wd"4453" /wd"28204" /Zc:wchar_t /Gm- /Od /fp:precise /D "_UNICODE" /D "UNICODE" /D "WINAPI_FAMILY=WINAPI_FAMILY_APP" /errorReport:prompt /WX- /Zc:forScope /RTC1 /Gd /MDd /EHsc /nologo')) - env.Append(CXXFLAGS=string.split('/ZW')) - env.Append(CCFLAGS=['/AI', os.environ['VCINSTALLDIR']+'\\vcpackages', '/AI', os.environ['WINDOWSSDKDIR']+'\\References\\CommonConfiguration\\Neutral']) #env.Append(CCFLAGS=['/Gd','/GR','/nologo', '/EHsc']) #env.Append(CXXFLAGS=['/TP', '/ZW']) @@ -69,7 +130,6 @@ def configure(env): ##env.Append(CCFLAGS=['/I'+os.getenv("WindowsSdkDir")+"/Include"]) env.Append(CCFLAGS=['/DWINRT_ENABLED']) env.Append(CCFLAGS=['/DWINDOWS_ENABLED']) - env.Append(CCFLAGS=['/DWINAPI_FAMILY=WINAPI_FAMILY_APP', '/D_WIN32_WINNT=0x0603', '/DNTDDI_VERSION=0x06030000']) env.Append(CCFLAGS=['/DRTAUDIO_ENABLED']) #env.Append(CCFLAGS=['/DWIN32']) env.Append(CCFLAGS=['/DTYPED_METHOD_BIND']) @@ -92,5 +152,5 @@ def configure(env): env.Append( BUILDERS = { 'HLSL9' : env.Builder(action = methods.build_hlsl_dx9_headers, suffix = 'hlsl.h',src_suffix = '.hlsl') } ) env.Append( BUILDERS = { 'GLSL120GLES' : env.Builder(action = methods.build_gles2_headers, suffix = 'glsl.h',src_suffix = '.glsl') } ) - env['ENV'] = os.environ; +#/c/Program Files (x86)/Windows Phone Kits/8.1/lib/ARM/WindowsPhoneCore.lib diff --git a/platform/winrt/gl_context_egl.cpp b/platform/winrt/gl_context_egl.cpp index ca592c5d1..fd9fbe406 100644 --- a/platform/winrt/gl_context_egl.cpp +++ b/platform/winrt/gl_context_egl.cpp @@ -1,5 +1,7 @@ #include "gl_context_egl.h" +#include "EGL/eglext.h" + using namespace Platform; void ContextEGL::release_current() { @@ -22,6 +24,14 @@ int ContextEGL::get_window_height() { return height; }; +void ContextEGL::reset() { + + cleanup(); + + window = CoreWindow::GetForCurrentThread(); + initialize(); +}; + void ContextEGL::swap_buffers() { if (eglSwapBuffers(mEglDisplay, mEglSurface) != EGL_TRUE) @@ -63,7 +73,23 @@ Error ContextEGL::initialize() { try { - display = eglGetDisplay(EGL_DEFAULT_DISPLAY); + const EGLint displayAttributes[] = + { + EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, + EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, 9, + EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, 3, + EGL_NONE, + }; + + PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT = reinterpret_cast(eglGetProcAddress("eglGetPlatformDisplayEXT")); + + if (!eglGetPlatformDisplayEXT) + { + throw Exception::CreateException(E_FAIL, L"Failed to get function eglGetPlatformDisplayEXT"); + } + + display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, displayAttributes); + if (display == EGL_NO_DISPLAY) { throw Exception::CreateException(E_FAIL, L"Failed to get default EGL display"); diff --git a/platform/winrt/gl_context_egl.h b/platform/winrt/gl_context_egl.h index 56bf654ee..ca3760e72 100644 --- a/platform/winrt/gl_context_egl.h +++ b/platform/winrt/gl_context_egl.h @@ -32,6 +32,7 @@ public: virtual void swap_buffers(); virtual Error initialize(); + void reset(); void cleanup(); diff --git a/platform/winrt/include/EGL/eglext.h b/platform/winrt/include/EGL/eglext.h index 9828628e7..459ecf4a3 100644 --- a/platform/winrt/include/EGL/eglext.h +++ b/platform/winrt/include/EGL/eglext.h @@ -432,31 +432,38 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurfacePointerANGLE (EGLDisplay dpy, EGLSu #define EGL_ANGLE_direct3d_display 1 #define EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ((EGLNativeDisplayType)-2) #define EGL_D3D11_ONLY_DISPLAY_ANGLE ((EGLNativeDisplayType)-3) -#define EGL_D3D11_FL9_3_ONLY_DISPLAY_ANGLE ((EGLNativeDisplayType)-4) #endif /* EGL_ANGLE_direct3d_display */ #ifndef EGL_ANGLE_surface_d3d_texture_2d_share_handle #define EGL_ANGLE_surface_d3d_texture_2d_share_handle 1 #endif /* EGL_ANGLE_surface_d3d_texture_2d_share_handle */ +#ifndef EGL_ANGLE_surface_d3d_render_to_back_buffer +#define EGL_ANGLE_surface_d3d_render_to_back_buffer 1 +#define EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER 0x320B +#define EGL_ANGLE_SURFACE_RENDER_TO_BACK_BUFFER 0x320C +#endif /* EGL_ANGLE_surface_d3d_render_to_back_buffer */ + #ifndef EGL_ANGLE_platform_angle #define EGL_ANGLE_platform_angle 1 #define EGL_PLATFORM_ANGLE_ANGLE 0x3201 #define EGL_PLATFORM_ANGLE_TYPE_ANGLE 0x3202 -#define EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE 0x3203 +#define EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE 0x3203 +#define EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE 0x3204 +#define EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE 0x3205 #endif /* EGL_ANGLE_platform_angle */ #ifndef EGL_ANGLE_platform_angle_d3d #define EGL_ANGLE_platform_angle_d3d 1 -#define EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE 0x3204 -#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3205 -#define EGL_PLATFORM_ANGLE_TYPE_D3D11_WARP_ANGLE 0x3206 +#define EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE 0x3206 +#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3207 +#define EGL_PLATFORM_ANGLE_USE_WARP_ANGLE 0x3208 #endif /* EGL_ANGLE_platform_angle_d3d */ #ifndef EGL_ANGLE_platform_angle_opengl #define EGL_ANGLE_platform_angle_opengl 1 -#define EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE 0x3207 -#define EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE 0x3208 +#define EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE 0x3209 +#define EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE 0x320A #endif /* EGL_ANGLE_platform_angle_opengl */ #ifndef EGL_ARM_pixmap_multisample_discard diff --git a/platform/winrt/include/EGL/eglplatform.h b/platform/winrt/include/EGL/eglplatform.h index d2e30bddb..b0e88f94d 100644 --- a/platform/winrt/include/EGL/eglplatform.h +++ b/platform/winrt/include/EGL/eglplatform.h @@ -76,12 +76,12 @@ typedef HDC EGLNativeDisplayType; typedef HBITMAP EGLNativePixmapType; -#if defined(WINAPI_FAMILY) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PC_APP || WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) /* Windows Store */ #include typedef IInspectable* EGLNativeWindowType; #else typedef HWND EGLNativeWindowType; -#endif // defined(WINAPI_FAMILY) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +#endif #elif defined(__WINSCW__) || defined(__SYMBIAN32__) /* Symbian */ diff --git a/platform/winrt/include/GLSLANG/ShaderLang.h b/platform/winrt/include/GLSLANG/ShaderLang.h index 86bf221c9..d925b88f2 100644 --- a/platform/winrt/include/GLSLANG/ShaderLang.h +++ b/platform/winrt/include/GLSLANG/ShaderLang.h @@ -27,6 +27,10 @@ #include "KHR/khrplatform.h" +#include +#include +#include + // // This is the platform independent interface between an OGL driver // and the shading language compiler. @@ -39,20 +43,20 @@ typedef unsigned int GLenum; } // Must be included after GLenum proxy typedef +// Note: make sure to increment ANGLE_SH_VERSION when changing ShaderVars.h #include "ShaderVars.h" -#ifdef __cplusplus -extern "C" { -#endif - // Version number for shader translation API. // It is incremented every time the API changes. -#define ANGLE_SH_VERSION 129 +#define ANGLE_SH_VERSION 132 typedef enum { SH_GLES2_SPEC = 0x8B40, SH_WEBGL_SPEC = 0x8B41, + SH_GLES3_SPEC = 0x8B86, + SH_WEBGL2_SPEC = 0x8B87, + // The CSS Shaders spec is a subset of the WebGL spec. // // In both CSS vertex and fragment shaders, ANGLE: @@ -84,31 +88,6 @@ typedef enum { SH_HLSL11_OUTPUT = 0x8B48 } ShShaderOutput; -typedef enum { - SH_PRECISION_HIGHP = 0x5001, - SH_PRECISION_MEDIUMP = 0x5002, - SH_PRECISION_LOWP = 0x5003, - SH_PRECISION_UNDEFINED = 0 -} ShPrecisionType; - -typedef enum { - SH_INFO_LOG_LENGTH = 0x8B84, - SH_OBJECT_CODE_LENGTH = 0x8B88, // GL_SHADER_SOURCE_LENGTH - SH_ACTIVE_UNIFORMS = 0x8B86, - SH_ACTIVE_UNIFORM_MAX_LENGTH = 0x8B87, - SH_ACTIVE_ATTRIBUTES = 0x8B89, - SH_ACTIVE_ATTRIBUTE_MAX_LENGTH = 0x8B8A, - SH_VARYINGS = 0x8BBB, - SH_VARYING_MAX_LENGTH = 0x8BBC, - SH_MAPPED_NAME_MAX_LENGTH = 0x6000, - SH_NAME_MAX_LENGTH = 0x6001, - SH_HASHED_NAME_MAX_LENGTH = 0x6002, - SH_HASHED_NAMES_COUNT = 0x6003, - SH_SHADER_VERSION = 0x6004, - SH_RESOURCES_STRING_LENGTH = 0x6005, - SH_OUTPUT_TYPE = 0x6006 -} ShShaderInfo; - // Compile options. typedef enum { SH_VALIDATE = 0, @@ -188,6 +167,11 @@ typedef enum { // This flag scalarizes vec/ivec/bvec/mat constructor args. // It is intended as a workaround for Linux/Mac driver bugs. SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS = 0x40000, + + // This flag overwrites a struct name with a unique prefix. + // It is intended as a workaround for drivers that do not handle + // struct scopes correctly, including all Mac drivers and Linux AMD. + SH_REGENERATE_STRUCT_NAMES = 0x80000, } ShCompileOptions; // Defines alternate strategies for implementing array index clamping. @@ -202,14 +186,14 @@ typedef enum { // // Driver must call this first, once, before doing any other // compiler operations. -// If the function succeeds, the return value is nonzero, else zero. +// If the function succeeds, the return value is true, else false. // -COMPILER_EXPORT int ShInitialize(); +COMPILER_EXPORT bool ShInitialize(); // // Driver should call this at shutdown. -// If the function succeeds, the return value is nonzero, else zero. +// If the function succeeds, the return value is true, else false. // -COMPILER_EXPORT int ShFinalize(); +COMPILER_EXPORT bool ShFinalize(); // The 64 bits hash function. The first parameter is the input string; the // second parameter is the string length. @@ -240,6 +224,12 @@ typedef struct int EXT_frag_depth; int EXT_shader_texture_lod; + // Set to 1 to enable replacing GL_EXT_draw_buffers #extension directives + // with GL_NV_draw_buffers in ESSL output. This flag can be used to emulate + // EXT_draw_buffers by using it in combination with GLES3.0 glDrawBuffers + // function. This applies to Tegra K1 devices. + int NV_draw_buffers; + // Set to 1 if highp precision is supported in the fragment language. // Default is 0. int FragmentPrecisionHigh; @@ -268,8 +258,10 @@ typedef struct // // Initialize built-in resources with minimum expected values. +// Parameters: +// resources: The object to initialize. Will be comparable with memcmp. // -COMPILER_EXPORT void ShInitBuiltInResources(ShBuiltInResources* resources); +COMPILER_EXPORT void ShInitBuiltInResources(ShBuiltInResources *resources); // // ShHandle held by but opaque to the driver. It is allocated, @@ -278,18 +270,15 @@ COMPILER_EXPORT void ShInitBuiltInResources(ShBuiltInResources* resources); // // If handle creation fails, 0 will be returned. // -typedef void* ShHandle; +typedef void *ShHandle; // -// Returns the a concatenated list of the items in ShBuiltInResources as a string. +// Returns the a concatenated list of the items in ShBuiltInResources as a +// null-terminated string. // This function must be updated whenever ShBuiltInResources is changed. // Parameters: // handle: Specifies the handle of the compiler to be used. -// outStringLen: Specifies the size of the buffer, in number of characters. The size -// of the buffer required to store the resources string can be obtained -// by calling ShGetInfo with SH_RESOURCES_STRING_LENGTH. -// outStr: Returns a null-terminated string representing all the built-in resources. -COMPILER_EXPORT void ShGetBuiltInResourcesString(const ShHandle handle, size_t outStringLen, char *outStr); +COMPILER_EXPORT const std::string &ShGetBuiltInResourcesString(const ShHandle handle); // // Driver calls these to create and destroy compiler objects. @@ -307,12 +296,12 @@ COMPILER_EXPORT ShHandle ShConstructCompiler( sh::GLenum type, ShShaderSpec spec, ShShaderOutput output, - const ShBuiltInResources* resources); + const ShBuiltInResources *resources); COMPILER_EXPORT void ShDestruct(ShHandle handle); // // Compiles the given shader source. -// If the function succeeds, the return value is nonzero, else zero. +// If the function succeeds, the return value is true, else false. // Parameters: // handle: Specifies the handle of compiler to be used. // shaderStrings: Specifies an array of pointers to null-terminated strings @@ -334,123 +323,36 @@ COMPILER_EXPORT void ShDestruct(ShHandle handle); // SH_VARIABLES: Extracts attributes, uniforms, and varyings. // Can be queried by calling ShGetVariableInfo(). // -COMPILER_EXPORT int ShCompile( +COMPILER_EXPORT bool ShCompile( const ShHandle handle, - const char* const shaderStrings[], + const char * const shaderStrings[], size_t numStrings, - int compileOptions - ); + int compileOptions); -// Returns a parameter from a compiled shader. -// Parameters: -// handle: Specifies the compiler -// pname: Specifies the parameter to query. -// The following parameters are defined: -// SH_INFO_LOG_LENGTH: the number of characters in the information log -// including the null termination character. -// SH_OBJECT_CODE_LENGTH: the number of characters in the object code -// including the null termination character. -// SH_ACTIVE_ATTRIBUTES: the number of active attribute variables. -// SH_ACTIVE_ATTRIBUTE_MAX_LENGTH: the length of the longest active attribute -// variable name including the null -// termination character. -// SH_ACTIVE_UNIFORMS: the number of active uniform variables. -// SH_ACTIVE_UNIFORM_MAX_LENGTH: the length of the longest active uniform -// variable name including the null -// termination character. -// SH_VARYINGS: the number of varying variables. -// SH_VARYING_MAX_LENGTH: the length of the longest varying variable name -// including the null termination character. -// SH_MAPPED_NAME_MAX_LENGTH: the length of the mapped variable name including -// the null termination character. -// SH_NAME_MAX_LENGTH: the max length of a user-defined name including the -// null termination character. -// SH_HASHED_NAME_MAX_LENGTH: the max length of a hashed name including the -// null termination character. -// SH_HASHED_NAMES_COUNT: the number of hashed names from the latest compile. -// SH_SHADER_VERSION: the version of the shader language -// SH_OUTPUT_TYPE: the currently set language output type -// -// params: Requested parameter -COMPILER_EXPORT void ShGetInfo(const ShHandle handle, - ShShaderInfo pname, - size_t* params); +// Return the version of the shader language. +COMPILER_EXPORT int ShGetShaderVersion(const ShHandle handle); -// Returns nul-terminated information log for a compiled shader. +// Return the currently set language output type. +COMPILER_EXPORT ShShaderOutput ShGetShaderOutputType( + const ShHandle handle); + +// Returns null-terminated information log for a compiled shader. // Parameters: // handle: Specifies the compiler -// infoLog: Specifies an array of characters that is used to return -// the information log. It is assumed that infoLog has enough memory -// to accomodate the information log. The size of the buffer required -// to store the returned information log can be obtained by calling -// ShGetInfo with SH_INFO_LOG_LENGTH. -COMPILER_EXPORT void ShGetInfoLog(const ShHandle handle, char* infoLog); +COMPILER_EXPORT const std::string &ShGetInfoLog(const ShHandle handle); // Returns null-terminated object code for a compiled shader. // Parameters: // handle: Specifies the compiler -// infoLog: Specifies an array of characters that is used to return -// the object code. It is assumed that infoLog has enough memory to -// accomodate the object code. The size of the buffer required to -// store the returned object code can be obtained by calling -// ShGetInfo with SH_OBJECT_CODE_LENGTH. -COMPILER_EXPORT void ShGetObjectCode(const ShHandle handle, char* objCode); - -// Returns information about a shader variable. -// Parameters: -// handle: Specifies the compiler -// variableType: Specifies the variable type; options include -// SH_ACTIVE_ATTRIBUTES, SH_ACTIVE_UNIFORMS, SH_VARYINGS. -// index: Specifies the index of the variable to be queried. -// length: Returns the number of characters actually written in the string -// indicated by name (excluding the null terminator) if a value other -// than NULL is passed. -// size: Returns the size of the variable. -// type: Returns the data type of the variable. -// precision: Returns the precision of the variable. -// staticUse: Returns 1 if the variable is accessed in a statement after -// pre-processing, whether or not run-time flow of control will -// cause that statement to be executed. -// Returns 0 otherwise. -// name: Returns a null terminated string containing the name of the -// variable. It is assumed that name has enough memory to accormodate -// the variable name. The size of the buffer required to store the -// variable name can be obtained by calling ShGetInfo with -// SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, SH_ACTIVE_UNIFORM_MAX_LENGTH, -// SH_VARYING_MAX_LENGTH. -// mappedName: Returns a null terminated string containing the mapped name of -// the variable, It is assumed that mappedName has enough memory -// (SH_MAPPED_NAME_MAX_LENGTH), or NULL if don't care about the -// mapped name. If the name is not mapped, then name and mappedName -// are the same. -COMPILER_EXPORT void ShGetVariableInfo(const ShHandle handle, - ShShaderInfo variableType, - int index, - size_t* length, - int* size, - sh::GLenum* type, - ShPrecisionType* precision, - int* staticUse, - char* name, - char* mappedName); - -// Returns information about a name hashing entry from the latest compile. +COMPILER_EXPORT const std::string &ShGetObjectCode(const ShHandle handle); + +// Returns a (original_name, hash) map containing all the user defined +// names in the shader, including variable names, function names, struct +// names, and struct field names. // Parameters: // handle: Specifies the compiler -// index: Specifies the index of the name hashing entry to be queried. -// name: Returns a null terminated string containing the user defined name. -// It is assumed that name has enough memory to accomodate the name. -// The size of the buffer required to store the user defined name can -// be obtained by calling ShGetInfo with SH_NAME_MAX_LENGTH. -// hashedName: Returns a null terminated string containing the hashed name of -// the uniform variable, It is assumed that hashedName has enough -// memory to accomodate the name. The size of the buffer required -// to store the name can be obtained by calling ShGetInfo with -// SH_HASHED_NAME_MAX_LENGTH. -COMPILER_EXPORT void ShGetNameHashingEntry(const ShHandle handle, - int index, - char* name, - char* hashedName); +COMPILER_EXPORT const std::map *ShGetNameHashingMap( + const ShHandle handle); // Shader variable inspection. // Returns a pointer to a list of variables of the designated type. @@ -470,17 +372,17 @@ typedef struct int size; } ShVariableInfo; -// Returns 1 if the passed in variables pack in maxVectors following +// Returns true if the passed in variables pack in maxVectors following // the packing rules from the GLSL 1.017 spec, Appendix A, section 7. -// Returns 0 otherwise. Also look at the SH_ENFORCE_PACKING_RESTRICTIONS +// Returns false otherwise. Also look at the SH_ENFORCE_PACKING_RESTRICTIONS // flag above. // Parameters: // maxVectors: the available rows of registers. // varInfoArray: an array of variable info (types and sizes). // varInfoArraySize: the size of the variable array. -COMPILER_EXPORT int ShCheckVariablesWithinPackingLimits( +COMPILER_EXPORT bool ShCheckVariablesWithinPackingLimits( int maxVectors, - ShVariableInfo* varInfoArray, + ShVariableInfo *varInfoArray, size_t varInfoArraySize); // Gives the compiler-assigned register for an interface block. @@ -491,7 +393,7 @@ COMPILER_EXPORT int ShCheckVariablesWithinPackingLimits( // interfaceBlockName: Specifies the interface block // indexOut: output variable that stores the assigned register COMPILER_EXPORT bool ShGetInterfaceBlockRegister(const ShHandle handle, - const char *interfaceBlockName, + const std::string &interfaceBlockName, unsigned int *indexOut); // Gives the compiler-assigned register for uniforms in the default @@ -503,11 +405,7 @@ COMPILER_EXPORT bool ShGetInterfaceBlockRegister(const ShHandle handle, // interfaceBlockName: Specifies the uniform // indexOut: output variable that stores the assigned register COMPILER_EXPORT bool ShGetUniformRegister(const ShHandle handle, - const char *uniformName, + const std::string &uniformName, unsigned int *indexOut); -#ifdef __cplusplus -} -#endif - #endif // _COMPILER_INTERFACE_INCLUDED_ diff --git a/platform/winrt/include/GLSLANG/ShaderVars.h b/platform/winrt/include/GLSLANG/ShaderVars.h index 03ddf956f..dc452b0cf 100644 --- a/platform/winrt/include/GLSLANG/ShaderVars.h +++ b/platform/winrt/include/GLSLANG/ShaderVars.h @@ -15,6 +15,7 @@ #include // Assume ShaderLang.h is included before ShaderVars.h, for sh::GLenum +// Note: make sure to increment ANGLE_SH_VERSION when changing ShaderVars.h namespace sh { @@ -39,7 +40,7 @@ enum BlockLayoutType // Note: we must override the copy constructor and assignment operator so we can // work around excessive GCC binary bloating: // See https://code.google.com/p/angleproject/issues/detail?id=697 -struct ShaderVariable +struct COMPILER_EXPORT ShaderVariable { ShaderVariable(); ShaderVariable(GLenum typeIn, unsigned int arraySizeIn); @@ -49,6 +50,22 @@ struct ShaderVariable bool isArray() const { return arraySize > 0; } unsigned int elementCount() const { return std::max(1u, arraySize); } + bool isStruct() const { return !fields.empty(); } + + // All of the shader's variables are described using nested data + // structures. This is needed in order to disambiguate similar looking + // types, such as two structs containing the same fields, but in + // different orders. "findInfoByMappedName" provides an easy query for + // users to dive into the data structure and fetch the unique variable + // instance corresponding to a dereferencing chain of the top-level + // variable. + // Given a mapped name like 'a[0].b.c[0]', return the ShaderVariable + // that defines 'c' in |leafVar|, and the original name 'A[0].B.C[0]' + // in |originalName|, based on the assumption that |this| defines 'a'. + // If no match is found, return false. + bool findInfoByMappedName(const std::string &mappedFullName, + const ShaderVariable **leafVar, + std::string* originalFullName) const; GLenum type; GLenum precision; @@ -56,58 +73,97 @@ struct ShaderVariable std::string mappedName; unsigned int arraySize; bool staticUse; + std::vector fields; + std::string structName; + + protected: + bool isSameVariableAtLinkTime(const ShaderVariable &other, + bool matchPrecision) const; + + bool operator==(const ShaderVariable &other) const; + bool operator!=(const ShaderVariable &other) const + { + return !operator==(other); + } }; -struct Uniform : public ShaderVariable +struct COMPILER_EXPORT Uniform : public ShaderVariable { Uniform(); ~Uniform(); Uniform(const Uniform &other); Uniform &operator=(const Uniform &other); - - bool isStruct() const { return !fields.empty(); } - - std::vector fields; + bool operator==(const Uniform &other) const; + bool operator!=(const Uniform &other) const + { + return !operator==(other); + } + + // Decide whether two uniforms are the same at shader link time, + // assuming one from vertex shader and the other from fragment shader. + // See GLSL ES Spec 3.00.3, sec 4.3.5. + bool isSameUniformAtLinkTime(const Uniform &other) const; }; -struct Attribute : public ShaderVariable +struct COMPILER_EXPORT Attribute : public ShaderVariable { Attribute(); ~Attribute(); Attribute(const Attribute &other); Attribute &operator=(const Attribute &other); + bool operator==(const Attribute &other) const; + bool operator!=(const Attribute &other) const + { + return !operator==(other); + } int location; }; -struct InterfaceBlockField : public ShaderVariable +struct COMPILER_EXPORT InterfaceBlockField : public ShaderVariable { InterfaceBlockField(); ~InterfaceBlockField(); InterfaceBlockField(const InterfaceBlockField &other); InterfaceBlockField &operator=(const InterfaceBlockField &other); + bool operator==(const InterfaceBlockField &other) const; + bool operator!=(const InterfaceBlockField &other) const + { + return !operator==(other); + } + + // Decide whether two InterfaceBlock fields are the same at shader + // link time, assuming one from vertex shader and the other from + // fragment shader. + // See GLSL ES Spec 3.00.3, sec 4.3.7. + bool isSameInterfaceBlockFieldAtLinkTime( + const InterfaceBlockField &other) const; - bool isStruct() const { return !fields.empty(); } - - bool isRowMajorMatrix; - std::vector fields; + bool isRowMajorLayout; }; -struct Varying : public ShaderVariable +struct COMPILER_EXPORT Varying : public ShaderVariable { Varying(); ~Varying(); - Varying(const Varying &other); + Varying(const Varying &otherg); Varying &operator=(const Varying &other); + bool operator==(const Varying &other) const; + bool operator!=(const Varying &other) const + { + return !operator==(other); + } - bool isStruct() const { return !fields.empty(); } + // Decide whether two varyings are the same at shader link time, + // assuming one from vertex shader and the other from fragment shader. + // See GLSL ES Spec 3.00.3, sec 4.3.9. + bool isSameVaryingAtLinkTime(const Varying &other) const; InterpolationType interpolation; - std::vector fields; - std::string structName; + bool isInvariant; }; -struct InterfaceBlock +struct COMPILER_EXPORT InterfaceBlock { InterfaceBlock(); ~InterfaceBlock(); @@ -116,6 +172,7 @@ struct InterfaceBlock std::string name; std::string mappedName; + std::string instanceName; unsigned int arraySize; BlockLayoutType layout; bool isRowMajorLayout; diff --git a/platform/winrt/os_winrt.cpp b/platform/winrt/os_winrt.cpp index 81f3d7adf..89fa93c5c 100644 --- a/platform/winrt/os_winrt.cpp +++ b/platform/winrt/os_winrt.cpp @@ -142,6 +142,11 @@ void OSWinrt::set_gl_context(ContextEGL* p_context) { gl_context = p_context; }; +void OSWinrt::screen_size_changed() { + + gl_context->reset(); +}; + void OSWinrt::initialize(const VideoMode& p_desired,int p_video_driver,int p_audio_driver) { main_loop=NULL; @@ -568,8 +573,12 @@ Error OSWinrt::shell_open(String p_uri) { String OSWinrt::get_locale() const { +#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP // this should work on phone 8.1, but it doesn't + return "en"; +#else Platform::String ^language = Windows::Globalization::Language::CurrentInputMethodLanguageTag; return language->Data(); +#endif } void OSWinrt::release_rendering_thread() { diff --git a/platform/winrt/os_winrt.h b/platform/winrt/os_winrt.h index 13b77f7f0..68236309a 100644 --- a/platform/winrt/os_winrt.h +++ b/platform/winrt/os_winrt.h @@ -228,6 +228,7 @@ public: virtual String get_data_dir() const; void set_gl_context(ContextEGL* p_context); + void screen_size_changed(); virtual void release_rendering_thread(); virtual void make_rendering_thread(); diff --git a/scene/2d/collision_polygon_2d.cpp b/scene/2d/collision_polygon_2d.cpp index 57495b5cb..1c0be6076 100644 --- a/scene/2d/collision_polygon_2d.cpp +++ b/scene/2d/collision_polygon_2d.cpp @@ -41,7 +41,6 @@ void CollisionPolygon2D::_add_to_collision_object(Object *p_obj) { bool solids=build_mode==BUILD_SOLIDS; - if (solids) { //here comes the sun, lalalala @@ -51,6 +50,8 @@ void CollisionPolygon2D::_add_to_collision_object(Object *p_obj) { Ref convex = memnew( ConvexPolygonShape2D ); convex->set_points(decomp[i]); co->add_shape(convex,get_transform()); + if (trigger) + co->set_shape_as_trigger(co->get_shape_count()-1,true); } @@ -71,6 +72,8 @@ void CollisionPolygon2D::_add_to_collision_object(Object *p_obj) { concave->set_segments(segments); co->add_shape(concave,get_transform()); + if (trigger) + co->set_shape_as_trigger(co->get_shape_count()-1,true); } @@ -166,6 +169,18 @@ Rect2 CollisionPolygon2D::get_item_rect() const { return aabb; } +void CollisionPolygon2D::set_trigger(bool p_trigger) { + + trigger=p_trigger; + _update_parent(); +} + +bool CollisionPolygon2D::is_trigger() const{ + + return trigger; +} + + void CollisionPolygon2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("_add_to_collision_object"),&CollisionPolygon2D::_add_to_collision_object); @@ -175,14 +190,19 @@ void CollisionPolygon2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_build_mode"),&CollisionPolygon2D::set_build_mode); ObjectTypeDB::bind_method(_MD("get_build_mode"),&CollisionPolygon2D::get_build_mode); + ObjectTypeDB::bind_method(_MD("set_trigger"),&CollisionPolygon2D::set_trigger); + ObjectTypeDB::bind_method(_MD("is_trigger"),&CollisionPolygon2D::is_trigger); + ADD_PROPERTY( PropertyInfo(Variant::INT,"build_mode",PROPERTY_HINT_ENUM,"Solids,Segments"),_SCS("set_build_mode"),_SCS("get_build_mode")); ADD_PROPERTY( PropertyInfo(Variant::VECTOR2_ARRAY,"polygon"),_SCS("set_polygon"),_SCS("get_polygon")); + ADD_PROPERTY( PropertyInfo(Variant::BOOL,"trigger"),_SCS("set_trigger"),_SCS("is_trigger")); } CollisionPolygon2D::CollisionPolygon2D() { aabb=Rect2(-10,-10,20,20); build_mode=BUILD_SOLIDS; + trigger=false; } diff --git a/scene/2d/collision_polygon_2d.h b/scene/2d/collision_polygon_2d.h index 09c206008..b8e27b6fb 100644 --- a/scene/2d/collision_polygon_2d.h +++ b/scene/2d/collision_polygon_2d.h @@ -50,6 +50,7 @@ protected: Rect2 aabb; BuildMode build_mode; Vector polygon; + bool trigger; void _add_to_collision_object(Object *p_obj); void _update_parent(); @@ -60,6 +61,9 @@ protected: static void _bind_methods(); public: + void set_trigger(bool p_trigger); + bool is_trigger() const; + void set_build_mode(BuildMode p_mode); BuildMode get_build_mode() const; diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index 655c6e8bf..9d10000d2 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -858,7 +858,8 @@ Vector2 KinematicBody2D::move(const Vector2& p_motion) { //motion recover for(int i=0;icollide_shape(get_shape(i)->get_rid(), get_global_transform() * get_shape_transform(i),Vector2(),margin,sr,max_shapes,res_shapes,exclude,get_layer_mask(),mask)) collided=true; @@ -902,6 +903,8 @@ Vector2 KinematicBody2D::move(const Vector2& p_motion) { for(int i=0;icast_motion(get_shape(i)->get_rid(), get_global_transform() * get_shape_transform(i), p_motion, 0,lsafe,lunsafe,exclude,get_layer_mask(),mask); diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp index 21ecac6e3..5c047b3fe 100644 --- a/scene/3d/physics_body.cpp +++ b/scene/3d/physics_body.cpp @@ -870,6 +870,9 @@ Vector3 KinematicBody::move(const Vector3& p_motion) { for(int j=0;j<8;j++) { for(int i=0;i "+b); @@ -930,6 +933,8 @@ Vector3 KinematicBody::move(const Vector3& p_motion) { for(int i=0;iintersect_shape(get_shape(i)->get_rid(), xform * get_shape_transform(i),0,NULL,0,exclude,get_layer_mask(),mask); if (col) -- cgit v1.2.3-70-g09d2