summaryrefslogtreecommitdiff
path: root/scene
diff options
context:
space:
mode:
authorJuan Linietsky <reduzio@gmail.com>2014-04-10 00:18:27 -0300
committerJuan Linietsky <reduzio@gmail.com>2014-04-10 00:18:27 -0300
commit7ea3e8267afaf626256c84a9a3dc61e2954fc6a2 (patch)
tree0aa7588918b814d1781fc94e8b518c7095a0bab7 /scene
parentb4969373b3475799d6b24cdffeda4659c37f0b8a (diff)
-Fixed a few bugs in Viewport
-Made a few demos using Viewport to show it's true power! -Fixed some start-up error messages.
Diffstat (limited to 'scene')
-rw-r--r--scene/2d/canvas_item.cpp35
-rw-r--r--scene/2d/canvas_item.h4
-rw-r--r--scene/2d/sprite.cpp201
-rw-r--r--scene/2d/sprite.h40
-rw-r--r--scene/3d/quad.h1
-rw-r--r--scene/gui/control.cpp4
-rw-r--r--scene/gui/file_dialog.cpp54
-rw-r--r--scene/gui/file_dialog.h1
-rw-r--r--scene/gui/menu_button.cpp2
-rw-r--r--scene/main/node.cpp67
-rw-r--r--scene/main/node.h9
-rw-r--r--scene/main/scene_main_loop.cpp19
-rw-r--r--scene/main/scene_main_loop.h2
-rw-r--r--scene/main/viewport.cpp137
-rw-r--r--scene/main/viewport.h19
-rw-r--r--scene/register_scene_types.cpp1
-rw-r--r--scene/resources/default_theme/default_theme.cpp2
17 files changed, 552 insertions, 46 deletions
diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp
index 2e10ae2edb..8eb5c9dfc8 100644
--- a/scene/2d/canvas_item.cpp
+++ b/scene/2d/canvas_item.cpp
@@ -255,7 +255,7 @@ void CanvasItem::_enter_canvas() {
if ((!get_parent() || !get_parent()->cast_to<CanvasItem>()) || toplevel) {
Node *n = this;
- viewport=NULL;
+ Viewport *viewport=NULL;
canvas_layer=NULL;
while(n) {
@@ -288,15 +288,10 @@ void CanvasItem::_enter_canvas() {
} else {
CanvasItem *parent = get_parent_item();
- viewport=parent->viewport;
VisualServer::get_singleton()->canvas_item_set_parent(canvas_item,parent->get_canvas_item());
parent->_queue_sort_children();
}
- if (!viewport) {
-
- print_line("no viewport wtf!");
- }
pending_update=false;
update();
@@ -308,7 +303,6 @@ void CanvasItem::_exit_canvas() {
notification(NOTIFICATION_EXIT_CANVAS,true); //reverse the notification
VisualServer::get_singleton()->canvas_item_set_parent(canvas_item,RID());
- viewport=NULL;
canvas_layer=NULL;
group="";
@@ -655,7 +649,7 @@ void CanvasItem::_notify_transform(CanvasItem *p_node) {
Rect2 CanvasItem::get_viewport_rect() const {
ERR_FAIL_COND_V(!is_inside_scene(),Rect2());
- return viewport->get_visible_rect();
+ return get_viewport()->get_visible_rect();
}
RID CanvasItem::get_canvas() const {
@@ -665,7 +659,7 @@ RID CanvasItem::get_canvas() const {
if (canvas_layer)
return canvas_layer->get_world_2d()->get_canvas();
else
- return viewport->find_world_2d()->get_canvas();
+ return get_viewport()->find_world_2d()->get_canvas();
}
@@ -680,11 +674,6 @@ CanvasItem *CanvasItem::get_toplevel() const {
return ci;
}
-Viewport *CanvasItem::get_viewport() const {
-
- return viewport;
-}
-
Ref<World2D> CanvasItem::get_world_2d() const {
@@ -694,8 +683,8 @@ Ref<World2D> CanvasItem::get_world_2d() const {
if (tl->canvas_layer) {
return tl->canvas_layer->get_world_2d();
- } else if (tl->viewport) {
- return tl->viewport->find_world_2d();
+ } else if (tl->get_viewport()) {
+ return tl->get_viewport()->find_world_2d();
} else {
return Ref<World2D>();
}
@@ -705,7 +694,7 @@ Ref<World2D> CanvasItem::get_world_2d() const {
RID CanvasItem::get_viewport_rid() const {
ERR_FAIL_COND_V(!is_inside_scene(),RID());
- return viewport->get_viewport();
+ return get_viewport()->get_viewport();
}
void CanvasItem::set_block_transform_notify(bool p_enable) {
@@ -795,7 +784,7 @@ void CanvasItem::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_viewport_rect"),&CanvasItem::get_viewport_rect);
ObjectTypeDB::bind_method(_MD("get_canvas"),&CanvasItem::get_canvas);
ObjectTypeDB::bind_method(_MD("get_world_2d"),&CanvasItem::get_world_2d);
- ObjectTypeDB::bind_method(_MD("get_viewport"),&CanvasItem::get_viewport);
+ //ObjectTypeDB::bind_method(_MD("get_viewport"),&CanvasItem::get_viewport);
BIND_VMETHOD(MethodInfo("_draw"));
@@ -838,14 +827,14 @@ Matrix32 CanvasItem::get_viewport_transform() const {
if (canvas_layer) {
- if (viewport) {
- return viewport->get_final_transform() * canvas_layer->get_transform();
+ if (get_viewport()) {
+ return get_viewport()->get_final_transform() * canvas_layer->get_transform();
} else {
return canvas_layer->get_transform();
}
- } else if (viewport) {
- return viewport->get_final_transform() * viewport->get_canvas_transform();
+ } else if (get_viewport()) {
+ return get_viewport()->get_final_transform() * get_viewport()->get_canvas_transform();
}
return Matrix32();
@@ -868,7 +857,7 @@ CanvasItem::CanvasItem() : xform_change(this) {
drawing=false;
behind=false;
block_transform_notify=false;
- viewport=NULL;
+// viewport=NULL;
canvas_layer=NULL;
global_invalid=true;
diff --git a/scene/2d/canvas_item.h b/scene/2d/canvas_item.h
index 5489e105d9..397b206677 100644
--- a/scene/2d/canvas_item.h
+++ b/scene/2d/canvas_item.h
@@ -59,7 +59,7 @@ private:
RID canvas_item;
String group;
- Viewport *viewport;
+
CanvasLayer *canvas_layer;
float opacity;
@@ -200,7 +200,7 @@ public:
RID get_viewport_rid() const;
RID get_canvas() const;
Ref<World2D> get_world_2d() const;
- Viewport *get_viewport() const;
+
CanvasItem();
diff --git a/scene/2d/sprite.cpp b/scene/2d/sprite.cpp
index ad9a76ee35..7d033ed87f 100644
--- a/scene/2d/sprite.cpp
+++ b/scene/2d/sprite.cpp
@@ -29,6 +29,8 @@
#include "sprite.h"
#include "core/core_string_names.h"
#include "scene/scene_string_names.h"
+#include "scene/main/viewport.h"
+
void Sprite::edit_set_pivot(const Point2& p_pivot) {
set_offset(p_pivot);
@@ -335,3 +337,202 @@ Sprite::Sprite() {
}
+
+
+
+
+//////////////////////////// VPSPRITE
+///
+///
+///
+
+
+void ViewportSprite::edit_set_pivot(const Point2& p_pivot) {
+
+ set_offset(p_pivot);
+}
+
+Point2 ViewportSprite::edit_get_pivot() const {
+
+ return get_offset();
+}
+bool ViewportSprite::edit_has_pivot() const {
+
+ return true;
+}
+
+void ViewportSprite::_notification(int p_what) {
+
+ switch(p_what) {
+
+ case NOTIFICATION_ENTER_SCENE: {
+
+ if (!viewport_path.is_empty()) {
+
+ Node *n = get_node(viewport_path);
+ ERR_FAIL_COND(!n);
+ Viewport *vp=n->cast_to<Viewport>();
+ ERR_FAIL_COND(!vp);
+
+ Ref<RenderTargetTexture> rtt = vp->get_render_target_texture();
+ texture=rtt;
+ texture->connect("changed",this,"update");
+ item_rect_changed();
+ }
+ } break;
+ case NOTIFICATION_EXIT_SCENE: {
+
+ if (texture.is_valid()) {
+
+ texture->disconnect("changed",this,"update");
+ texture=Ref<Texture>();
+ }
+ } break;
+ case NOTIFICATION_DRAW: {
+
+ if (texture.is_null())
+ return;
+
+ RID ci = get_canvas_item();
+
+ /*
+ texture->draw(ci,Point2());
+ break;
+ */
+
+ Size2i s;
+ Rect2i src_rect;
+
+ s = texture->get_size();
+
+ src_rect.size=s;
+
+ Point2i ofs=offset;
+ if (centered)
+ ofs-=s/2;
+
+ Rect2i dst_rect(ofs,s);
+ texture->draw_rect_region(ci,dst_rect,src_rect,modulate);
+
+ } break;
+ }
+}
+
+void ViewportSprite::set_viewport_path(const NodePath& p_viewport) {
+
+ viewport_path=p_viewport;
+ update();
+ if (!is_inside_scene())
+ return;
+
+ if (texture.is_valid()) {
+ texture->disconnect("changed",this,"update");
+ texture=Ref<Texture>();
+ }
+
+ if (viewport_path.is_empty())
+ return;
+
+
+ Node *n = get_node(viewport_path);
+ ERR_FAIL_COND(!n);
+ Viewport *vp=n->cast_to<Viewport>();
+ ERR_FAIL_COND(!vp);
+
+ Ref<RenderTargetTexture> rtt = vp->get_render_target_texture();
+ texture=rtt;
+
+ if (texture.is_valid()) {
+ texture->connect("changed",this,"update");
+ }
+
+ item_rect_changed();
+
+}
+
+NodePath ViewportSprite::get_viewport_path() const {
+
+ return viewport_path;
+}
+
+void ViewportSprite::set_centered(bool p_center) {
+
+ centered=p_center;
+ update();
+ item_rect_changed();
+}
+
+bool ViewportSprite::is_centered() const {
+
+ return centered;
+}
+
+void ViewportSprite::set_offset(const Point2& p_offset) {
+
+ offset=p_offset;
+ update();
+ item_rect_changed();
+}
+Point2 ViewportSprite::get_offset() const {
+
+ return offset;
+}
+void ViewportSprite::set_modulate(const Color& p_color) {
+
+ modulate=p_color;
+ update();
+}
+
+Color ViewportSprite::get_modulate() const{
+
+ return modulate;
+}
+
+
+Rect2 ViewportSprite::get_item_rect() const {
+
+ if (texture.is_null())
+ return Rect2(0,0,1,1);
+ //if (texture.is_null())
+ // return CanvasItem::get_item_rect();
+
+ Size2i s;
+
+ s = texture->get_size();
+ Point2i ofs=offset;
+ if (centered)
+ ofs-=s/2;
+
+ if (s==Size2(0,0))
+ s=Size2(1,1);
+
+ return Rect2(ofs,s);
+}
+
+
+void ViewportSprite::_bind_methods() {
+
+ ObjectTypeDB::bind_method(_MD("set_viewport_path","path"),&ViewportSprite::set_viewport_path);
+ ObjectTypeDB::bind_method(_MD("get_viewport_path"),&ViewportSprite::get_viewport_path);
+
+ ObjectTypeDB::bind_method(_MD("set_centered","centered"),&ViewportSprite::set_centered);
+ ObjectTypeDB::bind_method(_MD("is_centered"),&ViewportSprite::is_centered);
+
+ ObjectTypeDB::bind_method(_MD("set_offset","offset"),&ViewportSprite::set_offset);
+ ObjectTypeDB::bind_method(_MD("get_offset"),&ViewportSprite::get_offset);
+
+ ObjectTypeDB::bind_method(_MD("set_modulate","modulate"),&ViewportSprite::set_modulate);
+ ObjectTypeDB::bind_method(_MD("get_modulate"),&ViewportSprite::get_modulate);
+
+ ADD_PROPERTY( PropertyInfo( Variant::NODE_PATH, "viewport"), _SCS("set_viewport_path"),_SCS("get_viewport_path"));
+ ADD_PROPERTY( PropertyInfo( Variant::BOOL, "centered"), _SCS("set_centered"),_SCS("is_centered"));
+ ADD_PROPERTY( PropertyInfo( Variant::VECTOR2, "offset"), _SCS("set_offset"),_SCS("get_offset"));
+ ADD_PROPERTY( PropertyInfo( Variant::COLOR, "modulate"), _SCS("set_modulate"),_SCS("get_modulate"));
+
+}
+
+ViewportSprite::ViewportSprite() {
+
+ centered=true;
+ modulate=Color(1,1,1,1);
+}
diff --git a/scene/2d/sprite.h b/scene/2d/sprite.h
index 42f737fa91..f26852fea6 100644
--- a/scene/2d/sprite.h
+++ b/scene/2d/sprite.h
@@ -105,4 +105,44 @@ public:
Sprite();
};
+class ViewportSprite : public Node2D {
+
+ OBJ_TYPE( ViewportSprite, Node2D );
+
+ Ref<Texture> texture;
+ NodePath viewport_path;
+
+ bool centered;
+ Point2 offset;
+ Color modulate;
+
+protected:
+
+ void _notification(int p_what);
+
+ static void _bind_methods();;
+
+public:
+
+ virtual void edit_set_pivot(const Point2& p_pivot);
+ virtual Point2 edit_get_pivot() const;
+ virtual bool edit_has_pivot() const;
+
+ void set_viewport_path(const NodePath& p_viewport);
+ NodePath get_viewport_path() const;
+
+ void set_centered(bool p_center);
+ bool is_centered() const;
+
+ void set_offset(const Point2& p_offset);
+ Point2 get_offset() const;
+
+ void set_modulate(const Color& p_color);
+ Color get_modulate() const;
+
+ virtual Rect2 get_item_rect() const;
+
+ ViewportSprite();
+};
+
#endif // SPRITE_H
diff --git a/scene/3d/quad.h b/scene/3d/quad.h
index 7d1b4f5dc4..4870b988f2 100644
--- a/scene/3d/quad.h
+++ b/scene/3d/quad.h
@@ -73,4 +73,5 @@ public:
Quad();
};
+
#endif // QUAD_H
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index 83c0397554..9e0faac716 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -346,7 +346,7 @@ void Control::_notification(int p_notification) {
if (data.window==this) {
window = memnew( Window );
- add_to_group("_gui_input");
+ add_to_group("_vp_gui_input"+itos(get_viewport()->get_instance_ID()));
add_to_group("windows");
window->tooltip_timer = memnew( Timer );
@@ -401,7 +401,7 @@ void Control::_notification(int p_notification) {
if (window) {
- remove_from_group("_gui_input");
+ remove_from_group("_vp_gui_input"+itos(get_viewport()->get_instance_ID()));
remove_from_group("windows");
if (window->tooltip_timer)
memdelete(window->tooltip_timer);
diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp
index c4226e0f23..a7ff1431bd 100644
--- a/scene/gui/file_dialog.cpp
+++ b/scene/gui/file_dialog.cpp
@@ -156,11 +156,61 @@ void FileDialog::_action_pressed() {
if (mode==MODE_SAVE_FILE) {
+ String ext = f.extension();
+ bool valid=false;
+
+ if (filter->get_selected()==filter->get_item_count()-1) {
+ valid=true; //match none
+ } else if (filters.size()>1 && filter->get_selected()==0) {
+ // match all filters
+ for (int i=0;i<filters.size();i++) {
+
+ String flt=filters[i].get_slice(";",0);
+ for (int j=0;j<flt.get_slice_count(",");j++) {
+
+ String str = flt.get_slice(",",j).strip_edges();
+ if (f.match(str)) {
+ valid=true;
+ break;
+ }
+ }
+ if (valid)
+ break;
+ }
+ } else {
+ int idx=filter->get_selected();
+ if (filters.size()>1)
+ idx--;
+ if (idx>=0 && idx<filters.size()) {
+
+ String flt=filters[idx].get_slice(";",0);
+ for (int j=0;j<flt.get_slice_count(",");j++) {
+
+ String str = (flt.get_slice(",",j).strip_edges());
+ if (f.match(str)) {
+ valid=true;
+ break;
+ }
+ }
+ } else {
+ valid=true;
+ }
+ }
+
+
+ if (!valid) {
+
+ exterr->popup_centered_minsize(Size2(250,80));
+ return;
+
+ }
+
if (dir_access->file_exists(f)) {
confirm_save->set_text("File Exists, Overwrite?");
confirm_save->popup_centered(Size2(200,80));
} else {
+
emit_signal("file_selected",f);
hide();
}
@@ -682,6 +732,10 @@ FileDialog::FileDialog() {
mkdirerr->set_text("Could not create folder.");
add_child(mkdirerr);
+ exterr = memnew( AcceptDialog );
+ exterr->set_text("Must use a valid extension.");
+ add_child(exterr);
+
//update_file_list();
update_filters();
diff --git a/scene/gui/file_dialog.h b/scene/gui/file_dialog.h
index 6f274de52a..bda1797696 100644
--- a/scene/gui/file_dialog.h
+++ b/scene/gui/file_dialog.h
@@ -82,6 +82,7 @@ private:
Tree *tree;
LineEdit *file;
AcceptDialog *mkdirerr;
+ AcceptDialog *exterr;
OptionButton *filter;
DirAccess *dir_access;
ConfirmationDialog *confirm_save;
diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp
index 4d1609bef9..7353744d07 100644
--- a/scene/gui/menu_button.cpp
+++ b/scene/gui/menu_button.cpp
@@ -141,7 +141,7 @@ MenuButton::MenuButton() {
popup->hide();
add_child(popup);
popup->set_as_toplevel(true);
- add_to_group("unhandled_key_input");
+ set_process_unhandled_key_input(true);
set_click_on_press(true);
}
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index 9b592a77d5..d4f043c538 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -33,6 +33,7 @@
#include "scene/scene_string_names.h"
#include "scene/resources/packed_scene.h"
#include "io/resource_loader.h"
+#include "viewport.h"
VARIANT_ENUM_CAST(Node::PauseMode);
@@ -76,12 +77,25 @@ void Node::_notification(int p_notification) {
data.pause_owner=this;
}
+ if (data.input)
+ add_to_group("_vp_input"+itos(get_viewport()->get_instance_ID()));
+ if (data.unhandled_input)
+ add_to_group("_vp_unhandled_input"+itos(get_viewport()->get_instance_ID()));
+ if (data.unhandled_key_input)
+ add_to_group("_vp_unhandled_key_input"+itos(get_viewport()->get_instance_ID()));
+
get_scene()->node_count++;
} break;
case NOTIFICATION_EXIT_SCENE: {
get_scene()->node_count--;
+ if (data.input)
+ remove_from_group("_vp_input"+itos(get_viewport()->get_instance_ID()));
+ if (data.unhandled_input)
+ remove_from_group("_vp_unhandled_input"+itos(get_viewport()->get_instance_ID()));
+ if (data.unhandled_key_input)
+ remove_from_group("_vp_unhandled_key_input"+itos(get_viewport()->get_instance_ID()));
} break;
case NOTIFICATION_READY: {
@@ -148,6 +162,9 @@ void Node::_propagate_enter_scene() {
data.depth=1;
}
+ data.viewport = cast_to<Viewport>();
+ if (!data.viewport)
+ data.viewport = data.parent->data.viewport;
data.inside_scene=true;
@@ -158,6 +175,7 @@ void Node::_propagate_enter_scene() {
data.scene->add_to_group(*K,this);
}
+
notification(NOTIFICATION_ENTER_SCENE);
if (get_script_instance()) {
@@ -216,6 +234,8 @@ void Node::_propagate_exit_scene() {
data.scene->remove_from_group(*K,this);
}
+ data.viewport = NULL;
+
if (data.scene)
data.scene->tree_changed();
@@ -324,7 +344,7 @@ void Node::set_pause_mode(PauseMode p_mode) {
if (data.pause_mode==PAUSE_MODE_INHERIT) {
if (data.parent)
- data.parent->data.pause_owner;
+ owner=data.parent->data.pause_owner;
} else {
owner=this;
}
@@ -421,11 +441,17 @@ void Node::set_process_input(bool p_enable) {
if (p_enable==data.input)
return;
+
data.input=p_enable;
+ if (!is_inside_scene())
+ return;
+
if (p_enable)
- add_to_group("input");
+ add_to_group("_vp_input"+itos(get_viewport()->get_instance_ID()));
else
- remove_from_group("input");
+ remove_from_group("_vp_input"+itos(get_viewport()->get_instance_ID()));
+
+
}
bool Node::is_processing_input() const {
@@ -437,18 +463,41 @@ void Node::set_process_unhandled_input(bool p_enable) {
if (p_enable==data.unhandled_input)
return;
data.unhandled_input=p_enable;
+ if (!is_inside_scene())
+ return;
if (p_enable)
- add_to_group("unhandled_input");
+ add_to_group("_vp_unhandled_input"+itos(get_viewport()->get_instance_ID()));
else
- remove_from_group("unhandled_input");
+ remove_from_group("_vp_unhandled_input"+itos(get_viewport()->get_instance_ID()));
}
+
bool Node::is_processing_unhandled_input() const {
return data.unhandled_input;
}
+void Node::set_process_unhandled_key_input(bool p_enable) {
+
+ if (p_enable==data.unhandled_key_input)
+ return;
+ data.unhandled_key_input=p_enable;
+ if (!is_inside_scene())
+ return;
+
+ if (p_enable)
+ add_to_group("_vp_unhandled_key_input"+itos(get_viewport()->get_instance_ID()));
+ else
+ remove_from_group("_vp_unhandled_key_input"+itos(get_viewport()->get_instance_ID()));
+}
+
+
+bool Node::is_processing_unhandled_key_input() const {
+ return data.unhandled_key_input;
+}
+
+
StringName Node::get_name() const {
return data.name;
@@ -1682,6 +1731,8 @@ void Node::_bind_methods() {
ObjectTypeDB::bind_method(_MD("is_processing_input"),&Node::is_processing_input);
ObjectTypeDB::bind_method(_MD("set_process_unhandled_input","enable"),&Node::set_process_unhandled_input);
ObjectTypeDB::bind_method(_MD("is_processing_unhandled_input"),&Node::is_processing_unhandled_input);
+ ObjectTypeDB::bind_method(_MD("set_process_unhandled_key_input","enable"),&Node::set_process_unhandled_key_input);
+ ObjectTypeDB::bind_method(_MD("is_processing_unhandled_key_input"),&Node::is_processing_unhandled_key_input);
ObjectTypeDB::bind_method(_MD("set_pause_mode","mode"),&Node::set_pause_mode);
ObjectTypeDB::bind_method(_MD("get_pause_mode"),&Node::get_pause_mode);
ObjectTypeDB::bind_method(_MD("can_process"),&Node::can_process);
@@ -1693,6 +1744,8 @@ void Node::_bind_methods() {
ObjectTypeDB::bind_method(_MD("duplicate:Node"),&Node::duplicate);
ObjectTypeDB::bind_method(_MD("replace_by","node:Node","keep_data"),&Node::replace_by,DEFVAL(false));
+ ObjectTypeDB::bind_method(_MD("get_viewport"),&Node::get_viewport);
+
ObjectTypeDB::bind_method(_MD("queue_free"),&Node::queue_delete);
BIND_CONSTANT( NOTIFICATION_ENTER_SCENE );
@@ -1748,13 +1801,15 @@ Node::Node() {
data.inside_scene=false;
data.owner=NULL;
- data.OW=false;
+ data.OW=NULL;
data.input=false;
data.unhandled_input=false;
+ data.unhandled_key_input=false;
data.pause_mode=PAUSE_MODE_INHERIT;
data.pause_owner=NULL;
data.parent_owned=false;
data.in_constructor=true;
+ data.viewport=NULL;
}
Node::~Node() {
diff --git a/scene/main/node.h b/scene/main/node.h
index 828acb8de7..b8981d3307 100644
--- a/scene/main/node.h
+++ b/scene/main/node.h
@@ -37,6 +37,7 @@
#include "scene/main/scene_main_loop.h"
+class Viewport;
class Node : public Object {
OBJ_TYPE( Node, Object );
@@ -82,6 +83,8 @@ private:
SceneMainLoop *scene;
bool inside_scene;
+ Viewport *viewport;
+
HashMap< StringName, GroupData,StringNameHasher> grouped;
List<Node*>::Element *OW; // owned element
@@ -95,6 +98,7 @@ private:
bool input;
bool unhandled_input;
+ bool unhandled_key_input;
bool parent_owned;
bool in_constructor;
@@ -237,6 +241,9 @@ public:
void set_process_unhandled_input(bool p_enable);
bool is_processing_unhandled_input() const;
+ void set_process_unhandled_key_input(bool p_enable);
+ bool is_processing_unhandled_key_input() const;
+
int get_position_in_parent() const;
Node *duplicate() const;
@@ -266,6 +273,8 @@ public:
void force_parent_owned() { data.parent_owned=true; } //hack to avoid duplicate nodes
+ _FORCE_INLINE_ Viewport *get_viewport() const { return data.viewport; }
+
/* CANVAS */
Node();
diff --git a/scene/main/scene_main_loop.cpp b/scene/main/scene_main_loop.cpp
index cb3188b3b4..32bc4b3e16 100644
--- a/scene/main/scene_main_loop.cpp
+++ b/scene/main/scene_main_loop.cpp
@@ -340,7 +340,7 @@ void SceneMainLoop::input_event( const InputEvent& p_event ) {
InputEvent ev = p_event;
-
+#if 0
switch(ev.type) {
case InputEvent::MOUSE_BUTTON: {
@@ -391,15 +391,12 @@ void SceneMainLoop::input_event( const InputEvent& p_event ) {
} break;
}
-
+#endif
MainLoop::input_event(p_event);
-
+#if 0
_call_input_pause("input","_input",ev);
-
-
-
call_group(GROUP_CALL_REVERSE|GROUP_CALL_REALTIME|GROUP_CALL_MULIILEVEL,"_gui_input","_gui_input",p_event); //special one for GUI, as controls use their own process check
//call_group(GROUP_CALL_REVERSE|GROUP_CALL_REALTIME|GROUP_CALL_MULIILEVEL,"input","_input",ev);
@@ -416,7 +413,11 @@ void SceneMainLoop::input_event( const InputEvent& p_event ) {
//}
//transform for the rest
+#else
+
+ call_group(GROUP_CALL_REALTIME,"_viewports","_vp_input",p_event); //special one for GUI, as controls use their own process check
+#endif
if (ScriptDebugger::get_singleton() && ScriptDebugger::get_singleton()->is_remote() && ev.type==InputEvent::KEY && ev.key.pressed && !ev.key.echo && ev.key.scancode==KEY_F8) {
ScriptDebugger::get_singleton()->request_quit();
@@ -429,13 +430,19 @@ void SceneMainLoop::input_event( const InputEvent& p_event ) {
root_lock++;
if (!input_handled) {
+
+#if 0
_call_input_pause("unhandled_input","_unhandled_input",ev);
//call_group(GROUP_CALL_REVERSE|GROUP_CALL_REALTIME|GROUP_CALL_MULIILEVEL,"unhandled_input","_unhandled_input",ev);
if (!input_handled && ev.type==InputEvent::KEY) {
_call_input_pause("unhandled_key_input","_unhandled_key_input",ev);
//call_group(GROUP_CALL_REVERSE|GROUP_CALL_REALTIME|GROUP_CALL_MULIILEVEL,"unhandled_key_input","_unhandled_key_input",ev);
}
+#else
+
+ call_group(GROUP_CALL_REALTIME,"_viewports","_vp_unhandled_input",p_event); //special one for GUI, as controls use their own process check
+#endif
input_handled=true;
_flush_ugc();
root_lock--;
diff --git a/scene/main/scene_main_loop.h b/scene/main/scene_main_loop.h
index a3776152ce..1c8e0c90ae 100644
--- a/scene/main/scene_main_loop.h
+++ b/scene/main/scene_main_loop.h
@@ -129,6 +129,8 @@ friend class Node;
//optimization
friend class CanvasItem;
friend class Spatial;
+friend class Viewport;
+
SelfList<Node>::List xform_change_list;
protected:
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 4aed217cef..56d0544abd 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -129,6 +129,9 @@ void Viewport::_update_rect() {
}
emit_signal("size_changed");
+ render_target_texture->emit_changed();
+
+
}
void Viewport::_parent_resized() {
@@ -658,6 +661,7 @@ void Viewport::set_size_override(bool p_enable, const Size2& p_size, const Vecto
_update_rect();
_update_stretch_transform();
+
}
Size2 Viewport::get_size_override() const {
@@ -711,6 +715,8 @@ void Viewport::set_as_render_target(bool p_enable){
render_target_texture_rid=RID();
}
+
+ render_target_texture->emit_changed();
}
bool Viewport::is_set_as_render_target() const{
@@ -743,6 +749,120 @@ Ref<RenderTargetTexture> Viewport::get_render_target_texture() const {
return render_target_texture;
}
+void Viewport::set_render_target_vflip(bool p_enable) {
+
+ render_target_vflip=p_enable;
+ VisualServer::get_singleton()->viewport_set_render_target_vflip(viewport,p_enable);
+}
+
+bool Viewport::get_render_target_vflip() const{
+
+ return render_target_vflip;
+}
+
+
+void Viewport::_make_input_local(InputEvent& ev) {
+
+ switch(ev.type) {
+
+ case InputEvent::MOUSE_BUTTON: {
+
+ Matrix32 ai = get_final_transform().affine_inverse();
+ Vector2 g = ai.xform(Vector2(ev.mouse_button.global_x,ev.mouse_button.global_y));
+ Vector2 l = ai.xform(Vector2(ev.mouse_button.x,ev.mouse_button.y));
+ ev.mouse_button.x=l.x;
+ ev.mouse_button.y=l.y;
+ ev.mouse_button.global_x=g.x;
+ ev.mouse_button.global_y=g.y;
+
+ } break;
+ case InputEvent::MOUSE_MOTION: {
+
+ Matrix32 ai = get_final_transform().affine_inverse();
+ Vector2 g = ai.xform(Vector2(ev.mouse_motion.global_x,ev.mouse_motion.global_y));
+ Vector2 l = ai.xform(Vector2(ev.mouse_motion.x,ev.mouse_motion.y));
+ Vector2 r = ai.xform(Vector2(ev.mouse_motion.relative_x,ev.mouse_motion.relative_y));
+ ev.mouse_motion.x=l.x;
+ ev.mouse_motion.y=l.y;
+ ev.mouse_motion.global_x=g.x;
+ ev.mouse_motion.global_y=g.y;
+ ev.mouse_motion.relative_x=r.x;
+ ev.mouse_motion.relative_y=r.y;
+
+ } break;
+ case InputEvent::SCREEN_TOUCH: {
+
+ Matrix32 ai = get_final_transform().affine_inverse();
+ Vector2 t = ai.xform(Vector2(ev.screen_touch.x,ev.screen_touch.y));
+ ev.screen_touch.x=t.x;
+ ev.screen_touch.y=t.y;
+
+ } break;
+ case InputEvent::SCREEN_DRAG: {
+
+ Matrix32 ai = get_final_transform().affine_inverse();
+ Vector2 t = ai.xform(Vector2(ev.screen_drag.x,ev.screen_drag.y));
+ Vector2 r = ai.xform(Vector2(ev.screen_drag.relative_x,ev.screen_drag.relative_y));
+ Vector2 s = ai.xform(Vector2(ev.screen_drag.speed_x,ev.screen_drag.speed_y));
+ ev.screen_drag.x=t.x;
+ ev.screen_drag.y=t.y;
+ ev.screen_drag.relative_x=r.x;
+ ev.screen_drag.relative_y=r.y;
+ ev.screen_drag.speed_x=s.x;
+ ev.screen_drag.speed_y=s.y;
+ } break;
+ }
+
+}
+
+
+void Viewport::_vp_input(const InputEvent& p_ev) {
+
+ if (render_target)
+ return; //if render target, can't get input events
+
+ //this one handles system input, p_ev are in system coordinates
+ //they are converted to viewport coordinates
+
+ InputEvent ev = p_ev;
+ _make_input_local(ev);
+ input(ev);
+
+}
+
+void Viewport::_vp_unhandled_input(const InputEvent& p_ev) {
+
+ if (render_target)
+ return; //if render target, can't get input events
+
+ //this one handles system input, p_ev are in system coordinates
+ //they are converted to viewport coordinates
+
+ InputEvent ev = p_ev;
+ _make_input_local(ev);
+ unhandled_input(ev);
+
+}
+
+void Viewport::input(const InputEvent& p_event) {
+
+ ERR_FAIL_COND(!is_inside_scene());
+ get_scene()->_call_input_pause(input_group,"_input",p_event);
+ get_scene()->call_group(SceneMainLoop::GROUP_CALL_REVERSE|SceneMainLoop::GROUP_CALL_REALTIME|SceneMainLoop::GROUP_CALL_MULIILEVEL,gui_input_group,"_gui_input",p_event); //special one for GUI, as controls use their own process check
+}
+
+void Viewport::unhandled_input(const InputEvent& p_event) {
+
+ ERR_FAIL_COND(!is_inside_scene());
+
+ get_scene()->_call_input_pause(unhandled_input_group,"_unhandled_input",p_event);
+ //call_group(GROUP_CALL_REVERSE|GROUP_CALL_REALTIME|GROUP_CALL_MULIILEVEL,"unhandled_input","_unhandled_input",ev);
+ if (!get_scene()->input_handled && p_event.type==InputEvent::KEY) {
+ get_scene()->_call_input_pause(unhandled_key_input_group,"_unhandled_key_input",p_event);
+ //call_group(GROUP_CALL_REVERSE|GROUP_CALL_REALTIME|GROUP_CALL_MULIILEVEL,"unhandled_key_input","_unhandled_key_input",ev);
+ }
+}
+
void Viewport::_bind_methods() {
@@ -770,6 +890,8 @@ void Viewport::_bind_methods() {
ObjectTypeDB::bind_method(_MD("_parent_visibility_changed"), &Viewport::_parent_visibility_changed);
ObjectTypeDB::bind_method(_MD("_parent_resized"), &Viewport::_parent_resized);
+ ObjectTypeDB::bind_method(_MD("_vp_input"), &Viewport::_vp_input);
+ ObjectTypeDB::bind_method(_MD("_vp_unhandled_input"), &Viewport::_vp_unhandled_input);
ObjectTypeDB::bind_method(_MD("set_size_override","enable","size","margin"), &Viewport::set_size_override,DEFVAL(Size2(-1,-1)),DEFVAL(Size2(0,0)));
ObjectTypeDB::bind_method(_MD("get_size_override"), &Viewport::get_size_override);
@@ -782,14 +904,17 @@ void Viewport::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_as_render_target","enable"), &Viewport::set_as_render_target);
ObjectTypeDB::bind_method(_MD("is_set_as_render_target"), &Viewport::is_set_as_render_target);
+ ObjectTypeDB::bind_method(_MD("set_render_target_vflip","enable"), &Viewport::set_render_target_vflip);
+ ObjectTypeDB::bind_method(_MD("get_render_target_vflip"), &Viewport::get_render_target_vflip);
+
ObjectTypeDB::bind_method(_MD("set_render_target_update_mode","mode"), &Viewport::set_render_target_update_mode);
ObjectTypeDB::bind_method(_MD("get_render_target_update_mode"), &Viewport::get_render_target_update_mode);
ObjectTypeDB::bind_method(_MD("get_render_target_texture:RenderTargetTexture"), &Viewport::get_render_target_texture);
-
ObjectTypeDB::bind_method(_MD("get_viewport"), &Viewport::get_viewport);
-
+ ObjectTypeDB::bind_method(_MD("input","local_event"), &Viewport::input);
+ ObjectTypeDB::bind_method(_MD("unhandled_input","local_event"), &Viewport::unhandled_input);
ObjectTypeDB::bind_method(_MD("update_worlds"), &Viewport::update_worlds);
@@ -806,6 +931,7 @@ void Viewport::_bind_methods() {
// ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"world_2d",PROPERTY_HINT_RESOURCE_TYPE,"World2D"), _SCS("set_world_2d"), _SCS("get_world_2d") );
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"transparent_bg"), _SCS("set_transparent_background"), _SCS("has_transparent_background") );
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"render_target/enabled"), _SCS("set_as_render_target"), _SCS("is_set_as_render_target") );
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"render_target/v_flip"), _SCS("set_render_target_vflip"), _SCS("get_render_target_vflip") );
ADD_PROPERTY( PropertyInfo(Variant::INT,"render_target/update_mode",PROPERTY_HINT_ENUM,"Disabled,Once,When Visible,Always"), _SCS("set_render_target_update_mode"), _SCS("get_render_target_update_mode") );
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"audio_listener/enable_2d"), _SCS("set_as_audio_listener_2d"), _SCS("is_audio_listener_2d") );
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"audio_listener/enable_3d"), _SCS("set_as_audio_listener"), _SCS("is_audio_listener") );
@@ -839,10 +965,15 @@ Viewport::Viewport() {
size_override_stretch=false;
size_override_size=Size2(1,1);
render_target=false;
+ render_target_vflip=false;
render_target_update_mode=RENDER_TARGET_UPDATE_WHEN_VISIBLE;
render_target_texture = Ref<RenderTargetTexture>( memnew( RenderTargetTexture(this) ) );
-
+ String id=itos(get_instance_ID());
+ input_group = "_vp_input"+id;
+ gui_input_group = "_vp_gui_input"+id;
+ unhandled_input_group = "_vp_unhandled_input"+id;
+ unhandled_key_input_group = "_vp_unhandled_key_input"+id;
}
diff --git a/scene/main/viewport.h b/scene/main/viewport.h
index 7fbae20f7d..8ba84651f8 100644
--- a/scene/main/viewport.h
+++ b/scene/main/viewport.h
@@ -110,6 +110,7 @@ friend class RenderTargetTexture;
bool transparent_bg;
+ bool render_target_vflip;
void _update_rect();
@@ -120,6 +121,11 @@ friend class RenderTargetTexture;
Ref<World2D> world_2d;
Ref<World> world;
+ StringName input_group;
+ StringName gui_input_group;
+ StringName unhandled_input_group;
+ StringName unhandled_key_input_group;
+
void _update_listener();
void _update_listener_2d();
@@ -142,6 +148,10 @@ friend class RenderTargetTexture;
void _vp_enter_scene();
void _vp_exit_scene();
+ void _vp_input(const InputEvent& p_ev);
+ void _vp_unhandled_input(const InputEvent& p_ev);
+ void _make_input_local(InputEvent& ev);
+
friend class Camera;
void _camera_transform_changed_notify();
void _set_camera(Camera* p_camera);
@@ -190,10 +200,12 @@ public:
void set_size_override_stretch(bool p_enable);
bool is_size_override_stretch_enabled() const;
-
-
void set_as_render_target(bool p_enable);
bool is_set_as_render_target() const;
+
+ void set_render_target_vflip(bool p_enable);
+ bool get_render_target_vflip() const;
+
void set_render_target_update_mode(RenderTargetUpdateMode p_mode);
RenderTargetUpdateMode get_render_target_update_mode() const;
Ref<RenderTargetTexture> get_render_target_texture() const;
@@ -201,6 +213,9 @@ public:
void queue_screen_capture();
Image get_screen_capture() const;
+ void input(const InputEvent& p_event);
+ void unhandled_input(const InputEvent& p_event);
+
Viewport();
~Viewport();
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index 007ecb88b7..8fd39b0d74 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -446,6 +446,7 @@ void register_scene_types() {
ObjectTypeDB::register_type<Particles2D>();
ObjectTypeDB::register_type<ParticleAttractor2D>();
ObjectTypeDB::register_type<Sprite>();
+ ObjectTypeDB::register_type<ViewportSprite>();
ObjectTypeDB::register_type<SpriteFrames>();
ObjectTypeDB::register_type<AnimatedSprite>();
ObjectTypeDB::register_type<Position2D>();
diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp
index 3c992a93b9..d10bb37f60 100644
--- a/scene/resources/default_theme/default_theme.cpp
+++ b/scene/resources/default_theme/default_theme.cpp
@@ -583,7 +583,7 @@ void make_default_theme() {
t->set_stylebox("panel","PanelContainer", tc_sb );
- t->set_stylebox( "logo","Icons", make_icon(logo_png) );
+ t->set_icon( "logo","Icons", make_icon(logo_png) );
Theme::set_default( t );
Theme::set_default_icon( make_icon(error_icon_png) );