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

This commit is contained in:
Juan Linietsky 2016-01-02 17:18:45 -03:00
parent 8fb70142e4
commit 2db78e8f87
4 changed files with 56 additions and 73 deletions

View File

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

View File

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

View File

@ -620,6 +620,10 @@ void SceneTree::set_editor_hint(bool p_enabled) {
editor_hint=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 { bool SceneTree::is_editor_hint() const {
return editor_hint; return editor_hint;
@ -965,6 +969,10 @@ Array SceneTree::_get_nodes_in_group(const StringName& p_group) {
return ret; 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) { 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_nodes_in_group","group"),&SceneTree::_get_nodes_in_group);
ObjectTypeDB::bind_method(_MD("get_root:Viewport"),&SceneTree::get_root); 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); ObjectTypeDB::bind_method(_MD("set_auto_accept_quit","enabled"),&SceneTree::set_auto_accept_quit);

View File

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