summaryrefslogtreecommitdiff
path: root/scene/main/viewport.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'scene/main/viewport.cpp')
-rw-r--r--scene/main/viewport.cpp224
1 files changed, 223 insertions, 1 deletions
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index ea78ece9dc..92dcef803c 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -36,6 +36,7 @@
#include "scene/gui/control.h"
#include "scene/3d/camera.h"
#include "scene/3d/spatial_indexer.h"
+#include "scene/3d/collision_object.h"
@@ -94,6 +95,8 @@ void Viewport::_update_stretch_transform() {
if (size_override_stretch && size_override) {
+ print_line("sive override size "+size_override_size);
+ print_line("rect size "+rect.size);
stretch_transform=Matrix32();
Size2 scale = rect.size/(size_override_size+size_override_margin*2);
stretch_transform.scale(scale);
@@ -233,6 +236,40 @@ void Viewport::update_worlds() {
find_world()->_update(get_scene()->get_frame());
}
+
+void Viewport::_test_new_mouseover(ObjectID new_collider) {
+
+ if (new_collider!=physics_object_over) {
+
+ if (physics_object_over) {
+ Object *obj = ObjectDB::get_instance(physics_object_over);
+ if (obj) {
+ CollisionObject *co = obj->cast_to<CollisionObject>();
+ if (co) {
+ co->_mouse_exit();
+ }
+ }
+ }
+
+ if (new_collider) {
+ Object *obj = ObjectDB::get_instance(new_collider);
+ if (obj) {
+ CollisionObject *co = obj->cast_to<CollisionObject>();
+ if (co) {
+ co->_mouse_enter();
+
+ }
+ }
+
+ }
+
+ physics_object_over=new_collider;
+
+ }
+
+
+}
+
void Viewport::_notification(int p_what) {
@@ -308,6 +345,155 @@ void Viewport::_notification(int p_what) {
remove_from_group("_viewports");
} break;
+ case NOTIFICATION_FIXED_PROCESS: {
+
+ if (physics_object_picking) {
+
+ Vector2 last_pos(1e20,1e20);
+ CollisionObject *last_object;
+ ObjectID last_id=0;
+ PhysicsDirectSpaceState::RayResult result;
+
+ bool motion_tested=false;
+
+ while(physics_picking_events.size()) {
+
+ InputEvent ev = physics_picking_events.front()->get();
+ physics_picking_events.pop_front();
+
+ Vector2 pos;
+ switch(ev.type) {
+ case InputEvent::MOUSE_MOTION: {
+ pos.x=ev.mouse_motion.x;
+ pos.y=ev.mouse_motion.y;
+ motion_tested=true;
+ physics_last_mousepos=pos;
+ } break;
+ case InputEvent::MOUSE_BUTTON: {
+ pos.x=ev.mouse_button.x;
+ pos.y=ev.mouse_button.y;
+
+ } break;
+ case InputEvent::SCREEN_DRAG: {
+ pos.x=ev.screen_drag.x;
+ pos.y=ev.screen_drag.y;
+ } break;
+ case InputEvent::SCREEN_TOUCH: {
+ pos.x=ev.screen_touch.x;
+ pos.y=ev.screen_touch.y;
+ } break;
+
+ }
+
+ bool captured=false;
+
+ if (physics_object_capture!=0) {
+
+
+ Object *obj = ObjectDB::get_instance(physics_object_capture);
+ if (obj) {
+ CollisionObject *co = obj->cast_to<CollisionObject>();
+ if (co) {
+ co->_input_event(ev,Vector3(),Vector3(),0);
+ captured=true;
+ if (ev.type==InputEvent::MOUSE_BUTTON && ev.mouse_button.button_index==1 && !ev.mouse_button.pressed) {
+ physics_object_capture=0;
+ }
+
+ } else {
+ physics_object_capture=0;
+ }
+ } else {
+ physics_object_capture=0;
+ }
+ }
+
+
+ if (captured) {
+ //none
+ } else if (pos==last_pos) {
+
+ if (last_id) {
+ if (ObjectDB::get_instance(last_id)) {
+ //good, exists
+ last_object->_input_event(ev,result.position,result.normal,result.shape);
+ if (last_object->get_capture_input_on_drag() && ev.type==InputEvent::MOUSE_BUTTON && ev.mouse_button.button_index==1 && ev.mouse_button.pressed) {
+ physics_object_capture=last_id;
+ }
+
+
+ }
+ }
+ } else {
+
+
+
+
+ if (camera) {
+
+ Vector3 from = camera->project_ray_origin(pos);
+ Vector3 dir = camera->project_ray_normal(pos);
+
+ PhysicsDirectSpaceState *space = PhysicsServer::get_singleton()->space_get_direct_state(find_world()->get_space());
+ if (space) {
+
+ bool col = space->intersect_ray(from,from+dir*10000,result,Set<RID>(),0xFFFFFFFF,0xFFFFFFFF);
+ ObjectID new_collider=0;
+ if (col) {
+ if (result.collider) {
+ CollisionObject *co = result.collider->cast_to<CollisionObject>();
+ if (co) {
+ co->_input_event(ev,result.position,result.normal,result.shape);
+ last_object=co;
+ last_id=result.collider_id;
+ new_collider=last_id;
+ if (co->get_capture_input_on_drag() && ev.type==InputEvent::MOUSE_BUTTON && ev.mouse_button.button_index==1 && ev.mouse_button.pressed) {
+ physics_object_capture=last_id;
+ }
+
+ }
+ }
+ }
+
+ if (ev.type==InputEvent::MOUSE_MOTION) {
+ _test_new_mouseover(new_collider);
+ }
+ }
+
+ last_pos=pos;
+ }
+ }
+ }
+
+ if (!motion_tested && camera && physics_last_mousepos!=Vector2(1e20,1e20)) {
+
+ //test anyway for mouseenter/exit because objects might move
+ Vector3 from = camera->project_ray_origin(physics_last_mousepos);
+ Vector3 dir = camera->project_ray_normal(physics_last_mousepos);
+
+ PhysicsDirectSpaceState *space = PhysicsServer::get_singleton()->space_get_direct_state(find_world()->get_space());
+ if (space) {
+
+ bool col = space->intersect_ray(from,from+dir*10000,result,Set<RID>(),0xFFFFFFFF,0xFFFFFFFF);
+ ObjectID new_collider=0;
+ if (col) {
+ if (result.collider) {
+ CollisionObject *co = result.collider->cast_to<CollisionObject>();
+ if (co) {
+ new_collider=result.collider_id;
+
+ }
+ }
+ }
+
+ _test_new_mouseover(new_collider);
+
+ }
+
+ }
+ }
+
+ } break;
}
}
@@ -888,7 +1074,8 @@ void Viewport::_vp_input(const InputEvent& p_ev) {
void Viewport::_vp_unhandled_input(const InputEvent& p_ev) {
- if (render_target)
+
+ if (render_target && to_screen_rect==Rect2())
return; //if render target, can't get input events
//this one handles system input, p_ev are in system coordinates
@@ -917,6 +1104,15 @@ void Viewport::unhandled_input(const InputEvent& p_event) {
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);
}
+
+
+ if (physics_object_picking && !get_scene()->input_handled) {
+
+ if (p_event.type==InputEvent::MOUSE_BUTTON || p_event.type==InputEvent::MOUSE_MOTION || p_event.type==InputEvent::SCREEN_DRAG || p_event.type==InputEvent::SCREEN_TOUCH) {
+ physics_picking_events.push_back(p_event);
+ }
+ }
+
}
void Viewport::set_use_own_world(bool p_world) {
@@ -973,6 +1169,22 @@ Rect2 Viewport::get_render_target_to_screen_rect() const{
return to_screen_rect;
}
+void Viewport::set_physics_object_picking(bool p_enable) {
+
+ physics_object_picking=p_enable;
+ set_fixed_process(physics_object_picking);
+ if (!physics_object_picking)
+ physics_picking_events.clear();
+
+
+}
+
+bool Viewport::get_physics_object_picking() {
+
+
+ return physics_object_picking;
+}
+
void Viewport::_bind_methods() {
@@ -1028,6 +1240,9 @@ void Viewport::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_render_target_texture:RenderTargetTexture"), &Viewport::get_render_target_texture);
+ ObjectTypeDB::bind_method(_MD("set_physics_object_picking","enable"), &Viewport::set_physics_object_picking);
+ ObjectTypeDB::bind_method(_MD("get_physics_object_picking"), &Viewport::get_physics_object_picking);
+
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);
@@ -1037,6 +1252,7 @@ void Viewport::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_use_own_world","enable"), &Viewport::set_use_own_world);
ObjectTypeDB::bind_method(_MD("is_using_own_world"), &Viewport::is_using_own_world);
+ ObjectTypeDB::bind_method(_MD("get_camera:Camera"), &Viewport::get_camera);
ObjectTypeDB::bind_method(_MD("set_as_audio_listener","enable"), &Viewport::set_as_audio_listener);
ObjectTypeDB::bind_method(_MD("is_audio_listener","enable"), &Viewport::is_audio_listener);
@@ -1058,6 +1274,7 @@ void Viewport::_bind_methods() {
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") );
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"physics/object_picking"), _SCS("set_physics_object_picking"), _SCS("get_physics_object_picking") );
ADD_SIGNAL(MethodInfo("size_changed"));
@@ -1093,6 +1310,11 @@ Viewport::Viewport() {
render_target_update_mode=RENDER_TARGET_UPDATE_WHEN_VISIBLE;
render_target_texture = Ref<RenderTargetTexture>( memnew( RenderTargetTexture(this) ) );
+ physics_object_picking=false;
+ physics_object_capture=0;
+ physics_object_over=0;
+ physics_last_mousepos=Vector2(1e20,1e20);
+
String id=itos(get_instance_ID());
input_group = "_vp_input"+id;