mirror of
https://github.com/godotengine/godot.git
synced 2026-01-03 18:11:19 +03:00
Ability to reload scripts on running game
This commit is contained in:
@@ -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->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_info.clear();
|
||||
p_script->initializer=NULL;
|
||||
|
||||
p_script->subclasses.clear();
|
||||
p_script->_owner=p_owner;
|
||||
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++) {
|
||||
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)
|
||||
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
|
||||
|
||||
p_script->valid=true;
|
||||
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_column=-1;
|
||||
@@ -1772,9 +1836,7 @@ Error GDCompiler::compile(const GDParser *p_parser,GDScript *p_script) {
|
||||
|
||||
source=p_script->get_path();
|
||||
|
||||
|
||||
|
||||
Error err = _parse_class(p_script,NULL,static_cast<const GDParser::ClassNode*>(root));
|
||||
Error err = _parse_class(p_script,NULL,static_cast<const GDParser::ClassNode*>(root),p_keep_state);
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
Reference in New Issue
Block a user