Likely with bugs and with some features are missing, as well as profiler support, but VisualScript should be more or less done!
This commit is contained in:
@ -1,8 +1,19 @@
|
||||
#include "visual_script.h"
|
||||
#include "visual_script_nodes.h"
|
||||
|
||||
#include "globals.h"
|
||||
#define SCRIPT_VARIABLES_PREFIX "script_variables/"
|
||||
|
||||
|
||||
//used by editor, this is not really saved
|
||||
void VisualScriptNode::set_breakpoint(bool p_breakpoint) {
|
||||
breakpoint=p_breakpoint;
|
||||
}
|
||||
|
||||
bool VisualScriptNode::is_breakpoint() const {
|
||||
|
||||
return breakpoint;
|
||||
}
|
||||
|
||||
void VisualScriptNode::_notification(int p_what) {
|
||||
|
||||
if (p_what==NOTIFICATION_POSTINITIALIZE) {
|
||||
@ -96,6 +107,10 @@ Ref<VisualScript> VisualScriptNode::get_visual_script() const {
|
||||
|
||||
}
|
||||
|
||||
VisualScriptNode::VisualScriptNode() {
|
||||
breakpoint=false;
|
||||
}
|
||||
|
||||
////////////////
|
||||
|
||||
/////////////////////
|
||||
@ -129,6 +144,7 @@ void VisualScript::add_function(const StringName& p_name) {
|
||||
ERR_FAIL_COND(functions.has(p_name));
|
||||
|
||||
functions[p_name]=Function();
|
||||
functions[p_name].scroll=Vector2(-50,-100);
|
||||
}
|
||||
|
||||
bool VisualScript::has_function(const StringName& p_name) const {
|
||||
@ -169,6 +185,21 @@ void VisualScript::rename_function(const StringName& p_name,const StringName& p_
|
||||
|
||||
}
|
||||
|
||||
void VisualScript::set_function_scroll(const StringName& p_name, const Vector2& p_scroll) {
|
||||
|
||||
ERR_FAIL_COND(!functions.has(p_name));
|
||||
functions[p_name].scroll=p_scroll;
|
||||
|
||||
}
|
||||
|
||||
Vector2 VisualScript::get_function_scroll(const StringName& p_name) const {
|
||||
|
||||
ERR_FAIL_COND_V(!functions.has(p_name),Vector2());
|
||||
return functions[p_name].scroll;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void VisualScript::get_function_list(List<StringName> *r_functions) const {
|
||||
|
||||
for (const Map<StringName,Function>::Element *E=functions.front();E;E=E->next()) {
|
||||
@ -338,6 +369,13 @@ void VisualScript::remove_node(const StringName& p_func,int p_id){
|
||||
}
|
||||
|
||||
|
||||
bool VisualScript::has_node(const StringName& p_func,int p_id) const {
|
||||
|
||||
ERR_FAIL_COND_V(!functions.has(p_func),false);
|
||||
const Function &func = functions[p_func];
|
||||
|
||||
return func.nodes.has(p_id);
|
||||
}
|
||||
|
||||
Ref<VisualScriptNode> VisualScript::get_node(const StringName& p_func,int p_id) const{
|
||||
|
||||
@ -1012,10 +1050,13 @@ void VisualScript::_set_data(const Dictionary& p_data) {
|
||||
|
||||
Dictionary func=funcs[i];
|
||||
|
||||
|
||||
StringName name=func["name"];
|
||||
//int id=func["function_id"];
|
||||
add_function(name);
|
||||
|
||||
set_function_scroll(name,func["scroll"]);
|
||||
|
||||
Array nodes = func["nodes"];
|
||||
|
||||
for(int i=0;i<nodes.size();i+=3) {
|
||||
@ -1083,6 +1124,7 @@ Dictionary VisualScript::_get_data() const{
|
||||
Dictionary func;
|
||||
func["name"]=E->key();
|
||||
func["function_id"]=E->get().function_id;
|
||||
func["scroll"]=E->get().scroll;
|
||||
|
||||
Array nodes;
|
||||
|
||||
@ -1144,12 +1186,15 @@ void VisualScript::_bind_methods() {
|
||||
ObjectTypeDB::bind_method(_MD("has_function","name"),&VisualScript::has_function);
|
||||
ObjectTypeDB::bind_method(_MD("remove_function","name"),&VisualScript::remove_function);
|
||||
ObjectTypeDB::bind_method(_MD("rename_function","name","new_name"),&VisualScript::rename_function);
|
||||
ObjectTypeDB::bind_method(_MD("set_function_scroll","ofs"),&VisualScript::set_function_scroll);
|
||||
ObjectTypeDB::bind_method(_MD("get_function_scroll"),&VisualScript::get_function_scroll);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("add_node","func","id","node","pos"),&VisualScript::add_node,DEFVAL(Point2()));
|
||||
ObjectTypeDB::bind_method(_MD("remove_node","func","id"),&VisualScript::remove_node);
|
||||
ObjectTypeDB::bind_method(_MD("get_function_node_id","name"),&VisualScript::get_function_node_id);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("get_node","func","id"),&VisualScript::get_node);
|
||||
ObjectTypeDB::bind_method(_MD("has_node","func","id"),&VisualScript::has_node);
|
||||
ObjectTypeDB::bind_method(_MD("set_node_pos","func","id","pos"),&VisualScript::set_node_pos);
|
||||
ObjectTypeDB::bind_method(_MD("get_node_pos","func","id"),&VisualScript::get_node_pos);
|
||||
|
||||
@ -1306,8 +1351,8 @@ bool VisualScriptInstance::has_method(const StringName& p_method) const{
|
||||
}
|
||||
|
||||
|
||||
//#define VSDEBUG(m_text) print_line(m_text)
|
||||
#define VSDEBUG(m_text)
|
||||
#define VSDEBUG(m_text) print_line(m_text)
|
||||
//#define VSDEBUG(m_text)
|
||||
|
||||
Variant VisualScriptInstance::call(const StringName& p_method,const Variant** p_args,int p_argcount,Variant::CallError &r_error){
|
||||
|
||||
@ -1395,9 +1440,14 @@ Variant VisualScriptInstance::call(const StringName& p_method,const Variant** p_
|
||||
String error_str;
|
||||
|
||||
bool error=false;
|
||||
int current_node_id;
|
||||
int current_node_id=f->node;
|
||||
Variant return_value;
|
||||
|
||||
Variant *working_mem=NULL;
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (ScriptDebugger::get_singleton()) {
|
||||
VisualScriptLanguage::singleton->enter_function(this,&p_method,variant_stack,&working_mem,¤t_node_id);
|
||||
}
|
||||
#endif
|
||||
|
||||
while(true) {
|
||||
|
||||
@ -1408,7 +1458,7 @@ Variant VisualScriptInstance::call(const StringName& p_method,const Variant** p_
|
||||
|
||||
|
||||
//setup working mem
|
||||
Variant *working_mem=node->working_mem_idx>=0 ? &variant_stack[node->working_mem_idx] : (Variant*)NULL;
|
||||
working_mem=node->working_mem_idx>=0 ? &variant_stack[node->working_mem_idx] : (Variant*)NULL;
|
||||
|
||||
VSDEBUG("WORKING MEM: "+itos(node->working_mem_idx));
|
||||
|
||||
@ -1440,6 +1490,7 @@ Variant VisualScriptInstance::call(const StringName& p_method,const Variant** p_
|
||||
r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
|
||||
current_node_id=ug->from->get_id();
|
||||
error=true;
|
||||
working_mem=NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1469,6 +1520,7 @@ Variant VisualScriptInstance::call(const StringName& p_method,const Variant** p_
|
||||
|
||||
bool start_sequence = flow_stack && !(flow_stack[flow_stack_pos] & VisualScriptNodeInstance::FLOW_STACK_PUSHED_BIT); //if there is a push bit, it means we are continuing a sequence
|
||||
|
||||
|
||||
VSDEBUG("STEP - STARTSEQ: "+itos(start_sequence));
|
||||
|
||||
int ret = node->step(input_args,output_args,start_sequence,working_mem,r_error,error_str);
|
||||
@ -1479,6 +1531,30 @@ Variant VisualScriptInstance::call(const StringName& p_method,const Variant** p_
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (ScriptDebugger::get_singleton()) {
|
||||
// line
|
||||
bool do_break=false;
|
||||
|
||||
if (ScriptDebugger::get_singleton()->get_lines_left()>0) {
|
||||
|
||||
if (ScriptDebugger::get_singleton()->get_depth()<=0)
|
||||
ScriptDebugger::get_singleton()->set_lines_left( ScriptDebugger::get_singleton()->get_lines_left() -1 );
|
||||
if (ScriptDebugger::get_singleton()->get_lines_left()<=0)
|
||||
do_break=true;
|
||||
}
|
||||
|
||||
if (ScriptDebugger::get_singleton()->is_breakpoint(current_node_id,source))
|
||||
do_break=true;
|
||||
|
||||
if (do_break) {
|
||||
VisualScriptLanguage::singleton->debug_break("Breakpoint",true);
|
||||
}
|
||||
|
||||
ScriptDebugger::get_singleton()->line_poll();
|
||||
|
||||
}
|
||||
#endif
|
||||
int output = ret & VisualScriptNodeInstance::STEP_MASK;
|
||||
|
||||
VSDEBUG("STEP RETURN: "+itos(ret));
|
||||
@ -1573,6 +1649,7 @@ Variant VisualScriptInstance::call(const StringName& p_method,const Variant** p_
|
||||
break;
|
||||
}
|
||||
|
||||
node=next;
|
||||
VSDEBUG("RE-ENTERED A LOOP, RETURNED STACK POS TO - "+itos(flow_stack_pos));
|
||||
|
||||
} else {
|
||||
@ -1638,8 +1715,10 @@ Variant VisualScriptInstance::call(const StringName& p_method,const Variant** p_
|
||||
//if (!GDScriptLanguage::get_singleton()->debug_break(err_text,false)) {
|
||||
// debugger break did not happen
|
||||
|
||||
VSDEBUG("ERRSTR: "+error_str);
|
||||
_err_print_error(err_func.utf8().get_data(),err_file.utf8().get_data(),err_line,error_str.utf8().get_data(),ERR_HANDLER_SCRIPT);
|
||||
if (!VisualScriptLanguage::singleton->debug_break(error_str,false)) {
|
||||
|
||||
_err_print_error(err_func.utf8().get_data(),err_file.utf8().get_data(),err_line,error_str.utf8().get_data(),ERR_HANDLER_SCRIPT);
|
||||
}
|
||||
|
||||
//}
|
||||
} else {
|
||||
@ -1648,6 +1727,11 @@ Variant VisualScriptInstance::call(const StringName& p_method,const Variant** p_
|
||||
//return_value=
|
||||
}
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (ScriptDebugger::get_singleton()) {
|
||||
VisualScriptLanguage::singleton->exit_function();
|
||||
}
|
||||
#endif
|
||||
|
||||
//clean up variant stack
|
||||
for(int i=0;i<f->max_stack;i++) {
|
||||
@ -1679,6 +1763,7 @@ void VisualScriptInstance::create(const Ref<VisualScript>& p_script,Object *p_ow
|
||||
|
||||
script=p_script;
|
||||
owner=p_owner;
|
||||
source=p_script->get_path();
|
||||
|
||||
max_input_args = 0;
|
||||
max_output_args = 0;
|
||||
@ -1697,7 +1782,7 @@ void VisualScriptInstance::create(const Ref<VisualScript>& p_script,Object *p_ow
|
||||
function.node_count=0;
|
||||
|
||||
if (function.node<0) {
|
||||
//@todo break debugger
|
||||
VisualScriptLanguage::singleton->debug_break_parse(get_script()->get_path(),0,"No start node in function: "+String(E->key()));
|
||||
|
||||
ERR_CONTINUE( function.node < 0 );
|
||||
}
|
||||
@ -1705,7 +1790,10 @@ void VisualScriptInstance::create(const Ref<VisualScript>& p_script,Object *p_ow
|
||||
{
|
||||
Ref<VisualScriptFunction> func_node = script->get_node(E->key(),E->get().function_id);
|
||||
|
||||
//@todo break debugger
|
||||
if (func_node.is_null()) {
|
||||
VisualScriptLanguage::singleton->debug_break_parse(get_script()->get_path(),0,"No VisualScriptFunction typed start node in function: "+String(E->key()));
|
||||
}
|
||||
|
||||
ERR_CONTINUE( !func_node.is_valid() );
|
||||
|
||||
function.argument_count=func_node->get_argument_count();
|
||||
@ -1977,44 +2065,199 @@ void VisualScriptLanguage::add_global_constant(const StringName& p_variable,cons
|
||||
|
||||
/* DEBUGGER FUNCTIONS */
|
||||
|
||||
|
||||
|
||||
bool VisualScriptLanguage::debug_break_parse(const String& p_file, int p_node,const String& p_error) {
|
||||
//break because of parse error
|
||||
|
||||
if (ScriptDebugger::get_singleton() && Thread::get_caller_ID()==Thread::get_main_ID()) {
|
||||
|
||||
_debug_parse_err_node=p_node;
|
||||
_debug_parse_err_file=p_file;
|
||||
_debug_error=p_error;
|
||||
ScriptDebugger::get_singleton()->debug(this,false);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool VisualScriptLanguage::debug_break(const String& p_error,bool p_allow_continue) {
|
||||
|
||||
if (ScriptDebugger::get_singleton() && Thread::get_caller_ID()==Thread::get_main_ID()) {
|
||||
|
||||
_debug_parse_err_node=-1;
|
||||
_debug_parse_err_file="";
|
||||
_debug_error=p_error;
|
||||
ScriptDebugger::get_singleton()->debug(this,p_allow_continue);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
String VisualScriptLanguage::debug_get_error() const {
|
||||
|
||||
return String();
|
||||
return _debug_error;
|
||||
}
|
||||
|
||||
int VisualScriptLanguage::debug_get_stack_level_count() const {
|
||||
|
||||
return 0;
|
||||
if (_debug_parse_err_node>=0)
|
||||
return 1;
|
||||
|
||||
|
||||
return _debug_call_stack_pos;
|
||||
}
|
||||
int VisualScriptLanguage::debug_get_stack_level_line(int p_level) const {
|
||||
|
||||
return 0;
|
||||
if (_debug_parse_err_node>=0)
|
||||
return _debug_parse_err_node;
|
||||
|
||||
ERR_FAIL_INDEX_V(p_level,_debug_call_stack_pos,-1);
|
||||
|
||||
int l = _debug_call_stack_pos - p_level -1;
|
||||
|
||||
return *(_call_stack[l].current_id);
|
||||
|
||||
}
|
||||
String VisualScriptLanguage::debug_get_stack_level_function(int p_level) const {
|
||||
|
||||
return String();
|
||||
if (_debug_parse_err_node>=0)
|
||||
return "";
|
||||
|
||||
ERR_FAIL_INDEX_V(p_level,_debug_call_stack_pos,"");
|
||||
int l = _debug_call_stack_pos - p_level -1;
|
||||
return *_call_stack[l].function;
|
||||
}
|
||||
String VisualScriptLanguage::debug_get_stack_level_source(int p_level) const {
|
||||
|
||||
return String();
|
||||
if (_debug_parse_err_node>=0)
|
||||
return _debug_parse_err_file;
|
||||
|
||||
ERR_FAIL_INDEX_V(p_level,_debug_call_stack_pos,"");
|
||||
int l = _debug_call_stack_pos - p_level -1;
|
||||
return _call_stack[l].instance->get_script_ptr()->get_path();
|
||||
|
||||
}
|
||||
void VisualScriptLanguage::debug_get_stack_level_locals(int p_level,List<String> *p_locals, List<Variant> *p_values, int p_max_subitems,int p_max_depth) {
|
||||
|
||||
if (_debug_parse_err_node>=0)
|
||||
return;
|
||||
|
||||
ERR_FAIL_INDEX(p_level,_debug_call_stack_pos);
|
||||
|
||||
int l = _debug_call_stack_pos - p_level -1;
|
||||
const StringName *f = _call_stack[l].function;
|
||||
|
||||
ERR_FAIL_COND(!_call_stack[l].instance->functions.has(*f));
|
||||
VisualScriptInstance::Function *func = &_call_stack[l].instance->functions[*f];
|
||||
|
||||
VisualScriptNodeInstance *node =_call_stack[l].instance->instances[*_call_stack[l].current_id];
|
||||
ERR_FAIL_COND(!node);
|
||||
|
||||
p_locals->push_back("node_name");
|
||||
p_values->push_back(node->get_base_node()->get_text());
|
||||
|
||||
for(int i=0;i<node->input_port_count;i++) {
|
||||
String name = node->get_base_node()->get_input_value_port_info(i).name;
|
||||
if (name==String()) {
|
||||
name="in_"+itos(i);
|
||||
}
|
||||
|
||||
p_locals->push_back("input/"+name);
|
||||
|
||||
//value is trickier
|
||||
|
||||
int in_from = node->input_ports[i];
|
||||
int in_value = in_from&VisualScriptNodeInstance::INPUT_MASK;
|
||||
|
||||
if (in_from&VisualScriptNodeInstance::INPUT_DEFAULT_VALUE_BIT) {
|
||||
p_values->push_back(_call_stack[l].instance->default_values[in_value]);
|
||||
} else if (in_from&VisualScriptNodeInstance::INPUT_UNSEQUENCED_READ_BIT) {
|
||||
p_values->push_back( _call_stack[l].stack[ func->unsequenced_gets[ in_value ].to_stack ] );
|
||||
} else {
|
||||
p_values->push_back( _call_stack[l].stack[ in_value] );
|
||||
}
|
||||
}
|
||||
|
||||
for(int i=0;i<node->output_port_count;i++) {
|
||||
|
||||
String name = node->get_base_node()->get_output_value_port_info(i).name;
|
||||
if (name==String()) {
|
||||
name="out_"+itos(i);
|
||||
}
|
||||
|
||||
p_locals->push_back("output/"+name);
|
||||
|
||||
//value is trickier
|
||||
|
||||
int in_from = node->output_ports[i];
|
||||
p_values->push_back( _call_stack[l].stack[ in_from] );
|
||||
|
||||
}
|
||||
|
||||
for(int i=0;i<node->get_working_memory_size();i++) {
|
||||
p_locals->push_back("working_mem/mem_"+itos(i));
|
||||
p_values->push_back( (*_call_stack[l].work_mem)[i]);
|
||||
}
|
||||
|
||||
/*
|
||||
ERR_FAIL_INDEX(p_level,_debug_call_stack_pos);
|
||||
|
||||
|
||||
VisualFunction *f = _call_stack[l].function;
|
||||
|
||||
List<Pair<StringName,int> > locals;
|
||||
|
||||
f->debug_get_stack_member_state(*_call_stack[l].line,&locals);
|
||||
for( List<Pair<StringName,int> >::Element *E = locals.front();E;E=E->next() ) {
|
||||
|
||||
p_locals->push_back(E->get().first);
|
||||
p_values->push_back(_call_stack[l].stack[E->get().second]);
|
||||
}
|
||||
*/
|
||||
}
|
||||
void VisualScriptLanguage::debug_get_stack_level_members(int p_level,List<String> *p_members, List<Variant> *p_values, int p_max_subitems,int p_max_depth) {
|
||||
|
||||
if (_debug_parse_err_node>=0)
|
||||
return;
|
||||
|
||||
ERR_FAIL_INDEX(p_level,_debug_call_stack_pos);
|
||||
int l = _debug_call_stack_pos - p_level -1;
|
||||
|
||||
|
||||
Ref<VisualScript> vs = _call_stack[l].instance->get_script();
|
||||
if (vs.is_null())
|
||||
return;
|
||||
|
||||
List<StringName> vars;
|
||||
vs->get_variable_list(&vars);
|
||||
for (List<StringName>::Element *E=vars.front();E;E=E->next()) {
|
||||
Variant v;
|
||||
if (_call_stack[l].instance->get_variable(E->get(),&v)) {
|
||||
p_members->push_back("variables/"+E->get());
|
||||
p_values->push_back(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VisualScriptLanguage::debug_get_globals(List<String> *p_locals, List<Variant> *p_values, int p_max_subitems,int p_max_depth) {
|
||||
|
||||
|
||||
//no globals are really reachable in gdscript
|
||||
}
|
||||
String VisualScriptLanguage::debug_parse_stack_level_expression(int p_level,const String& p_expression,int p_max_subitems,int p_max_depth) {
|
||||
|
||||
return String();
|
||||
if (_debug_parse_err_node>=0)
|
||||
return "";
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
|
||||
void VisualScriptLanguage::reload_all_scripts() {
|
||||
|
||||
|
||||
@ -2090,10 +2333,33 @@ VisualScriptLanguage::VisualScriptLanguage() {
|
||||
#ifndef NO_THREADS
|
||||
lock = Mutex::create();
|
||||
#endif
|
||||
|
||||
|
||||
_debug_parse_err_node=-1;
|
||||
_debug_parse_err_file="";
|
||||
_debug_call_stack_pos=0;
|
||||
int dmcs=GLOBAL_DEF("debug/script_max_call_stack",1024);
|
||||
if (ScriptDebugger::get_singleton()) {
|
||||
//debugging enabled!
|
||||
_debug_max_call_stack = dmcs;
|
||||
if (_debug_max_call_stack<1024)
|
||||
_debug_max_call_stack=1024;
|
||||
_call_stack = memnew_arr( CallLevel, _debug_max_call_stack+1 );
|
||||
|
||||
} else {
|
||||
_debug_max_call_stack=0;
|
||||
_call_stack=NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
VisualScriptLanguage::~VisualScriptLanguage() {
|
||||
|
||||
if (lock)
|
||||
memdelete(lock);
|
||||
|
||||
if (_call_stack) {
|
||||
memdelete_arr(_call_stack);
|
||||
}
|
||||
singleton=NULL;
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
#define VSCRIPT_H
|
||||
|
||||
#include "script_language.h"
|
||||
|
||||
#include "os/thread.h"
|
||||
|
||||
class VisualScriptInstance;
|
||||
class VisualScriptNodeInstance;
|
||||
@ -16,6 +16,7 @@ friend class VisualScript;
|
||||
Set<VisualScript*> scripts_used;
|
||||
|
||||
Array default_input_values;
|
||||
bool breakpoint;
|
||||
|
||||
void _set_default_input_values(Array p_values);
|
||||
Array _get_default_input_values() const;
|
||||
@ -47,14 +48,19 @@ public:
|
||||
virtual String get_text() const=0;
|
||||
virtual String get_category() const=0;
|
||||
|
||||
//used by editor, this is not really saved
|
||||
void set_breakpoint(bool p_breakpoint);
|
||||
bool is_breakpoint() const;
|
||||
|
||||
virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance)=0;
|
||||
|
||||
VisualScriptNode();
|
||||
};
|
||||
|
||||
|
||||
class VisualScriptNodeInstance {
|
||||
friend class VisualScriptInstance;
|
||||
|
||||
friend class VisualScriptLanguage; //for debugger
|
||||
|
||||
|
||||
enum { //input argument addressing
|
||||
@ -181,6 +187,8 @@ friend class VisualScriptInstance;
|
||||
|
||||
int function_id;
|
||||
|
||||
Vector2 scroll;
|
||||
|
||||
|
||||
Function() { function_id=-1; }
|
||||
|
||||
@ -225,12 +233,15 @@ public:
|
||||
bool has_function(const StringName& p_name) const;
|
||||
void remove_function(const StringName& p_name);
|
||||
void rename_function(const StringName& p_name,const StringName& p_new_name);
|
||||
void set_function_scroll(const StringName& p_name, const Vector2& p_scroll);
|
||||
Vector2 get_function_scroll(const StringName& p_name) const;
|
||||
void get_function_list(List<StringName> *r_functions) const;
|
||||
int get_function_node_id(const StringName& p_name) const;
|
||||
|
||||
|
||||
void add_node(const StringName& p_func,int p_id,const Ref<VisualScriptNode>& p_node,const Point2& p_pos=Point2());
|
||||
void remove_node(const StringName& p_func,int p_id);
|
||||
bool has_node(const StringName& p_func,int p_id) const;
|
||||
Ref<VisualScriptNode> get_node(const StringName& p_func,int p_id) const;
|
||||
void set_node_pos(const StringName& p_func,int p_id,const Point2& p_pos);
|
||||
Point2 get_node_pos(const StringName& p_func,int p_id) const;
|
||||
@ -308,7 +319,6 @@ public:
|
||||
|
||||
|
||||
class VisualScriptInstance : public ScriptInstance {
|
||||
|
||||
Object *owner;
|
||||
Ref<VisualScript> script;
|
||||
|
||||
@ -340,9 +350,10 @@ class VisualScriptInstance : public ScriptInstance {
|
||||
Vector<Variant> default_values;
|
||||
int max_input_args,max_output_args;
|
||||
|
||||
StringName source;
|
||||
|
||||
//Map<StringName,Function> functions;
|
||||
|
||||
friend class VisualScriptLanguage; //for debugger
|
||||
public:
|
||||
virtual bool set(const StringName& p_name, const Variant& p_value);
|
||||
virtual bool get(const StringName& p_name, Variant &r_ret) const;
|
||||
@ -396,6 +407,23 @@ class VisualScriptLanguage : public ScriptLanguage {
|
||||
|
||||
Map<String,VisualScriptNodeRegisterFunc> register_funcs;
|
||||
|
||||
struct CallLevel {
|
||||
|
||||
Variant *stack;
|
||||
Variant **work_mem;
|
||||
const StringName *function;
|
||||
VisualScriptInstance *instance;
|
||||
int *current_id;
|
||||
|
||||
};
|
||||
|
||||
|
||||
int _debug_parse_err_node;
|
||||
String _debug_parse_err_file;
|
||||
String _debug_error;
|
||||
int _debug_call_stack_pos;
|
||||
int _debug_max_call_stack;
|
||||
CallLevel *_call_stack;
|
||||
|
||||
public:
|
||||
StringName notification;
|
||||
@ -404,6 +432,52 @@ public:
|
||||
|
||||
Mutex *lock;
|
||||
|
||||
bool debug_break(const String& p_error,bool p_allow_continue=true);
|
||||
bool debug_break_parse(const String& p_file, int p_node,const String& p_error);
|
||||
|
||||
_FORCE_INLINE_ void enter_function(VisualScriptInstance *p_instance,const StringName* p_function, Variant *p_stack, Variant **p_work_mem,int *current_id) {
|
||||
|
||||
if (Thread::get_main_ID()!=Thread::get_caller_ID())
|
||||
return; //no support for other threads than main for now
|
||||
|
||||
if (ScriptDebugger::get_singleton()->get_lines_left()>0 && ScriptDebugger::get_singleton()->get_depth()>=0)
|
||||
ScriptDebugger::get_singleton()->set_depth( ScriptDebugger::get_singleton()->get_depth() +1 );
|
||||
|
||||
if (_debug_call_stack_pos >= _debug_max_call_stack) {
|
||||
//stack overflow
|
||||
_debug_error="Stack Overflow (Stack Size: "+itos(_debug_max_call_stack)+")";
|
||||
ScriptDebugger::get_singleton()->debug(this);
|
||||
return;
|
||||
}
|
||||
|
||||
_call_stack[_debug_call_stack_pos].stack=p_stack;
|
||||
_call_stack[_debug_call_stack_pos].instance=p_instance;
|
||||
_call_stack[_debug_call_stack_pos].function=p_function;
|
||||
_call_stack[_debug_call_stack_pos].work_mem=p_work_mem;
|
||||
_call_stack[_debug_call_stack_pos].current_id=current_id;
|
||||
_debug_call_stack_pos++;
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ void exit_function() {
|
||||
|
||||
if (Thread::get_main_ID()!=Thread::get_caller_ID())
|
||||
return; //no support for other threads than main for now
|
||||
|
||||
if (ScriptDebugger::get_singleton()->get_lines_left()>0 && ScriptDebugger::get_singleton()->get_depth()>=0)
|
||||
ScriptDebugger::get_singleton()->set_depth( ScriptDebugger::get_singleton()->get_depth() -1 );
|
||||
|
||||
if (_debug_call_stack_pos==0) {
|
||||
|
||||
_debug_error="Stack Underflow (Engine Bug)";
|
||||
ScriptDebugger::get_singleton()->debug(this);
|
||||
return;
|
||||
}
|
||||
|
||||
_debug_call_stack_pos--;
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
|
||||
virtual String get_name() const;
|
||||
|
||||
/* LANGUAGE FUNCTIONS */
|
||||
|
||||
@ -347,6 +347,8 @@ void VisualScriptEditor::_update_graph_connections() {
|
||||
void VisualScriptEditor::_update_graph(int p_only_id) {
|
||||
|
||||
|
||||
updating_graph=true;
|
||||
|
||||
//byebye all nodes
|
||||
if (p_only_id>=0) {
|
||||
if (graph->has_node(itos(p_only_id))) {
|
||||
@ -368,6 +370,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
|
||||
if (!script->has_function(edited_func)) {
|
||||
graph->hide();
|
||||
select_func_text->show();
|
||||
updating_graph=false;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -424,9 +427,14 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
|
||||
|
||||
GraphNode *gnode = memnew( GraphNode );
|
||||
gnode->set_title(node->get_caption());
|
||||
if (error_line==E->get()) {
|
||||
gnode->set_overlay(GraphNode::OVERLAY_POSITION);
|
||||
} else if (node->is_breakpoint()) {
|
||||
gnode->set_overlay(GraphNode::OVERLAY_BREAKPOINT);
|
||||
}
|
||||
|
||||
if (EditorSettings::get_singleton()->has("visual_script/color_"+node->get_category())) {
|
||||
gnode->set_modulate(EditorSettings::get_singleton()->get("visual_script/color_"+node->get_category()));
|
||||
if (EditorSettings::get_singleton()->has("visual_script_editor/color_"+node->get_category())) {
|
||||
gnode->set_modulate(EditorSettings::get_singleton()->get("visual_script_editor/color_"+node->get_category()));
|
||||
}
|
||||
|
||||
gnode->set_meta("__vnode",node);
|
||||
@ -555,6 +563,8 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
|
||||
}
|
||||
|
||||
_update_graph_connections();
|
||||
graph->call_deferred("set_scroll_ofs",script->get_function_scroll(edited_func)*EDSCALE); //may need to adapt a bit, let it do so
|
||||
updating_graph=false;
|
||||
|
||||
}
|
||||
|
||||
@ -583,6 +593,10 @@ void VisualScriptEditor::_update_members() {
|
||||
//ti->add_button(0,Control::get_icon("Edit","EditorIcons"),0); function arguments are in the node now
|
||||
ti->add_button(0,Control::get_icon("Del","EditorIcons"),1);
|
||||
ti->set_metadata(0,E->get());
|
||||
if (E->get()==edited_func) {
|
||||
ti->set_custom_bg_color(0,get_color("prop_category","Editor"));
|
||||
ti->set_custom_color(0,Color(1,1,1,1));
|
||||
}
|
||||
if (selected==E->get())
|
||||
ti->select(0);
|
||||
}
|
||||
@ -660,6 +674,7 @@ void VisualScriptEditor::_member_selected() {
|
||||
|
||||
revert_on_drag=edited_func;
|
||||
edited_func=selected;
|
||||
_update_members();
|
||||
_update_graph();
|
||||
}
|
||||
|
||||
@ -1804,23 +1819,91 @@ Ref<Texture> VisualScriptEditor::get_icon(){
|
||||
}
|
||||
|
||||
bool VisualScriptEditor::is_unsaved(){
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
return script->is_edited();
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
Variant VisualScriptEditor::get_edit_state(){
|
||||
|
||||
return Variant();
|
||||
Dictionary d;
|
||||
d["function"]=edited_func;
|
||||
d["scroll"]=graph->get_scroll_ofs();
|
||||
d["zoom"]=graph->get_zoom();
|
||||
d["using_snap"]=graph->is_using_snap();
|
||||
d["snap"]=graph->get_snap();
|
||||
return d;
|
||||
}
|
||||
|
||||
void VisualScriptEditor::set_edit_state(const Variant& p_state){
|
||||
|
||||
Dictionary d = p_state;
|
||||
if (d.has("function")) {
|
||||
edited_func=p_state;
|
||||
selected=edited_func;
|
||||
|
||||
}
|
||||
|
||||
_update_graph();
|
||||
_update_members();
|
||||
|
||||
if (d.has("scroll")) {
|
||||
graph->set_scroll_ofs(d["scroll"]);
|
||||
}
|
||||
if (d.has("zoom")) {
|
||||
graph->set_zoom(d["zoom"]);
|
||||
}
|
||||
if (d.has("snap")) {
|
||||
graph->set_snap(d["snap"]);
|
||||
}
|
||||
if (d.has("snap_enabled")) {
|
||||
graph->set_use_snap(d["snap_enabled"]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void VisualScriptEditor::goto_line(int p_line){
|
||||
|
||||
void VisualScriptEditor::_center_on_node(int p_id) {
|
||||
|
||||
Node *n = graph->get_node(itos(p_id));
|
||||
if (!n)
|
||||
return;
|
||||
GraphNode *gn = n->cast_to<GraphNode>();
|
||||
if (gn) {
|
||||
gn->set_selected(true);
|
||||
Vector2 new_scroll = gn->get_offset() - graph->get_size()*0.5 + gn->get_size()*0.5;
|
||||
graph->set_scroll_ofs( new_scroll );
|
||||
script->set_function_scroll(edited_func,new_scroll/EDSCALE);
|
||||
script->set_edited(true); //so it's saved
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void VisualScriptEditor::goto_line(int p_line, bool p_with_error){
|
||||
|
||||
p_line+=1; //add one because script lines begin from 0.
|
||||
|
||||
if (p_with_error)
|
||||
error_line=p_line;
|
||||
|
||||
List<StringName> functions;
|
||||
script->get_function_list(&functions);
|
||||
for (List<StringName>::Element *E=functions.front();E;E=E->next()) {
|
||||
|
||||
if (script->has_node(E->get(),p_line)) {
|
||||
|
||||
edited_func=E->get();
|
||||
selected=edited_func;
|
||||
_update_graph();
|
||||
_update_members();
|
||||
|
||||
call_deferred("_center_on_node",p_line); //editor might be just created and size might not exist yet
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VisualScriptEditor::trim_trailing_whitespace(){
|
||||
@ -1830,7 +1913,7 @@ void VisualScriptEditor::trim_trailing_whitespace(){
|
||||
|
||||
void VisualScriptEditor::ensure_focus(){
|
||||
|
||||
|
||||
graph->grab_focus();
|
||||
}
|
||||
|
||||
void VisualScriptEditor::tag_saved_version(){
|
||||
@ -1845,24 +1928,92 @@ void VisualScriptEditor::reload(bool p_soft){
|
||||
|
||||
void VisualScriptEditor::get_breakpoints(List<int> *p_breakpoints){
|
||||
|
||||
List<StringName> functions;
|
||||
script->get_function_list(&functions);
|
||||
for (List<StringName>::Element *E=functions.front();E;E=E->next()) {
|
||||
|
||||
List<int> nodes;
|
||||
script->get_node_list(E->get(),&nodes);
|
||||
for (List<int>::Element *F=nodes.front();F;F=F->next()) {
|
||||
|
||||
Ref<VisualScriptNode> vsn = script->get_node(E->get(),F->get());
|
||||
if (vsn->is_breakpoint()) {
|
||||
p_breakpoints->push_back(F->get()-1); //subtract 1 because breakpoints in text start from zero
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool VisualScriptEditor::goto_method(const String& p_method){
|
||||
|
||||
return false;
|
||||
if (!script->has_function(p_method))
|
||||
return false;
|
||||
|
||||
edited_func=p_method;
|
||||
selected=edited_func;
|
||||
_update_members();
|
||||
_update_graph();
|
||||
return true;
|
||||
}
|
||||
|
||||
void VisualScriptEditor::add_callback(const String& p_function,StringArray p_args){
|
||||
|
||||
if (script->has_function(p_function)) {
|
||||
edited_func=p_function;
|
||||
selected=edited_func;
|
||||
_update_members();
|
||||
_update_graph();
|
||||
return;
|
||||
}
|
||||
|
||||
Ref<VisualScriptFunction> func;
|
||||
func.instance();
|
||||
for(int i=0;i<p_args.size();i++) {
|
||||
|
||||
String name = p_args[i];
|
||||
Variant::Type type=Variant::NIL;
|
||||
|
||||
if (name.find(":")!=-1) {
|
||||
String tt = name.get_slice(":",1);
|
||||
name=name.get_slice(":",0);
|
||||
for(int j=0;j<Variant::VARIANT_MAX;j++) {
|
||||
|
||||
String tname = Variant::get_type_name(Variant::Type(j));
|
||||
if (tname==tt) {
|
||||
type=Variant::Type(j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func->add_argument(type,name);
|
||||
}
|
||||
|
||||
func->set_name(p_function);
|
||||
script->add_function(p_function);
|
||||
script->add_node(p_function,script->get_available_id(),func);
|
||||
|
||||
edited_func=p_function;
|
||||
selected=edited_func;
|
||||
_update_members();
|
||||
_update_graph();
|
||||
graph->call_deferred("set_scroll_ofs",script->get_function_scroll(edited_func)); //for first time it might need to be later
|
||||
|
||||
//undo_redo->clear_history();
|
||||
|
||||
}
|
||||
|
||||
void VisualScriptEditor::update_settings(){
|
||||
|
||||
|
||||
_update_graph();
|
||||
}
|
||||
|
||||
void VisualScriptEditor::set_debugger_active(bool p_active) {
|
||||
if (!p_active) {
|
||||
error_line=-1;
|
||||
_update_graph(); //clear line break
|
||||
}
|
||||
}
|
||||
|
||||
void VisualScriptEditor::set_tooltip_request_func(String p_method,Object* p_obj){
|
||||
|
||||
@ -1871,7 +2022,7 @@ void VisualScriptEditor::set_tooltip_request_func(String p_method,Object* p_obj)
|
||||
|
||||
Control *VisualScriptEditor::get_edit_menu(){
|
||||
|
||||
return NULL;
|
||||
return edit_menu;
|
||||
}
|
||||
|
||||
void VisualScriptEditor::_change_base_type() {
|
||||
@ -2166,6 +2317,55 @@ void VisualScriptEditor::_notification(int p_what) {
|
||||
}
|
||||
}
|
||||
|
||||
void VisualScriptEditor::_graph_ofs_changed(const Vector2& p_ofs) {
|
||||
|
||||
if (updating_graph)
|
||||
return;
|
||||
|
||||
updating_graph=true;
|
||||
|
||||
if (script->has_function(edited_func)) {
|
||||
script->set_function_scroll(edited_func,graph->get_scroll_ofs()/EDSCALE);
|
||||
script->set_edited(true);
|
||||
}
|
||||
updating_graph=false;
|
||||
}
|
||||
|
||||
void VisualScriptEditor::_menu_option(int p_what) {
|
||||
|
||||
switch(p_what) {
|
||||
case EDIT_DELETE_NODES: {
|
||||
_on_nodes_delete();
|
||||
} break;
|
||||
case EDIT_TOGGLE_BREAKPOINT: {
|
||||
|
||||
List<String> reselect;
|
||||
for(int i=0;i<graph->get_child_count();i++) {
|
||||
GraphNode *gn = graph->get_child(i)->cast_to<GraphNode>();
|
||||
if (gn) {
|
||||
if (gn->is_selected()) {
|
||||
int id = String(gn->get_name()).to_int();
|
||||
Ref<VisualScriptNode> vsn = script->get_node(edited_func,id);
|
||||
if (vsn.is_valid()) {
|
||||
vsn->set_breakpoint(!vsn->is_breakpoint());
|
||||
reselect.push_back(gn->get_name());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_update_graph();
|
||||
|
||||
for(List<String>::Element *E=reselect.front();E;E=E->next()) {
|
||||
GraphNode *gn = graph->get_node(E->get())->cast_to<GraphNode>();
|
||||
gn->set_selected(true);
|
||||
}
|
||||
|
||||
} break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void VisualScriptEditor::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method("_member_button",&VisualScriptEditor::_member_button);
|
||||
@ -2186,6 +2386,9 @@ void VisualScriptEditor::_bind_methods() {
|
||||
ObjectTypeDB::bind_method("_available_node_doubleclicked",&VisualScriptEditor::_available_node_doubleclicked);
|
||||
ObjectTypeDB::bind_method("_default_value_edited",&VisualScriptEditor::_default_value_edited);
|
||||
ObjectTypeDB::bind_method("_default_value_changed",&VisualScriptEditor::_default_value_changed);
|
||||
ObjectTypeDB::bind_method("_menu_option",&VisualScriptEditor::_menu_option);
|
||||
ObjectTypeDB::bind_method("_graph_ofs_changed",&VisualScriptEditor::_graph_ofs_changed);
|
||||
ObjectTypeDB::bind_method("_center_on_node",&VisualScriptEditor::_center_on_node);
|
||||
|
||||
|
||||
|
||||
@ -2211,6 +2414,14 @@ void VisualScriptEditor::_bind_methods() {
|
||||
|
||||
VisualScriptEditor::VisualScriptEditor() {
|
||||
|
||||
updating_graph=false;
|
||||
|
||||
edit_menu = memnew( MenuButton );
|
||||
edit_menu->set_text(TTR("Edit"));
|
||||
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("visual_script_editor/delete_selected"), EDIT_DELETE_NODES);
|
||||
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("visual_script_editor/toggle_breakpoint"), EDIT_TOGGLE_BREAKPOINT);
|
||||
edit_menu->get_popup()->connect("item_pressed",this,"_menu_option");
|
||||
|
||||
main_hsplit = memnew( HSplitContainer );
|
||||
add_child(main_hsplit);
|
||||
main_hsplit->set_area_as_parent_rect();
|
||||
@ -2232,7 +2443,7 @@ VisualScriptEditor::VisualScriptEditor() {
|
||||
members->set_hide_root(true);
|
||||
members->connect("button_pressed",this,"_member_button");
|
||||
members->connect("item_edited",this,"_member_edited");
|
||||
members->connect("cell_selected",this,"_member_selected");
|
||||
members->connect("cell_selected",this,"_member_selected",varray(),CONNECT_DEFERRED);
|
||||
members->set_single_select_cell_editing_only_when_already_selected(true);
|
||||
members->set_hide_folding(true);
|
||||
members->set_drag_forwarding(this);
|
||||
@ -2274,6 +2485,7 @@ VisualScriptEditor::VisualScriptEditor() {
|
||||
graph->connect("duplicate_nodes_request",this,"_on_nodes_duplicate");
|
||||
graph->set_drag_forwarding(this);
|
||||
graph->hide();
|
||||
graph->connect("scroll_offset_changed",this,"_graph_ofs_changed");
|
||||
|
||||
select_func_text = memnew( Label );
|
||||
select_func_text->set_text(TTR("Select or create a function to edit graph"));
|
||||
@ -2358,6 +2570,7 @@ VisualScriptEditor::VisualScriptEditor() {
|
||||
add_child(default_value_edit);
|
||||
default_value_edit->connect("variant_changed",this,"_default_value_changed");
|
||||
|
||||
error_line=-1;
|
||||
}
|
||||
|
||||
VisualScriptEditor::~VisualScriptEditor() {
|
||||
@ -2376,9 +2589,26 @@ static ScriptEditorBase * create_editor(const Ref<Script>& p_script) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void register_editor_callback() {
|
||||
|
||||
ScriptEditor::register_create_script_editor_function(create_editor);
|
||||
EditorSettings::get_singleton()->set("visual_script_editor/color_functions",Color(1,0.9,0.9));
|
||||
EditorSettings::get_singleton()->set("visual_script_editor/color_data",Color(0.9,1.0,0.9));
|
||||
EditorSettings::get_singleton()->set("visual_script_editor/color_operators",Color(0.9,0.9,1.0));
|
||||
EditorSettings::get_singleton()->set("visual_script_editor/color_flow_control",Color(1.0,1.0,0.8));
|
||||
|
||||
|
||||
ED_SHORTCUT("visual_script_editor/delete_selected", TTR("Delete Selected"));
|
||||
ED_SHORTCUT("visual_script_editor/toggle_breakpoint", TTR("Toggle Breakpoint"), KEY_F9);
|
||||
|
||||
}
|
||||
|
||||
void VisualScriptEditor::register_editor() {
|
||||
|
||||
ScriptEditor::register_create_script_editor_function(create_editor);
|
||||
//too early to register stuff here, request a callback
|
||||
EditorNode::add_plugin_init_callback(register_editor_callback);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -22,6 +22,13 @@ class VisualScriptEditor : public ScriptEditorBase {
|
||||
|
||||
};
|
||||
|
||||
enum {
|
||||
EDIT_DELETE_NODES,
|
||||
EDIT_TOGGLE_BREAKPOINT
|
||||
};
|
||||
|
||||
MenuButton *edit_menu;
|
||||
|
||||
Ref<VisualScript> script;
|
||||
|
||||
Button *base_type_select;
|
||||
@ -57,6 +64,8 @@ class VisualScriptEditor : public ScriptEditorBase {
|
||||
|
||||
Label *select_func_text;
|
||||
|
||||
bool updating_graph;
|
||||
|
||||
void _show_hint(const String& p_hint);
|
||||
void _hide_timer();
|
||||
|
||||
@ -88,7 +97,10 @@ class VisualScriptEditor : public ScriptEditorBase {
|
||||
String _validate_name(const String& p_name) const;
|
||||
|
||||
|
||||
int error_line;
|
||||
|
||||
void _node_selected(Node* p_node);
|
||||
void _center_on_node(int p_id);
|
||||
|
||||
void _node_filter_changed(const String& p_text);
|
||||
void _change_base_type_callback();
|
||||
@ -129,6 +141,10 @@ class VisualScriptEditor : public ScriptEditorBase {
|
||||
|
||||
void _default_value_changed();
|
||||
void _default_value_edited(Node * p_button,int p_id,int p_input_port);
|
||||
|
||||
void _menu_option(int p_what);
|
||||
|
||||
void _graph_ofs_changed(const Vector2& p_ofs);
|
||||
protected:
|
||||
|
||||
void _notification(int p_what);
|
||||
@ -145,7 +161,7 @@ public:
|
||||
virtual bool is_unsaved();
|
||||
virtual Variant get_edit_state();
|
||||
virtual void set_edit_state(const Variant& p_state);
|
||||
virtual void goto_line(int p_line);
|
||||
virtual void goto_line(int p_line,bool p_with_error=false);
|
||||
virtual void trim_trailing_whitespace();
|
||||
virtual void ensure_focus();
|
||||
virtual void tag_saved_version();
|
||||
@ -154,7 +170,7 @@ public:
|
||||
virtual bool goto_method(const String& p_method);
|
||||
virtual void add_callback(const String& p_function,StringArray p_args);
|
||||
virtual void update_settings();
|
||||
|
||||
virtual void set_debugger_active(bool p_active);
|
||||
virtual void set_tooltip_request_func(String p_method,Object* p_obj);
|
||||
virtual Control *get_edit_menu();
|
||||
|
||||
|
||||
@ -529,9 +529,15 @@ public:
|
||||
}
|
||||
|
||||
if (!valid) {
|
||||
|
||||
r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
|
||||
if (p_outputs[0]->get_type()==Variant::STRING) {
|
||||
r_error_str=*p_outputs[0];
|
||||
} else {
|
||||
if (unary)
|
||||
r_error_str=String(op_names[op])+RTR(": Invalid argument of type: ")+Variant::get_type_name(p_inputs[0]->get_type());
|
||||
else
|
||||
r_error_str=String(op_names[op])+RTR(": Invalid arguments: ")+"A: "+Variant::get_type_name(p_inputs[0]->get_type())+" B: "+Variant::get_type_name(p_inputs[1]->get_type());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user