aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJuan Linietsky2017-01-10 01:04:31 -0300
committerJuan Linietsky2017-01-10 01:07:03 -0300
commita503f8aadcb8cbc85bde589fb25ea06e599b367b (patch)
tree070ebbf0dd6af2d43c5519f5e32045b3512f0e9e
parent68c008ca8d87a1f72fcf17467ee43714954e9ce4 (diff)
downloadgodot-a503f8aadcb8cbc85bde589fb25ea06e599b367b.tar.gz
godot-a503f8aadcb8cbc85bde589fb25ea06e599b367b.tar.zst
godot-a503f8aadcb8cbc85bde589fb25ea06e599b367b.zip
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.cpp125
-rw-r--r--core/resource.h15
-rw-r--r--scene/gui/base_button.cpp107
-rw-r--r--scene/gui/base_button.h24
-rw-r--r--scene/gui/button.h3
-rw-r--r--scene/gui/button_group.cpp3
-rw-r--r--scene/gui/button_group.h3
-rw-r--r--scene/gui/check_box.cpp8
-rw-r--r--scene/main/viewport.cpp94
-rw-r--r--scene/main/viewport.h20
-rw-r--r--scene/resources/packed_scene.cpp70
-rw-r--r--scene/resources/packed_scene.h19
-rw-r--r--tools/editor/editor_data.cpp2
-rw-r--r--tools/editor/editor_node.cpp9
-rw-r--r--tools/editor/io_plugins/editor_texture_import_plugin.cpp2
-rw-r--r--tools/editor/plugins/canvas_item_editor_plugin.cpp17
-rw-r--r--tools/editor/plugins/canvas_item_editor_plugin.h3
-rw-r--r--tools/editor/plugins/theme_editor_plugin.cpp2
-rw-r--r--tools/editor/property_editor.cpp43
-rw-r--r--tools/editor/property_editor.h1
-rw-r--r--tools/editor/scene_tree_dock.cpp6
21 files changed, 481 insertions, 95 deletions
diff --git a/core/resource.cpp b/core/resource.cpp
index 7bcdd8889..9545d8c3d 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 40b6dd78a..8b73bcdc5 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 05646320c..45c491cd7 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 ed39b34aa..898c19e81 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 710581a55..2fd3a0cac 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 8586296ba..01a3f633c 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 e3380295e..38acd0698 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 901386eb4..c9803bc65 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 8d8e41812..02d5d5ce3 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 702c9f792..5feeae623 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 c3b98af81..b0161f689 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 fd4ed106d..381b356b1 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 11ba30f4f..f27fe79a8 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 5eb5f4200..2306f9834 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 16bc334cc..96e49a0a7 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 7fecd6048..683932688 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 f74df9d6e..ee3655447 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 ad0968178..a700ddce7 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 1a2749cd9..4c69412b3 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 df180cab1..af7d01f93 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 70195862d..c171c49c7 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 {