diff options
-rw-r--r-- | core/resource.cpp | 125 | ||||
-rw-r--r-- | core/resource.h | 15 | ||||
-rw-r--r-- | scene/gui/base_button.cpp | 107 | ||||
-rw-r--r-- | scene/gui/base_button.h | 24 | ||||
-rw-r--r-- | scene/gui/button.h | 3 | ||||
-rw-r--r-- | scene/gui/button_group.cpp | 3 | ||||
-rw-r--r-- | scene/gui/button_group.h | 3 | ||||
-rw-r--r-- | scene/gui/check_box.cpp | 8 | ||||
-rw-r--r-- | scene/main/viewport.cpp | 94 | ||||
-rw-r--r-- | scene/main/viewport.h | 20 | ||||
-rw-r--r-- | scene/resources/packed_scene.cpp | 70 | ||||
-rw-r--r-- | scene/resources/packed_scene.h | 19 | ||||
-rw-r--r-- | tools/editor/editor_data.cpp | 2 | ||||
-rw-r--r-- | tools/editor/editor_node.cpp | 9 | ||||
-rw-r--r-- | tools/editor/io_plugins/editor_texture_import_plugin.cpp | 2 | ||||
-rw-r--r-- | tools/editor/plugins/canvas_item_editor_plugin.cpp | 17 | ||||
-rw-r--r-- | tools/editor/plugins/canvas_item_editor_plugin.h | 3 | ||||
-rw-r--r-- | tools/editor/plugins/theme_editor_plugin.cpp | 2 | ||||
-rw-r--r-- | tools/editor/property_editor.cpp | 43 | ||||
-rw-r--r-- | tools/editor/property_editor.h | 1 | ||||
-rw-r--r-- | tools/editor/scene_tree_dock.cpp | 6 |
21 files changed, 481 insertions, 95 deletions
diff --git a/core/resource.cpp b/core/resource.cpp index 7bcdd88891..9545d8c3da 100644 --- a/core/resource.cpp +++ b/core/resource.cpp @@ -31,6 +31,7 @@ #include <stdio.h> #include "os/file_access.h" #include "io/resource_loader.h" +#include "script_language.h" void ResourceImportMetadata::set_editor(const String& p_editor) { @@ -201,7 +202,7 @@ void Resource::set_path(const String& p_path, bool p_take_over) { ResourceCache::lock->write_unlock(); } - _change_notify("resource/path"); + _change_notify("resource_path"); _resource_path_changed(); } @@ -225,7 +226,7 @@ int Resource::get_subindex() const{ void Resource::set_name(const String& p_name) { name=p_name; - _change_notify("resource/name"); + _change_notify("resource_name"); } String Resource::get_name() const { @@ -257,7 +258,7 @@ void Resource::reload_from_file() { if (!(E->get().usage&PROPERTY_USAGE_STORAGE)) continue; - if (E->get().name=="resource/path") + if (E->get().name=="resource_path") continue; //do not change path set(E->get().name,s->get(E->get().name)); @@ -266,8 +267,51 @@ void Resource::reload_from_file() { } +Ref<Resource> Resource::duplicate_for_local_scene(Node *p_for_scene, Map<Ref<Resource>, Ref<Resource> > &remap_cache) { + + + List<PropertyInfo> plist; + get_property_list(&plist); + + + Resource *r = (Resource*)ClassDB::instance(get_class()); + ERR_FAIL_COND_V(!r,Ref<Resource>()); + + r->local_scene=p_for_scene; + + for(List<PropertyInfo>::Element *E=plist.front();E;E=E->next()) { + + if (!(E->get().usage&PROPERTY_USAGE_STORAGE)) + continue; + Variant p = get(E->get().name); + if (p.get_type()==Variant::OBJECT) { + + RES sr = p; + if (sr.is_valid()) { + + if (sr->is_local_to_scene()) { + if (remap_cache.has(sr)) { + p=remap_cache[sr]; + } else { + + + RES dupe = sr->duplicate_for_local_scene(p_for_scene,remap_cache); + p=dupe; + remap_cache[sr]=dupe; + } + } + } + } + + r->set(E->get().name,p); + } + + return Ref<Resource>(r); +} + Ref<Resource> Resource::duplicate(bool p_subresources) { + List<PropertyInfo> plist; get_property_list(&plist); @@ -305,24 +349,6 @@ void Resource::_take_over_path(const String& p_path) { } -void Resource::_bind_methods() { - - ClassDB::bind_method(_MD("set_path","path"),&Resource::_set_path); - ClassDB::bind_method(_MD("take_over_path","path"),&Resource::_take_over_path); - ClassDB::bind_method(_MD("get_path"),&Resource::get_path); - ClassDB::bind_method(_MD("set_name","name"),&Resource::set_name); - ClassDB::bind_method(_MD("get_name"),&Resource::get_name); - ClassDB::bind_method(_MD("get_rid"),&Resource::get_rid); - ClassDB::bind_method(_MD("set_import_metadata","metadata"),&Resource::set_import_metadata); - ClassDB::bind_method(_MD("get_import_metadata"),&Resource::get_import_metadata); - - ClassDB::bind_method(_MD("duplicate","subresources"),&Resource::duplicate,DEFVAL(false)); - ADD_SIGNAL( MethodInfo("changed") ); - ADD_GROUP("Resource","resource_"); - ADD_PROPERTY( PropertyInfo(Variant::STRING,"resource_path",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_EDITOR ), _SCS("set_path"),_SCS("get_path")); - ADD_PROPERTYNZ( PropertyInfo(Variant::STRING,"resource_name"), _SCS("set_name"),_SCS("get_name")); -} - RID Resource::get_rid() const { return RID(); @@ -394,6 +420,62 @@ uint32_t Resource::hash_edited_version() const { #endif +void Resource::set_local_to_scene(bool p_enable) { + + local_to_scene=p_enable; +} + +bool Resource::is_local_to_scene() const { + + return local_to_scene; +} + +Node* Resource::get_local_scene() const { + + if (local_scene) + return local_scene; + + if (_get_local_scene_func) { + return _get_local_scene_func(); + } + + return NULL; +} + +void Resource::setup_local_to_scene() { + + if (get_script_instance()) + get_script_instance()->call("_setup_local_to_scene"); +} + +Node* (*Resource::_get_local_scene_func)()=NULL; + + +void Resource::_bind_methods() { + + ClassDB::bind_method(_MD("set_path","path"),&Resource::_set_path); + ClassDB::bind_method(_MD("take_over_path","path"),&Resource::_take_over_path); + ClassDB::bind_method(_MD("get_path"),&Resource::get_path); + ClassDB::bind_method(_MD("set_name","name"),&Resource::set_name); + ClassDB::bind_method(_MD("get_name"),&Resource::get_name); + ClassDB::bind_method(_MD("get_rid"),&Resource::get_rid); + ClassDB::bind_method(_MD("set_import_metadata","metadata"),&Resource::set_import_metadata); + ClassDB::bind_method(_MD("get_import_metadata"),&Resource::get_import_metadata); + ClassDB::bind_method(_MD("set_local_to_scene","enable"),&Resource::set_local_to_scene); + ClassDB::bind_method(_MD("is_local_to_scene"),&Resource::is_local_to_scene); + ClassDB::bind_method(_MD("get_local_scene:Node"),&Resource::get_local_scene); + ClassDB::bind_method(_MD("setup_local_to_scene"),&Resource::setup_local_to_scene); + + ClassDB::bind_method(_MD("duplicate","subresources"),&Resource::duplicate,DEFVAL(false)); + ADD_SIGNAL( MethodInfo("changed") ); + ADD_GROUP("Resource","resource_"); + ADD_PROPERTYNZ( PropertyInfo(Variant::BOOL,"resource_local_to_scene" ), _SCS("set_local_to_scene"),_SCS("is_local_to_scene")); + ADD_PROPERTY( PropertyInfo(Variant::STRING,"resource_path",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_EDITOR ), _SCS("set_path"),_SCS("get_path")); + ADD_PROPERTYNZ( PropertyInfo(Variant::STRING,"resource_name"), _SCS("set_name"),_SCS("get_name")); + + BIND_VMETHOD( MethodInfo("_setup_local_to_scene") ); + +} Resource::Resource() { @@ -402,6 +484,7 @@ Resource::Resource() { #endif subindex=0; + local_scene=NULL; } diff --git a/core/resource.h b/core/resource.h index 40b6dd78a0..8b73bcdc57 100644 --- a/core/resource.h +++ b/core/resource.h @@ -61,6 +61,7 @@ class ResourceImportMetadata : public Reference { Map<String,Variant> options; StringArray _get_options() const; + protected: static void _bind_methods(); @@ -82,6 +83,7 @@ public: void get_options(List<String> *r_options) const; + ResourceImportMetadata(); }; @@ -108,6 +110,10 @@ friend class ResourceCache; uint64_t last_modified_time; #endif + bool local_to_scene; +friend class SceneState; + Node* local_scene; + protected: void emit_changed(); @@ -121,6 +127,8 @@ protected: void _take_over_path(const String& p_path); public: + static Node* (*_get_local_scene_func)(); //used by editor + virtual bool editor_can_reload_from_file(); virtual void reload_from_file(); @@ -137,12 +145,17 @@ public: int get_subindex() const; Ref<Resource> duplicate(bool p_subresources=false); + Ref<Resource> duplicate_for_local_scene(Node *p_scene,Map<Ref<Resource>,Ref<Resource> >& remap_cache); + void set_import_metadata(const Ref<ResourceImportMetadata>& p_metadata); Ref<ResourceImportMetadata> get_import_metadata() const; + void set_local_to_scene(bool p_enable); + bool is_local_to_scene() const; + virtual void setup_local_to_scene(); - + Node* get_local_scene() const; #ifdef TOOLS_ENABLED diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp index 05646320cc..45c491cd74 100644 --- a/scene/gui/base_button.cpp +++ b/scene/gui/base_button.cpp @@ -29,10 +29,23 @@ #include "base_button.h" #include "os/keyboard.h" #include "print_string.h" -#include "button_group.h" #include "scene/scene_string_names.h" #include "scene/main/viewport.h" + +void BaseButton::_unpress_group() { + + if (!button_group.is_valid()) + return; + + for (Set<BaseButton*>::Element *E=button_group->buttons.front();E;E=E->next()) { + if (E->get()==this) + continue; + + E->get()->set_pressed(false); + } +} + void BaseButton::_gui_input(InputEvent p_event) { @@ -69,6 +82,8 @@ void BaseButton::_gui_input(InputEvent p_event) { } emit_signal("pressed"); + _unpress_group(); + } else { @@ -79,6 +94,8 @@ void BaseButton::_gui_input(InputEvent p_event) { get_script_instance()->call(SceneStringNames::get_singleton()->_pressed,NULL,0,ce); } emit_signal("pressed"); + _unpress_group(); + toggled(status.pressed); emit_signal("toggled",status.pressed); @@ -139,6 +156,9 @@ void BaseButton::_gui_input(InputEvent p_event) { } + _unpress_group(); + + } status.press_attempt=false; @@ -212,6 +232,9 @@ void BaseButton::_gui_input(InputEvent p_event) { } emit_signal("toggled",status.pressed); } + + _unpress_group(); + } accept_event(); @@ -266,24 +289,12 @@ void BaseButton::_notification(int p_what) { if (p_what==NOTIFICATION_ENTER_TREE) { - CanvasItem *ci=this; - while(ci) { - - ButtonGroup *bg = ci->cast_to<ButtonGroup>(); - if (bg) { - group=bg; - group->_add_button(this); - } - - ci=ci->get_parent_item(); - } } if (p_what==NOTIFICATION_EXIT_TREE) { - if (group) - group->_remove_button(this); + } if (p_what==NOTIFICATION_VISIBILITY_CHANGED && !is_visible()) { @@ -306,8 +317,9 @@ void BaseButton::pressed() { void BaseButton::toggled(bool p_pressed) { - if (get_script_instance()) + if (get_script_instance()) { get_script_instance()->call("toggled",p_pressed); + } } @@ -336,6 +348,11 @@ void BaseButton::set_pressed(bool p_pressed) { return; _change_notify("pressed"); status.pressed=p_pressed; + + if (p_pressed) { + _unpress_group(); + + } update(); } @@ -463,6 +480,29 @@ String BaseButton::get_tooltip(const Point2& p_pos) const { return tooltip; } + +void BaseButton::set_button_group(const Ref<ButtonGroup>& p_group) { + + if (button_group.is_valid()) { + button_group->buttons.erase(this); + } + + button_group=p_group; + + if (button_group.is_valid()) { + button_group->buttons.insert(this); + } + + update(); //checkbox changes to radio if set a buttongroup + +} + +Ref<ButtonGroup> BaseButton::get_button_group() const { + + return button_group; +} + + void BaseButton::_bind_methods() { ClassDB::bind_method(_MD("_gui_input"),&BaseButton::_gui_input); @@ -479,9 +519,13 @@ void BaseButton::_bind_methods() { ClassDB::bind_method(_MD("get_draw_mode"),&BaseButton::get_draw_mode); ClassDB::bind_method(_MD("set_enabled_focus_mode","mode"),&BaseButton::set_enabled_focus_mode); ClassDB::bind_method(_MD("get_enabled_focus_mode"),&BaseButton::get_enabled_focus_mode); + ClassDB::bind_method(_MD("set_shortcut","shortcut"),&BaseButton::set_shortcut); ClassDB::bind_method(_MD("get_shortcut"),&BaseButton::get_shortcut); + ClassDB::bind_method(_MD("set_button_group","button_group"),&BaseButton::set_button_group); + ClassDB::bind_method(_MD("get_button_group"),&BaseButton::get_button_group); + BIND_VMETHOD(MethodInfo("_pressed")); BIND_VMETHOD(MethodInfo("_toggled",PropertyInfo(Variant::BOOL,"pressed"))); @@ -495,6 +539,7 @@ void BaseButton::_bind_methods() { ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "click_on_press"), _SCS("set_click_on_press"), _SCS("get_click_on_press")); ADD_PROPERTY( PropertyInfo( Variant::INT,"enabled_focus_mode", PROPERTY_HINT_ENUM, "None,Click,All" ), _SCS("set_enabled_focus_mode"), _SCS("get_enabled_focus_mode") ); ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "shortcut",PROPERTY_HINT_RESOURCE_TYPE,"ShortCut"), _SCS("set_shortcut"), _SCS("get_shortcut")); + ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "group",PROPERTY_HINT_RESOURCE_TYPE,"ButtonGroup"), _SCS("set_button_group"), _SCS("get_button_group")); BIND_CONSTANT( DRAW_NORMAL ); @@ -516,7 +561,11 @@ BaseButton::BaseButton() { status.pressing_button=0; set_focus_mode( FOCUS_ALL ); enabled_focus_mode = FOCUS_ALL; - group=NULL; + + + if (button_group.is_valid()) { + button_group->buttons.erase(this); + } } @@ -525,4 +574,30 @@ BaseButton::~BaseButton() { } +void ButtonGroup::get_buttons(List<BaseButton*> *r_buttons) { + for (Set<BaseButton*>::Element *E=buttons.front();E;E=E->next()) { + r_buttons->push_back(E->get()); + } +} + +BaseButton* ButtonGroup::get_pressed_button() { + + for (Set<BaseButton*>::Element *E=buttons.front();E;E=E->next()) { + if (E->get()->is_pressed()) + return E->get(); + } + + return NULL; + +} + +void ButtonGroup::_bind_methods() { + + ClassDB::bind_method(_MD("get_pressed_button:BaseButton"),&ButtonGroup::get_pressed_button); +} + +ButtonGroup::ButtonGroup() { + + set_local_to_scene(true); +} diff --git a/scene/gui/base_button.h b/scene/gui/base_button.h index ed39b34aa8..898c19e811 100644 --- a/scene/gui/base_button.h +++ b/scene/gui/base_button.h @@ -59,9 +59,11 @@ class BaseButton : public Control { } status; - ButtonGroup *group; + Ref<ButtonGroup> button_group; + void _unpress_group(); + protected: @@ -109,11 +111,29 @@ public: virtual String get_tooltip(const Point2& p_pos) const; + void set_button_group(const Ref<ButtonGroup>& p_group); + Ref<ButtonGroup> get_button_group() const; + BaseButton(); ~BaseButton(); }; -VARIANT_ENUM_CAST( BaseButton::DrawMode ); +VARIANT_ENUM_CAST( BaseButton::DrawMode ) + + +class ButtonGroup : public Resource { + + GDCLASS(ButtonGroup,Resource) +friend class BaseButton; + Set<BaseButton*> buttons; +protected: + static void _bind_methods(); +public: + + BaseButton* get_pressed_button(); + void get_buttons(List<BaseButton*> *r_buttons); + ButtonGroup(); +}; #endif diff --git a/scene/gui/button.h b/scene/gui/button.h index 710581a556..2fd3a0cace 100644 --- a/scene/gui/button.h +++ b/scene/gui/button.h @@ -33,6 +33,9 @@ /** @author Juan Linietsky <reduzio@gmail.com> */ + + + class Button : public BaseButton { GDCLASS( Button, BaseButton ); diff --git a/scene/gui/button_group.cpp b/scene/gui/button_group.cpp index 8586296ba6..01a3f633c3 100644 --- a/scene/gui/button_group.cpp +++ b/scene/gui/button_group.cpp @@ -27,6 +27,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "button_group.h" + +#if 0 #include "base_button.h" void ButtonGroup::_add_button(BaseButton *p_button) { @@ -162,3 +164,4 @@ void ButtonGroup::_bind_methods() { ButtonGroup::ButtonGroup() : BoxContainer(true) { } +#endif diff --git a/scene/gui/button_group.h b/scene/gui/button_group.h index e3380295e7..38acd06984 100644 --- a/scene/gui/button_group.h +++ b/scene/gui/button_group.h @@ -31,7 +31,7 @@ #include "scene/gui/box_container.h" - +#if 0 class BaseButton; class ButtonGroup : public BoxContainer { @@ -63,4 +63,5 @@ public: ButtonGroup(); }; +#endif #endif // BUTTON_GROUP_H diff --git a/scene/gui/check_box.cpp b/scene/gui/check_box.cpp index 901386eb45..c9803bc654 100644 --- a/scene/gui/check_box.cpp +++ b/scene/gui/check_box.cpp @@ -56,14 +56,8 @@ void CheckBox::_notification(int p_what) { bool CheckBox::is_radio() { - Node* parent = this; - do { - parent = parent->get_parent(); - if (parent->cast_to<ButtonGroup>()) - break; - } while (parent); - return (parent != 0); + return get_button_group().is_valid(); } CheckBox::CheckBox(const String &p_text): diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 8d8e41812b..02d5d5ce30 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -51,6 +51,49 @@ #include "globals.h" +void ViewportTexture::setup_local_to_scene() { + + if (vp) { + vp->viewport_textures.erase(this); + } + + vp=NULL; + + Node *local_scene = get_local_scene(); + if (!local_scene) { + return; + } + + Node *vpn = local_scene->get_node(path); + ERR_EXPLAIN("ViewportTexture: Path to node is invalid"); + ERR_FAIL_COND(!vpn); + + vp = vpn->cast_to<Viewport>(); + + ERR_EXPLAIN("ViewportTexture: Path to node does not point to a viewport"); + ERR_FAIL_COND(!vp); + + vp->viewport_textures.insert(this); +} + +void ViewportTexture::set_viewport_path_in_scene(const NodePath& p_path) { + + if (path==p_path) + return; + + path=p_path; + + if (get_local_scene()) { + setup_local_to_scene(); + } + +} + +NodePath ViewportTexture::get_viewport_path_in_scene() const { + + return path; +} + int ViewportTexture::get_width() const { ERR_FAIL_COND_V(!vp,0); @@ -82,24 +125,40 @@ void ViewportTexture::set_flags(uint32_t p_flags){ if (!vp) return; - if (p_flags&FLAG_FILTER) - flags=FLAG_FILTER; - else - flags=0; - - VS::get_singleton()->texture_set_flags(vp->texture_rid,flags); + vp->texture_flags=p_flags; + VS::get_singleton()->texture_set_flags(vp->texture_rid,p_flags); } uint32_t ViewportTexture::get_flags() const{ - return flags; + if (!vp) + return 0; + + return vp->texture_flags; +} + +void ViewportTexture::_bind_methods() { + + ClassDB::bind_method(_MD("set_viewport_path_in_scene","path"),&ViewportTexture::set_viewport_path_in_scene); + ClassDB::bind_method(_MD("get_viewport_path_in_scene"),&ViewportTexture::get_viewport_path_in_scene); + + ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH,"viewport_path"),_SCS("set_viewport_path_in_scene"),_SCS("get_viewport_path_in_scene")); + +} + +ViewportTexture::ViewportTexture(){ + + vp=NULL; + set_local_to_scene(true); + } -ViewportTexture::ViewportTexture(Viewport *p_vp){ +ViewportTexture::~ViewportTexture(){ - vp=p_vp; - flags=0; + if (vp) { + vp->viewport_textures.erase(this); + } } ///////////////////////////////////// @@ -1256,7 +1315,11 @@ Image Viewport::get_screen_capture() const { Ref<ViewportTexture> Viewport::get_texture() const { - return texture; + Ref<ViewportTexture> vt; + vt.instance(); + vt->vp=const_cast<Viewport*>(this); + + return vt; } void Viewport::set_vflip(bool p_enable) { @@ -2788,6 +2851,7 @@ Viewport::Viewport() { viewport = VisualServer::get_singleton()->viewport_create(); texture_rid=VisualServer::get_singleton()->viewport_get_texture(viewport); + texture_flags=0; internal_listener = SpatialSoundServer::get_singleton()->listener_create(); audio_listener=false; internal_listener_2d = SpatialSound2DServer::get_singleton()->listener_create(); @@ -2805,7 +2869,6 @@ Viewport::Viewport() { clear_on_new_frame=true; //clear=true; update_mode=UPDATE_WHEN_VISIBLE; - texture = Ref<ViewportTexture>( memnew( ViewportTexture(this) ) ); physics_object_picking=false; physics_object_capture=0; @@ -2853,11 +2916,14 @@ Viewport::Viewport() { Viewport::~Viewport() { + //erase itself from viewport textures + for(Set<ViewportTexture*>::Element *E=viewport_textures.front();E;E=E->next()) { + E->get()->vp=NULL; + } VisualServer::get_singleton()->free( viewport ); SpatialSoundServer::get_singleton()->free(internal_listener); SpatialSound2DServer::get_singleton()->free(internal_listener_2d); - if (texture.is_valid()) - texture->vp=NULL; //so if used, will crash + } diff --git a/scene/main/viewport.h b/scene/main/viewport.h index 702c9f792f..5feeae6237 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -52,13 +52,20 @@ class ViewportTexture : public Texture { GDCLASS( ViewportTexture, Texture ); - int flags; -friend class Viewport; - Viewport *vp; + NodePath path; +friend class Viewport; + Viewport* vp; +protected: + static void _bind_methods(); public: + void set_viewport_path_in_scene(const NodePath& p_path); + NodePath get_viewport_path_in_scene() const; + + virtual void setup_local_to_scene(); + virtual int get_width() const; virtual int get_height() const; @@ -70,7 +77,8 @@ public: virtual void set_flags(uint32_t p_flags); virtual uint32_t get_flags() const; - ViewportTexture(Viewport *p_vp=NULL); + ViewportTexture(); + ~ViewportTexture(); }; @@ -191,7 +199,7 @@ friend class ViewportTexture; bool disable_3d; UpdateMode update_mode; RID texture_rid; - Ref<ViewportTexture> texture; + uint32_t texture_flags; int shadow_atlas_size; ShadowAtlasQuadrantSubdiv shadow_atlas_quadrant_subdiv[4]; @@ -199,6 +207,8 @@ friend class ViewportTexture; MSAA msaa; bool hdr; + Set<ViewportTexture*> viewport_textures; + struct GUI { // info used when this is a window diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp index c3b98af811..b0161f6898 100644 --- a/scene/resources/packed_scene.cpp +++ b/scene/resources/packed_scene.cpp @@ -42,7 +42,7 @@ bool SceneState::can_instance() const { } -Node *SceneState::instance(bool p_gen_edit_state) const { +Node *SceneState::instance(GenEditState p_edit_state) const { // nodes where instancing failed (because something is missing) List<Node*> stray_instances; @@ -76,7 +76,9 @@ Node *SceneState::instance(bool p_gen_edit_state) const { Node **ret_nodes=(Node**)alloca( sizeof(Node*)*nc ); - bool gen_node_path_cache=p_gen_edit_state && node_path_cache.empty(); + bool gen_node_path_cache=p_edit_state!=GEN_EDIT_STATE_DISABLED && node_path_cache.empty(); + + Map<Ref<Resource>,Ref<Resource> > resources_local_to_scene; for(int i=0;i<nc;i++) { @@ -105,9 +107,9 @@ Node *SceneState::instance(bool p_gen_edit_state) const { //print_line("scene inherit"); Ref<PackedScene> sdata = props[ base_scene_idx ]; ERR_FAIL_COND_V( !sdata.is_valid(), NULL); - node = sdata->instance(p_gen_edit_state); + node = sdata->instance(p_edit_state==GEN_EDIT_STATE_DISABLED ? PackedScene::GEN_EDIT_STATE_DISABLED : PackedScene::GEN_EDIT_STATE_INSTANCE); //only main gets main edit state ERR_FAIL_COND_V(!node,NULL); - if (p_gen_edit_state) { + if (p_edit_state!=GEN_EDIT_STATE_DISABLED) { node->set_scene_inherited_state(sdata->get_state()); } @@ -121,7 +123,7 @@ Node *SceneState::instance(bool p_gen_edit_state) const { Ref<PackedScene> sdata = ResourceLoader::load(path,"PackedScene"); ERR_FAIL_COND_V( !sdata.is_valid(), NULL); - node = sdata->instance(p_gen_edit_state); + node = sdata->instance(p_edit_state==GEN_EDIT_STATE_DISABLED ? PackedScene::GEN_EDIT_STATE_DISABLED : PackedScene::GEN_EDIT_STATE_INSTANCE); ERR_FAIL_COND_V(!node,NULL); } else { InstancePlaceholder *ip = memnew( InstancePlaceholder ); @@ -132,7 +134,7 @@ Node *SceneState::instance(bool p_gen_edit_state) const { } else { Ref<PackedScene> sdata = props[ n.instance&FLAG_MASK ]; ERR_FAIL_COND_V( !sdata.is_valid(), NULL); - node = sdata->instance(p_gen_edit_state); + node = sdata->instance(p_edit_state==GEN_EDIT_STATE_DISABLED ? PackedScene::GEN_EDIT_STATE_DISABLED : PackedScene::GEN_EDIT_STATE_INSTANCE); ERR_FAIL_COND_V(!node,NULL); } @@ -166,8 +168,8 @@ Node *SceneState::instance(bool p_gen_edit_state) const { } else if (ret_nodes[n.parent]->cast_to<Node2D>()) { obj = memnew( Node2D ); } - } + if (!obj) { obj = memnew( Node ); } @@ -212,7 +214,43 @@ Node *SceneState::instance(bool p_gen_edit_state) const { } } else { - node->set(snames[ nprops[j].name ],props[ nprops[j].value ],&valid); + Variant value = props[ nprops[j].value ]; + + if (value.get_type()==Variant::OBJECT) { + //handle resources that are local to scene by duplicating them if needed + Ref<Resource> res = value; + if (res.is_valid()) { + if (res->is_local_to_scene()) { + + Map<Ref<Resource>,Ref<Resource> >::Element *E=resources_local_to_scene.find(res); + + if (E) { + value=E->get(); + } else { + + Node *base = i==0?node:ret_nodes[0]; + + if (p_edit_state==GEN_EDIT_STATE_MAIN) { + + res->local_scene=base; + resources_local_to_scene[res]=res; + + } else { + Node *base = i==0?node:ret_nodes[0]; + Ref<Resource> local_dupe = res->duplicate_for_local_scene(base,resources_local_to_scene); + resources_local_to_scene[res]=local_dupe; + res=local_dupe; + value=local_dupe; + } + + res->setup_local_to_scene(); + + } + //must make a copy, because this res is local to scene + } + } + } + node->set(snames[ nprops[j].name ],value,&valid); } } } @@ -1693,6 +1731,10 @@ void SceneState::_bind_methods() { ClassDB::bind_method(_MD("get_connection_method","idx"),&SceneState::get_connection_method); ClassDB::bind_method(_MD("get_connection_flags","idx"),&SceneState::get_connection_flags); ClassDB::bind_method(_MD("get_connection_binds","idx"),&SceneState::get_connection_binds); + + BIND_CONSTANT( GEN_EDIT_STATE_DISABLED ); + BIND_CONSTANT( GEN_EDIT_STATE_INSTANCE ); + BIND_CONSTANT( GEN_EDIT_STATE_MAIN ); } SceneState::SceneState() { @@ -1732,7 +1774,7 @@ bool PackedScene::can_instance() const { return state->can_instance(); } -Node *PackedScene::instance(bool p_gen_edit_state) const { +Node *PackedScene::instance(GenEditState p_edit_state) const { #ifndef TOOLS_ENABLED if (p_gen_edit_state) { @@ -1741,11 +1783,11 @@ Node *PackedScene::instance(bool p_gen_edit_state) const { } #endif - Node *s = state->instance(p_gen_edit_state); + Node *s = state->instance((SceneState::GenEditState)p_edit_state); if (!s) return NULL; - if (p_gen_edit_state) { + if (p_edit_state!=GEN_EDIT_STATE_DISABLED) { s->set_scene_instance_state(state); } @@ -1792,7 +1834,7 @@ void PackedScene::set_path(const String& p_path,bool p_take_over) { void PackedScene::_bind_methods() { ClassDB::bind_method(_MD("pack","path:Node"),&PackedScene::pack); - ClassDB::bind_method(_MD("instance:Node","gen_edit_state"),&PackedScene::instance,DEFVAL(false)); + ClassDB::bind_method(_MD("instance:Node","edit_state"),&PackedScene::instance,DEFVAL(false)); ClassDB::bind_method(_MD("can_instance"),&PackedScene::can_instance); ClassDB::bind_method(_MD("_set_bundled_scene"),&PackedScene::_set_bundled_scene); ClassDB::bind_method(_MD("_get_bundled_scene"),&PackedScene::_get_bundled_scene); @@ -1800,6 +1842,10 @@ void PackedScene::_bind_methods() { ADD_PROPERTY( PropertyInfo(Variant::DICTIONARY,"_bundled"),_SCS("_set_bundled_scene"),_SCS("_get_bundled_scene")); + BIND_CONSTANT( GEN_EDIT_STATE_DISABLED ); + BIND_CONSTANT( GEN_EDIT_STATE_INSTANCE ); + BIND_CONSTANT( GEN_EDIT_STATE_MAIN ); + } PackedScene::PackedScene() { diff --git a/scene/resources/packed_scene.h b/scene/resources/packed_scene.h index fd4ed106df..381b356b1e 100644 --- a/scene/resources/packed_scene.h +++ b/scene/resources/packed_scene.h @@ -117,6 +117,12 @@ public: FLAG_MASK=(1<<24)-1, }; + enum GenEditState { + GEN_EDIT_STATE_DISABLED, + GEN_EDIT_STATE_INSTANCE, + GEN_EDIT_STATE_MAIN, + }; + static void set_disable_placeholders(bool p_disable); int find_node_by_path(const NodePath& p_node) const; @@ -136,7 +142,7 @@ public: void clear(); bool can_instance() const; - Node *instance(bool p_gen_edit_state=false) const; + Node *instance(GenEditState p_edit_state) const; //unbuild API @@ -187,6 +193,8 @@ public: SceneState(); }; +VARIANT_ENUM_CAST(SceneState::GenEditState) + class PackedScene : public Resource { GDCLASS(PackedScene, Resource ); @@ -203,13 +211,18 @@ protected: static void _bind_methods(); public: + enum GenEditState { + GEN_EDIT_STATE_DISABLED, + GEN_EDIT_STATE_INSTANCE, + GEN_EDIT_STATE_MAIN, + }; Error pack(Node *p_scene); void clear(); bool can_instance() const; - Node *instance(bool p_gen_edit_state=false) const; + Node *instance(GenEditState p_edit_state=GEN_EDIT_STATE_DISABLED) const; void recreate_state(); void replace_state(Ref<SceneState> p_by); @@ -225,4 +238,6 @@ public: }; +VARIANT_ENUM_CAST(PackedScene::GenEditState) + #endif // SCENE_PRELOADER_H diff --git a/tools/editor/editor_data.cpp b/tools/editor/editor_data.cpp index 11ba30f4f0..f27fe79a85 100644 --- a/tools/editor/editor_data.cpp +++ b/tools/editor/editor_data.cpp @@ -584,7 +584,7 @@ bool EditorData::check_and_update_scene(int p_idx) { Error err = pscene->pack(edited_scene[p_idx].root); ERR_FAIL_COND_V(err!=OK,false); ep.step(TTR("Updating scene.."),1); - Node *new_scene = pscene->instance(true); + Node *new_scene = pscene->instance(PackedScene::GEN_EDIT_STATE_MAIN); ERR_FAIL_COND_V(!new_scene,false); //transfer selection diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp index 5eb5f42001..2306f98349 100644 --- a/tools/editor/editor_node.cpp +++ b/tools/editor/editor_node.cpp @@ -3745,7 +3745,7 @@ Error EditorNode::load_scene(const String& p_scene, bool p_ignore_broken_deps,bo sdata->set_path(lpath,true); //take over path } - Node*new_scene=sdata->instance(true); + Node*new_scene=sdata->instance(PackedScene::GEN_EDIT_STATE_MAIN); if (!new_scene) { @@ -5365,8 +5365,15 @@ void EditorNode::_bind_methods() { } +static Node* _resource_get_edited_scene() { + + return EditorNode::get_singleton()->get_edited_scene(); +} + EditorNode::EditorNode() { + Resource::_get_local_scene_func=_resource_get_edited_scene; + VisualServer::get_singleton()->textures_keep_original(true); EditorHelp::generate_doc(); //before any editor classes are crated diff --git a/tools/editor/io_plugins/editor_texture_import_plugin.cpp b/tools/editor/io_plugins/editor_texture_import_plugin.cpp index 16bc334cce..96e49a0a7f 100644 --- a/tools/editor/io_plugins/editor_texture_import_plugin.cpp +++ b/tools/editor/io_plugins/editor_texture_import_plugin.cpp @@ -664,7 +664,7 @@ EditorTextureImportDialog::EditorTextureImportDialog(EditorTextureImportPlugin* mode_hb->add_child(vbcg); mode_hb->add_constant_override("separation",15); - ButtonGroup *bg = memnew( ButtonGroup ); + VBoxContainer *bg = memnew( VBoxContainer ); vbcg->add_margin_child("Import Mode",bg); for(int i=0;i<EditorTextureImportPlugin::MODE_MAX;i++) { diff --git a/tools/editor/plugins/canvas_item_editor_plugin.cpp b/tools/editor/plugins/canvas_item_editor_plugin.cpp index 7fecd60484..6839326886 100644 --- a/tools/editor/plugins/canvas_item_editor_plugin.cpp +++ b/tools/editor/plugins/canvas_item_editor_plugin.cpp @@ -3671,7 +3671,10 @@ void CanvasItemEditorViewport::_on_select_type(Object* selected) { } void CanvasItemEditorViewport::_on_change_type() { - CheckBox* check=btn_group->get_pressed_button()->cast_to<CheckBox>(); + if (!button_group->get_pressed_button()) + return; + + CheckBox* check=button_group->get_pressed_button()->cast_to<CheckBox>(); default_type=check->get_text(); _perform_drop_data(); selector->hide(); @@ -3798,7 +3801,7 @@ bool CanvasItemEditorViewport::_create_instance(Node* parent, String& path, cons return false; } - Node* instanced_scene=sdata->instance(true); + Node* instanced_scene=sdata->instance(PackedScene::GEN_EDIT_STATE_INSTANCE); if (!instanced_scene) { // error on instancing return false; } @@ -3899,7 +3902,7 @@ bool CanvasItemEditorViewport::can_drop_data(const Point2& p_point,const Variant String type=res->get_class(); if (type=="PackedScene") { Ref<PackedScene> sdata=ResourceLoader::load(files[i]); - Node* instanced_scene=sdata->instance(true); + Node* instanced_scene=sdata->instance(PackedScene::GEN_EDIT_STATE_INSTANCE); if (!instanced_scene) { continue; } @@ -3957,7 +3960,8 @@ void CanvasItemEditorViewport::drop_data(const Point2& p_point,const Variant& p_ if (is_alt) { List<BaseButton*> btn_list; - btn_group->get_button_list(&btn_list); + button_group->get_buttons(&btn_list); + for (int i=0;i<btn_list.size();i++) { CheckBox* check=btn_list[i]->cast_to<CheckBox>(); check->set_pressed(check->get_text()==default_type); @@ -4016,7 +4020,9 @@ CanvasItemEditorViewport::CanvasItemEditorViewport(EditorNode *p_node, CanvasIte selector_label->set_custom_minimum_size(Size2(0,30)*EDSCALE); vbc->add_child(selector_label); - btn_group=memnew( ButtonGroup ); + button_group.instance(); + + btn_group=memnew( VBoxContainer ); btn_group->set_h_size_flags(0); btn_group->connect("button_selected", this, "_on_select_type"); @@ -4024,6 +4030,7 @@ CanvasItemEditorViewport::CanvasItemEditorViewport(EditorNode *p_node, CanvasIte CheckBox* check=memnew(CheckBox); check->set_text(types[i]); btn_group->add_child(check); + check->set_button_group(button_group); } vbc->add_child(btn_group); diff --git a/tools/editor/plugins/canvas_item_editor_plugin.h b/tools/editor/plugins/canvas_item_editor_plugin.h index f74df9d6e0..ee36554477 100644 --- a/tools/editor/plugins/canvas_item_editor_plugin.h +++ b/tools/editor/plugins/canvas_item_editor_plugin.h @@ -473,7 +473,8 @@ class CanvasItemEditorViewport : public VBoxContainer { Label* selector_label; Label* label; Label* label_desc; - ButtonGroup* btn_group; + VBoxContainer* btn_group; + Ref<ButtonGroup> button_group; void _on_mouse_exit(); void _on_select_type(Object* selected); diff --git a/tools/editor/plugins/theme_editor_plugin.cpp b/tools/editor/plugins/theme_editor_plugin.cpp index ad0968178b..a700ddce7a 100644 --- a/tools/editor/plugins/theme_editor_plugin.cpp +++ b/tools/editor/plugins/theme_editor_plugin.cpp @@ -711,7 +711,7 @@ ThemeEditor::ThemeEditor() { first_vb->add_child(cbx ); - ButtonGroup *bg = memnew( ButtonGroup ); + VBoxContainer *bg = memnew( VBoxContainer ); bg->set_v_size_flags(SIZE_EXPAND_FILL); VBoxContainer *gbvb = memnew( VBoxContainer ); gbvb->set_v_size_flags(SIZE_EXPAND_FILL); diff --git a/tools/editor/property_editor.cpp b/tools/editor/property_editor.cpp index 1a2749cd95..4c69412b3b 100644 --- a/tools/editor/property_editor.cpp +++ b/tools/editor/property_editor.cpp @@ -226,8 +226,19 @@ void CustomPropertyEditor::_menu_option(int p_which) { ERR_FAIL_COND( inheritors_array.empty() ); + + String intype=inheritors_array[p_which-TYPE_BASE_ID]; + if (intype=="ViewportTexture") { + + scene_tree->set_title(TTR("Pick a Viewport")); + scene_tree->popup_centered_ratio(); + picking_viewport=true; + return; + + } + Object *obj = ClassDB::instance(intype); ERR_BREAK( !obj ); Resource *res=obj->cast_to<Resource>(); @@ -1126,6 +1137,22 @@ void CustomPropertyEditor::_color_changed(const Color& p_color) { void CustomPropertyEditor::_node_path_selected(NodePath p_path) { + if (picking_viewport) { + + Node* to_node=get_node(p_path); + if (!to_node->cast_to<Viewport>()) { + EditorNode::get_singleton()->show_warning("Selected node is not a Viewport!"); + return; + } + + Ref<ViewportTexture> vt; + vt.instance(); + vt->set_viewport_path_in_scene(get_tree()->get_edited_scene_root()->get_path_to(to_node)); + vt->setup_local_to_scene(); + v=vt; + emit_signal("variant_changed"); + return; + } if (hint==PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE && hint_text!=String()) { @@ -1262,7 +1289,8 @@ void CustomPropertyEditor::_action_pressed(int p_which) { if (p_which==0) { - + picking_viewport=false; + scene_tree->set_title(TTR("Pick a Node")); scene_tree->popup_centered_ratio(); } else if (p_which==1) { @@ -3807,6 +3835,8 @@ void PropertyEditor::_edit_set(const String& p_name, const Variant& p_value) { undo_redo->create_action(TTR("Set")+" "+p_name,UndoRedo::MERGE_ENDS); undo_redo->add_do_property(obj,p_name,p_value); undo_redo->add_undo_property(obj,p_name,obj->get(p_name)); + + undo_redo->add_do_method(this,"_changed_callback",obj,p_name); undo_redo->add_undo_method(this,"_changed_callback",obj,p_name); @@ -3816,6 +3846,17 @@ void PropertyEditor::_edit_set(const String& p_name, const Variant& p_value) { undo_redo->add_do_method(r,"set_edited",true); undo_redo->add_undo_method(r,"set_edited",false); } + + if (String(p_name)=="resource_local_to_scene") { + bool prev = obj->get(p_name); + bool next = p_value; + if (next) { + undo_redo->add_do_method(this,"setup_local_to_scene"); + } + if (prev) { + undo_redo->add_undo_method(this,"setup_local_to_scene"); + } + } } undo_redo->add_do_method(this,"emit_signal",_prop_edited,p_name); undo_redo->add_undo_method(this,"emit_signal",_prop_edited,p_name); diff --git a/tools/editor/property_editor.h b/tools/editor/property_editor.h index df180cab18..af7d01f935 100644 --- a/tools/editor/property_editor.h +++ b/tools/editor/property_editor.h @@ -99,6 +99,7 @@ class CustomPropertyEditor : public Popup { ColorPicker *color_picker; TextEdit *text_edit; bool read_only; + bool picking_viewport; CheckBox *checks20[20]; SpinBox *spinbox; HSlider *slider; diff --git a/tools/editor/scene_tree_dock.cpp b/tools/editor/scene_tree_dock.cpp index 70195862de..c171c49c7b 100644 --- a/tools/editor/scene_tree_dock.cpp +++ b/tools/editor/scene_tree_dock.cpp @@ -174,7 +174,7 @@ void SceneTreeDock::_perform_instance_scenes(const Vector<String>& p_files,Node* } - Node*instanced_scene=sdata->instance(true); + Node*instanced_scene=sdata->instance(PackedScene::GEN_EDIT_STATE_INSTANCE); if (!instanced_scene) { current_option=-1; //accept->get_cancel()->hide(); @@ -250,7 +250,7 @@ void SceneTreeDock::_replace_with_branch_scene(const String& p_file,Node* base) return; } - Node *instanced_scene=sdata->instance(true); + Node *instanced_scene=sdata->instance(PackedScene::GEN_EDIT_STATE_INSTANCE); if (!instanced_scene) { accept->get_ok()->set_text(TTR("Ugh")); accept->set_text(vformat(TTR("Error instancing scene from %s"),p_file)); @@ -744,7 +744,7 @@ Node *SceneTreeDock::_duplicate(Node *p_node, Map<Node*,Node*> &duplimap) { Ref<PackedScene> sd = ResourceLoader::load( p_node->get_filename() ); ERR_FAIL_COND_V(!sd.is_valid(),NULL); - node = sd->instance(true); + node = sd->instance(PackedScene::GEN_EDIT_STATE_INSTANCE); ERR_FAIL_COND_V(!node,NULL); //node->generate_instance_state(); } else { |