-GDScript support for accessing properties directly
-Added code lookup and code completion support for properties too
This commit is contained in:
parent
76c2e8583e
commit
9e477babb3
@ -580,6 +580,28 @@ static void _disassemble_class(const Ref<GDScript>& p_class,const Vector<String>
|
|||||||
txt+="\"]";
|
txt+="\"]";
|
||||||
incr+=4;
|
incr+=4;
|
||||||
|
|
||||||
|
} break;
|
||||||
|
case GDFunction::OPCODE_SET_MEMBER: {
|
||||||
|
|
||||||
|
txt+=" set_member ";
|
||||||
|
txt+="[\"";
|
||||||
|
txt+=func.get_global_name(code[ip+1]);
|
||||||
|
txt+="\"]=";
|
||||||
|
txt+=DADDR(2);
|
||||||
|
incr+=3;
|
||||||
|
|
||||||
|
|
||||||
|
} break;
|
||||||
|
case GDFunction::OPCODE_GET_MEMBER: {
|
||||||
|
|
||||||
|
txt+=" get_member ";
|
||||||
|
txt+=DADDR(2);
|
||||||
|
txt+="=";
|
||||||
|
txt+="[\"";
|
||||||
|
txt+=func.get_global_name(code[ip+1]);
|
||||||
|
txt+="\"]";
|
||||||
|
incr+=3;
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case GDFunction::OPCODE_ASSIGN: {
|
case GDFunction::OPCODE_ASSIGN: {
|
||||||
|
|
||||||
|
@ -991,6 +991,22 @@ StringName ClassDB::get_property_getter(StringName p_class,const StringName p_pr
|
|||||||
return StringName();
|
return StringName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ClassDB::has_property(const StringName& p_class, const StringName& p_property, bool p_no_inheritance) {
|
||||||
|
|
||||||
|
|
||||||
|
ClassInfo *type=classes.getptr(p_class);
|
||||||
|
ClassInfo *check=type;
|
||||||
|
while(check) {
|
||||||
|
if (check->property_setget.has(p_property))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (p_no_inheritance)
|
||||||
|
break;
|
||||||
|
check=check->inherits_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void ClassDB::set_method_flags(StringName p_class,StringName p_method,int p_flags) {
|
void ClassDB::set_method_flags(StringName p_class,StringName p_method,int p_flags) {
|
||||||
|
|
||||||
|
@ -481,6 +481,7 @@ public:
|
|||||||
static void get_property_list(StringName p_class, List<PropertyInfo> *p_list, bool p_no_inheritance=false, const Object *p_validator=NULL);
|
static void get_property_list(StringName p_class, List<PropertyInfo> *p_list, bool p_no_inheritance=false, const Object *p_validator=NULL);
|
||||||
static bool set_property(Object* p_object, const StringName& p_property, const Variant& p_value, bool *r_valid=NULL);
|
static bool set_property(Object* p_object, const StringName& p_property, const Variant& p_value, bool *r_valid=NULL);
|
||||||
static bool get_property(Object* p_object,const StringName& p_property, Variant& r_value);
|
static bool get_property(Object* p_object,const StringName& p_property, Variant& r_value);
|
||||||
|
static bool has_property(const StringName& p_class,const StringName& p_property,bool p_no_inheritance=false);
|
||||||
static Variant::Type get_property_type(const StringName& p_class, const StringName& p_property,bool *r_is_valid=NULL);
|
static Variant::Type get_property_type(const StringName& p_class, const StringName& p_property,bool *r_is_valid=NULL);
|
||||||
static StringName get_property_setter(StringName p_class,const StringName p_property);
|
static StringName get_property_setter(StringName p_class,const StringName p_property);
|
||||||
static StringName get_property_getter(StringName p_class,const StringName p_property);
|
static StringName get_property_getter(StringName p_class,const StringName p_property);
|
||||||
|
@ -29,6 +29,31 @@
|
|||||||
#include "gd_compiler.h"
|
#include "gd_compiler.h"
|
||||||
#include "gd_script.h"
|
#include "gd_script.h"
|
||||||
|
|
||||||
|
bool GDCompiler::_is_class_member_property(CodeGen & codegen, const StringName & p_name) {
|
||||||
|
|
||||||
|
if (!codegen.function_node || codegen.function_node->_static)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return _is_class_member_property(codegen.script,p_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GDCompiler::_is_class_member_property(GDScript *owner, const StringName & p_name) {
|
||||||
|
|
||||||
|
|
||||||
|
GDScript *scr = owner;
|
||||||
|
GDNativeClass *nc=NULL;
|
||||||
|
while(scr) {
|
||||||
|
|
||||||
|
if (scr->native.is_valid())
|
||||||
|
nc=scr->native.ptr();
|
||||||
|
scr=scr->_base;
|
||||||
|
}
|
||||||
|
|
||||||
|
ERR_FAIL_COND_V(!nc,false);
|
||||||
|
|
||||||
|
return ClassDB::has_property(nc->get_name(),p_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void GDCompiler::_set_error(const String& p_error,const GDParser::Node *p_node) {
|
void GDCompiler::_set_error(const String& p_error,const GDParser::Node *p_node) {
|
||||||
|
|
||||||
@ -164,6 +189,17 @@ int GDCompiler::_parse_expression(CodeGen& codegen,const GDParser::Node *p_expre
|
|||||||
|
|
||||||
StringName identifier = in->name;
|
StringName identifier = in->name;
|
||||||
|
|
||||||
|
|
||||||
|
if (_is_class_member_property(codegen,identifier)) {
|
||||||
|
//get property
|
||||||
|
codegen.opcodes.push_back(GDFunction::OPCODE_GET_MEMBER); // perform operator
|
||||||
|
codegen.opcodes.push_back(codegen.get_name_map_pos(identifier)); // argument 2 (unary only takes one parameter)
|
||||||
|
int dst_addr=(p_stack_level)|(GDFunction::ADDR_TYPE_STACK<<GDFunction::ADDR_BITS);
|
||||||
|
codegen.opcodes.push_back(dst_addr); // append the stack level as destination address of the opcode
|
||||||
|
codegen.alloc_stack(p_stack_level);
|
||||||
|
return dst_addr;
|
||||||
|
}
|
||||||
|
|
||||||
// TRY STACK!
|
// TRY STACK!
|
||||||
if (!p_initializer && codegen.stack_identifiers.has(identifier)) {
|
if (!p_initializer && codegen.stack_identifiers.has(identifier)) {
|
||||||
|
|
||||||
@ -776,6 +812,8 @@ int GDCompiler::_parse_expression(CodeGen& codegen,const GDParser::Node *p_expre
|
|||||||
|
|
||||||
/* Find chain of sets */
|
/* Find chain of sets */
|
||||||
|
|
||||||
|
StringName assign_property;
|
||||||
|
|
||||||
List<GDParser::OperatorNode*> chain;
|
List<GDParser::OperatorNode*> chain;
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -784,8 +822,20 @@ int GDCompiler::_parse_expression(CodeGen& codegen,const GDParser::Node *p_expre
|
|||||||
while(true) {
|
while(true) {
|
||||||
|
|
||||||
chain.push_back(n);
|
chain.push_back(n);
|
||||||
if (n->arguments[0]->type!=GDParser::Node::TYPE_OPERATOR)
|
if (n->arguments[0]->type!=GDParser::Node::TYPE_OPERATOR) {
|
||||||
|
|
||||||
|
//check for a built-in property
|
||||||
|
if (n->arguments[0]->type==GDParser::Node::TYPE_IDENTIFIER) {
|
||||||
|
|
||||||
|
GDParser::IdentifierNode *identifier = static_cast<GDParser::IdentifierNode*>(n->arguments[0]);
|
||||||
|
if (_is_class_member_property(codegen,identifier->name)) {
|
||||||
|
assign_property = identifier->name;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
n = static_cast<GDParser::OperatorNode*>(n->arguments[0]);
|
n = static_cast<GDParser::OperatorNode*>(n->arguments[0]);
|
||||||
if (n->op!=GDParser::OperatorNode::OP_INDEX && n->op!=GDParser::OperatorNode::OP_INDEX_NAMED)
|
if (n->op!=GDParser::OperatorNode::OP_INDEX && n->op!=GDParser::OperatorNode::OP_INDEX_NAMED)
|
||||||
break;
|
break;
|
||||||
@ -810,6 +860,17 @@ int GDCompiler::_parse_expression(CodeGen& codegen,const GDParser::Node *p_expre
|
|||||||
|
|
||||||
Vector<int> setchain;
|
Vector<int> setchain;
|
||||||
|
|
||||||
|
|
||||||
|
if (assign_property!=StringName()) {
|
||||||
|
|
||||||
|
// recover and assign at the end, this allows stuff like
|
||||||
|
// position.x+=2.0
|
||||||
|
// in Node2D
|
||||||
|
setchain.push_back(prev_pos);
|
||||||
|
setchain.push_back(codegen.get_name_map_pos(assign_property));
|
||||||
|
setchain.push_back(GDFunction::OPCODE_SET_MEMBER);
|
||||||
|
}
|
||||||
|
|
||||||
for(List<GDParser::OperatorNode*>::Element *E=chain.back();E;E=E->prev()) {
|
for(List<GDParser::OperatorNode*>::Element *E=chain.back();E;E=E->prev()) {
|
||||||
|
|
||||||
|
|
||||||
@ -840,7 +901,7 @@ int GDCompiler::_parse_expression(CodeGen& codegen,const GDParser::Node *p_expre
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key_idx<0)
|
if (key_idx<0) //error
|
||||||
return key_idx;
|
return key_idx;
|
||||||
|
|
||||||
codegen.opcodes.push_back(named ? GDFunction::OPCODE_GET_NAMED : GDFunction::OPCODE_GET);
|
codegen.opcodes.push_back(named ? GDFunction::OPCODE_GET_NAMED : GDFunction::OPCODE_GET);
|
||||||
@ -852,7 +913,10 @@ int GDCompiler::_parse_expression(CodeGen& codegen,const GDParser::Node *p_expre
|
|||||||
|
|
||||||
codegen.opcodes.push_back(dst_pos);
|
codegen.opcodes.push_back(dst_pos);
|
||||||
|
|
||||||
|
|
||||||
//add in reverse order, since it will be reverted
|
//add in reverse order, since it will be reverted
|
||||||
|
|
||||||
|
|
||||||
setchain.push_back(dst_pos);
|
setchain.push_back(dst_pos);
|
||||||
setchain.push_back(key_idx);
|
setchain.push_back(key_idx);
|
||||||
setchain.push_back(prev_pos);
|
setchain.push_back(prev_pos);
|
||||||
@ -881,7 +945,7 @@ int GDCompiler::_parse_expression(CodeGen& codegen,const GDParser::Node *p_expre
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (set_index<0)
|
if (set_index<0) //error
|
||||||
return set_index;
|
return set_index;
|
||||||
|
|
||||||
if (set_index&GDFunction::ADDR_TYPE_STACK<<GDFunction::ADDR_BITS) {
|
if (set_index&GDFunction::ADDR_TYPE_STACK<<GDFunction::ADDR_BITS) {
|
||||||
@ -891,7 +955,7 @@ int GDCompiler::_parse_expression(CodeGen& codegen,const GDParser::Node *p_expre
|
|||||||
|
|
||||||
|
|
||||||
int set_value = _parse_assign_right_expression(codegen,on,slevel+1);
|
int set_value = _parse_assign_right_expression(codegen,on,slevel+1);
|
||||||
if (set_value<0)
|
if (set_value<0) //error
|
||||||
return set_value;
|
return set_value;
|
||||||
|
|
||||||
codegen.opcodes.push_back(named?GDFunction::OPCODE_SET_NAMED:GDFunction::OPCODE_SET);
|
codegen.opcodes.push_back(named?GDFunction::OPCODE_SET_NAMED:GDFunction::OPCODE_SET);
|
||||||
@ -899,20 +963,36 @@ int GDCompiler::_parse_expression(CodeGen& codegen,const GDParser::Node *p_expre
|
|||||||
codegen.opcodes.push_back(set_index);
|
codegen.opcodes.push_back(set_index);
|
||||||
codegen.opcodes.push_back(set_value);
|
codegen.opcodes.push_back(set_value);
|
||||||
|
|
||||||
for(int i=0;i<setchain.size();i+=4) {
|
for(int i=0;i<setchain.size();i++) {
|
||||||
|
|
||||||
|
|
||||||
codegen.opcodes.push_back(setchain[i+0]);
|
codegen.opcodes.push_back(setchain[i]);
|
||||||
codegen.opcodes.push_back(setchain[i+1]);
|
|
||||||
codegen.opcodes.push_back(setchain[i+2]);
|
|
||||||
codegen.opcodes.push_back(setchain[i+3]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
|
|
||||||
|
} else if (on->arguments[0]->type==GDParser::Node::TYPE_IDENTIFIER && _is_class_member_property(codegen,static_cast<GDParser::IdentifierNode*>(on->arguments[0])->name)) {
|
||||||
|
//assignment to member property
|
||||||
|
|
||||||
|
int slevel = p_stack_level;
|
||||||
|
|
||||||
|
int src_address = _parse_assign_right_expression(codegen,on,slevel);
|
||||||
|
if (src_address<0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
StringName name = static_cast<GDParser::IdentifierNode*>(on->arguments[0])->name;
|
||||||
|
|
||||||
|
codegen.opcodes.push_back(GDFunction::OPCODE_SET_MEMBER);
|
||||||
|
codegen.opcodes.push_back(codegen.get_name_map_pos(name));
|
||||||
|
codegen.opcodes.push_back(src_address);
|
||||||
|
|
||||||
|
return GDFunction::ADDR_TYPE_NIL<<GDFunction::ADDR_BITS;
|
||||||
} else {
|
} else {
|
||||||
//ASSIGNMENT MODE!!
|
|
||||||
|
|
||||||
|
|
||||||
|
//REGULAR ASSIGNMENT MODE!!
|
||||||
|
|
||||||
int slevel = p_stack_level;
|
int slevel = p_stack_level;
|
||||||
|
|
||||||
@ -1211,6 +1291,11 @@ Error GDCompiler::_parse_block(CodeGen& codegen,const GDParser::BlockNode *p_blo
|
|||||||
|
|
||||||
const GDParser::LocalVarNode *lv = static_cast<const GDParser::LocalVarNode*>(s);
|
const GDParser::LocalVarNode *lv = static_cast<const GDParser::LocalVarNode*>(s);
|
||||||
|
|
||||||
|
if (_is_class_member_property(codegen,lv->name)) {
|
||||||
|
_set_error("Name for local variable '"+String(lv->name)+"' can't shadow class property of the same name.",lv);
|
||||||
|
return ERR_ALREADY_EXISTS;
|
||||||
|
}
|
||||||
|
|
||||||
codegen.add_stack_identifier(lv->name,p_stack_level++);
|
codegen.add_stack_identifier(lv->name,p_stack_level++);
|
||||||
codegen.alloc_stack(p_stack_level);
|
codegen.alloc_stack(p_stack_level);
|
||||||
new_identifiers++;
|
new_identifiers++;
|
||||||
@ -1249,6 +1334,10 @@ Error GDCompiler::_parse_function(GDScript *p_script,const GDParser::ClassNode *
|
|||||||
|
|
||||||
if (p_func) {
|
if (p_func) {
|
||||||
for(int i=0;i<p_func->arguments.size();i++) {
|
for(int i=0;i<p_func->arguments.size();i++) {
|
||||||
|
if (_is_class_member_property(p_script,p_func->arguments[i])) {
|
||||||
|
_set_error("Name for argument '"+String(p_func->arguments[i])+"' can't shadow class property of the same name.",p_func);
|
||||||
|
return ERR_ALREADY_EXISTS;
|
||||||
|
}
|
||||||
codegen.add_stack_identifier(p_func->arguments[i],i);
|
codegen.add_stack_identifier(p_func->arguments[i],i);
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
argnames.push_back(p_func->arguments[i]);
|
argnames.push_back(p_func->arguments[i]);
|
||||||
@ -1653,6 +1742,10 @@ Error GDCompiler::_parse_class(GDScript *p_script, GDScript *p_owner, const GDPa
|
|||||||
_set_error("Member '"+name+"' already exists (in current or parent class)",p_class);
|
_set_error("Member '"+name+"' already exists (in current or parent class)",p_class);
|
||||||
return ERR_ALREADY_EXISTS;
|
return ERR_ALREADY_EXISTS;
|
||||||
}
|
}
|
||||||
|
if (_is_class_member_property(p_script,name)) {
|
||||||
|
_set_error("Member '"+name+"' already exists as a class property.",p_class);
|
||||||
|
return ERR_ALREADY_EXISTS;
|
||||||
|
}
|
||||||
|
|
||||||
if (p_class->variables[i]._export.type!=Variant::NIL) {
|
if (p_class->variables[i]._export.type!=Variant::NIL) {
|
||||||
|
|
||||||
@ -1691,6 +1784,11 @@ Error GDCompiler::_parse_class(GDScript *p_script, GDScript *p_owner, const GDPa
|
|||||||
StringName name = p_class->constant_expressions[i].identifier;
|
StringName name = p_class->constant_expressions[i].identifier;
|
||||||
ERR_CONTINUE( p_class->constant_expressions[i].expression->type!=GDParser::Node::TYPE_CONSTANT );
|
ERR_CONTINUE( p_class->constant_expressions[i].expression->type!=GDParser::Node::TYPE_CONSTANT );
|
||||||
|
|
||||||
|
if (_is_class_member_property(p_script,name)) {
|
||||||
|
_set_error("Member '"+name+"' already exists as a class property.",p_class);
|
||||||
|
return ERR_ALREADY_EXISTS;
|
||||||
|
}
|
||||||
|
|
||||||
GDParser::ConstantNode *constant = static_cast<GDParser::ConstantNode*>(p_class->constant_expressions[i].expression);
|
GDParser::ConstantNode *constant = static_cast<GDParser::ConstantNode*>(p_class->constant_expressions[i].expression);
|
||||||
|
|
||||||
p_script->constants.insert(name,constant->value);
|
p_script->constants.insert(name,constant->value);
|
||||||
|
@ -37,6 +37,7 @@ class GDCompiler {
|
|||||||
|
|
||||||
const GDParser *parser;
|
const GDParser *parser;
|
||||||
struct CodeGen {
|
struct CodeGen {
|
||||||
|
|
||||||
GDScript *script;
|
GDScript *script;
|
||||||
const GDParser::ClassNode *class_node;
|
const GDParser::ClassNode *class_node;
|
||||||
const GDParser::FunctionNode *function_node;
|
const GDParser::FunctionNode *function_node;
|
||||||
@ -134,6 +135,9 @@ class GDCompiler {
|
|||||||
Ref<GDScript> _parse_class(GDParser::ClassNode *p_class);
|
Ref<GDScript> _parse_class(GDParser::ClassNode *p_class);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
bool _is_class_member_property(CodeGen & codegen, const StringName & p_name);
|
||||||
|
bool _is_class_member_property(GDScript *owner, const StringName & p_name);
|
||||||
|
|
||||||
void _set_error(const String& p_error,const GDParser::Node *p_node);
|
void _set_error(const String& p_error,const GDParser::Node *p_node);
|
||||||
|
|
||||||
bool _create_unary_operator(CodeGen& codegen,const GDParser::OperatorNode *on,Variant::Operator op, int p_stack_level);
|
bool _create_unary_operator(CodeGen& codegen,const GDParser::OperatorNode *on,Variant::Operator op, int p_stack_level);
|
||||||
|
@ -347,7 +347,7 @@ String GDScriptLanguage::make_function(const String& p_class,const String& p_nam
|
|||||||
|
|
||||||
struct GDCompletionIdentifier {
|
struct GDCompletionIdentifier {
|
||||||
|
|
||||||
StringName GDCLASS;
|
StringName obj_type;
|
||||||
Ref<GDScript> script;
|
Ref<GDScript> script;
|
||||||
Variant::Type type;
|
Variant::Type type;
|
||||||
Variant value; //im case there is a value, also return it
|
Variant value; //im case there is a value, also return it
|
||||||
@ -365,10 +365,10 @@ static GDCompletionIdentifier _get_type_from_variant(const Variant& p_variant) {
|
|||||||
Object *obj = p_variant;
|
Object *obj = p_variant;
|
||||||
if (obj) {
|
if (obj) {
|
||||||
//if (obj->cast_to<GDNativeClass>()) {
|
//if (obj->cast_to<GDNativeClass>()) {
|
||||||
// t.GDCLASS=obj->cast_to<GDNativeClass>()->get_name();
|
// t.obj_type=obj->cast_to<GDNativeClass>()->get_name();
|
||||||
// t.value=Variant();
|
// t.value=Variant();
|
||||||
//} else {
|
//} else {
|
||||||
t.GDCLASS=obj->get_class();
|
t.obj_type=obj->get_class();
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -380,7 +380,7 @@ static GDCompletionIdentifier _get_type_from_pinfo(const PropertyInfo& p_info) {
|
|||||||
GDCompletionIdentifier t;
|
GDCompletionIdentifier t;
|
||||||
t.type=p_info.type;
|
t.type=p_info.type;
|
||||||
if (p_info.hint==PROPERTY_HINT_RESOURCE_TYPE) {
|
if (p_info.hint==PROPERTY_HINT_RESOURCE_TYPE) {
|
||||||
t.GDCLASS=p_info.hint_string;
|
t.obj_type=p_info.hint_string;
|
||||||
}
|
}
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
@ -508,7 +508,7 @@ static GDCompletionIdentifier _get_native_class(GDCompletionContext& context) {
|
|||||||
id.type=Variant::OBJECT;
|
id.type=Variant::OBJECT;
|
||||||
if (context.base)
|
if (context.base)
|
||||||
id.value=context.base;
|
id.value=context.base;
|
||||||
id.GDCLASS=nc->get_name();
|
id.obj_type=nc->get_name();
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -609,15 +609,15 @@ static bool _guess_expression_type(GDCompletionContext& context,const GDParser::
|
|||||||
GDNativeClass *gdnc = obj->cast_to<GDNativeClass>();
|
GDNativeClass *gdnc = obj->cast_to<GDNativeClass>();
|
||||||
r_type.type=Variant::OBJECT;
|
r_type.type=Variant::OBJECT;
|
||||||
r_type.value=Variant();
|
r_type.value=Variant();
|
||||||
r_type.GDCLASS=gdnc->get_name();
|
r_type.obj_type=gdnc->get_name();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ClassDB::has_method(base.GDCLASS,id)) {
|
if (ClassDB::has_method(base.obj_type,id)) {
|
||||||
|
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
MethodBind *mb = ClassDB::get_method(base.GDCLASS,id);
|
MethodBind *mb = ClassDB::get_method(base.obj_type,id);
|
||||||
PropertyInfo pi = mb->get_argument_info(-1);
|
PropertyInfo pi = mb->get_argument_info(-1);
|
||||||
|
|
||||||
//try calling the function if constant and all args are constant, should not crash..
|
//try calling the function if constant and all args are constant, should not crash..
|
||||||
@ -643,7 +643,7 @@ static bool _guess_expression_type(GDCompletionContext& context,const GDParser::
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (all_valid && String(id)=="get_node" && ClassDB::is_parent_class(base.GDCLASS,"Node") && args.size()) {
|
if (all_valid && String(id)=="get_node" && ClassDB::is_parent_class(base.obj_type,"Node") && args.size()) {
|
||||||
|
|
||||||
String arg1=args[0];
|
String arg1=args[0];
|
||||||
if (arg1.begins_with("/root/")) {
|
if (arg1.begins_with("/root/")) {
|
||||||
@ -686,7 +686,7 @@ static bool _guess_expression_type(GDCompletionContext& context,const GDParser::
|
|||||||
scr = ResourceLoader::load(script);
|
scr = ResourceLoader::load(script);
|
||||||
|
|
||||||
|
|
||||||
r_type.GDCLASS="Node";
|
r_type.obj_type="Node";
|
||||||
r_type.type=Variant::OBJECT;
|
r_type.type=Variant::OBJECT;
|
||||||
r_type.script=scr;
|
r_type.script=scr;
|
||||||
r_type.value=Variant();
|
r_type.value=Variant();
|
||||||
@ -729,7 +729,7 @@ static bool _guess_expression_type(GDCompletionContext& context,const GDParser::
|
|||||||
|
|
||||||
r_type.type=pi.type;
|
r_type.type=pi.type;
|
||||||
if (pi.hint==PROPERTY_HINT_RESOURCE_TYPE) {
|
if (pi.hint==PROPERTY_HINT_RESOURCE_TYPE) {
|
||||||
r_type.GDCLASS=pi.hint_string;
|
r_type.obj_type=pi.hint_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -755,7 +755,7 @@ static bool _guess_expression_type(GDCompletionContext& context,const GDParser::
|
|||||||
MethodInfo mi = E->get();
|
MethodInfo mi = E->get();
|
||||||
r_type.type=mi.return_val.type;
|
r_type.type=mi.return_val.type;
|
||||||
if (mi.return_val.hint==PROPERTY_HINT_RESOURCE_TYPE) {
|
if (mi.return_val.hint==PROPERTY_HINT_RESOURCE_TYPE) {
|
||||||
r_type.GDCLASS=mi.return_val.hint_string;
|
r_type.obj_type=mi.return_val.hint_string;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -940,6 +940,15 @@ static bool _guess_expression_type(GDCompletionContext& context,const GDParser::
|
|||||||
static bool _guess_identifier_type_in_block(GDCompletionContext& context,int p_line,const StringName& p_identifier,GDCompletionIdentifier &r_type) {
|
static bool _guess_identifier_type_in_block(GDCompletionContext& context,int p_line,const StringName& p_identifier,GDCompletionIdentifier &r_type) {
|
||||||
|
|
||||||
|
|
||||||
|
GDCompletionIdentifier gdi = _get_native_class(context);
|
||||||
|
if (gdi.obj_type!=StringName()) {
|
||||||
|
bool valid;
|
||||||
|
Variant::Type t = ClassDB::get_property_type(gdi.obj_type,p_identifier,&valid);
|
||||||
|
if (t!=Variant::NIL && valid) {
|
||||||
|
r_type.type=t;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const GDParser::Node *last_assign=NULL;
|
const GDParser::Node *last_assign=NULL;
|
||||||
int last_assign_line=-1;
|
int last_assign_line=-1;
|
||||||
@ -1064,11 +1073,11 @@ static bool _guess_identifier_type(GDCompletionContext& context,int p_line,const
|
|||||||
|
|
||||||
if (argindex!=-1) {
|
if (argindex!=-1) {
|
||||||
GDCompletionIdentifier id =_get_native_class(context);
|
GDCompletionIdentifier id =_get_native_class(context);
|
||||||
if (id.type==Variant::OBJECT && id.GDCLASS!=StringName()) {
|
if (id.type==Variant::OBJECT && id.obj_type!=StringName()) {
|
||||||
//this kinda sucks but meh
|
//this kinda sucks but meh
|
||||||
|
|
||||||
List<MethodInfo> vmethods;
|
List<MethodInfo> vmethods;
|
||||||
ClassDB::get_virtual_methods(id.GDCLASS,&vmethods);
|
ClassDB::get_virtual_methods(id.obj_type,&vmethods);
|
||||||
for (List<MethodInfo>::Element *E=vmethods.front();E;E=E->next()) {
|
for (List<MethodInfo>::Element *E=vmethods.front();E;E=E->next()) {
|
||||||
|
|
||||||
|
|
||||||
@ -1081,14 +1090,14 @@ static bool _guess_identifier_type(GDCompletionContext& context,int p_line,const
|
|||||||
|
|
||||||
|
|
||||||
r_type.type=Variant::OBJECT;
|
r_type.type=Variant::OBJECT;
|
||||||
r_type.GDCLASS=arg.name.substr(scp+1,arg.name.length());
|
r_type.obj_type=arg.name.substr(scp+1,arg.name.length());
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
r_type.type=arg.type;
|
r_type.type=arg.type;
|
||||||
if (arg.hint==PROPERTY_HINT_RESOURCE_TYPE)
|
if (arg.hint==PROPERTY_HINT_RESOURCE_TYPE)
|
||||||
r_type.GDCLASS=arg.hint_string;
|
r_type.obj_type=arg.hint_string;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1174,7 +1183,7 @@ static bool _guess_identifier_type(GDCompletionContext& context,int p_line,const
|
|||||||
scr = ResourceLoader::load(script);
|
scr = ResourceLoader::load(script);
|
||||||
|
|
||||||
|
|
||||||
r_type.GDCLASS="Node";
|
r_type.obj_type="Node";
|
||||||
r_type.type=Variant::OBJECT;
|
r_type.type=Variant::OBJECT;
|
||||||
r_type.script=scr;
|
r_type.script=scr;
|
||||||
r_type.value=Variant();
|
r_type.value=Variant();
|
||||||
@ -1298,26 +1307,43 @@ static void _find_identifiers_in_class(GDCompletionContext& context,bool p_stati
|
|||||||
base=script->get_native();
|
base=script->get_native();
|
||||||
} else if (nc.is_valid()) {
|
} else if (nc.is_valid()) {
|
||||||
|
|
||||||
|
StringName type = nc->get_name();
|
||||||
|
|
||||||
if (!p_only_functions) {
|
if (!p_only_functions) {
|
||||||
|
|
||||||
StringName type = nc->get_name();
|
|
||||||
List<String> constants;
|
List<String> constants;
|
||||||
ClassDB::get_integer_constant_list(type,&constants);
|
ClassDB::get_integer_constant_list(type,&constants);
|
||||||
for(List<String>::Element *E=constants.front();E;E=E->next()) {
|
for(List<String>::Element *E=constants.front();E;E=E->next()) {
|
||||||
result.insert(E->get());
|
result.insert(E->get());
|
||||||
}
|
}
|
||||||
|
|
||||||
List<MethodInfo> methods;
|
List<PropertyInfo> pinfo;
|
||||||
ClassDB::get_method_list(type,&methods);
|
|
||||||
for(List<MethodInfo>::Element *E=methods.front();E;E=E->next()) {
|
ClassDB::get_property_list(type,&pinfo);
|
||||||
if (E->get().name.begins_with("_"))
|
|
||||||
|
for (List<PropertyInfo>::Element *E=pinfo.front();E;E=E->next()) {
|
||||||
|
if (E->get().usage&(PROPERTY_USAGE_GROUP|PROPERTY_USAGE_CATEGORY))
|
||||||
continue;
|
continue;
|
||||||
if (E->get().arguments.size())
|
if (E->get().name.find("/")!=-1)
|
||||||
result.insert(E->get().name+"(");
|
continue;
|
||||||
else
|
result.insert(E->get().name);
|
||||||
result.insert(E->get().name+"()");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
List<MethodInfo> methods;
|
||||||
|
ClassDB::get_method_list(type,&methods);
|
||||||
|
for(List<MethodInfo>::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
|
||||||
|
result.insert(E->get().name+"()");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
} else
|
} else
|
||||||
break;
|
break;
|
||||||
@ -1483,10 +1509,10 @@ static void _find_type_arguments(GDCompletionContext& context,const GDParser::No
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} else if (id.type==Variant::OBJECT && id.GDCLASS!=StringName()) {
|
} else if (id.type==Variant::OBJECT && id.obj_type!=StringName()) {
|
||||||
|
|
||||||
|
|
||||||
MethodBind *m = ClassDB::get_method(id.GDCLASS,p_method);
|
MethodBind *m = ClassDB::get_method(id.obj_type,p_method);
|
||||||
if (!m) {
|
if (!m) {
|
||||||
//not in static method, see script
|
//not in static method, see script
|
||||||
|
|
||||||
@ -1699,7 +1725,7 @@ static void _find_type_arguments(GDCompletionContext& context,const GDParser::No
|
|||||||
|
|
||||||
if (p_argidx==0) {
|
if (p_argidx==0) {
|
||||||
List<MethodInfo> sigs;
|
List<MethodInfo> sigs;
|
||||||
ClassDB::get_signal_list(id.GDCLASS,&sigs);
|
ClassDB::get_signal_list(id.obj_type,&sigs);
|
||||||
|
|
||||||
if (id.script.is_valid()) {
|
if (id.script.is_valid()) {
|
||||||
id.script->get_script_signal_list(&sigs);
|
id.script->get_script_signal_list(&sigs);
|
||||||
@ -1735,7 +1761,7 @@ static void _find_type_arguments(GDCompletionContext& context,const GDParser::No
|
|||||||
}*/
|
}*/
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (p_argidx==0 && (String(p_method)=="get_node" || String(p_method)=="has_node") && ClassDB::is_parent_class(id.GDCLASS,"Node")) {
|
if (p_argidx==0 && (String(p_method)=="get_node" || String(p_method)=="has_node") && ClassDB::is_parent_class(id.obj_type,"Node")) {
|
||||||
|
|
||||||
List<PropertyInfo> props;
|
List<PropertyInfo> props;
|
||||||
Globals::get_singleton()->get_property_list(&props);
|
Globals::get_singleton()->get_property_list(&props);
|
||||||
@ -1962,7 +1988,7 @@ static void _find_call_arguments(GDCompletionContext& context,const GDParser::No
|
|||||||
|
|
||||||
GDCompletionIdentifier ci;
|
GDCompletionIdentifier ci;
|
||||||
ci.type=Variant::OBJECT;
|
ci.type=Variant::OBJECT;
|
||||||
ci.GDCLASS=nc->get_name();
|
ci.obj_type=nc->get_name();
|
||||||
if (!context._class->owner)
|
if (!context._class->owner)
|
||||||
ci.value=context.base;
|
ci.value=context.base;
|
||||||
|
|
||||||
@ -2143,7 +2169,7 @@ Error GDScriptLanguage::complete_code(const String& p_code, const String& p_base
|
|||||||
GDCompletionIdentifier t;
|
GDCompletionIdentifier t;
|
||||||
if (_guess_expression_type(context,static_cast<const GDParser::OperatorNode *>(node)->arguments[0],p.get_completion_line(),t)) {
|
if (_guess_expression_type(context,static_cast<const GDParser::OperatorNode *>(node)->arguments[0],p.get_completion_line(),t)) {
|
||||||
|
|
||||||
if (t.type==Variant::OBJECT && t.GDCLASS=="GDNativeClass") {
|
if (t.type==Variant::OBJECT && t.obj_type=="GDNativeClass") {
|
||||||
//native enum
|
//native enum
|
||||||
Ref<GDNativeClass> gdn = t.value;
|
Ref<GDNativeClass> gdn = t.value;
|
||||||
if (gdn.is_valid()) {
|
if (gdn.is_valid()) {
|
||||||
@ -2153,8 +2179,19 @@ Error GDScriptLanguage::complete_code(const String& p_code, const String& p_base
|
|||||||
for (List<String>::Element *E=cnames.front();E;E=E->next()) {
|
for (List<String>::Element *E=cnames.front();E;E=E->next()) {
|
||||||
options.insert(E->get());
|
options.insert(E->get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<PropertyInfo> pinfo;
|
||||||
|
ClassDB::get_property_list(cn,&pinfo);
|
||||||
|
|
||||||
|
for (List<PropertyInfo>::Element *E=pinfo.front();E;E=E->next()) {
|
||||||
|
if (E->get().usage&(PROPERTY_USAGE_GROUP|PROPERTY_USAGE_CATEGORY))
|
||||||
|
continue;
|
||||||
|
if (E->get().name.find("/")!=-1)
|
||||||
|
continue;
|
||||||
|
options.insert(E->get().name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (t.type==Variant::OBJECT && t.GDCLASS!=StringName()) {
|
} else if (t.type==Variant::OBJECT && t.obj_type!=StringName()) {
|
||||||
|
|
||||||
Ref<GDScript> on_script;
|
Ref<GDScript> on_script;
|
||||||
|
|
||||||
@ -2288,10 +2325,23 @@ Error GDScriptLanguage::complete_code(const String& p_code, const String& p_base
|
|||||||
|
|
||||||
|
|
||||||
if (!isfunction) {
|
if (!isfunction) {
|
||||||
ClassDB::get_integer_constant_list(t.GDCLASS,r_options);
|
ClassDB::get_integer_constant_list(t.obj_type,r_options);
|
||||||
|
|
||||||
|
List<PropertyInfo> pinfo;
|
||||||
|
ClassDB::get_property_list(t.obj_type,&pinfo);
|
||||||
|
|
||||||
|
for (List<PropertyInfo>::Element *E=pinfo.front();E;E=E->next()) {
|
||||||
|
if (E->get().usage&(PROPERTY_USAGE_GROUP|PROPERTY_USAGE_CATEGORY))
|
||||||
|
continue;
|
||||||
|
if (E->get().name.find("/")!=-1)
|
||||||
|
continue;
|
||||||
|
r_options->push_back(E->get().name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
List<MethodInfo> mi;
|
List<MethodInfo> mi;
|
||||||
ClassDB::get_method_list(t.GDCLASS,&mi);
|
ClassDB::get_method_list(t.obj_type,&mi);
|
||||||
for (List<MethodInfo>::Element *E=mi.front();E;E=E->next()) {
|
for (List<MethodInfo>::Element *E=mi.front();E;E=E->next()) {
|
||||||
|
|
||||||
if (E->get().name.begins_with("_"))
|
if (E->get().name.begins_with("_"))
|
||||||
@ -2395,9 +2445,9 @@ Error GDScriptLanguage::complete_code(const String& p_code, const String& p_base
|
|||||||
|
|
||||||
GDCompletionIdentifier cid = _get_native_class(context);
|
GDCompletionIdentifier cid = _get_native_class(context);
|
||||||
|
|
||||||
if (cid.GDCLASS!=StringName()) {
|
if (cid.obj_type!=StringName()) {
|
||||||
List<MethodInfo> vm;
|
List<MethodInfo> vm;
|
||||||
ClassDB::get_virtual_methods(cid.GDCLASS,&vm);
|
ClassDB::get_virtual_methods(cid.obj_type,&vm);
|
||||||
for(List<MethodInfo>::Element *E=vm.front();E;E=E->next()) {
|
for(List<MethodInfo>::Element *E=vm.front();E;E=E->next()) {
|
||||||
|
|
||||||
MethodInfo &mi=E->get();
|
MethodInfo &mi=E->get();
|
||||||
@ -2430,10 +2480,10 @@ Error GDScriptLanguage::complete_code(const String& p_code, const String& p_base
|
|||||||
if (!_guess_expression_type(context,node,p.get_completion_line(),t))
|
if (!_guess_expression_type(context,node,p.get_completion_line(),t))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (t.type==Variant::OBJECT && t.GDCLASS!=StringName()) {
|
if (t.type==Variant::OBJECT && t.obj_type!=StringName()) {
|
||||||
|
|
||||||
List<MethodInfo> sigs;
|
List<MethodInfo> sigs;
|
||||||
ClassDB::get_signal_list(t.GDCLASS,&sigs);
|
ClassDB::get_signal_list(t.obj_type,&sigs);
|
||||||
for (List<MethodInfo>::Element *E=sigs.front();E;E=E->next()) {
|
for (List<MethodInfo>::Element *E=sigs.front();E;E=E->next()) {
|
||||||
options.insert("\""+E->get().name+"\"");
|
options.insert("\""+E->get().name+"\"");
|
||||||
}
|
}
|
||||||
@ -2610,12 +2660,12 @@ Error GDScriptLanguage::lookup_code(const String& p_code, const String& p_symbol
|
|||||||
}
|
}
|
||||||
|
|
||||||
GDCompletionIdentifier identifier = _get_native_class(context);
|
GDCompletionIdentifier identifier = _get_native_class(context);
|
||||||
print_line("identifier: "+String(identifier.GDCLASS));
|
print_line("identifier: "+String(identifier.obj_type));
|
||||||
|
|
||||||
if (ClassDB::has_method(identifier.GDCLASS,p_symbol)) {
|
if (ClassDB::has_method(identifier.obj_type,p_symbol)) {
|
||||||
|
|
||||||
r_result.type=ScriptLanguage::LookupResult::RESULT_CLASS_METHOD;
|
r_result.type=ScriptLanguage::LookupResult::RESULT_CLASS_METHOD;
|
||||||
r_result.class_name=identifier.GDCLASS;
|
r_result.class_name=identifier.obj_type;
|
||||||
r_result.class_member=p_symbol;
|
r_result.class_member=p_symbol;
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
@ -2653,16 +2703,29 @@ Error GDScriptLanguage::lookup_code(const String& p_code, const String& p_symbol
|
|||||||
GDCompletionIdentifier identifier = _get_native_class(context);
|
GDCompletionIdentifier identifier = _get_native_class(context);
|
||||||
|
|
||||||
|
|
||||||
if (ClassDB::has_method(identifier.GDCLASS,p_symbol)) {
|
if (ClassDB::has_method(identifier.obj_type,p_symbol)) {
|
||||||
|
|
||||||
r_result.type=ScriptLanguage::LookupResult::RESULT_CLASS_METHOD;
|
r_result.type=ScriptLanguage::LookupResult::RESULT_CLASS_METHOD;
|
||||||
r_result.class_name=identifier.GDCLASS;
|
r_result.class_name=identifier.obj_type;
|
||||||
r_result.class_member=p_symbol;
|
r_result.class_member=p_symbol;
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
|
||||||
|
GDCompletionIdentifier gdi = _get_native_class(context);
|
||||||
|
if (gdi.obj_type!=StringName()) {
|
||||||
|
bool valid;
|
||||||
|
Variant::Type t = ClassDB::get_property_type(gdi.obj_type,p_symbol,&valid);
|
||||||
|
if (t!=Variant::NIL && valid) {
|
||||||
|
r_result.type=ScriptLanguage::LookupResult::RESULT_CLASS_PROPERTY;
|
||||||
|
r_result.class_name=gdi.obj_type;
|
||||||
|
r_result.class_member=p_symbol;
|
||||||
|
return OK;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const GDParser::BlockNode *block=context.block;
|
const GDParser::BlockNode *block=context.block;
|
||||||
//search in blocks going up (local var?)
|
//search in blocks going up (local var?)
|
||||||
while(block) {
|
while(block) {
|
||||||
@ -2799,7 +2862,7 @@ Error GDScriptLanguage::lookup_code(const String& p_code, const String& p_symbol
|
|||||||
if (identifier.script.is_valid()) {
|
if (identifier.script.is_valid()) {
|
||||||
print_line("var script: "+identifier.script->get_path());
|
print_line("var script: "+identifier.script->get_path());
|
||||||
}
|
}
|
||||||
print_line("obj type: "+String(identifier.GDCLASS));
|
print_line("obj type: "+String(identifier.obj_type));
|
||||||
print_line("value: "+String(identifier.value));
|
print_line("value: "+String(identifier.value));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -2823,7 +2886,7 @@ Error GDScriptLanguage::lookup_code(const String& p_code, const String& p_symbol
|
|||||||
GDCompletionIdentifier t;
|
GDCompletionIdentifier t;
|
||||||
if (_guess_expression_type(context,static_cast<const GDParser::OperatorNode *>(node)->arguments[0],p.get_completion_line(),t)) {
|
if (_guess_expression_type(context,static_cast<const GDParser::OperatorNode *>(node)->arguments[0],p.get_completion_line(),t)) {
|
||||||
|
|
||||||
if (t.type==Variant::OBJECT && t.GDCLASS=="GDNativeClass") {
|
if (t.type==Variant::OBJECT && t.obj_type=="GDNativeClass") {
|
||||||
//native enum
|
//native enum
|
||||||
Ref<GDNativeClass> gdn = t.value;
|
Ref<GDNativeClass> gdn = t.value;
|
||||||
if (gdn.is_valid()) {
|
if (gdn.is_valid()) {
|
||||||
@ -2833,7 +2896,7 @@ Error GDScriptLanguage::lookup_code(const String& p_code, const String& p_symbol
|
|||||||
return OK;
|
return OK;
|
||||||
|
|
||||||
}
|
}
|
||||||
} else if (t.type==Variant::OBJECT && t.GDCLASS!=StringName()) {
|
} else if (t.type==Variant::OBJECT && t.obj_type!=StringName()) {
|
||||||
|
|
||||||
Ref<GDScript> on_script;
|
Ref<GDScript> on_script;
|
||||||
|
|
||||||
@ -2858,29 +2921,30 @@ Error GDScriptLanguage::lookup_code(const String& p_code, const String& p_symbol
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ClassDB::has_method(t.GDCLASS,p_symbol)) {
|
if (ClassDB::has_method(t.obj_type,p_symbol)) {
|
||||||
|
|
||||||
r_result.type=ScriptLanguage::LookupResult::RESULT_CLASS_METHOD;
|
r_result.type=ScriptLanguage::LookupResult::RESULT_CLASS_METHOD;
|
||||||
r_result.class_name=t.GDCLASS;
|
r_result.class_name=t.obj_type;
|
||||||
r_result.class_member=p_symbol;
|
r_result.class_member=p_symbol;
|
||||||
return OK;
|
return OK;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool success;
|
bool success;
|
||||||
ClassDB::get_integer_constant(t.GDCLASS,p_symbol,&success);
|
ClassDB::get_integer_constant(t.obj_type,p_symbol,&success);
|
||||||
if (success) {
|
if (success) {
|
||||||
r_result.type=ScriptLanguage::LookupResult::RESULT_CLASS_CONSTANT;
|
r_result.type=ScriptLanguage::LookupResult::RESULT_CLASS_CONSTANT;
|
||||||
r_result.class_name=t.GDCLASS;
|
r_result.class_name=t.obj_type;
|
||||||
r_result.class_member=p_symbol;
|
r_result.class_member=p_symbol;
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ClassDB::get_property_type(t.GDCLASS,p_symbol,&success);
|
|
||||||
|
ClassDB::get_property_type(t.obj_type,p_symbol,&success);
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
r_result.type=ScriptLanguage::LookupResult::RESULT_CLASS_PROPERTY;
|
r_result.type=ScriptLanguage::LookupResult::RESULT_CLASS_PROPERTY;
|
||||||
r_result.class_name=t.GDCLASS;
|
r_result.class_name=t.obj_type;
|
||||||
r_result.class_member=p_symbol;
|
r_result.class_member=p_symbol;
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
@ -2934,15 +2998,15 @@ Error GDScriptLanguage::lookup_code(const String& p_code, const String& p_symbol
|
|||||||
|
|
||||||
GDCompletionIdentifier cid = _get_native_class(context);
|
GDCompletionIdentifier cid = _get_native_class(context);
|
||||||
|
|
||||||
if (cid.GDCLASS!=StringName()) {
|
if (cid.obj_type!=StringName()) {
|
||||||
List<MethodInfo> vm;
|
List<MethodInfo> vm;
|
||||||
ClassDB::get_virtual_methods(cid.GDCLASS,&vm);
|
ClassDB::get_virtual_methods(cid.obj_type,&vm);
|
||||||
for(List<MethodInfo>::Element *E=vm.front();E;E=E->next()) {
|
for(List<MethodInfo>::Element *E=vm.front();E;E=E->next()) {
|
||||||
|
|
||||||
if (p_symbol==E->get().name) {
|
if (p_symbol==E->get().name) {
|
||||||
|
|
||||||
r_result.type=ScriptLanguage::LookupResult::RESULT_CLASS_METHOD;
|
r_result.type=ScriptLanguage::LookupResult::RESULT_CLASS_METHOD;
|
||||||
r_result.class_name=cid.GDCLASS;
|
r_result.class_name=cid.obj_type;
|
||||||
r_result.class_member=p_symbol;
|
r_result.class_member=p_symbol;
|
||||||
return OK;
|
return OK;
|
||||||
|
|
||||||
|
@ -487,7 +487,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
|
|||||||
case OPCODE_GET_NAMED: {
|
case OPCODE_GET_NAMED: {
|
||||||
|
|
||||||
|
|
||||||
CHECK_SPACE(3);
|
CHECK_SPACE(4);
|
||||||
|
|
||||||
GET_VARIANT_PTR(src,1);
|
GET_VARIANT_PTR(src,1);
|
||||||
GET_VARIANT_PTR(dst,3);
|
GET_VARIANT_PTR(dst,3);
|
||||||
@ -519,6 +519,46 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
|
|||||||
#endif
|
#endif
|
||||||
ip+=4;
|
ip+=4;
|
||||||
} continue;
|
} continue;
|
||||||
|
case OPCODE_SET_MEMBER: {
|
||||||
|
|
||||||
|
CHECK_SPACE(3);
|
||||||
|
int indexname = _code_ptr[ip+1];
|
||||||
|
ERR_BREAK(indexname<0 || indexname>=_global_names_count);
|
||||||
|
const StringName *index = &_global_names_ptr[indexname];
|
||||||
|
GET_VARIANT_PTR(src,2);
|
||||||
|
|
||||||
|
bool valid;
|
||||||
|
bool ok = ClassDB::set_property(p_instance->owner,*index,*src,&valid);
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
if (!ok) {
|
||||||
|
err_text="Internal error setting property: "+String(*index);
|
||||||
|
break;
|
||||||
|
} else if (!valid) {
|
||||||
|
err_text="Error setting property '"+String(*index)+"' with value of type "+Variant::get_type_name(src->get_type())+".";
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
ip+=3;
|
||||||
|
} continue;
|
||||||
|
case OPCODE_GET_MEMBER: {
|
||||||
|
|
||||||
|
CHECK_SPACE(3);
|
||||||
|
int indexname = _code_ptr[ip+1];
|
||||||
|
ERR_BREAK(indexname<0 || indexname>=_global_names_count);
|
||||||
|
const StringName *index = &_global_names_ptr[indexname];
|
||||||
|
GET_VARIANT_PTR(dst,2);
|
||||||
|
bool ok = ClassDB::get_property(p_instance->owner,*index,*dst);
|
||||||
|
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
if (!ok) {
|
||||||
|
err_text="Internal error getting property: "+String(*index);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
ip+=3;
|
||||||
|
|
||||||
|
} continue;
|
||||||
case OPCODE_ASSIGN: {
|
case OPCODE_ASSIGN: {
|
||||||
|
|
||||||
CHECK_SPACE(3);
|
CHECK_SPACE(3);
|
||||||
|
@ -23,6 +23,8 @@ public:
|
|||||||
OPCODE_GET,
|
OPCODE_GET,
|
||||||
OPCODE_SET_NAMED,
|
OPCODE_SET_NAMED,
|
||||||
OPCODE_GET_NAMED,
|
OPCODE_GET_NAMED,
|
||||||
|
OPCODE_SET_MEMBER,
|
||||||
|
OPCODE_GET_MEMBER,
|
||||||
OPCODE_ASSIGN,
|
OPCODE_ASSIGN,
|
||||||
OPCODE_ASSIGN_TRUE,
|
OPCODE_ASSIGN_TRUE,
|
||||||
OPCODE_ASSIGN_FALSE,
|
OPCODE_ASSIGN_FALSE,
|
||||||
|
@ -1363,8 +1363,12 @@ void ScriptTextEditor::register_editor() {
|
|||||||
ED_SHORTCUT("script_text_editor/select_all", TTR("Select All"), KEY_MASK_CMD|KEY_A);
|
ED_SHORTCUT("script_text_editor/select_all", TTR("Select All"), KEY_MASK_CMD|KEY_A);
|
||||||
ED_SHORTCUT("script_text_editor/move_up", TTR("Move Up"), KEY_MASK_ALT|KEY_UP);
|
ED_SHORTCUT("script_text_editor/move_up", TTR("Move Up"), KEY_MASK_ALT|KEY_UP);
|
||||||
ED_SHORTCUT("script_text_editor/move_down", TTR("Move Down"), KEY_MASK_ALT|KEY_DOWN);
|
ED_SHORTCUT("script_text_editor/move_down", TTR("Move Down"), KEY_MASK_ALT|KEY_DOWN);
|
||||||
ED_SHORTCUT("script_text_editor/indent_left", TTR("Indent Left"), KEY_MASK_ALT|KEY_LEFT);
|
|
||||||
ED_SHORTCUT("script_text_editor/indent_right", TTR("Indent Right"), KEY_MASK_ALT|KEY_RIGHT);
|
//leave these at zero, same can be accomplished with tab/shift-tab, including selection
|
||||||
|
//the next/previous in history shortcut in this case makes a lot more sene.
|
||||||
|
|
||||||
|
ED_SHORTCUT("script_text_editor/indent_left", TTR("Indent Left"), 0);
|
||||||
|
ED_SHORTCUT("script_text_editor/indent_right", TTR("Indent Right"), 0);
|
||||||
ED_SHORTCUT("script_text_editor/toggle_comment", TTR("Toggle Comment"), KEY_MASK_CMD|KEY_K);
|
ED_SHORTCUT("script_text_editor/toggle_comment", TTR("Toggle Comment"), KEY_MASK_CMD|KEY_K);
|
||||||
ED_SHORTCUT("script_text_editor/clone_down", TTR("Clone Down"), KEY_MASK_CMD|KEY_B);
|
ED_SHORTCUT("script_text_editor/clone_down", TTR("Clone Down"), KEY_MASK_CMD|KEY_B);
|
||||||
#ifdef OSX_ENABLED
|
#ifdef OSX_ENABLED
|
||||||
|
Loading…
Reference in New Issue
Block a user