Browse Source

Properly clear/restore current camera when switching scenes. Fixes #2137

Juan Linietsky 9 years ago
parent
commit
2db78e8f87
4 changed files with 56 additions and 73 deletions
  1. 42 69
      scene/3d/camera.cpp
  2. 1 4
      scene/3d/camera.h
  3. 9 0
      scene/main/scene_main_loop.cpp
  4. 4 0
      scene/main/scene_main_loop.h

+ 42 - 69
scene/3d/camera.cpp

@@ -125,7 +125,7 @@ bool Camera::_get(const StringName& p_name,Variant &r_ret) const {
 		r_ret= int(keep_aspect);
 	else if (p_name=="current") {
 
-		if (is_inside_tree() && get_tree()->is_editor_hint()) {
+		if (is_inside_tree() && get_tree()->is_node_being_edited(this)) {
 			r_ret=current;
 		} else {
 			r_ret=is_current();
@@ -192,12 +192,11 @@ void Camera::_update_camera() {
 
 // here goes listener stuff
 //	if (viewport_ptr && is_inside_scene() && is_current())
-//		viewport_ptr->_camera_transform_changed_notify();
+//		get_viewport()->_camera_transform_changed_notify();
 
 	if (is_inside_tree() && is_current()) {
-		if (viewport_ptr) {
-			viewport_ptr->_camera_transform_changed_notify();
-		}
+		get_viewport()->_camera_transform_changed_notify();
+
 	}
 
 	if (is_current() && get_world().is_valid()) {
@@ -213,29 +212,10 @@ void Camera::_notification(int p_what) {
 	
 		case NOTIFICATION_ENTER_WORLD: {
 
-			viewport_ptr=NULL;
-
-			{ //find viewport stuff
-				Node *parent=get_parent();
 
-				while(parent) {
-
-					Viewport* viewport = parent->cast_to<Viewport>();
-
-					if (viewport) {
-						viewport_ptr=viewport;
-						break;
-					}
-					parent=parent->get_parent();
-				}
-
-			}
-
-			camera_group = "_vp_cameras"+itos(get_viewport()->get_instance_ID());
-			add_to_group(camera_group);
-			if (viewport_ptr)
-				viewport_ptr->cameras.insert(this);
-			if (current)
+			bool first_camera = get_viewport()->cameras.size()==0;
+			get_viewport()->cameras.insert(this);
+			if (!get_tree()->is_node_being_edited(this) && (current || first_camera))
 				make_current();
 
 
@@ -246,17 +226,17 @@ void Camera::_notification(int p_what) {
 		} break;
 		case NOTIFICATION_EXIT_WORLD: {
 		
-			if (is_current()) {
-				clear_current();
-				current=true; //keep it true
+			if (!get_tree()->is_node_being_edited(this)) {
+				if (is_current()) {
+					clear_current();
+					current=true; //keep it true
 
-			} else {
-				current=false;
+				} else {
+					current=false;
+				}
 			}
-			if (viewport_ptr)
-				viewport_ptr->cameras.erase(this);
-			viewport_ptr=NULL;
-			remove_from_group(camera_group);
+
+			get_viewport()->cameras.erase(this);
 
 
 		} break;
@@ -324,25 +304,12 @@ void Camera::make_current() {
 	if (!is_inside_tree())
 		return;
 
-	if (viewport_ptr) {
-		viewport_ptr->_set_camera(this);
-	}
+	get_viewport()->_set_camera(this);
 
 	//get_scene()->call_group(SceneMainLoop::GROUP_CALL_REALTIME,camera_group,"_camera_make_current",this);
 }
 
 
-void Camera::_camera_make_next_current(Node *p_exclude) {
-
-	if (this==p_exclude)
-		return;
-	if (!is_inside_tree())
-		return;
-	if (get_viewport()->get_camera()!=NULL)
-		return;
-
-	make_current();
-}
 
 
 void Camera::clear_current() {
@@ -351,12 +318,20 @@ void Camera::clear_current() {
 	if (!is_inside_tree())
 		return;
 
-	if (viewport_ptr) {
-		if (viewport_ptr->get_camera()==this) {
-			viewport_ptr->_set_camera(NULL);
-			//a group is used beause this needs to be in order to be deterministic
-			get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,camera_group,"_camera_make_next_current",this);
+	if (get_viewport()->get_camera()==this) {
+		get_viewport()->_set_camera(NULL);
+		//a group is used beause this needs to be in order to be deterministic
+
+		for (Set<Camera*>::Element *E=get_viewport()->cameras.front();E;E=E->next()) {
 
+			if (this==E->get())
+				continue;
+			if (!E->get()->is_inside_tree())
+				continue;
+			if (get_viewport()->get_camera()!=NULL)
+				return;
+
+			E->get()->make_current();
 		}
 	}
 
@@ -364,9 +339,9 @@ void Camera::clear_current() {
 
 bool Camera::is_current() const {
 
-	if (is_inside_tree()) {
-		if (viewport_ptr)
-			return viewport_ptr->get_camera()==this;
+	if (is_inside_tree() && !get_tree()->is_node_being_edited(this)) {
+
+		return get_viewport()->get_camera()==this;
 	} else
 		return current;
 
@@ -481,12 +456,12 @@ Vector3 Camera::project_local_ray_normal(const Point2& p_pos) const {
 
 
 #if 0
-	Size2 viewport_size = viewport_ptr->get_visible_rect().size;
+	Size2 viewport_size = get_viewport()->get_visible_rect().size;
 	Vector2 cpos = p_pos;
 #else
 
-	Size2 viewport_size = viewport_ptr->get_camera_rect_size();
-	Vector2 cpos = viewport_ptr->get_camera_coords(p_pos);
+	Size2 viewport_size = get_viewport()->get_camera_rect_size();
+	Vector2 cpos = get_viewport()->get_camera_coords(p_pos);
 #endif
 
 	Vector3 ray;
@@ -514,12 +489,12 @@ Vector3 Camera::project_ray_origin(const Point2& p_pos) const {
 	}
 
 #if 0
-	Size2 viewport_size = viewport_ptr->get_visible_rect().size;
+	Size2 viewport_size = get_viewport()->get_visible_rect().size;
 	Vector2 cpos = p_pos;
 #else
 
-	Size2 viewport_size = viewport_ptr->get_camera_rect_size();
-	Vector2 cpos = viewport_ptr->get_camera_coords(p_pos);
+	Size2 viewport_size = get_viewport()->get_camera_rect_size();
+	Vector2 cpos = get_viewport()->get_camera_coords(p_pos);
 #endif
 
 	ERR_FAIL_COND_V( viewport_size.y == 0, Vector3() );
@@ -566,7 +541,7 @@ Point2 Camera::unproject_position(const Vector3& p_pos) const {
 		ERR_FAIL_COND_V(!is_inside_tree(),Vector2());
 	}
 
-	Size2 viewport_size = viewport_ptr->get_visible_rect().size;
+	Size2 viewport_size = get_viewport()->get_visible_rect().size;
 
 	CameraMatrix cm;
 
@@ -597,7 +572,7 @@ Vector3 Camera::project_position(const Point2& p_point) const {
 		ERR_FAIL_COND_V(!is_inside_tree(),Vector3());
 	}
 
-	Size2 viewport_size = viewport_ptr->get_visible_rect().size;
+	Size2 viewport_size = get_viewport()->get_visible_rect().size;
 
 	CameraMatrix cm;
 
@@ -692,7 +667,6 @@ void Camera::_bind_methods() {
 	ObjectTypeDB::bind_method(_MD("get_environment:Environment"),&Camera::get_environment);
 	ObjectTypeDB::bind_method(_MD("set_keep_aspect_mode","mode"),&Camera::set_keep_aspect_mode);
 	ObjectTypeDB::bind_method(_MD("get_keep_aspect_mode"),&Camera::get_keep_aspect_mode);
-	ObjectTypeDB::bind_method(_MD("_camera_make_next_current"),&Camera::_camera_make_next_current);
 	//ObjectTypeDB::bind_method( _MD("_camera_make_current"),&Camera::_camera_make_current );
 
 	BIND_CONSTANT( PROJECTION_PERSPECTIVE );
@@ -745,7 +719,7 @@ Vector<Plane> Camera::get_frustum() const {
 
 	ERR_FAIL_COND_V(!is_inside_world(),Vector<Plane>());
 
-	Size2 viewport_size = viewport_ptr->get_visible_rect().size;
+	Size2 viewport_size = get_viewport()->get_visible_rect().size;
 	CameraMatrix cm;
 	if (mode==PROJECTION_PERSPECTIVE)
 		cm.set_perspective(fov,viewport_size.get_aspect(),near,far,keep_aspect==KEEP_WIDTH);
@@ -789,7 +763,6 @@ Camera::Camera() {
 	near=0;
 	far=0;
 	current=false;
-	viewport_ptr=NULL;
 	force_change=false;
 	mode=PROJECTION_PERSPECTIVE;
 	set_perspective(60.0,0.1,100.0);

+ 1 - 4
scene/3d/camera.h

@@ -68,18 +68,15 @@ private:
 	RID camera;
 	RID scenario_id;
 
-	String camera_group;
+	//String camera_group;
 
 	uint32_t layers;
 
-	Viewport *viewport_ptr;
 	Ref<Environment> environment;
 
 	virtual bool _can_gizmo_scale() const;
 	virtual RES _get_gizmo_geometry() const;
 
-	void _camera_make_next_current(Node *p_exclude);
-
 
 	//void _camera_make_current(Node *p_camera);
 friend class Viewport;

+ 9 - 0
scene/main/scene_main_loop.cpp

@@ -620,6 +620,10 @@ void SceneTree::set_editor_hint(bool p_enabled) {
 	editor_hint=p_enabled;
 }
 
+bool SceneTree::is_node_being_edited(const Node* p_node) const {
+	return editor_hint && edited_scene_root && edited_scene_root->is_a_parent_of(p_node);
+}
+
 bool SceneTree::is_editor_hint() const {
 
 	return editor_hint;
@@ -965,6 +969,10 @@ Array SceneTree::_get_nodes_in_group(const StringName& p_group) {
 	return ret;
 }
 
+bool SceneTree::has_group(const StringName& p_identifier) const {
+
+	return group_map.has(p_identifier);
+}
 void SceneTree::get_nodes_in_group(const StringName& p_group,List<Node*> *p_list) {
 
 
@@ -1589,6 +1597,7 @@ void SceneTree::_bind_methods() {
 	ObjectTypeDB::bind_method(_MD("get_nodes_in_group","group"),&SceneTree::_get_nodes_in_group);
 
 	ObjectTypeDB::bind_method(_MD("get_root:Viewport"),&SceneTree::get_root);
+	ObjectTypeDB::bind_method(_MD("has_group","name"),&SceneTree::has_group);
 
 	ObjectTypeDB::bind_method(_MD("set_auto_accept_quit","enabled"),&SceneTree::set_auto_accept_quit);
 

+ 4 - 0
scene/main/scene_main_loop.h

@@ -279,6 +279,8 @@ public:
 	void set_editor_hint(bool p_enabled);
 	bool is_editor_hint() const;
 
+	bool is_node_being_edited(const Node* p_node) const;
+
 	void set_pause(bool p_enabled);
 	bool is_paused() const;
 
@@ -318,6 +320,8 @@ public:
 	void queue_delete(Object *p_object);
 
 	void get_nodes_in_group(const StringName& p_group,List<Node*> *p_list);
+	bool has_group(const StringName& p_identifier) const;
+
 
 	void set_screen_stretch(StretchMode p_mode,StretchAspect p_aspect,const Size2 p_minsize);