Browse Source

Merge pull request #7522 from Faless/2.1-split

2.1.x Cherry pick patch to enable 2D split screen. ( #6486 )
Rémi Verschelde 8 years ago
parent
commit
6b5a852bd8

+ 48 - 9
scene/2d/camera_2d.cpp

@@ -42,6 +42,9 @@ void Camera2D::_update_scroll() {
 	}
 
 	if (current) {
+
+		ERR_FAIL_COND( custom_viewport && !ObjectDB::get_instance(custom_viewport_id) );
+
 		Matrix32 xform = get_camera_transform();
 
 		if (viewport) {
@@ -220,14 +223,10 @@ void Camera2D::_notification(int p_what) {
 		case NOTIFICATION_ENTER_TREE: {
 
 
-			viewport = NULL;
-			Node *n=this;
-			while(n){
-
-				viewport = n->cast_to<Viewport>();
-				if (viewport)
-					break;
-				n=n->get_parent();
+			if (custom_viewport && ObjectDB::get_instance(custom_viewport_id)) {
+				viewport=custom_viewport;
+			} else {
+				viewport=get_viewport();
 			}
 
 			canvas = get_canvas();
@@ -251,7 +250,7 @@ void Camera2D::_notification(int p_what) {
 		case NOTIFICATION_EXIT_TREE: {
 
 			if (is_current()) {
-				if (viewport) {
+				if (viewport && !(custom_viewport && !ObjectDB::get_instance(custom_viewport_id))) {
 					viewport->set_canvas_transform( Matrix32() );
 				}
 			}
@@ -518,6 +517,42 @@ bool Camera2D::is_follow_smoothing_enabled() const {
 	return smoothing_enabled;
 }
 
+void Camera2D::set_custom_viewport(Node *p_viewport) {
+	ERR_FAIL_NULL(p_viewport);
+	if (is_inside_tree()) {
+		remove_from_group(group_name);
+		remove_from_group(canvas_group_name);
+	}
+
+	custom_viewport=p_viewport->cast_to<Viewport>();
+
+	if (custom_viewport) {
+		custom_viewport_id=custom_viewport->get_instance_ID();
+	} else {
+		custom_viewport_id=0;
+	}
+
+	if (is_inside_tree()) {
+
+		if (custom_viewport)
+			viewport=custom_viewport;
+		else
+			viewport=get_viewport();
+
+		RID vp = viewport->get_viewport();
+		group_name = "__cameras_"+itos(vp.get_id());
+		canvas_group_name ="__cameras_c"+itos(canvas.get_id());
+		add_to_group(group_name);
+		add_to_group(canvas_group_name);
+	}
+
+}
+
+Node* Camera2D::get_custom_viewport() const {
+
+	return custom_viewport;
+}
+
 
 void Camera2D::_bind_methods() {
 
@@ -564,6 +599,8 @@ void Camera2D::_bind_methods() {
 	ObjectTypeDB::bind_method(_MD("set_zoom","zoom"),&Camera2D::set_zoom);
 	ObjectTypeDB::bind_method(_MD("get_zoom"),&Camera2D::get_zoom);
 
+	ObjectTypeDB::bind_method(_MD("set_custom_viewport","viewport:Viewport"),&Camera2D::set_custom_viewport);
+	ObjectTypeDB::bind_method(_MD("get_custom_viewport:Viewport"),&Camera2D::get_custom_viewport);
 
 	ObjectTypeDB::bind_method(_MD("set_follow_smoothing","follow_smoothing"),&Camera2D::set_follow_smoothing);
 	ObjectTypeDB::bind_method(_MD("get_follow_smoothing"),&Camera2D::get_follow_smoothing);
@@ -626,6 +663,8 @@ Camera2D::Camera2D() {
 	camera_pos=Vector2();
 	first=true;
 	smoothing_enabled=false;
+	custom_viewport=NULL;
+	custom_viewport_id=0;
 
 	smoothing=5.0;
 	zoom = Vector2(1, 1);

+ 5 - 0
scene/2d/camera_2d.h

@@ -48,6 +48,8 @@ protected:
 	Point2 smoothed_camera_pos;
 	bool first;
 
+	ObjectID custom_viewport_id; // to check validity
+	Viewport *custom_viewport;
 	Viewport *viewport;
 
 	StringName group_name;
@@ -126,6 +128,9 @@ public:
 
 	Point2 get_camera_screen_center() const;
 
+	void set_custom_viewport(Node *p_viewport);
+	Node* get_custom_viewport() const;
+
 	Vector2 get_camera_pos() const;
 	void force_update_scroll();
 	void reset_smoothing();

+ 48 - 12
scene/main/canvas_layer.cpp

@@ -168,20 +168,13 @@ void CanvasLayer::_notification(int p_what) {
 
 		case NOTIFICATION_ENTER_TREE: {
 
-			Node *n = this;
-			vp=NULL;
+			if (custom_viewport && ObjectDB::get_instance(custom_viewport_id)) {
 
-			while(n) {
+				vp=custom_viewport;
+			} else {
+				vp=Node::get_viewport();
 
-				if (n->cast_to<Viewport>()) {
-
-					vp = n->cast_to<Viewport>();
-					break;
-				}
-				n=n->get_parent();
 			}
-
-
 			ERR_FAIL_COND(!vp);
 			viewport=vp->get_viewport();
 
@@ -205,6 +198,7 @@ Size2 CanvasLayer::get_viewport_size() const {
 	if (!is_inside_tree())
 		return Size2(1,1);
 
+
 	Rect2 r = vp->get_visible_rect();
 	return r.size;
 }
@@ -215,6 +209,43 @@ RID CanvasLayer::get_viewport() const {
 	return viewport;
 }
 
+void CanvasLayer::set_custom_viewport(Node *p_viewport) {
+	ERR_FAIL_NULL(p_viewport);
+	if (is_inside_tree()) {
+		VisualServer::get_singleton()->viewport_remove_canvas(viewport,canvas->get_canvas());
+		viewport=RID();
+	}
+
+	custom_viewport=p_viewport->cast_to<Viewport>();
+
+	if (custom_viewport) {
+		custom_viewport_id=custom_viewport->get_instance_ID();
+	} else {
+		custom_viewport_id=0;
+	}
+
+	if (is_inside_tree()) {
+
+
+		if (custom_viewport)
+			vp=custom_viewport;
+		else
+			vp=Node::get_viewport();
+
+		viewport = vp->get_viewport();
+
+		VisualServer::get_singleton()->viewport_attach_canvas(viewport,canvas->get_canvas());
+		VisualServer::get_singleton()->viewport_set_canvas_layer(viewport,canvas->get_canvas(),layer);
+		VisualServer::get_singleton()->viewport_set_canvas_transform(viewport,canvas->get_canvas(),transform);
+	}
+
+}
+
+Node* CanvasLayer::get_custom_viewport() const {
+
+	return custom_viewport;
+}
+
 
 void CanvasLayer::_bind_methods() {
 
@@ -241,8 +272,11 @@ void CanvasLayer::_bind_methods() {
 	ObjectTypeDB::bind_method(_MD("set_scale","scale"),&CanvasLayer::set_scale);
 	ObjectTypeDB::bind_method(_MD("get_scale"),&CanvasLayer::get_scale);
 
+	ObjectTypeDB::bind_method(_MD("set_custom_viewport","viewport:Viewport"),&CanvasLayer::set_custom_viewport);
+	ObjectTypeDB::bind_method(_MD("get_custom_viewport:Viewport"),&CanvasLayer::get_custom_viewport);
+
 	ObjectTypeDB::bind_method(_MD("get_world_2d:World2D"),&CanvasLayer::get_world_2d);
-	ObjectTypeDB::bind_method(_MD("get_viewport"),&CanvasLayer::get_viewport);
+//	ObjectTypeDB::bind_method(_MD("get_viewport"),&CanvasLayer::get_viewport);
 
 	ADD_PROPERTY( PropertyInfo(Variant::INT,"layer",PROPERTY_HINT_RANGE,"-128,128,1"),_SCS("set_layer"),_SCS("get_layer") );
 	//ADD_PROPERTY( PropertyInfo(Variant::MATRIX32,"transform",PROPERTY_HINT_RANGE),_SCS("set_transform"),_SCS("get_transform") );
@@ -260,4 +294,6 @@ CanvasLayer::CanvasLayer() {
 	locrotscale_dirty=false;
 	layer=1;
 	canvas = Ref<World2D>( memnew(World2D) );
+	custom_viewport=NULL;
+	custom_viewport_id=0;
 }

+ 8 - 0
scene/main/canvas_layer.h

@@ -45,6 +45,10 @@ class CanvasLayer : public Node {
 	int layer;
 	Matrix32 transform;
 	Ref<World2D> canvas;
+
+	ObjectID custom_viewport_id; // to check validity
+	Viewport *custom_viewport;
+
 	RID viewport;
 	Viewport *vp;
 
@@ -55,6 +59,7 @@ class CanvasLayer : public Node {
 	void _update_xform();
 	void _update_locrotscale();
 
+
 protected:
 
 	void _notification(int p_what);
@@ -85,6 +90,9 @@ public:
 
 	RID get_viewport() const;
 
+	void set_custom_viewport(Node *p_viewport);
+	Node* get_custom_viewport() const;
+
 	CanvasLayer();
 };
 

+ 32 - 22
scene/main/viewport.cpp

@@ -359,13 +359,7 @@ void Viewport::_notification(int p_what) {
 			_update_listener_2d();
 			_update_rect();
 
-			if (world_2d.is_valid()) {
-				find_world_2d()->_register_viewport(this,Rect2());
-//best to defer this and not do it here, as it can annoy a lot of setup logic if user
-//adds a node and then moves it, will get enter/exit screen/viewport notifications
-//unnecesarily
-//				update_worlds();
-			}
+			find_world_2d()->_register_viewport(this,Rect2());
 
 			add_to_group("_viewports");
 			if (get_tree()->is_debugging_collisions_hint()) {
@@ -1001,19 +995,34 @@ bool Viewport::has_transparent_background() const {
 	return transparent_bg;
 }
 
-#if 0
 void Viewport::set_world_2d(const Ref<World2D>& p_world_2d) {
+	if (world_2d==p_world_2d)
+		return;
+
+	if (parent && parent->find_world_2d()==p_world_2d) {
+		WARN_PRINT("Unable to use parent world as world_2d");
+		return;
+	}
+
+	if (is_inside_tree()) {
+		find_world_2d()->_remove_viewport(this);
+		VisualServer::get_singleton()->viewport_remove_canvas(viewport,current_canvas);
+	}
+
+	if (p_world_2d.is_valid())
+		world_2d=p_world_2d;
+	else {
+		WARN_PRINT("Invalid world");
+		world_2d=Ref<World2D>( memnew( World2D ));
+	}
 
-	world_2d=p_world_2d;
 	_update_listener_2d();
 
-	if (is_inside_scene()) {
-		if (current_canvas.is_valid())
-			VisualServer::get_singleton()->viewport_remove_canvas(viewport,current_canvas);
+	if (is_inside_tree()) {
 		current_canvas=find_world_2d()->get_canvas();
 		VisualServer::get_singleton()->viewport_attach_canvas(viewport,current_canvas);
+		find_world_2d()->_register_viewport(this,Rect2());
 	}
-
 }
 
 Ref<World2D> Viewport::find_world_2d() const{
@@ -1025,13 +1034,6 @@ Ref<World2D> Viewport::find_world_2d() const{
 	else
 		return Ref<World2D>();
 }
-#endif
-
-Ref<World2D> Viewport::find_world_2d() const{
-
-	return world_2d;
-}
-
 
 void Viewport::_propagate_enter_world(Node *p_node) {
 
@@ -1141,6 +1143,11 @@ Ref<World> Viewport::get_world() const{
 	return world;
 }
 
+Ref<World2D> Viewport::get_world_2d() const{
+
+	return world_2d;
+}
+
 Ref<World> Viewport::find_world() const{
 
 	if (own_world.is_valid())
@@ -1303,6 +1310,9 @@ void Viewport::render_target_clear() {
 
 void Viewport::set_render_target_filter(bool p_enable) {
 
+	if(!render_target)
+		return;
+
 	render_target_texture->set_flags(p_enable?int(Texture::FLAG_FILTER):int(0));
 
 }
@@ -2590,8 +2600,8 @@ void Viewport::_bind_methods() {
 
 	ObjectTypeDB::bind_method(_MD("set_rect","rect"), &Viewport::set_rect);
 	ObjectTypeDB::bind_method(_MD("get_rect"), &Viewport::get_rect);
-	//ObjectTypeDB::bind_method(_MD("set_world_2d","world_2d:World2D"), &Viewport::set_world_2d);
-	//ObjectTypeDB::bind_method(_MD("get_world_2d:World2D"), &Viewport::get_world_2d);
+	ObjectTypeDB::bind_method(_MD("set_world_2d","world_2d:World2D"), &Viewport::set_world_2d);
+	ObjectTypeDB::bind_method(_MD("get_world_2d:World2D"), &Viewport::get_world_2d);
 	ObjectTypeDB::bind_method(_MD("find_world_2d:World2D"), &Viewport::find_world_2d);
 	ObjectTypeDB::bind_method(_MD("set_world","world:World"), &Viewport::set_world);
 	ObjectTypeDB::bind_method(_MD("get_world:World"), &Viewport::get_world);

+ 2 - 0
scene/main/viewport.h

@@ -305,9 +305,11 @@ public:
 	RID get_viewport() const;
 
 	void set_world(const Ref<World>& p_world);
+	void set_world_2d(const Ref<World2D>& p_world_2d);
 	Ref<World> get_world() const;
 	Ref<World> find_world() const;
 
+	Ref<World2D> get_world_2d() const;
 	Ref<World2D> find_world_2d() const;