diff options
author | Juan Linietsky <reduzio@gmail.com> | 2017-01-10 01:04:31 -0300 |
---|---|---|
committer | Juan Linietsky <reduzio@gmail.com> | 2017-01-10 01:07:03 -0300 |
commit | a503f8aadcb8cbc85bde589fb25ea06e599b367b (patch) | |
tree | 070ebbf0dd6af2d43c5519f5e32045b3512f0e9e | |
parent | 68c008ca8d87a1f72fcf17467ee43714954e9ce4 (diff) |
Groundbreaking!! Godot resources can now be flagged to be local to the scene being edited!
This means that each time this scene is instanced, the resource will be unique!
As such, thanks to this, the following features were implemented:
-ButtonGroup is no longer a control, it's now a resource local to the scene
-ViewportTexture can be created from the editor and set to any object, making ViewportSprite and other kind of nodes obsolete!
-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 { |