Ability to reload scripts on running game
This commit is contained in:
parent
45752eaae4
commit
9e745b920f
@ -291,6 +291,8 @@ void ScriptDebuggerRemote::debug(ScriptLanguage *p_script,bool p_can_continue) {
|
|||||||
|
|
||||||
_set_object_property(cmd[1],cmd[2],cmd[3]);
|
_set_object_property(cmd[1],cmd[2],cmd[3]);
|
||||||
|
|
||||||
|
} else if (command=="reload_scripts") {
|
||||||
|
reload_all_scripts=true;
|
||||||
} else if (command=="breakpoint") {
|
} else if (command=="breakpoint") {
|
||||||
|
|
||||||
bool set = cmd[3];
|
bool set = cmd[3];
|
||||||
@ -698,7 +700,8 @@ void ScriptDebuggerRemote::_poll_events() {
|
|||||||
profiling=false;
|
profiling=false;
|
||||||
_send_profiling_data(false);
|
_send_profiling_data(false);
|
||||||
print_line("PROFILING END!");
|
print_line("PROFILING END!");
|
||||||
|
} else if (command=="reload_scripts") {
|
||||||
|
reload_all_scripts=true;
|
||||||
} else if (command=="breakpoint") {
|
} else if (command=="breakpoint") {
|
||||||
|
|
||||||
bool set = cmd[3];
|
bool set = cmd[3];
|
||||||
@ -863,6 +866,14 @@ void ScriptDebuggerRemote::idle_poll() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (reload_all_scripts) {
|
||||||
|
|
||||||
|
for(int i=0;i<ScriptServer::get_language_count();i++) {
|
||||||
|
ScriptServer::get_language(i)->reload_all_scripts();
|
||||||
|
}
|
||||||
|
reload_all_scripts=false;
|
||||||
|
}
|
||||||
|
|
||||||
_poll_events();
|
_poll_events();
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1012,6 +1023,7 @@ ScriptDebuggerRemote::ScriptDebuggerRemote() {
|
|||||||
profile_info_ptrs.resize(profile_info.size());
|
profile_info_ptrs.resize(profile_info.size());
|
||||||
profiling=false;
|
profiling=false;
|
||||||
max_frame_functions=16;
|
max_frame_functions=16;
|
||||||
|
reload_all_scripts=false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,6 +60,7 @@ class ScriptDebuggerRemote : public ScriptDebugger {
|
|||||||
bool profiling;
|
bool profiling;
|
||||||
int max_frame_functions;
|
int max_frame_functions;
|
||||||
bool skip_profile_frame;
|
bool skip_profile_frame;
|
||||||
|
bool reload_all_scripts;
|
||||||
|
|
||||||
|
|
||||||
Ref<StreamPeerTCP> tcp_client;
|
Ref<StreamPeerTCP> tcp_client;
|
||||||
@ -168,6 +169,7 @@ public:
|
|||||||
virtual void profiling_end();
|
virtual void profiling_end();
|
||||||
virtual void profiling_set_frame_times(float p_frame_time,float p_idle_time,float p_fixed_time,float p_fixed_frame_time);
|
virtual void profiling_set_frame_times(float p_frame_time,float p_idle_time,float p_fixed_time,float p_fixed_frame_time);
|
||||||
|
|
||||||
|
|
||||||
ScriptDebuggerRemote();
|
ScriptDebuggerRemote();
|
||||||
~ScriptDebuggerRemote();
|
~ScriptDebuggerRemote();
|
||||||
};
|
};
|
||||||
|
@ -51,7 +51,7 @@ void Script::_bind_methods() {
|
|||||||
ObjectTypeDB::bind_method(_MD("has_source_code"),&Script::has_source_code);
|
ObjectTypeDB::bind_method(_MD("has_source_code"),&Script::has_source_code);
|
||||||
ObjectTypeDB::bind_method(_MD("get_source_code"),&Script::get_source_code);
|
ObjectTypeDB::bind_method(_MD("get_source_code"),&Script::get_source_code);
|
||||||
ObjectTypeDB::bind_method(_MD("set_source_code","source"),&Script::set_source_code);
|
ObjectTypeDB::bind_method(_MD("set_source_code","source"),&Script::set_source_code);
|
||||||
ObjectTypeDB::bind_method(_MD("reload"),&Script::reload);
|
ObjectTypeDB::bind_method(_MD("reload","keep_state"),&Script::reload,DEFVAL(false));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,7 +87,7 @@ public:
|
|||||||
virtual bool has_source_code() const=0;
|
virtual bool has_source_code() const=0;
|
||||||
virtual String get_source_code() const=0;
|
virtual String get_source_code() const=0;
|
||||||
virtual void set_source_code(const String& p_code)=0;
|
virtual void set_source_code(const String& p_code)=0;
|
||||||
virtual Error reload()=0;
|
virtual Error reload(bool p_keep_state=false)=0;
|
||||||
|
|
||||||
virtual bool is_tool() const=0;
|
virtual bool is_tool() const=0;
|
||||||
|
|
||||||
@ -127,6 +127,8 @@ public:
|
|||||||
|
|
||||||
virtual Ref<Script> get_script() const=0;
|
virtual Ref<Script> get_script() const=0;
|
||||||
|
|
||||||
|
virtual bool is_placeholder() const { return false; }
|
||||||
|
|
||||||
virtual ScriptLanguage *get_language()=0;
|
virtual ScriptLanguage *get_language()=0;
|
||||||
virtual ~ScriptInstance();
|
virtual ~ScriptInstance();
|
||||||
};
|
};
|
||||||
@ -189,6 +191,7 @@ public:
|
|||||||
|
|
||||||
virtual Vector<StackInfo> debug_get_current_stack_info() { return Vector<StackInfo>(); }
|
virtual Vector<StackInfo> debug_get_current_stack_info() { return Vector<StackInfo>(); }
|
||||||
|
|
||||||
|
virtual void reload_all_scripts()=0;
|
||||||
/* LOADER FUNCTIONS */
|
/* LOADER FUNCTIONS */
|
||||||
|
|
||||||
virtual void get_recognized_extensions(List<String> *p_extensions) const=0;
|
virtual void get_recognized_extensions(List<String> *p_extensions) const=0;
|
||||||
@ -248,6 +251,8 @@ public:
|
|||||||
|
|
||||||
void update(const List<PropertyInfo> &p_properties,const Map<StringName,Variant>& p_values); //likely changed in editor
|
void update(const List<PropertyInfo> &p_properties,const Map<StringName,Variant>& p_values); //likely changed in editor
|
||||||
|
|
||||||
|
virtual bool is_placeholder() const { return true; }
|
||||||
|
|
||||||
PlaceHolderScriptInstance(ScriptLanguage *p_language, Ref<Script> p_script,Object *p_owner);
|
PlaceHolderScriptInstance(ScriptLanguage *p_language, Ref<Script> p_script,Object *p_owner);
|
||||||
~PlaceHolderScriptInstance();
|
~PlaceHolderScriptInstance();
|
||||||
|
|
||||||
|
@ -1414,8 +1414,13 @@ Error GDCompiler::_parse_function(GDScript *p_script,const GDParser::ClassNode *
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
Error GDCompiler::_parse_class(GDScript *p_script,GDScript *p_owner,const GDParser::ClassNode *p_class) {
|
Error GDCompiler::_parse_class(GDScript *p_script, GDScript *p_owner, const GDParser::ClassNode *p_class, bool p_keep_state) {
|
||||||
|
|
||||||
|
Map<StringName,Ref<GDScript> > old_subclasses;
|
||||||
|
|
||||||
|
if (p_keep_state) {
|
||||||
|
old_subclasses=p_script->subclasses;
|
||||||
|
}
|
||||||
|
|
||||||
p_script->native=Ref<GDNativeClass>();
|
p_script->native=Ref<GDNativeClass>();
|
||||||
p_script->base=Ref<GDScript>();
|
p_script->base=Ref<GDScript>();
|
||||||
@ -1429,6 +1434,7 @@ Error GDCompiler::_parse_class(GDScript *p_script,GDScript *p_owner,const GDPars
|
|||||||
p_script->member_indices.clear();
|
p_script->member_indices.clear();
|
||||||
p_script->member_info.clear();
|
p_script->member_info.clear();
|
||||||
p_script->initializer=NULL;
|
p_script->initializer=NULL;
|
||||||
|
|
||||||
p_script->subclasses.clear();
|
p_script->subclasses.clear();
|
||||||
p_script->_owner=p_owner;
|
p_script->_owner=p_owner;
|
||||||
p_script->tool=p_class->tool;
|
p_script->tool=p_class->tool;
|
||||||
@ -1662,9 +1668,15 @@ Error GDCompiler::_parse_class(GDScript *p_script,GDScript *p_owner,const GDPars
|
|||||||
for(int i=0;i<p_class->subclasses.size();i++) {
|
for(int i=0;i<p_class->subclasses.size();i++) {
|
||||||
StringName name = p_class->subclasses[i]->name;
|
StringName name = p_class->subclasses[i]->name;
|
||||||
|
|
||||||
Ref<GDScript> subclass = memnew( GDScript );
|
Ref<GDScript> subclass;
|
||||||
|
|
||||||
Error err = _parse_class(subclass.ptr(),p_script,p_class->subclasses[i]);
|
if (old_subclasses.has(name)) {
|
||||||
|
subclass=old_subclasses[name];
|
||||||
|
} else {
|
||||||
|
subclass.instance();
|
||||||
|
}
|
||||||
|
|
||||||
|
Error err = _parse_class(subclass.ptr(),p_script,p_class->subclasses[i],p_keep_state);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
@ -1755,13 +1767,65 @@ Error GDCompiler::_parse_class(GDScript *p_script,GDScript *p_owner,const GDPars
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//validate instances if keeping state
|
||||||
|
|
||||||
|
if (p_keep_state) {
|
||||||
|
|
||||||
|
print_line("RELOAD KEEP "+p_script->path);
|
||||||
|
for (Set<Object*>::Element *E=p_script->instances.front();E;) {
|
||||||
|
|
||||||
|
Set<Object*>::Element *N = E->next();
|
||||||
|
|
||||||
|
ScriptInstance *si = E->get()->get_script_instance();
|
||||||
|
if (si->is_placeholder()) {
|
||||||
|
PlaceHolderScriptInstance *psi = static_cast<PlaceHolderScriptInstance*>(si);
|
||||||
|
|
||||||
|
if (p_script->is_tool()) {
|
||||||
|
//re-create as an instance
|
||||||
|
p_script->placeholders.erase(psi); //remove placeholder
|
||||||
|
|
||||||
|
GDInstance* instance = memnew( GDInstance );
|
||||||
|
instance->base_ref=E->get()->cast_to<Reference>();
|
||||||
|
instance->members.resize(p_script->member_indices.size());
|
||||||
|
instance->script=Ref<GDScript>(p_script);
|
||||||
|
instance->owner=E->get();
|
||||||
|
|
||||||
|
//needed for hot reloading
|
||||||
|
for(Map<StringName,GDScript::MemberInfo>::Element *E=p_script->member_indices.front();E;E=E->next()) {
|
||||||
|
instance->member_indices_cache[E->key()]=E->get().index;
|
||||||
|
}
|
||||||
|
instance->owner->set_script_instance(instance);
|
||||||
|
|
||||||
|
|
||||||
|
/* STEP 2, INITIALIZE AND CONSRTUCT */
|
||||||
|
|
||||||
|
Variant::CallError ce;
|
||||||
|
p_script->initializer->call(instance,NULL,0,ce);
|
||||||
|
|
||||||
|
if (ce.error!=Variant::CallError::CALL_OK) {
|
||||||
|
//well, tough luck, not goinna do anything here
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
print_line("RELOAD MEMBERS");
|
||||||
|
GDInstance *gi = static_cast<GDInstance*>(si);
|
||||||
|
gi->reload_members();
|
||||||
|
}
|
||||||
|
|
||||||
|
E=N;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
p_script->valid=true;
|
p_script->valid=true;
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
Error GDCompiler::compile(const GDParser *p_parser,GDScript *p_script) {
|
Error GDCompiler::compile(const GDParser *p_parser,GDScript *p_script,bool p_keep_state) {
|
||||||
|
|
||||||
err_line=-1;
|
err_line=-1;
|
||||||
err_column=-1;
|
err_column=-1;
|
||||||
@ -1772,9 +1836,7 @@ Error GDCompiler::compile(const GDParser *p_parser,GDScript *p_script) {
|
|||||||
|
|
||||||
source=p_script->get_path();
|
source=p_script->get_path();
|
||||||
|
|
||||||
|
Error err = _parse_class(p_script,NULL,static_cast<const GDParser::ClassNode*>(root),p_keep_state);
|
||||||
|
|
||||||
Error err = _parse_class(p_script,NULL,static_cast<const GDParser::ClassNode*>(root));
|
|
||||||
|
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
@ -144,7 +144,7 @@ class GDCompiler {
|
|||||||
int _parse_expression(CodeGen& codegen,const GDParser::Node *p_expression, int p_stack_level,bool p_root=false,bool p_initializer=false);
|
int _parse_expression(CodeGen& codegen,const GDParser::Node *p_expression, int p_stack_level,bool p_root=false,bool p_initializer=false);
|
||||||
Error _parse_block(CodeGen& codegen,const GDParser::BlockNode *p_block,int p_stack_level=0,int p_break_addr=-1,int p_continue_addr=-1);
|
Error _parse_block(CodeGen& codegen,const GDParser::BlockNode *p_block,int p_stack_level=0,int p_break_addr=-1,int p_continue_addr=-1);
|
||||||
Error _parse_function(GDScript *p_script,const GDParser::ClassNode *p_class,const GDParser::FunctionNode *p_func,bool p_for_ready=false);
|
Error _parse_function(GDScript *p_script,const GDParser::ClassNode *p_class,const GDParser::FunctionNode *p_func,bool p_for_ready=false);
|
||||||
Error _parse_class(GDScript *p_script,GDScript *p_owner,const GDParser::ClassNode *p_class);
|
Error _parse_class(GDScript *p_script,GDScript *p_owner,const GDParser::ClassNode *p_class,bool p_keep_state);
|
||||||
int err_line;
|
int err_line;
|
||||||
int err_column;
|
int err_column;
|
||||||
StringName source;
|
StringName source;
|
||||||
@ -152,7 +152,7 @@ class GDCompiler {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Error compile(const GDParser *p_parser,GDScript *p_script);
|
Error compile(const GDParser *p_parser, GDScript *p_script, bool p_keep_state=false);
|
||||||
|
|
||||||
String get_error() const;
|
String get_error() const;
|
||||||
int get_error_line() const;
|
int get_error_line() const;
|
||||||
|
@ -101,6 +101,12 @@ GDInstance* GDScript::_create_instance(const Variant** p_args,int p_argcount,Obj
|
|||||||
instance->members.resize(member_indices.size());
|
instance->members.resize(member_indices.size());
|
||||||
instance->script=Ref<GDScript>(this);
|
instance->script=Ref<GDScript>(this);
|
||||||
instance->owner=p_owner;
|
instance->owner=p_owner;
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
//needed for hot reloading
|
||||||
|
for(Map<StringName,MemberInfo>::Element *E=member_indices.front();E;E=E->next()) {
|
||||||
|
instance->member_indices_cache[E->key()]=E->get().index;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
instance->owner->set_script_instance(instance);
|
instance->owner->set_script_instance(instance);
|
||||||
|
|
||||||
/* STEP 2, INITIALIZE AND CONSRTUCT */
|
/* STEP 2, INITIALIZE AND CONSRTUCT */
|
||||||
@ -500,10 +506,10 @@ void GDScript::_set_subclass_path(Ref<GDScript>& p_sc,const String& p_path) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Error GDScript::reload() {
|
Error GDScript::reload(bool p_keep_state) {
|
||||||
|
|
||||||
|
|
||||||
ERR_FAIL_COND_V(instances.size(),ERR_ALREADY_IN_USE);
|
ERR_FAIL_COND_V(!p_keep_state && instances.size(),ERR_ALREADY_IN_USE);
|
||||||
|
|
||||||
String basedir=path;
|
String basedir=path;
|
||||||
|
|
||||||
@ -531,7 +537,7 @@ Error GDScript::reload() {
|
|||||||
bool can_run = ScriptServer::is_scripting_enabled() || parser.is_tool_script();
|
bool can_run = ScriptServer::is_scripting_enabled() || parser.is_tool_script();
|
||||||
|
|
||||||
GDCompiler compiler;
|
GDCompiler compiler;
|
||||||
err = compiler.compile(&parser,this);
|
err = compiler.compile(&parser,this,p_keep_state);
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
|
|
||||||
@ -837,7 +843,7 @@ void GDScript::get_script_signal_list(List<MethodInfo> *r_signals) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
GDScript::GDScript() {
|
GDScript::GDScript() : script_list(this) {
|
||||||
|
|
||||||
|
|
||||||
_static_ref=this;
|
_static_ref=this;
|
||||||
@ -851,12 +857,33 @@ GDScript::GDScript() {
|
|||||||
source_changed_cache=false;
|
source_changed_cache=false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
if (GDScriptLanguage::get_singleton()->lock) {
|
||||||
|
GDScriptLanguage::get_singleton()->lock->lock();
|
||||||
|
}
|
||||||
|
GDScriptLanguage::get_singleton()->script_list.add(&script_list);
|
||||||
|
|
||||||
|
if (GDScriptLanguage::get_singleton()->lock) {
|
||||||
|
GDScriptLanguage::get_singleton()->lock->unlock();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
GDScript::~GDScript() {
|
GDScript::~GDScript() {
|
||||||
for (Map<StringName,GDFunction*>::Element *E=member_functions.front();E;E=E->next()) {
|
for (Map<StringName,GDFunction*>::Element *E=member_functions.front();E;E=E->next()) {
|
||||||
memdelete( E->get() );
|
memdelete( E->get() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
if (GDScriptLanguage::get_singleton()->lock) {
|
||||||
|
GDScriptLanguage::get_singleton()->lock->lock();
|
||||||
|
}
|
||||||
|
GDScriptLanguage::get_singleton()->script_list.remove(&script_list);
|
||||||
|
|
||||||
|
if (GDScriptLanguage::get_singleton()->lock) {
|
||||||
|
GDScriptLanguage::get_singleton()->lock->unlock();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1218,6 +1245,37 @@ ScriptLanguage *GDInstance::get_language() {
|
|||||||
return GDScriptLanguage::get_singleton();
|
return GDScriptLanguage::get_singleton();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GDInstance::reload_members() {
|
||||||
|
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
|
||||||
|
members.resize(script->member_indices.size()); //resize
|
||||||
|
|
||||||
|
Vector<Variant> new_members;
|
||||||
|
new_members.resize(script->member_indices.size());
|
||||||
|
|
||||||
|
//pass the values to the new indices
|
||||||
|
for(Map<StringName,GDScript::MemberInfo>::Element *E=script->member_indices.front();E;E=E->next()) {
|
||||||
|
|
||||||
|
if (member_indices_cache.has(E->key())) {
|
||||||
|
Variant value = members[member_indices_cache[E->key()]];
|
||||||
|
new_members[E->get().index]=value;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//apply
|
||||||
|
members=new_members;
|
||||||
|
|
||||||
|
//pass the values to the new indices
|
||||||
|
member_indices_cache.clear();
|
||||||
|
for(Map<StringName,GDScript::MemberInfo>::Element *E=script->member_indices.front();E;E=E->next()) {
|
||||||
|
|
||||||
|
member_indices_cache[E->key()]=E->get().index;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
GDInstance::GDInstance() {
|
GDInstance::GDInstance() {
|
||||||
owner=NULL;
|
owner=NULL;
|
||||||
@ -1441,6 +1499,65 @@ int GDScriptLanguage::profiling_get_frame_data(ProfilingInfo *p_info_arr,int p_i
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct GDScriptDepSort {
|
||||||
|
|
||||||
|
//must support sorting so inheritance works properly (parent must be reloaded first)
|
||||||
|
bool operator()(const Ref<GDScript> &A, const Ref<GDScript>& B) const {
|
||||||
|
|
||||||
|
if (A==B)
|
||||||
|
return false; //shouldn't happen but..
|
||||||
|
const GDScript *I=B->get_base().ptr();
|
||||||
|
while(I) {
|
||||||
|
if (I==A.ptr()) {
|
||||||
|
// A is a base of B
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
I=I->get_base().ptr();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false; //not a base
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void GDScriptLanguage::reload_all_scripts() {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
print_line("RELOAD ALL SCRIPTS");
|
||||||
|
if (lock) {
|
||||||
|
lock->lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Ref<GDScript> > scripts;
|
||||||
|
|
||||||
|
SelfList<GDScript> *elem=script_list.first();
|
||||||
|
while(elem) {
|
||||||
|
if (elem->self()->get_path().is_resource_file()) {
|
||||||
|
print_line("FOUND: "+elem->self()->get_path());
|
||||||
|
scripts.push_back(Ref<GDScript>(elem->self())); //cast to gdscript to avoid being erased by accident
|
||||||
|
}
|
||||||
|
elem=elem->next();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lock) {
|
||||||
|
lock->unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
//as scripts are going to be reloaded, must proceed without locking here
|
||||||
|
|
||||||
|
scripts.sort_custom<GDScriptDepSort>(); //update in inheritance dependency order
|
||||||
|
|
||||||
|
for(List<Ref<GDScript> >::Element *E=scripts.front();E;E=E->next()) {
|
||||||
|
|
||||||
|
print_line("RELOADING: "+E->get()->get_path());
|
||||||
|
E->get()->load_source_code(E->get()->get_path());
|
||||||
|
E->get()->reload(true);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void GDScriptLanguage::frame() {
|
void GDScriptLanguage::frame() {
|
||||||
|
|
||||||
// print_line("calls: "+itos(calls));
|
// print_line("calls: "+itos(calls));
|
||||||
|
@ -107,6 +107,7 @@ friend class GDScriptLanguage;
|
|||||||
String source;
|
String source;
|
||||||
String path;
|
String path;
|
||||||
String name;
|
String name;
|
||||||
|
SelfList<GDScript> script_list;
|
||||||
|
|
||||||
|
|
||||||
GDInstance* _create_instance(const Variant** p_args,int p_argcount,Object *p_owner,bool p_isref,Variant::CallError &r_error);
|
GDInstance* _create_instance(const Variant** p_args,int p_argcount,Object *p_owner,bool p_isref,Variant::CallError &r_error);
|
||||||
@ -165,7 +166,7 @@ public:
|
|||||||
virtual void set_source_code(const String& p_code);
|
virtual void set_source_code(const String& p_code);
|
||||||
virtual void update_exports();
|
virtual void update_exports();
|
||||||
|
|
||||||
virtual Error reload();
|
virtual Error reload(bool p_keep_state=false);
|
||||||
|
|
||||||
virtual String get_node_type() const;
|
virtual String get_node_type() const;
|
||||||
void set_script_path(const String& p_path) { path=p_path; } //because subclasses need a path too...
|
void set_script_path(const String& p_path) { path=p_path; } //because subclasses need a path too...
|
||||||
@ -186,9 +187,13 @@ class GDInstance : public ScriptInstance {
|
|||||||
friend class GDScript;
|
friend class GDScript;
|
||||||
friend class GDFunction;
|
friend class GDFunction;
|
||||||
friend class GDFunctions;
|
friend class GDFunctions;
|
||||||
|
friend class GDCompiler;
|
||||||
|
|
||||||
Object *owner;
|
Object *owner;
|
||||||
Ref<GDScript> script;
|
Ref<GDScript> script;
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
Map<StringName,int> member_indices_cache; //used only for hot script reloading
|
||||||
|
#endif
|
||||||
Vector<Variant> members;
|
Vector<Variant> members;
|
||||||
bool base_ref;
|
bool base_ref;
|
||||||
|
|
||||||
@ -209,7 +214,7 @@ public:
|
|||||||
virtual void call_multilevel(const StringName& p_method,const Variant** p_args,int p_argcount);
|
virtual void call_multilevel(const StringName& p_method,const Variant** p_args,int p_argcount);
|
||||||
virtual void call_multilevel_reversed(const StringName& p_method,const Variant** p_args,int p_argcount);
|
virtual void call_multilevel_reversed(const StringName& p_method,const Variant** p_args,int p_argcount);
|
||||||
|
|
||||||
Variant debug_get_member_by_index(int p_idx) const { return members[p_idx]; }
|
Variant debug_get_member_by_index(int p_idx) const { return members[p_idx]; }
|
||||||
|
|
||||||
virtual void notification(int p_notification);
|
virtual void notification(int p_notification);
|
||||||
|
|
||||||
@ -219,6 +224,7 @@ public:
|
|||||||
|
|
||||||
void set_path(const String& p_path);
|
void set_path(const String& p_path);
|
||||||
|
|
||||||
|
void reload_members();
|
||||||
|
|
||||||
GDInstance();
|
GDInstance();
|
||||||
~GDInstance();
|
~GDInstance();
|
||||||
@ -256,6 +262,10 @@ class GDScriptLanguage : public ScriptLanguage {
|
|||||||
|
|
||||||
|
|
||||||
Mutex *lock;
|
Mutex *lock;
|
||||||
|
|
||||||
|
friend class GDScript;
|
||||||
|
|
||||||
|
SelfList<GDScript>::List script_list;
|
||||||
friend class GDFunction;
|
friend class GDFunction;
|
||||||
|
|
||||||
SelfList<GDFunction>::List function_list;
|
SelfList<GDFunction>::List function_list;
|
||||||
@ -378,6 +388,8 @@ public:
|
|||||||
virtual void debug_get_globals(List<String> *p_locals, List<Variant> *p_values, int p_max_subitems=-1,int p_max_depth=-1);
|
virtual void debug_get_globals(List<String> *p_locals, List<Variant> *p_values, int p_max_subitems=-1,int p_max_depth=-1);
|
||||||
virtual String debug_parse_stack_level_expression(int p_level,const String& p_expression,int p_max_subitems=-1,int p_max_depth=-1);
|
virtual String debug_parse_stack_level_expression(int p_level,const String& p_expression,int p_max_subitems=-1,int p_max_depth=-1);
|
||||||
|
|
||||||
|
virtual void reload_all_scripts();
|
||||||
|
|
||||||
virtual void frame();
|
virtual void frame();
|
||||||
|
|
||||||
virtual void get_public_functions(List<MethodInfo> *p_functions) const;
|
virtual void get_public_functions(List<MethodInfo> *p_functions) const;
|
||||||
|
@ -2795,6 +2795,10 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
|
|||||||
run_native->set_debug_navigation(!ischecked);
|
run_native->set_debug_navigation(!ischecked);
|
||||||
editor_run.set_debug_navigation(!ischecked);
|
editor_run.set_debug_navigation(!ischecked);
|
||||||
} break;
|
} break;
|
||||||
|
case RUN_RELOAD_SCRIPTS: {
|
||||||
|
|
||||||
|
ScriptEditor::get_singleton()->get_debugger()->reload_scripts();
|
||||||
|
} break;
|
||||||
case SETTINGS_UPDATE_ALWAYS: {
|
case SETTINGS_UPDATE_ALWAYS: {
|
||||||
|
|
||||||
update_menu->get_popup()->set_item_checked(0,true);
|
update_menu->get_popup()->set_item_checked(0,true);
|
||||||
@ -5717,6 +5721,8 @@ EditorNode::EditorNode() {
|
|||||||
p->add_separator();
|
p->add_separator();
|
||||||
p->add_check_item(TTR("Visible Collision Shapes"),RUN_DEBUG_COLLISONS);
|
p->add_check_item(TTR("Visible Collision Shapes"),RUN_DEBUG_COLLISONS);
|
||||||
p->add_check_item(TTR("Visible Navigation"),RUN_DEBUG_NAVIGATION);
|
p->add_check_item(TTR("Visible Navigation"),RUN_DEBUG_NAVIGATION);
|
||||||
|
p->add_separator();
|
||||||
|
p->add_item(TTR("Reload Scripts"),RUN_RELOAD_SCRIPTS);
|
||||||
p->connect("item_pressed",this,"_menu_option");
|
p->connect("item_pressed",this,"_menu_option");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -174,6 +174,7 @@ private:
|
|||||||
RUN_DEBUG_COLLISONS,
|
RUN_DEBUG_COLLISONS,
|
||||||
RUN_DEBUG_NAVIGATION,
|
RUN_DEBUG_NAVIGATION,
|
||||||
RUN_DEPLOY_REMOTE_DEBUG,
|
RUN_DEPLOY_REMOTE_DEBUG,
|
||||||
|
RUN_RELOAD_SCRIPTS,
|
||||||
SETTINGS_UPDATE_ALWAYS,
|
SETTINGS_UPDATE_ALWAYS,
|
||||||
SETTINGS_UPDATE_CHANGES,
|
SETTINGS_UPDATE_CHANGES,
|
||||||
SETTINGS_IMPORT,
|
SETTINGS_IMPORT,
|
||||||
|
@ -1573,6 +1573,16 @@ void ScriptEditorDebugger::set_breakpoint(const String& p_path,int p_line,bool p
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ScriptEditorDebugger::reload_scripts() {
|
||||||
|
|
||||||
|
if (connection.is_valid()) {
|
||||||
|
Array msg;
|
||||||
|
msg.push_back("reload_scripts");
|
||||||
|
ppeer->put_var(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void ScriptEditorDebugger::_error_selected(int p_idx) {
|
void ScriptEditorDebugger::_error_selected(int p_idx) {
|
||||||
|
|
||||||
error_stack->clear();
|
error_stack->clear();
|
||||||
|
@ -217,6 +217,8 @@ public:
|
|||||||
|
|
||||||
void set_tool_button(Button *p_tb) { debugger_button=p_tb; }
|
void set_tool_button(Button *p_tb) { debugger_button=p_tb; }
|
||||||
|
|
||||||
|
void reload_scripts();
|
||||||
|
|
||||||
virtual Size2 get_minimum_size() const;
|
virtual Size2 get_minimum_size() const;
|
||||||
ScriptEditorDebugger(EditorNode *p_editor=NULL);
|
ScriptEditorDebugger(EditorNode *p_editor=NULL);
|
||||||
~ScriptEditorDebugger();
|
~ScriptEditorDebugger();
|
||||||
|
Loading…
Reference in New Issue
Block a user