-scenes are properly reloaded when a dependency changes, fixes #2896

(it's clevery done so local changes to scenes are kept even if unsaved)
This commit is contained in:
Juan Linietsky 2015-12-13 20:39:01 -03:00
parent 72ff61963b
commit 7f96f0603e
8 changed files with 146 additions and 3 deletions

View file

@ -144,7 +144,7 @@ public:
#ifdef TOOLS_ENABLED
void set_last_modified_time(uint64_t p_time) { last_modified_time=p_time; }
virtual void set_last_modified_time(uint64_t p_time) { last_modified_time=p_time; }
uint64_t get_last_modified_time() const { return last_modified_time; }
#endif

View file

@ -1537,6 +1537,7 @@ void SceneState::add_editable_instance(const NodePath& p_path){
SceneState::SceneState() {
base_scene_idx=-1;
last_modified_time=0;
}
@ -1596,6 +1597,15 @@ Node *PackedScene::instance(bool p_gen_edit_state) const {
return s;
}
void PackedScene::recreate_state() {
state = Ref<SceneState>( memnew( SceneState ));
state->set_path(get_path());
#ifdef TOOLS_ENABLED
state->set_last_modified_time(get_last_modified_time());
#endif
}
Ref<SceneState> PackedScene::get_state() {
return state;
@ -1607,6 +1617,7 @@ void PackedScene::set_path(const String& p_path,bool p_take_over) {
Resource::set_path(p_path,p_take_over);
}
void PackedScene::_bind_methods() {
ObjectTypeDB::bind_method(_MD("pack","path:Node"),&PackedScene::pack);

View file

@ -99,6 +99,8 @@ class SceneState : public Reference {
String path;
uint64_t last_modified_time;
_FORCE_INLINE_ Ref<SceneState> _get_base_scene_state() const;
static bool disable_placeholders;
@ -162,6 +164,9 @@ public:
void add_connection(int p_from,int p_to, int p_signal, int p_method, int p_flags,const Vector<int>& p_binds);
void add_editable_instance(const NodePath& p_path);
virtual void set_last_modified_time(uint64_t p_time) { last_modified_time=p_time; }
uint64_t get_last_modified_time() const { return last_modified_time; }
SceneState();
};
@ -189,8 +194,13 @@ public:
bool can_instance() const;
Node *instance(bool p_gen_edit_state=false) const;
virtual void set_path(const String& p_path,bool p_take_over=false);
void recreate_state();
virtual void set_path(const String& p_path,bool p_take_over=false);
#ifdef TOOLS_ENABLED
virtual void set_last_modified_time(uint64_t p_time) { state->set_last_modified_time(p_time); }
#endif
Ref<SceneState> get_state();
PackedScene();

View file

@ -31,6 +31,9 @@
#include "editor_settings.h"
#include "os/dir_access.h"
#include "io/resource_loader.h"
#include "scene/resources/packed_scene.h"
#include "os/file_access.h"
#include "editor_node.h"
void EditorHistory::_cleanup_history() {
@ -493,6 +496,93 @@ void EditorData::remove_scene(int p_idx){
edited_scene.remove(p_idx);
}
bool EditorData::_find_updated_instances(Node* p_root,Node *p_node,Set<String> &checked_paths) {
if (p_root!=p_node && p_node->get_owner()!=p_root && !p_root->is_editable_instance(p_node->get_owner()))
return false;
Ref<SceneState> ss;
if (p_node==p_root) {
ss=p_node->get_scene_inherited_state();
} else if (p_node->get_filename()!=String()){
ss=p_node->get_scene_instance_state();
}
if (ss.is_valid()) {
String path = ss->get_path();
if (!checked_paths.has(path)) {
uint64_t modified_time = FileAccess::get_modified_time(path);
if (modified_time!=ss->get_last_modified_time()) {
return true; //external scene changed
}
checked_paths.insert(path);
}
}
for(int i=0;i<p_node->get_child_count();i++) {
bool found = _find_updated_instances(p_root,p_node->get_child(i),checked_paths);
if (found)
return true;
}
return false;
}
bool EditorData::check_and_update_scene(int p_idx) {
ERR_FAIL_INDEX_V(p_idx,edited_scene.size(),false);
if (!edited_scene[p_idx].root)
return false;
Set<String> checked_scenes;
bool must_reload = _find_updated_instances(edited_scene[p_idx].root,edited_scene[p_idx].root,checked_scenes);
if (must_reload) {
Ref<PackedScene> pscene;
pscene.instance();
EditorProgress ep("update_scene","Updating Scene",2);
ep.step("Storing local changes..",0);
//pack first, so it stores diffs to previous version of saved scene
Error err = pscene->pack(edited_scene[p_idx].root);
ERR_FAIL_COND_V(err!=OK,false);
ep.step("Updating scene..",1);
Node *new_scene = pscene->instance(true);
ERR_FAIL_COND_V(!new_scene,false);
//transfer selection
List<Node*> new_selection;
for (List<Node*>::Element *E=edited_scene[p_idx].selection.front();E;E=E->next()) {
NodePath p = edited_scene[p_idx].root->get_path_to(E->get());
Node *new_node = new_scene->get_node(p);
if (new_node)
new_selection.push_back(new_node);
}
new_scene->set_filename( edited_scene[p_idx].root->get_filename() );
memdelete(edited_scene[p_idx].root);
edited_scene[p_idx].root=new_scene;
edited_scene[p_idx].selection=new_selection;
return true;
}
return false;
}
int EditorData::get_edited_scene() const {
return current_edited_scene;

View file

@ -144,6 +144,8 @@ private:
Vector<EditedScene> edited_scene;
int current_edited_scene;
bool _find_updated_instances(Node* p_root,Node *p_node,Set<String> &checked_paths);
public:
EditorPlugin* get_editor(Object *p_object);
@ -193,6 +195,7 @@ public:
void clear_edited_scenes();
void set_edited_scene_live_edit_root(const NodePath& p_root);
NodePath get_edited_scene_live_edit_root();
bool check_and_update_scene(int p_idx);
void set_plugin_window_layout(Ref<ConfigFile> p_layout);

View file

@ -43,6 +43,7 @@
#include "tools/editor/plugins/script_editor_plugin.h"
#include "io/zip_io.h"
String EditorImportPlugin::validate_source_path(const String& p_path) {
String gp = Globals::get_singleton()->globalize_path(p_path);

View file

@ -955,7 +955,23 @@ void EditorNode::_save_scene(String p_file) {
_set_scene_metadata();
Ref<PackedScene> sdata = memnew( PackedScene );
Ref<PackedScene> sdata;
if (ResourceCache::has(p_file)) {
// something may be referencing this resource and we are good with that.
// we must update it, but also let the previous scene state go, as
// old version still work for referencing changes in instanced or inherited scenes
sdata = Ref<PackedScene>( ResourceCache::get(p_file)->cast_to<PackedScene>() );
if (sdata.is_valid())
sdata->recreate_state();
else
sdata.instance();
} else {
sdata.instance();
}
Error err = sdata->pack(scene);
@ -3414,8 +3430,18 @@ void EditorNode::set_current_version(uint64_t p_version) {
bool EditorNode::is_changing_scene() const {
return changing_scene;
}
void EditorNode::_clear_undo_history() {
get_undo_redo()->clear_history();
}
void EditorNode::set_current_scene(int p_idx) {
if (editor_data.check_and_update_scene(p_idx)) {
call_deferred("_clear_undo_history");
}
changing_scene=true;
editor_data.save_edited_scene_state(editor_selection,&editor_history,_get_main_scene_state());
@ -4113,6 +4139,7 @@ void EditorNode::_bind_methods() {
ObjectTypeDB::bind_method("_toggle_search_bar",&EditorNode::_toggle_search_bar);
ObjectTypeDB::bind_method("_clear_search_box",&EditorNode::_clear_search_box);
ObjectTypeDB::bind_method("_clear_undo_history",&EditorNode::_clear_undo_history);
ObjectTypeDB::bind_method(_MD("add_editor_import_plugin", "plugin"), &EditorNode::add_editor_import_plugin);
ObjectTypeDB::bind_method(_MD("remove_editor_import_plugin", "plugin"), &EditorNode::remove_editor_import_plugin);

View file

@ -540,6 +540,7 @@ class EditorNode : public Node {
void _toggle_search_bar(bool p_pressed);
void _clear_search_box();
void _clear_undo_history();
protected:
void _notification(int p_what);