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!
This commit is contained in:
Juan Linietsky 2017-01-10 01:04:31 -03:00
parent 68c008ca8d
commit a503f8aadc
21 changed files with 481 additions and 95 deletions

View file

@ -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;
}

View file

@ -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

View file

@ -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);
}

View file

@ -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

View file

@ -33,6 +33,9 @@
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
class Button : public BaseButton {
GDCLASS( Button, BaseButton );

View file

@ -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

View file

@ -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

View file

@ -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):

View file

@ -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;
}
ViewportTexture::ViewportTexture(Viewport *p_vp){
void ViewportTexture::_bind_methods() {
vp=p_vp;
flags=0;
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(){
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
}

View file

@ -52,13 +52,20 @@ class ViewportTexture : public Texture {
GDCLASS( ViewportTexture, Texture );
int flags;
NodePath path;
friend class Viewport;
Viewport *vp;
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

View file

@ -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() {

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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++) {

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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;

View file

@ -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 {