diff options
author | Juan Linietsky <reduzio@gmail.com> | 2015-03-22 01:46:18 -0300 |
---|---|---|
committer | Juan Linietsky <reduzio@gmail.com> | 2015-03-22 01:46:18 -0300 |
commit | c6c72a3c37a44964ec8e6b3353f78635bf588eab (patch) | |
tree | 07cdc6f2a776dece704cce526cfd15ae04e44360 /scene | |
parent | 40496dd76ae53c93ef5ea7e56671682a7cae9def (diff) |
input events on Area2D is now supported
also added a demo showing how this works
Diffstat (limited to 'scene')
-rw-r--r-- | scene/2d/canvas_item.cpp | 62 | ||||
-rw-r--r-- | scene/2d/canvas_item.h | 1 | ||||
-rw-r--r-- | scene/2d/collision_object_2d.cpp | 71 | ||||
-rw-r--r-- | scene/2d/collision_object_2d.h | 12 | ||||
-rw-r--r-- | scene/2d/physics_body_2d.cpp | 1 | ||||
-rw-r--r-- | scene/main/viewport.cpp | 65 | ||||
-rw-r--r-- | scene/main/viewport.h | 1 | ||||
-rw-r--r-- | scene/resources/font.cpp | 4 |
8 files changed, 212 insertions, 5 deletions
diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp index 436b77a1ac..c3ff03d8f4 100644 --- a/scene/2d/canvas_item.cpp +++ b/scene/2d/canvas_item.cpp @@ -943,7 +943,67 @@ Ref<CanvasItemMaterial> CanvasItem::get_material() const{ } +InputEvent CanvasItem::make_input_local(const InputEvent& p_event) const { + ERR_FAIL_COND_V(!is_inside_tree(),p_event); + + InputEvent ev = p_event; + + Matrix32 local_matrix = (get_canvas_transform() * get_global_transform()).affine_inverse(); + + switch(ev.type) { + + case InputEvent::MOUSE_BUTTON: { + + Vector2 g = local_matrix.xform(Vector2(ev.mouse_button.global_x,ev.mouse_button.global_y)); + Vector2 l = local_matrix.xform(Vector2(ev.mouse_button.x,ev.mouse_button.y)); + ev.mouse_button.x=l.x; + ev.mouse_button.y=l.y; + ev.mouse_button.global_x=g.x; + ev.mouse_button.global_y=g.y; + + } break; + case InputEvent::MOUSE_MOTION: { + + Vector2 g = local_matrix.xform(Vector2(ev.mouse_motion.global_x,ev.mouse_motion.global_y)); + Vector2 l = local_matrix.xform(Vector2(ev.mouse_motion.x,ev.mouse_motion.y)); + Vector2 r = local_matrix.basis_xform(Vector2(ev.mouse_motion.relative_x,ev.mouse_motion.relative_y)); + Vector2 s = local_matrix.basis_xform(Vector2(ev.mouse_motion.speed_x,ev.mouse_motion.speed_y)); + ev.mouse_motion.x=l.x; + ev.mouse_motion.y=l.y; + ev.mouse_motion.global_x=g.x; + ev.mouse_motion.global_y=g.y; + ev.mouse_motion.relative_x=r.x; + ev.mouse_motion.relative_y=r.y; + ev.mouse_motion.speed_x=s.x; + ev.mouse_motion.speed_y=s.y; + + } break; + case InputEvent::SCREEN_TOUCH: { + + + Vector2 t = local_matrix.xform(Vector2(ev.screen_touch.x,ev.screen_touch.y)); + ev.screen_touch.x=t.x; + ev.screen_touch.y=t.y; + + } break; + case InputEvent::SCREEN_DRAG: { + + + Vector2 t = local_matrix.xform(Vector2(ev.screen_drag.x,ev.screen_drag.y)); + Vector2 r = local_matrix.basis_xform(Vector2(ev.screen_drag.relative_x,ev.screen_drag.relative_y)); + Vector2 s = local_matrix.basis_xform(Vector2(ev.screen_drag.speed_x,ev.screen_drag.speed_y)); + ev.screen_drag.x=t.x; + ev.screen_drag.y=t.y; + ev.screen_drag.relative_x=r.x; + ev.screen_drag.relative_y=r.y; + ev.screen_drag.speed_x=s.x; + ev.screen_drag.speed_y=s.y; + } break; + } + + return ev; +} void CanvasItem::_bind_methods() { @@ -1021,6 +1081,8 @@ void CanvasItem::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_use_parent_material","enable"),&CanvasItem::set_use_parent_material); ObjectTypeDB::bind_method(_MD("get_use_parent_material"),&CanvasItem::get_use_parent_material); + ObjectTypeDB::bind_method(_MD("make_input_local","event"),&CanvasItem::make_input_local); + BIND_VMETHOD(MethodInfo("_draw")); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"visibility/visible"), _SCS("_set_visible_"),_SCS("_is_visible_") ); diff --git a/scene/2d/canvas_item.h b/scene/2d/canvas_item.h index 0c7be261ab..c43642a8ec 100644 --- a/scene/2d/canvas_item.h +++ b/scene/2d/canvas_item.h @@ -249,6 +249,7 @@ public: void set_use_parent_material(bool p_use_parent_material); bool get_use_parent_material() const; + InputEvent make_input_local(const InputEvent& pevent) const; CanvasItem(); ~CanvasItem(); diff --git a/scene/2d/collision_object_2d.cpp b/scene/2d/collision_object_2d.cpp index 3b859d9366..a883fee103 100644 --- a/scene/2d/collision_object_2d.cpp +++ b/scene/2d/collision_object_2d.cpp @@ -28,6 +28,7 @@ /*************************************************************************/ #include "collision_object_2d.h" #include "servers/physics_2d_server.h" +#include "scene/scene_string_names.h" void CollisionObject2D::_update_shapes_from_children() { @@ -58,9 +59,15 @@ void CollisionObject2D::_notification(int p_what) { } else Physics2DServer::get_singleton()->body_set_space(rid,space); + _update_pickable(); + //get space } + case NOTIFICATION_VISIBILITY_CHANGED: { + + _update_pickable(); + } break; case NOTIFICATION_TRANSFORM_CHANGED: { if (area) @@ -166,6 +173,57 @@ void CollisionObject2D::_get_property_list( List<PropertyInfo> *p_list) const { } } + +void CollisionObject2D::set_pickable(bool p_enabled) { + + if (pickable==p_enabled) + return; + + pickable=p_enabled; + _update_pickable(); +} + +bool CollisionObject2D::is_pickable() const { + + return pickable; +} + +void CollisionObject2D::_input_event(Node *p_viewport, const InputEvent& p_input_event, int p_shape) { + + if (get_script_instance()) { + get_script_instance()->call(SceneStringNames::get_singleton()->_input_event,p_viewport,p_input_event,p_shape); + } + emit_signal(SceneStringNames::get_singleton()->input_event,p_viewport,p_input_event,p_shape); +} + +void CollisionObject2D::_mouse_enter() { + + if (get_script_instance()) { + get_script_instance()->call(SceneStringNames::get_singleton()->_mouse_enter); + } + emit_signal(SceneStringNames::get_singleton()->mouse_enter); +} + + +void CollisionObject2D::_mouse_exit() { + + if (get_script_instance()) { + get_script_instance()->call(SceneStringNames::get_singleton()->_mouse_exit); + } + emit_signal(SceneStringNames::get_singleton()->mouse_exit); + +} + +void CollisionObject2D::_update_pickable() { + if (!is_inside_tree()) + return; + bool pickable = this->pickable && is_inside_tree() && is_visible(); + if (area) + Physics2DServer::get_singleton()->area_set_pickable(rid,pickable); + else + Physics2DServer::get_singleton()->body_set_pickable(rid,pickable); +} + void CollisionObject2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("add_shape","shape:Shape2D","transform"),&CollisionObject2D::add_shape,DEFVAL(Matrix32())); @@ -180,6 +238,17 @@ void CollisionObject2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("clear_shapes"),&CollisionObject2D::clear_shapes); ObjectTypeDB::bind_method(_MD("get_rid"),&CollisionObject2D::get_rid); + ObjectTypeDB::bind_method(_MD("set_pickable","enabled"),&CollisionObject2D::set_pickable); + ObjectTypeDB::bind_method(_MD("is_pickable"),&CollisionObject2D::is_pickable); + + BIND_VMETHOD( MethodInfo("_input_event",PropertyInfo(Variant::OBJECT,"viewport"),PropertyInfo(Variant::INPUT_EVENT,"event"),PropertyInfo(Variant::INT,"shape_idx"))); + + ADD_SIGNAL( MethodInfo("input_event",PropertyInfo(Variant::OBJECT,"viewport"),PropertyInfo(Variant::INPUT_EVENT,"event"),PropertyInfo(Variant::INT,"shape_idx"))); + ADD_SIGNAL( MethodInfo("mouse_enter")); + ADD_SIGNAL( MethodInfo("mouse_exit")); + + ADD_PROPERTY( PropertyInfo(Variant::BOOL,"input/pickable"),_SCS("set_pickable"),_SCS("is_pickable")); + } @@ -262,7 +331,9 @@ CollisionObject2D::CollisionObject2D(RID p_rid, bool p_area) { rid=p_rid; area=p_area; + pickable=true; if (p_area) { + Physics2DServer::get_singleton()->area_attach_object_instance_ID(rid,get_instance_ID()); } else { Physics2DServer::get_singleton()->body_attach_object_instance_ID(rid,get_instance_ID()); diff --git a/scene/2d/collision_object_2d.h b/scene/2d/collision_object_2d.h index 4a529ce062..393973ce90 100644 --- a/scene/2d/collision_object_2d.h +++ b/scene/2d/collision_object_2d.h @@ -38,6 +38,7 @@ class CollisionObject2D : public Node2D { bool area; RID rid; + bool pickable; struct ShapeData { Matrix32 xform; @@ -66,9 +67,17 @@ protected: bool _get(const StringName& p_name,Variant &r_ret) const; void _get_property_list( List<PropertyInfo> *p_list) const; static void _bind_methods(); + + void _update_pickable(); +friend class Viewport; + void _input_event(Node *p_viewport, const InputEvent& p_input_event, int p_shape); + void _mouse_enter(); + void _mouse_exit(); + public: + void add_shape(const Ref<Shape2D>& p_shape, const Matrix32& p_transform=Matrix32()); int get_shape_count() const; void set_shape(int p_shape_idx, const Ref<Shape2D>& p_shape); @@ -80,6 +89,9 @@ public: void remove_shape(int p_shape_idx); void clear_shapes(); + void set_pickable(bool p_enabled); + bool is_pickable() const; + _FORCE_INLINE_ RID get_rid() const { return rid; } CollisionObject2D(); diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index 6f18325212..22dd0f01d0 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -98,6 +98,7 @@ PhysicsBody2D::PhysicsBody2D(Physics2DServer::BodyMode p_mode) : CollisionObject mask=1; set_one_way_collision_max_depth(0); + set_pickable(false); } diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 02e009866f..18b8b46d90 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -30,7 +30,7 @@ #include "os/os.h" #include "scene/3d/spatial.h" #include "os/input.h" - +#include "servers/physics_2d_server.h" //#include "scene/3d/camera.h" #include "servers/spatial_sound_server.h" @@ -40,7 +40,7 @@ #include "scene/3d/spatial_indexer.h" #include "scene/3d/collision_object.h" - +#include "scene/2d/collision_object_2d.h" int RenderTargetTexture::get_width() const { @@ -355,11 +355,12 @@ void Viewport::_notification(int p_what) { case NOTIFICATION_FIXED_PROCESS: { if (physics_object_picking) { -#ifndef _3D_DISABLED + Vector2 last_pos(1e20,1e20); CollisionObject *last_object; ObjectID last_id=0; PhysicsDirectSpaceState::RayResult result; + Physics2DDirectSpaceState *ss2d=Physics2DServer::get_singleton()->space_get_direct_state(find_world_2d()->get_space()); bool motion_tested=false; @@ -392,6 +393,60 @@ void Viewport::_notification(int p_what) { } + if (ss2d) { + //send to 2D + + + uint64_t frame = get_tree()->get_frame(); + + Vector2 point = get_canvas_transform().affine_inverse().xform(pos); + Physics2DDirectSpaceState::ShapeResult res[64]; + int rc = ss2d->intersect_point(point,res,64,Set<RID>(),0xFFFFFFFF,0xFFFFFFFF); + for(int i=0;i<rc;i++) { + + if (res[i].collider) { + CollisionObject2D *co=res[i].collider->cast_to<CollisionObject2D>(); + if (co) { + + Map<ObjectID,uint64_t>::Element *E=physics_2d_mouseover.find(res[i].collider_id); + if (!E) { + E=physics_2d_mouseover.insert(res[i].collider_id,frame); + co->_mouse_enter(); + } else { + E->get()=frame; + } + + co->_input_event(this,ev,res[i].shape); + } + } + } + + List<Map<ObjectID,uint64_t>::Element*> to_erase; + + for (Map<ObjectID,uint64_t>::Element*E=physics_2d_mouseover.front();E;E=E->next()) { + if (E->get()!=frame) { + Object *o=ObjectDB::get_instance(E->key()); + if (o) { + + CollisionObject2D *co=o->cast_to<CollisionObject2D>(); + if (co) { + co->_mouse_exit(); + } + } + to_erase.push_back(E); + } + } + + while(to_erase.size()) { + physics_2d_mouseover.erase(to_erase.front()->get()); + to_erase.pop_front(); + } + + } + + + +#ifndef _3D_DISABLED bool captured=false; if (physics_object_capture!=0) { @@ -499,9 +554,9 @@ void Viewport::_notification(int p_what) { _test_new_mouseover(new_collider); } - - } #endif + } + } } break; diff --git a/scene/main/viewport.h b/scene/main/viewport.h index d2a22401bd..14f4f68217 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -124,6 +124,7 @@ friend class RenderTargetTexture; ObjectID physics_object_over; Vector2 physics_last_mousepos; void _test_new_mouseover(ObjectID new_collider); + Map<ObjectID,uint64_t> physics_2d_mouseover; void _update_rect(); diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp index 24d413ed60..79316f0019 100644 --- a/scene/resources/font.cpp +++ b/scene/resources/font.cpp @@ -523,6 +523,10 @@ void Font::_bind_methods() { ObjectTypeDB::bind_method(_MD("add_texture","texture:Texture"),&Font::add_texture); ObjectTypeDB::bind_method(_MD("add_char","character","texture","rect","align","advance"),&Font::add_char,DEFVAL(Point2()),DEFVAL(-1)); + + ObjectTypeDB::bind_method(_MD("get_texture_count"),&Font::get_texture_count); + ObjectTypeDB::bind_method(_MD("get_texture:Texture","idx"),&Font::get_texture); + ObjectTypeDB::bind_method(_MD("get_char_size","char","next"),&Font::get_char_size,DEFVAL(0)); ObjectTypeDB::bind_method(_MD("get_string_size","string"),&Font::get_string_size); |