diff options
Diffstat (limited to 'scene/main/viewport.cpp')
-rw-r--r-- | scene/main/viewport.cpp | 209 |
1 files changed, 173 insertions, 36 deletions
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 5017ae61ff..49ecfee548 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -37,6 +37,7 @@ #include "servers/spatial_sound_2d_server.h" #include "scene/gui/control.h" #include "scene/3d/camera.h" +#include "scene/3d/listener.h" #include "scene/resources/mesh.h" #include "scene/3d/spatial_indexer.h" #include "scene/3d/collision_object.h" @@ -388,6 +389,19 @@ void Viewport::_notification(int p_what) { } break; case NOTIFICATION_READY: { #ifndef _3D_DISABLED + if (listeners.size() && !listener) { + Listener *first=NULL; + for(Set<Listener*>::Element *E=listeners.front();E;E=E->next()) { + + if (first==NULL || first->is_greater_than(E->get())) { + first=E->get(); + } + } + + if (first) + first->make_current(); + } + if (cameras.size() && !camera) { //there are cameras but no current camera, pick first in tree and make it current Camera *first=NULL; @@ -414,7 +428,7 @@ void Viewport::_notification(int p_what) { _vp_exit_tree(); VisualServer::get_singleton()->viewport_set_scenario(viewport,RID()); - SpatialSoundServer::get_singleton()->listener_set_space(listener,RID()); + SpatialSoundServer::get_singleton()->listener_set_space(internal_listener, RID()); VisualServer::get_singleton()->viewport_remove_canvas(viewport,current_canvas); if (contact_2d_debug.is_valid()) { VisualServer::get_singleton()->free(contact_2d_debug); @@ -740,10 +754,10 @@ Rect2 Viewport::get_rect() const { void Viewport::_update_listener() { - if (is_inside_tree() && audio_listener && camera && (!get_parent() || (get_parent()->cast_to<Control>() && get_parent()->cast_to<Control>()->is_visible()))) { - SpatialSoundServer::get_singleton()->listener_set_space(listener,find_world()->get_sound_space()); + if (is_inside_tree() && audio_listener && (camera || listener) && (!get_parent() || (get_parent()->cast_to<Control>() && get_parent()->cast_to<Control>()->is_visible()))) { + SpatialSoundServer::get_singleton()->listener_set_space(internal_listener, find_world()->get_sound_space()); } else { - SpatialSoundServer::get_singleton()->listener_set_space(listener,RID()); + SpatialSoundServer::get_singleton()->listener_set_space(internal_listener, RID()); } @@ -752,9 +766,9 @@ void Viewport::_update_listener() { void Viewport::_update_listener_2d() { if (is_inside_tree() && audio_listener && (!get_parent() || (get_parent()->cast_to<Control>() && get_parent()->cast_to<Control>()->is_visible()))) - SpatialSound2DServer::get_singleton()->listener_set_space(listener_2d,find_world_2d()->get_sound_space()); + SpatialSound2DServer::get_singleton()->listener_set_space(internal_listener_2d, find_world_2d()->get_sound_space()); else - SpatialSound2DServer::get_singleton()->listener_set_space(listener_2d,RID()); + SpatialSound2DServer::get_singleton()->listener_set_space(internal_listener_2d, RID()); } @@ -798,11 +812,11 @@ void Viewport::set_canvas_transform(const Matrix32& p_transform) { Matrix32 xform = (global_canvas_transform * canvas_transform).affine_inverse(); Size2 ss = get_visible_rect().size; - SpatialSound2DServer::get_singleton()->listener_set_transform(listener_2d,Matrix32(0,xform.xform(ss*0.5))); + SpatialSound2DServer::get_singleton()->listener_set_transform(internal_listener_2d, Matrix32(0, xform.xform(ss*0.5))); Vector2 ss2 = ss*xform.get_scale(); float panrange = MAX(ss2.x,ss2.y); - SpatialSound2DServer::get_singleton()->listener_set_param(listener_2d,SpatialSound2DServer::LISTENER_PARAM_PAN_RANGE,panrange); + SpatialSound2DServer::get_singleton()->listener_set_param(internal_listener_2d, SpatialSound2DServer::LISTENER_PARAM_PAN_RANGE, panrange); } @@ -823,11 +837,11 @@ void Viewport::_update_global_transform() { Matrix32 xform = (sxform * canvas_transform).affine_inverse(); Size2 ss = get_visible_rect().size; - SpatialSound2DServer::get_singleton()->listener_set_transform(listener_2d,Matrix32(0,xform.xform(ss*0.5))); + SpatialSound2DServer::get_singleton()->listener_set_transform(internal_listener_2d, Matrix32(0, xform.xform(ss*0.5))); Vector2 ss2 = ss*xform.get_scale(); float panrange = MAX(ss2.x,ss2.y); - SpatialSound2DServer::get_singleton()->listener_set_param(listener_2d,SpatialSound2DServer::LISTENER_PARAM_PAN_RANGE,panrange); + SpatialSound2DServer::get_singleton()->listener_set_param(internal_listener_2d, SpatialSound2DServer::LISTENER_PARAM_PAN_RANGE, panrange); } @@ -846,12 +860,75 @@ Matrix32 Viewport::get_global_canvas_transform() const{ return global_canvas_transform; } +void Viewport::_listener_transform_changed_notify() { + +#ifndef _3D_DISABLED + if (listener) + SpatialSoundServer::get_singleton()->listener_set_transform(internal_listener, listener->get_listener_transform()); +#endif +} + +void Viewport::_listener_set(Listener* p_listener) { + +#ifndef _3D_DISABLED + + if (listener == p_listener) + return; + + listener = p_listener; + + _update_listener(); + _listener_transform_changed_notify(); +#endif +} + +bool Viewport::_listener_add(Listener* p_listener) { + + listeners.insert(p_listener); + return listeners.size() == 1; +} + +void Viewport::_listener_remove(Listener* p_listener) { + + listeners.erase(p_listener); + if (listener == p_listener) { + listener = NULL; + } +} + +#ifndef _3D_DISABLED +void Viewport::_listener_make_next_current(Listener* p_exclude) { + + if (listeners.size() > 0) { + for (Set<Listener*>::Element *E = listeners.front(); E; E = E->next()) { + + if (p_exclude == E->get()) + continue; + if (!E->get()->is_inside_tree()) + continue; + if (listener != NULL) + return; + + E->get()->make_current(); + + } + } + else { + // Attempt to reset listener to the camera position + if (camera != NULL) { + _update_listener(); + _camera_transform_changed_notify(); + } + } +} +#endif void Viewport::_camera_transform_changed_notify() { #ifndef _3D_DISABLED - if (camera) - SpatialSoundServer::get_singleton()->listener_set_transform(listener,camera->get_camera_transform()); + // If there is an active listener in the scene, it takes priority over the camera + if (camera && !listener) + SpatialSoundServer::get_singleton()->listener_set_transform(internal_listener, camera->get_camera_transform()); #endif } @@ -985,6 +1062,16 @@ void Viewport::_propagate_enter_world(Node *p_node) { } } +void Viewport::_propagate_viewport_notification(Node* p_node,int p_what) { + + p_node->notification(p_what); + for(int i=0;i<p_node->get_child_count();i++) { + Node *c = p_node->get_child(i); + if (c->cast_to<Viewport>()) + continue; + _propagate_viewport_notification(c,p_what); + } +} void Viewport::_propagate_exit_world(Node *p_node) { @@ -1066,6 +1153,11 @@ Ref<World> Viewport::find_world() const{ return Ref<World>(); } +Listener* Viewport::get_listener() const { + + return listener; +} + Camera* Viewport::get_camera() const { return camera; @@ -1147,6 +1239,8 @@ void Viewport::set_as_render_target(bool p_enable){ render_target_texture->set_flags(render_target_texture->flags); render_target_texture->emit_changed(); + + update_configuration_warning(); } bool Viewport::is_set_as_render_target() const{ @@ -1346,7 +1440,6 @@ void Viewport::_vp_unhandled_input(const InputEvent& p_ev) { if (disable_input) return; - #ifdef TOOLS_ENABLED if (get_tree()->is_editor_hint() && get_tree()->get_edited_scene_root()->is_a_parent_of(this)) { return; @@ -1481,22 +1574,30 @@ void Viewport::_gui_call_input(Control *p_control,const InputEvent& p_input) { // _block(); - while(p_control) { - - p_control->call_multilevel(SceneStringNames::get_singleton()->_input_event,p_input); - if (gui.key_event_accepted) - break; - if (!p_control->is_inside_tree()) - break; - p_control->emit_signal(SceneStringNames::get_singleton()->input_event,p_input); - if (!p_control->is_inside_tree() || p_control->is_set_as_toplevel()) { - break; - } - if (gui.key_event_accepted) - break; - if (p_control->data.stop_mouse && (p_input.type==InputEvent::MOUSE_BUTTON || p_input.type==InputEvent::MOUSE_MOTION)) - break; - p_control=p_control->data.parent; + CanvasItem *ci=p_control; + while(ci) { + + Control *control = ci->cast_to<Control>(); + if (control) { + control->call_multilevel(SceneStringNames::get_singleton()->_input_event,p_input); + if (gui.key_event_accepted) + break; + if (!control->is_inside_tree()) + break; + control->emit_signal(SceneStringNames::get_singleton()->input_event,p_input); + if (!control->is_inside_tree() || control->is_set_as_toplevel()) { + break; + } + if (gui.key_event_accepted) + break; + if (control->data.stop_mouse && (p_input.type==InputEvent::MOUSE_BUTTON || p_input.type==InputEvent::MOUSE_MOTION)) + break; + } + + if (ci->is_set_as_toplevel()) + break; + + ci=ci->get_parent_item(); } //_unblock(); @@ -1676,6 +1777,9 @@ void Viewport::_gui_input_event(InputEvent p_event) { if (p_event.mouse_button.button_index==BUTTON_LEFT) { gui.drag_accum=Vector2(); gui.drag_attempted=false; + if (gui.drag_data.get_type()!=Variant::NIL) { + _propagate_viewport_notification(this,NOTIFICATION_DRAG_END); + } gui.drag_data=Variant(); } @@ -1736,6 +1840,7 @@ void Viewport::_gui_input_event(InputEvent p_event) { gui.mouse_over->drop_data(pos,gui.drag_data); gui.drag_data=Variant(); + _propagate_viewport_notification(this,NOTIFICATION_DRAG_END); //change mouse accordingly } @@ -1759,6 +1864,7 @@ void Viewport::_gui_input_event(InputEvent p_event) { } if (gui.drag_data.get_type()!=Variant::NIL && p_event.mouse_button.button_index==BUTTON_LEFT) { + _propagate_viewport_notification(this,NOTIFICATION_DRAG_END); gui.drag_data=Variant(); //always clear } @@ -1790,6 +1896,10 @@ void Viewport::_gui_input_event(InputEvent p_event) { gui.mouse_focus=NULL; } gui.drag_attempted=true; + if (gui.drag_data.get_type()!=Variant::NIL) { + + _propagate_viewport_notification(this,NOTIFICATION_DRAG_BEGIN); + } } } @@ -1814,11 +1924,15 @@ void Viewport::_gui_input_event(InputEvent p_event) { } } + + if (over!=gui.mouse_over) { if (gui.mouse_over) gui.mouse_over->notification(Control::NOTIFICATION_MOUSE_EXIT); + _gui_cancel_tooltip(); + if (over) over->notification(Control::NOTIFICATION_MOUSE_ENTER); @@ -1826,8 +1940,6 @@ void Viewport::_gui_input_event(InputEvent p_event) { gui.mouse_over=over; - _gui_cancel_tooltip(); - if (gui.drag_preview) { gui.drag_preview->set_pos(mpos); } @@ -1896,7 +2008,15 @@ void Viewport::_gui_input_event(InputEvent p_event) { if (gui.drag_data.get_type()!=Variant::NIL && p_event.mouse_motion.button_mask&BUTTON_MASK_LEFT) { - /*bool can_drop =*/ over->can_drop_data(pos,gui.drag_data); + + bool can_drop = over->can_drop_data(pos,gui.drag_data); + + if (!can_drop) { + OS::get_singleton()->set_cursor_shape( OS::CURSOR_FORBIDDEN ); + } else { + OS::get_singleton()->set_cursor_shape( OS::CURSOR_CAN_DROP ); + + } //change mouse accordingly i guess } @@ -2367,6 +2487,21 @@ bool Viewport::is_input_disabled() const { return disable_input; } +Variant Viewport::gui_get_drag_data() const { + return gui.drag_data; +} + + +String Viewport::get_configuration_warning() const { + + if (get_parent() && !get_parent()->cast_to<Control>() && !render_target) { + + return TTR("This viewport is not set as render target. If you intend for it to display its contents directly to the screen, make it a child of a Control so it can obtain a size. Otherwise, make it a RenderTarget and assign its internal texture to some node for display."); + } + + return String(); +} + void Viewport::_bind_methods() { @@ -2452,6 +2587,7 @@ void Viewport::_bind_methods() { ObjectTypeDB::bind_method(_MD("warp_mouse","to_pos"), &Viewport::warp_mouse); ObjectTypeDB::bind_method(_MD("gui_has_modal_stack"), &Viewport::gui_has_modal_stack); + ObjectTypeDB::bind_method(_MD("gui_get_drag_data:Variant"), &Viewport::gui_get_drag_data); ObjectTypeDB::bind_method(_MD("set_disable_input","disable"), &Viewport::set_disable_input); ObjectTypeDB::bind_method(_MD("is_input_disabled"), &Viewport::is_input_disabled); @@ -2493,12 +2629,13 @@ Viewport::Viewport() { world_2d = Ref<World2D>( memnew( World2D )); viewport = VisualServer::get_singleton()->viewport_create(); - listener=SpatialSoundServer::get_singleton()->listener_create(); + internal_listener = SpatialSoundServer::get_singleton()->listener_create(); audio_listener=false; - listener_2d=SpatialSound2DServer::get_singleton()->listener_create(); + internal_listener_2d = SpatialSound2DServer::get_singleton()->listener_create(); audio_listener_2d=false; transparent_bg=false; parent=NULL; + listener=NULL; camera=NULL; size_override=false; size_override_stretch=false; @@ -2546,8 +2683,8 @@ Viewport::Viewport() { Viewport::~Viewport() { VisualServer::get_singleton()->free( viewport ); - SpatialSoundServer::get_singleton()->free(listener); - SpatialSound2DServer::get_singleton()->free(listener_2d); + SpatialSoundServer::get_singleton()->free(internal_listener); + SpatialSound2DServer::get_singleton()->free(internal_listener_2d); if (render_target_texture.is_valid()) render_target_texture->vp=NULL; //so if used, will crash } |