From 5e3a4c13da5971b48ff8f0434165ea9da2084479 Mon Sep 17 00:00:00 2001 From: yg2f Date: Sat, 10 Jan 2015 15:11:44 +0100 Subject: fixes cubemap ressource editor bug this fixes the cubemap ressource editor bug described in issue #908. some other littles fixes will be required to allow the Environment ressource to create and load Cubemap Ressources more easily --- scene/resources/texture.cpp | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'scene') diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index dae055890b..889042f451 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -935,21 +935,21 @@ float CubeMap::get_lossy_storage_quality() const { bool CubeMap::_set(const StringName& p_name, const Variant& p_value) { - if (p_name=="side/left") + if (p_name=="side/left") { set_side(SIDE_LEFT,p_value); - if (p_name=="side/right") + } else if (p_name=="side/right") { set_side(SIDE_RIGHT,p_value); - if (p_name=="side/bottom") + } else if (p_name=="side/bottom") { set_side(SIDE_BOTTOM,p_value); - if (p_name=="side/top") + } else if (p_name=="side/top") { set_side(SIDE_TOP,p_value); - if (p_name=="side/front") + } else if (p_name=="side/front") { set_side(SIDE_FRONT,p_value); - if (p_name=="side/back") + } else if (p_name=="side/back") { set_side(SIDE_BACK,p_value); - else if (p_name=="flags") + } else if (p_name=="flags") { set_flags(p_value); - else if (p_name=="storage") { + } else if (p_name=="storage") { storage=Storage(p_value.operator int()); } else if (p_name=="lossy_quality") { lossy_storage_quality=p_value; @@ -962,25 +962,25 @@ bool CubeMap::_set(const StringName& p_name, const Variant& p_value) { bool CubeMap::_get(const StringName& p_name,Variant &r_ret) const { - if (p_name=="side/left") + if (p_name=="side/left") { r_ret=get_side(SIDE_LEFT); - if (p_name=="side/right") + } else if (p_name=="side/right") { r_ret=get_side(SIDE_RIGHT); - if (p_name=="side/bottom") + } else if (p_name=="side/bottom") { r_ret=get_side(SIDE_BOTTOM); - if (p_name=="side/top") + } else if (p_name=="side/top") { r_ret=get_side(SIDE_TOP); - if (p_name=="side/front") + } else if (p_name=="side/front") { r_ret=get_side(SIDE_FRONT); - if (p_name=="side/back") + } else if (p_name=="side/back") { r_ret=get_side(SIDE_BACK); - else if (p_name=="flags") + } else if (p_name=="flags") { r_ret= flags; - else if (p_name=="storage") + } else if (p_name=="storage") { r_ret= storage; - else if (p_name=="lossy_quality") + } else if (p_name=="lossy_quality") { r_ret= lossy_storage_quality; - else + } else return false; return true; -- cgit v1.2.3 From 67d357191ff74b2cfc80015941363a97e7ee19fd Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Thu, 22 Jan 2015 11:07:16 -0300 Subject: begin work on lighting system for 2D nothing functional yet, just experimenting with API --- scene/gui/tree.cpp | 4 ++++ scene/resources/shader_graph.cpp | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'scene') diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index b7b52a39dc..035dbb8cc4 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -2472,6 +2472,10 @@ void Tree::_notification(int p_what) { } } + if (p_what==NOTIFICATION_THEME_CHANGED) { + update_cache(); + } + } diff --git a/scene/resources/shader_graph.cpp b/scene/resources/shader_graph.cpp index 2630bc5bad..b0d9ceee0e 100644 --- a/scene/resources/shader_graph.cpp +++ b/scene/resources/shader_graph.cpp @@ -1289,7 +1289,7 @@ const ShaderGraph::InOutParamInfo ShaderGraph::inout_param_info[]={ {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"Binormal","BINORMAL","",SLOT_TYPE_VEC,SLOT_IN}, {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"UV","vec3(UV,0);","",SLOT_TYPE_VEC,SLOT_IN}, {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"UV2","UV2","",SLOT_TYPE_VEC,SLOT_IN}, - {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"UVScreen","SCREEN_UV","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"UVScreen","vec3(SCREEN_UV,0)","",SLOT_TYPE_VEC,SLOT_IN}, {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"PointCoord","POINT_COORD","",SLOT_TYPE_VEC,SLOT_IN}, {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"Color","COLOR.rgb","",SLOT_TYPE_VEC,SLOT_IN}, {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"Alpha","COLOR.a","",SLOT_TYPE_SCALAR,SLOT_IN}, -- cgit v1.2.3 From 79e330c33ee04c04f5ce3e6f88cb767057184de2 Mon Sep 17 00:00:00 2001 From: jaromirhribal Date: Sat, 31 Jan 2015 18:02:49 +0100 Subject: fixed math in Camera::project_position --- scene/3d/camera.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scene') diff --git a/scene/3d/camera.cpp b/scene/3d/camera.cpp index 27420f8002..95eafa0df4 100644 --- a/scene/3d/camera.cpp +++ b/scene/3d/camera.cpp @@ -604,7 +604,7 @@ Vector3 Camera::project_position(const Point2& p_point) const { Vector2 point; point.x = (p_point.x/viewport_size.x) * 2.0 - 1.0; - point.y = (p_point.y/viewport_size.y) * 2.0 - 1.0; + point.y = (1.0-(p_point.y/viewport_size.y)) * 2.0 - 1.0; point*=vp_size; Vector3 p(point.x,point.y,-near); -- cgit v1.2.3 From 8db3c0a4dbf32d498bd9dfd84eab7f4a18757fea Mon Sep 17 00:00:00 2001 From: romulox_x Date: Sun, 1 Feb 2015 09:23:31 -0800 Subject: changed PolygonPathFinder::get_closest_point to return the closest position inside, rather then the closest vertex --- scene/resources/polygon_path_finder.cpp | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) (limited to 'scene') diff --git a/scene/resources/polygon_path_finder.cpp b/scene/resources/polygon_path_finder.cpp index 9f691d6ad3..e8cdec66df 100644 --- a/scene/resources/polygon_path_finder.cpp +++ b/scene/resources/polygon_path_finder.cpp @@ -525,24 +525,32 @@ bool PolygonPathFinder::is_point_inside(const Vector2& p_point) const { Vector2 PolygonPathFinder::get_closest_point(const Vector2& p_point) const { - int closest_idx=-1; float closest_dist=1e20; - for(int i=0;i::Element *E=edges.front();E;E=E->next()) { + + const Edge& e=E->get(); + Vector2 seg[2]={ + points[e.points[0]].pos, + points[e.points[1]].pos + }; + + + Vector2 closest = Geometry::get_closest_point_to_segment_2d(p_point,seg); + float d = p_point.distance_squared_to(closest); - float d = p_point.distance_squared_to(points[i].pos); if (d PolygonPathFinder::get_intersections(const Vector2& p_from, const Vector2& p_to) const { Vector inters; -- cgit v1.2.3 From d22b256f0841a0ff97f45c5a11aeccd7658b79fa Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Tue, 10 Feb 2015 23:53:04 -0300 Subject: customizable content margin in styleboxes --- scene/resources/style_box.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'scene') diff --git a/scene/resources/style_box.cpp b/scene/resources/style_box.cpp index 316b5e91eb..ca4bd3d253 100644 --- a/scene/resources/style_box.cpp +++ b/scene/resources/style_box.cpp @@ -85,6 +85,12 @@ void StyleBox::_bind_methods() { ObjectTypeDB::bind_method(_MD("draw"),&StyleBox::draw); + ADD_PROPERTYI( PropertyInfo( Variant::REAL, "content_margin/left", PROPERTY_HINT_RANGE,"-1,2048,1" ), _SCS("set_default_margin"),_SCS("get_default_margin"), MARGIN_LEFT ); + ADD_PROPERTYI( PropertyInfo( Variant::REAL, "content_margin/right", PROPERTY_HINT_RANGE,"-1,2048,1" ), _SCS("set_default_margin"),_SCS("get_default_margin"), MARGIN_RIGHT ); + ADD_PROPERTYI( PropertyInfo( Variant::REAL, "content_margin/top", PROPERTY_HINT_RANGE,"-1,2048,1" ), _SCS("set_default_margin"),_SCS("get_default_margin"), MARGIN_TOP); + ADD_PROPERTYI( PropertyInfo( Variant::REAL, "content_margin/bottom", PROPERTY_HINT_RANGE,"-1,2048,1" ), _SCS("set_default_margin"),_SCS("get_default_margin"), MARGIN_BOTTOM ); + + } StyleBox::StyleBox() { -- cgit v1.2.3 From 1d54c2dd1c94cd8b44fc9cd5a67deba88dbabdda Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Wed, 11 Feb 2015 06:51:20 -0300 Subject: added missing set_shader_param functions also added code completion hint for shader params --- scene/2d/canvas_item.cpp | 23 ++++++++++++++++++++++- scene/2d/canvas_item.h | 2 ++ scene/resources/material.cpp | 2 +- 3 files changed, 25 insertions(+), 2 deletions(-) (limited to 'scene') diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp index 6b892839bb..44a7e25725 100644 --- a/scene/2d/canvas_item.cpp +++ b/scene/2d/canvas_item.cpp @@ -810,6 +810,23 @@ void CanvasItem::_shader_changed() { } #endif +void CanvasItem::get_argument_options(const StringName& p_function,int p_idx,List*r_options) const { + + if (p_idx==0 && shader.is_valid() && (p_function.operator String()=="get_shader_param" || p_function.operator String()=="set_shader_param")) { + + List pl; + shader->get_param_list(&pl); + for(List::Element *E=pl.front();E;E=E->next()) { + r_options->push_back("\""+E->get().name.replace_first("shader_param/","")+"\""); + } + + return; + } + + Node::get_argument_options(p_function,p_idx,r_options); +} + + void CanvasItem::_bind_methods() { ObjectTypeDB::bind_method(_MD("_sort_children"),&CanvasItem::_sort_children); @@ -845,7 +862,7 @@ void CanvasItem::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_self_opacity","self_opacity"),&CanvasItem::set_self_opacity); ObjectTypeDB::bind_method(_MD("get_self_opacity"),&CanvasItem::get_self_opacity); - ObjectTypeDB::bind_method(_MD("set_draw_behind_parent","enabe"),&CanvasItem::set_draw_behind_parent); + ObjectTypeDB::bind_method(_MD("set_draw_behind_parent","enable"),&CanvasItem::set_draw_behind_parent); ObjectTypeDB::bind_method(_MD("is_draw_behind_parent_enabled"),&CanvasItem::is_draw_behind_parent_enabled); ObjectTypeDB::bind_method(_MD("_set_on_top","on_top"),&CanvasItem::_set_on_top); @@ -882,6 +899,10 @@ void CanvasItem::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_use_parent_shader","enable"),&CanvasItem::set_use_parent_shader); ObjectTypeDB::bind_method(_MD("get_use_parent_shader"),&CanvasItem::get_use_parent_shader); + ObjectTypeDB::bind_method(_MD("set_shader_param","param","value"),&CanvasItem::set_shader_param); + ObjectTypeDB::bind_method(_MD("get_shader_param","param"),&CanvasItem::get_shader_param); + + 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 ed3ade9df2..e7260a6530 100644 --- a/scene/2d/canvas_item.h +++ b/scene/2d/canvas_item.h @@ -221,6 +221,8 @@ public: void set_shader_param(const StringName& p_param,const Variant& p_value); Variant get_shader_param(const StringName& p_param) const; + void get_argument_options(const StringName& p_function,int p_idx,List*r_options) const; + CanvasItem(); ~CanvasItem(); }; diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index 08c752cff9..633dd72ce3 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -582,7 +582,7 @@ void ShaderMaterial::get_argument_options(const StringName& p_function,int p_idx List pl; shader->get_param_list(&pl); for (List::Element *E=pl.front();E;E=E->next()) { - r_options->push_back("\""+E->get().name.replace("shader_param/","")+"\""); + r_options->push_back("\""+E->get().name.replace_first("shader_param/","")+"\""); } } } -- cgit v1.2.3 From 9d182e93a3d75396405733109f9f086969c4b19b Mon Sep 17 00:00:00 2001 From: Carl Olsson Date: Fri, 13 Feb 2015 20:49:21 +1000 Subject: Added body mode property to TileMap to select between static and kinematic physics bodies. Kinematic allow use of TileMaps for moving platforms for example. Updated 2D Platformer demo to use kinematic TileMaps for moving platforms, in doing so discovered that the tileset was messed up and not converting properly, so fixed that too. And in order to fix the tileset I need to activate snapping for collision polygon vertices. --- scene/2d/tile_map.cpp | 51 ++++++++++++++++++++++++++++++++++----------------- scene/2d/tile_map.h | 11 ++++++++--- 2 files changed, 42 insertions(+), 20 deletions(-) (limited to 'scene') diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index 9fcf34cee6..06c97027f0 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -28,7 +28,7 @@ /*************************************************************************/ #include "tile_map.h" #include "io/marshalls.h" -#include "servers/physics_2d_server.h" + void TileMap::_notification(int p_what) { switch(p_what) { @@ -62,7 +62,7 @@ void TileMap::_update_quadrant_space(const RID& p_space) { for (Map::Element *E=quadrant_map.front();E;E=E->next()) { Quadrant &q=E->get(); - Physics2DServer::get_singleton()->body_set_space(q.static_body,p_space); + Physics2DServer::get_singleton()->body_set_space(q.body,p_space); } } @@ -79,7 +79,7 @@ void TileMap::_update_quadrant_transform() { Matrix32 xform; xform.set_origin( q.pos ); xform = global_transform * xform; - Physics2DServer::get_singleton()->body_set_state(q.static_body,Physics2DServer::BODY_STATE_TRANSFORM,xform); + Physics2DServer::get_singleton()->body_set_state(q.body,Physics2DServer::BODY_STATE_TRANSFORM,xform); } } @@ -178,7 +178,7 @@ void TileMap::_update_dirty_quadrants() { Quadrant &q = *dirty_quadrant_list.first()->self(); vs->canvas_item_clear(q.canvas_item); - ps->body_clear_shapes(q.static_body); + ps->body_clear_shapes(q.body); int shape_idx=0; for(int i=0;ibody_add_shape(q.static_body,shape->get_rid(),xform); - ps->body_set_shape_metadata(q.static_body,shape_idx++,Vector2(E->key().x,E->key().y)); + ps->body_add_shape(q.body,shape->get_rid(),xform); + ps->body_set_shape_metadata(q.body,shape_idx++,Vector2(E->key().x,E->key().y)); } } @@ -339,19 +339,19 @@ Map::Element *TileMap::_create_quadrant(const q.canvas_item = VisualServer::get_singleton()->canvas_item_create(); VisualServer::get_singleton()->canvas_item_set_parent( q.canvas_item, get_canvas_item() ); VisualServer::get_singleton()->canvas_item_set_transform( q.canvas_item, xform ); - q.static_body=Physics2DServer::get_singleton()->body_create(Physics2DServer::BODY_MODE_STATIC); - Physics2DServer::get_singleton()->body_attach_object_instance_ID(q.static_body,get_instance_ID()); - Physics2DServer::get_singleton()->body_set_layer_mask(q.static_body,collision_layer); - Physics2DServer::get_singleton()->body_set_param(q.static_body,Physics2DServer::BODY_PARAM_FRICTION,friction); - Physics2DServer::get_singleton()->body_set_param(q.static_body,Physics2DServer::BODY_PARAM_BOUNCE,bounce); + q.body=Physics2DServer::get_singleton()->body_create(body_mode); + Physics2DServer::get_singleton()->body_attach_object_instance_ID(q.body,get_instance_ID()); + Physics2DServer::get_singleton()->body_set_layer_mask(q.body,collision_layer); + Physics2DServer::get_singleton()->body_set_param(q.body,Physics2DServer::BODY_PARAM_FRICTION,friction); + Physics2DServer::get_singleton()->body_set_param(q.body,Physics2DServer::BODY_PARAM_BOUNCE,bounce); if (is_inside_tree()) { xform = get_global_transform() * xform; RID space = get_world_2d()->get_space(); - Physics2DServer::get_singleton()->body_set_space(q.static_body,space); + Physics2DServer::get_singleton()->body_set_space(q.body,space); } - Physics2DServer::get_singleton()->body_set_state(q.static_body,Physics2DServer::BODY_STATE_TRANSFORM,xform); + Physics2DServer::get_singleton()->body_set_state(q.body,Physics2DServer::BODY_STATE_TRANSFORM,xform); rect_cache_dirty=true; quadrant_order_dirty=true; @@ -361,7 +361,7 @@ Map::Element *TileMap::_create_quadrant(const void TileMap::_erase_quadrant(Map::Element *Q) { Quadrant &q=Q->get(); - Physics2DServer::get_singleton()->free(q.static_body); + Physics2DServer::get_singleton()->free(q.body); VisualServer::get_singleton()->free(q.canvas_item); if (q.dirty_list.in_list()) dirty_quadrant_list.remove(&q.dirty_list); @@ -586,17 +586,29 @@ void TileMap::set_collision_layer_mask(uint32_t p_layer) { for (Map::Element *E=quadrant_map.front();E;E=E->next()) { Quadrant &q=E->get(); - Physics2DServer::get_singleton()->body_set_layer_mask(q.static_body,collision_layer); + Physics2DServer::get_singleton()->body_set_layer_mask(q.body,collision_layer); } } +Physics2DServer::BodyMode TileMap::get_collision_body_mode() const{ + + return body_mode; +} + +void TileMap::set_collision_body_mode(Physics2DServer::BodyMode p_body_mode) { + + _clear_quadrants(); + body_mode=p_body_mode; + _recreate_quadrants(); +} + void TileMap::set_collision_friction(float p_friction) { friction=p_friction; for (Map::Element *E=quadrant_map.front();E;E=E->next()) { Quadrant &q=E->get(); - Physics2DServer::get_singleton()->body_set_param(q.static_body,Physics2DServer::BODY_PARAM_FRICTION,p_friction); + Physics2DServer::get_singleton()->body_set_param(q.body,Physics2DServer::BODY_PARAM_FRICTION,p_friction); } } @@ -612,7 +624,7 @@ void TileMap::set_collision_bounce(float p_bounce){ for (Map::Element *E=quadrant_map.front();E;E=E->next()) { Quadrant &q=E->get(); - Physics2DServer::get_singleton()->body_set_param(q.static_body,Physics2DServer::BODY_PARAM_BOUNCE,p_bounce); + Physics2DServer::get_singleton()->body_set_param(q.body,Physics2DServer::BODY_PARAM_BOUNCE,p_bounce); } } @@ -807,6 +819,9 @@ void TileMap::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_collision_layer_mask","mask"),&TileMap::set_collision_layer_mask); ObjectTypeDB::bind_method(_MD("get_collision_layer_mask"),&TileMap::get_collision_layer_mask); + ObjectTypeDB::bind_method(_MD("set_collision_body_mode","body_mode"),&TileMap::set_collision_body_mode); + ObjectTypeDB::bind_method(_MD("get_collision_body_mode"),&TileMap::get_collision_body_mode); + ObjectTypeDB::bind_method(_MD("set_collision_friction","value"),&TileMap::set_collision_friction); ObjectTypeDB::bind_method(_MD("get_collision_friction"),&TileMap::get_collision_friction); @@ -837,6 +852,7 @@ void TileMap::_bind_methods() { ADD_PROPERTY( PropertyInfo(Variant::INT,"cell/quadrant_size",PROPERTY_HINT_RANGE,"1,128,1"),_SCS("set_quadrant_size"),_SCS("get_quadrant_size")); ADD_PROPERTY( PropertyInfo(Variant::MATRIX32,"cell/custom_transform"),_SCS("set_custom_transform"),_SCS("get_custom_transform")); ADD_PROPERTY( PropertyInfo(Variant::INT,"cell/half_offset",PROPERTY_HINT_ENUM,"Offset X,Offset Y,Disabled"),_SCS("set_half_offset"),_SCS("get_half_offset")); + ADD_PROPERTY( PropertyInfo(Variant::INT,"collision/body_mode",PROPERTY_HINT_ENUM,"Static,Kinematic"),_SCS("set_collision_body_mode"),_SCS("get_collision_body_mode")); ADD_PROPERTY( PropertyInfo(Variant::REAL,"collision/friction",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_collision_friction"),_SCS("get_collision_friction")); ADD_PROPERTY( PropertyInfo(Variant::REAL,"collision/bounce",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_collision_bounce"),_SCS("get_collision_bounce")); ADD_PROPERTY( PropertyInfo(Variant::INT,"collision/layers",PROPERTY_HINT_ALL_FLAGS),_SCS("set_collision_layer_mask"),_SCS("get_collision_layer_mask")); @@ -870,6 +886,7 @@ TileMap::TileMap() { bounce=0; mode=MODE_SQUARE; half_offset=HALF_OFFSET_DISABLED; + body_mode=Physics2DServer::BODY_MODE_STATIC; fp_adjust=0.01; fp_adjust=0.01; diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h index 4e9e2e7e97..52e8eae306 100644 --- a/scene/2d/tile_map.h +++ b/scene/2d/tile_map.h @@ -33,6 +33,7 @@ #include "scene/resources/tile_set.h" #include "self_list.h" #include "vset.h" +#include "servers/physics_2d_server.h" class TileMap : public Node2D { @@ -60,6 +61,7 @@ private: Mode mode; Matrix32 custom_transform; HalfOffset half_offset; + Physics2DServer::BodyMode body_mode; union PosKey { @@ -97,14 +99,14 @@ private: Vector2 pos; RID canvas_item; - RID static_body; + RID body; SelfList dirty_list; VSet cells; - void operator=(const Quadrant& q) { pos=q.pos; canvas_item=q.canvas_item; static_body=q.static_body; cells=q.cells; } - Quadrant(const Quadrant& q) : dirty_list(this) { pos=q.pos; canvas_item=q.canvas_item; static_body=q.static_body; cells=q.cells;} + void operator=(const Quadrant& q) { pos=q.pos; canvas_item=q.canvas_item; body=q.body; cells=q.cells; } + Quadrant(const Quadrant& q) : dirty_list(this) { pos=q.pos; canvas_item=q.canvas_item; body=q.body; cells=q.cells;} Quadrant() : dirty_list(this) {} }; @@ -177,6 +179,9 @@ public: void set_collision_layer_mask(uint32_t p_layer); uint32_t get_collision_layer_mask() const; + void set_collision_body_mode(Physics2DServer::BodyMode p_body_mode); + Physics2DServer::BodyMode get_collision_body_mode() const; + void set_collision_friction(float p_friction); float get_collision_friction() const; -- cgit v1.2.3 From 8bb1e19d7355ac92ec5cfe39fbb6db73d6c0fffe Mon Sep 17 00:00:00 2001 From: Carl Olsson Date: Sat, 14 Feb 2015 06:43:50 +1000 Subject: Replace body_mode property with use_kinematic flag. Revert 2D Platformer demo's moving platforms to sprite plus body. --- scene/2d/tile_map.cpp | 21 +++++++++++---------- scene/2d/tile_map.h | 7 +++---- 2 files changed, 14 insertions(+), 14 deletions(-) (limited to 'scene') diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index 06c97027f0..52f4d27497 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -28,6 +28,7 @@ /*************************************************************************/ #include "tile_map.h" #include "io/marshalls.h" +#include "servers/physics_2d_server.h" void TileMap::_notification(int p_what) { @@ -339,7 +340,7 @@ Map::Element *TileMap::_create_quadrant(const q.canvas_item = VisualServer::get_singleton()->canvas_item_create(); VisualServer::get_singleton()->canvas_item_set_parent( q.canvas_item, get_canvas_item() ); VisualServer::get_singleton()->canvas_item_set_transform( q.canvas_item, xform ); - q.body=Physics2DServer::get_singleton()->body_create(body_mode); + q.body=Physics2DServer::get_singleton()->body_create(use_kinematic?Physics2DServer::BODY_MODE_KINEMATIC:Physics2DServer::BODY_MODE_STATIC); Physics2DServer::get_singleton()->body_attach_object_instance_ID(q.body,get_instance_ID()); Physics2DServer::get_singleton()->body_set_layer_mask(q.body,collision_layer); Physics2DServer::get_singleton()->body_set_param(q.body,Physics2DServer::BODY_PARAM_FRICTION,friction); @@ -590,15 +591,15 @@ void TileMap::set_collision_layer_mask(uint32_t p_layer) { } } -Physics2DServer::BodyMode TileMap::get_collision_body_mode() const{ +bool TileMap::get_collision_use_kinematic() const{ - return body_mode; + return use_kinematic; } -void TileMap::set_collision_body_mode(Physics2DServer::BodyMode p_body_mode) { +void TileMap::set_collision_use_kinematic(bool p_use_kinematic) { _clear_quadrants(); - body_mode=p_body_mode; + use_kinematic=p_use_kinematic; _recreate_quadrants(); } @@ -816,12 +817,12 @@ void TileMap::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_center_y","enable"),&TileMap::set_center_y); ObjectTypeDB::bind_method(_MD("get_center_y"),&TileMap::get_center_y); + ObjectTypeDB::bind_method(_MD("set_collision_use_kinematic","use_kinematic"),&TileMap::set_collision_use_kinematic); + ObjectTypeDB::bind_method(_MD("get_collision_use_kinematic"),&TileMap::get_collision_use_kinematic); + ObjectTypeDB::bind_method(_MD("set_collision_layer_mask","mask"),&TileMap::set_collision_layer_mask); ObjectTypeDB::bind_method(_MD("get_collision_layer_mask"),&TileMap::get_collision_layer_mask); - ObjectTypeDB::bind_method(_MD("set_collision_body_mode","body_mode"),&TileMap::set_collision_body_mode); - ObjectTypeDB::bind_method(_MD("get_collision_body_mode"),&TileMap::get_collision_body_mode); - ObjectTypeDB::bind_method(_MD("set_collision_friction","value"),&TileMap::set_collision_friction); ObjectTypeDB::bind_method(_MD("get_collision_friction"),&TileMap::get_collision_friction); @@ -852,7 +853,7 @@ void TileMap::_bind_methods() { ADD_PROPERTY( PropertyInfo(Variant::INT,"cell/quadrant_size",PROPERTY_HINT_RANGE,"1,128,1"),_SCS("set_quadrant_size"),_SCS("get_quadrant_size")); ADD_PROPERTY( PropertyInfo(Variant::MATRIX32,"cell/custom_transform"),_SCS("set_custom_transform"),_SCS("get_custom_transform")); ADD_PROPERTY( PropertyInfo(Variant::INT,"cell/half_offset",PROPERTY_HINT_ENUM,"Offset X,Offset Y,Disabled"),_SCS("set_half_offset"),_SCS("get_half_offset")); - ADD_PROPERTY( PropertyInfo(Variant::INT,"collision/body_mode",PROPERTY_HINT_ENUM,"Static,Kinematic"),_SCS("set_collision_body_mode"),_SCS("get_collision_body_mode")); + ADD_PROPERTY( PropertyInfo(Variant::BOOL,"collision/use_kinematic",PROPERTY_HINT_NONE,""),_SCS("set_collision_use_kinematic"),_SCS("get_collision_use_kinematic")); ADD_PROPERTY( PropertyInfo(Variant::REAL,"collision/friction",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_collision_friction"),_SCS("get_collision_friction")); ADD_PROPERTY( PropertyInfo(Variant::REAL,"collision/bounce",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_collision_bounce"),_SCS("get_collision_bounce")); ADD_PROPERTY( PropertyInfo(Variant::INT,"collision/layers",PROPERTY_HINT_ALL_FLAGS),_SCS("set_collision_layer_mask"),_SCS("get_collision_layer_mask")); @@ -886,7 +887,7 @@ TileMap::TileMap() { bounce=0; mode=MODE_SQUARE; half_offset=HALF_OFFSET_DISABLED; - body_mode=Physics2DServer::BODY_MODE_STATIC; + use_kinematic=false; fp_adjust=0.01; fp_adjust=0.01; diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h index 52e8eae306..c8708e1bed 100644 --- a/scene/2d/tile_map.h +++ b/scene/2d/tile_map.h @@ -33,7 +33,6 @@ #include "scene/resources/tile_set.h" #include "self_list.h" #include "vset.h" -#include "servers/physics_2d_server.h" class TileMap : public Node2D { @@ -61,7 +60,7 @@ private: Mode mode; Matrix32 custom_transform; HalfOffset half_offset; - Physics2DServer::BodyMode body_mode; + bool use_kinematic; union PosKey { @@ -179,8 +178,8 @@ public: void set_collision_layer_mask(uint32_t p_layer); uint32_t get_collision_layer_mask() const; - void set_collision_body_mode(Physics2DServer::BodyMode p_body_mode); - Physics2DServer::BodyMode get_collision_body_mode() const; + void set_collision_use_kinematic(bool p_use_kinematic); + bool get_collision_use_kinematic() const; void set_collision_friction(float p_friction); float get_collision_friction() const; -- cgit v1.2.3 From c5f509f238576dba39ffcce74ab2066f24e67b58 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Sat, 14 Feb 2015 12:09:52 -0300 Subject: New Navigation & Pathfinding support for 2D -Added Navigation & NavigationPolygon nodes -Added corresponding visual editor -New pathfinding algorithm is modern and fast! -Similar API to 3D Pathfinding (more coherent) --- scene/2d/navigation2d.cpp | 623 ++++++++++++++++++++++++++++++++++++++++ scene/2d/navigation2d.h | 137 +++++++++ scene/2d/navigation_polygon.cpp | 450 +++++++++++++++++++++++++++++ scene/2d/navigation_polygon.h | 84 ++++++ scene/2d/node_2d.cpp | 14 + scene/2d/node_2d.h | 3 + scene/gui/dialogs.cpp | 4 +- scene/gui/popup.cpp | 4 + scene/register_scene_types.cpp | 5 + 9 files changed, 1322 insertions(+), 2 deletions(-) create mode 100644 scene/2d/navigation2d.cpp create mode 100644 scene/2d/navigation2d.h create mode 100644 scene/2d/navigation_polygon.cpp create mode 100644 scene/2d/navigation_polygon.h (limited to 'scene') diff --git a/scene/2d/navigation2d.cpp b/scene/2d/navigation2d.cpp new file mode 100644 index 0000000000..5e93dac61d --- /dev/null +++ b/scene/2d/navigation2d.cpp @@ -0,0 +1,623 @@ +#include "navigation2d.h" + +void Navigation2D::_navpoly_link(int p_id) { + + ERR_FAIL_COND(!navpoly_map.has(p_id)); + NavMesh &nm=navpoly_map[p_id]; + ERR_FAIL_COND(nm.linked); + + print_line("LINK"); + + DVector vertices=nm.navpoly->get_vertices(); + int len = vertices.size(); + if (len==0) + return; + + DVector::Read r=vertices.read(); + + for(int i=0;iget_polygon_count();i++) { + + //build + + List::Element *P=nm.polygons.push_back(Polygon()); + Polygon &p=P->get(); + p.owner=&nm; + + Vector poly = nm.navpoly->get_polygon(i); + int plen=poly.size(); + const int *indices=poly.ptr(); + bool valid=true; + p.edges.resize(plen); + + Vector2 center; + + for(int j=0;j=len) { + valid=false; + break; + } + + Polygon::Edge e; + Vector2 ep=nm.xform.xform(r[idx]); + center+=ep; + e.point=_get_point(ep); + p.edges[j]=e; + } + + if (!valid) { + nm.polygons.pop_back(); + ERR_CONTINUE(!valid); + continue; + } + + p.center=center/plen; + + //connect + + for(int j=0;j::Element *C=connections.find(ek); + if (!C) { + + Connection c; + c.A=&p; + c.A_edge=j; + c.B=NULL; + c.B_edge=-1; + connections[ek]=c; + } else { + + if (C->get().B!=NULL) { + print_line(String()+_get_vertex(ek.a)+" -> "+_get_vertex(ek.b)); + } + ERR_CONTINUE(C->get().B!=NULL); //wut + + C->get().B=&p; + C->get().B_edge=j; + C->get().A->edges[C->get().A_edge].C=&p; + C->get().A->edges[C->get().A_edge].C_edge=j;; + p.edges[j].C=C->get().A; + p.edges[j].C_edge=C->get().A_edge; + //connection successful. + } + } + } + + nm.linked=true; + +} + + +void Navigation2D::_navpoly_unlink(int p_id) { + + ERR_FAIL_COND(!navpoly_map.has(p_id)); + NavMesh &nm=navpoly_map[p_id]; + ERR_FAIL_COND(!nm.linked); + + print_line("UNLINK"); + + for (List::Element *E=nm.polygons.front();E;E=E->next()) { + + + Polygon &p=E->get(); + + int ec = p.edges.size(); + Polygon::Edge *edges=p.edges.ptr(); + + for(int i=0;i::Element *C=connections.find(ek); + ERR_CONTINUE(!C); + if (C->get().B) { + //disconnect + + C->get().B->edges[C->get().B_edge].C=NULL; + C->get().B->edges[C->get().B_edge].C_edge=-1; + C->get().A->edges[C->get().A_edge].C=NULL; + C->get().A->edges[C->get().A_edge].C_edge=-1; + + if (C->get().A==&E->get()) { + + C->get().A=C->get().B; + C->get().A_edge=C->get().B_edge; + } + C->get().B=NULL; + C->get().B_edge=-1; + + } else { + connections.erase(C); + //erase + } + } + } + + nm.polygons.clear(); + + nm.linked=false; + + +} + + +int Navigation2D::navpoly_create(const Ref& p_mesh, const Matrix32& p_xform, Object *p_owner) { + + int id = last_id++; + NavMesh nm; + nm.linked=false; + nm.navpoly=p_mesh; + nm.xform=p_xform; + nm.owner=p_owner; + navpoly_map[id]=nm; + + _navpoly_link(id); + + return id; +} + +void Navigation2D::navpoly_set_transform(int p_id, const Matrix32& p_xform){ + + ERR_FAIL_COND(!navpoly_map.has(p_id)); + NavMesh &nm=navpoly_map[p_id]; + if (nm.xform==p_xform) + return; //bleh + _navpoly_unlink(p_id); + nm.xform=p_xform; + _navpoly_link(p_id); + + + +} +void Navigation2D::navpoly_remove(int p_id){ + + ERR_FAIL_COND(!navpoly_map.has(p_id)); + _navpoly_unlink(p_id); + navpoly_map.erase(p_id); + +} +#if 0 +void Navigation2D::_clip_path(Vector& path, Polygon *from_poly, const Vector2& p_to_point, Polygon* p_to_poly) { + + Vector2 from = path[path.size()-1]; + + if (from.distance_to(p_to_point)prev_edge; + Vector2 a = _get_vertex(from_poly->edges[pe].point); + Vector2 b = _get_vertex(from_poly->edges[(pe+1)%from_poly->edges.size()].point); + + from_poly=from_poly->edges[pe].C; + ERR_FAIL_COND(!from_poly); + + if (a.distance_to(b)>CMP_EPSILON) { + + Vector2 inters; + if (cut_plane.intersects_segment(a,b,&inters)) { + if (inters.distance_to(p_to_point)>CMP_EPSILON && inters.distance_to(path[path.size()-1])>CMP_EPSILON) { + path.push_back(inters); + } + } + } + } +} +#endif + +Vector Navigation2D::get_simple_path(const Vector2& p_start, const Vector2& p_end, bool p_optimize) { + + + Polygon *begin_poly=NULL; + Polygon *end_poly=NULL; + Vector2 begin_point; + Vector2 end_point; + float begin_d=1e20; + float end_d=1e20; + + //look for point inside triangle + + for (Map::Element*E=navpoly_map.front();E;E=E->next()) { + + if (!E->get().linked) + continue; + for(List::Element *F=E->get().polygons.front();F;F=F->next()) { + + + Polygon &p=F->get(); + if (begin_d || end_d) { + for(int i=2;i0) { + + if (Geometry::is_point_in_triangle(p_start,_get_vertex(p.edges[0].point),_get_vertex(p.edges[i-1].point),_get_vertex(p.edges[i].point))) { + + begin_poly=&p; + begin_point=p_start; + begin_d=0; + if (end_d==0) + break; + + } + } + + if (end_d>0) { + + if (Geometry::is_point_in_triangle(p_end,_get_vertex(p.edges[0].point),_get_vertex(p.edges[i-1].point),_get_vertex(p.edges[i].point))) { + + end_poly=&p; + end_point=p_end; + end_d=0; + if (begin_d==0) + break; + } + } + + } + } + + p.prev_edge=-1; + } + } + + //start or end not inside triangle.. look for closest segment :| + if (begin_d || end_d) { + for (Map::Element*E=navpoly_map.front();E;E=E->next()) { + + if (!E->get().linked) + continue; + for(List::Element *F=E->get().polygons.front();F;F=F->next()) { + + Polygon &p=F->get(); + int es = p.edges.size(); + for(int i=0;i0) { + Vector2 spoint=Geometry::get_closest_point_to_segment_2d(p_start,edge); + float d = spoint.distance_to(p_start); + if (d0) { + Vector2 spoint=Geometry::get_closest_point_to_segment_2d(p_end,edge); + float d = spoint.distance_to(p_end); + if (d(); //no path + } + + if (begin_poly==end_poly) { + + Vector path; + path.resize(2); + path[0]=begin_point; + path[1]=end_point; + //print_line("Direct Path"); + return path; + } + + + bool found_route=false; + + List open_list; + + for(int i=0;iedges.size();i++) { + + if (begin_poly->edges[i].C) { + + begin_poly->edges[i].C->prev_edge=begin_poly->edges[i].C_edge; + begin_poly->edges[i].C->distance=begin_poly->center.distance_to(begin_poly->edges[i].C->center); + open_list.push_back(begin_poly->edges[i].C); + + if (begin_poly->edges[i].C==end_poly) { + found_route=true; + } + } + } + + + while(!found_route) { + + if (open_list.size()==0) { + // print_line("NOU OPEN LIST"); + break; + } + //check open list + + List::Element *least_cost_poly=NULL; + float least_cost=1e30; + + //this could be faster (cache previous results) + for (List::Element *E=open_list.front();E;E=E->next()) { + + Polygon *p=E->get(); + + + float cost=p->distance; + cost+=p->center.distance_to(end_point); + + if (costget(); + //open the neighbours for search + + for(int i=0;iedges.size();i++) { + + + Polygon::Edge &e=p->edges[i]; + + if (!e.C) + continue; + + float distance = p->center.distance_to(e.C->center) + p->distance; + + if (e.C->prev_edge!=-1) { + //oh this was visited already, can we win the cost? + + if (e.C->distance>distance) { + + e.C->prev_edge=e.C_edge; + e.C->distance=distance; + } + } else { + //add to open neighbours + + e.C->prev_edge=e.C_edge; + e.C->distance=distance; + open_list.push_back(e.C); + + if (e.C==end_poly) { + //oh my reached end! stop algorithm + found_route=true; + break; + + } + + } + } + + if (found_route) + break; + + open_list.erase(least_cost_poly); + } + + if (found_route) { + + Vector path; + + if (p_optimize) { + //string pulling + + Polygon *apex_poly=end_poly; + Vector2 apex_point=end_point; + Vector2 portal_left=apex_point; + Vector2 portal_right=apex_point; + Polygon *left_poly=end_poly; + Polygon *right_poly=end_poly; + Polygon *p=end_poly; + path.push_back(end_point); + + while(p) { + + Vector2 left; + Vector2 right; + +//#define CLOCK_TANGENT(m_a,m_b,m_c) ( ((m_a)-(m_c)).cross((m_a)-(m_b)) ) +#define CLOCK_TANGENT(m_a,m_b,m_c) ((((m_a).x - (m_c).x) * ((m_b).y - (m_c).y) - ((m_b).x - (m_c).x) * ((m_a).y - (m_c).y))) + + if (p==begin_poly) { + left=begin_point; + right=begin_point; + } else { + int prev = p->prev_edge; + int prev_n = (p->prev_edge+1)%p->edges.size(); + left = _get_vertex(p->edges[prev].point); + right = _get_vertex(p->edges[prev_n].point); + + if (CLOCK_TANGENT(apex_point,left,(left+right)*0.5) < 0){ + SWAP(left,right); + } + } + + bool skip=false; + + + if (CLOCK_TANGENT(apex_point,portal_left,left) >= 0){ + //process + if (portal_left==apex_point || CLOCK_TANGENT(apex_point,left,portal_right) > 0) { + left_poly=p; + portal_left=left; + } else { + + //_clip_path(path,apex_poly,portal_right,right_poly); + + apex_point=portal_right; + p=right_poly; + left_poly=p; + apex_poly=p; + portal_left=apex_point; + portal_right=apex_point; + path.push_back(apex_point); + skip=true; + } + } + + if (!skip && CLOCK_TANGENT(apex_point,portal_right,right) <= 0){ + //process + if (portal_right==apex_point || CLOCK_TANGENT(apex_point,right,portal_left) < 0) { + right_poly=p; + portal_right=right; + } else { + + //_clip_path(path,apex_poly,portal_left,left_poly); + + apex_point=portal_left; + p=left_poly; + right_poly=p; + apex_poly=p; + portal_right=apex_point; + portal_left=apex_point; + path.push_back(apex_point); + } + } + + if (p!=begin_poly) + p=p->edges[p->prev_edge].C; + else + p=NULL; + + } + + if (path[path.size()-1]!=begin_point) + path.push_back(begin_point); + + path.invert(); + + + + + } else { + //midpoints + Polygon *p=end_poly; + + path.push_back(end_point); + while(true) { + int prev = p->prev_edge; + int prev_n = (p->prev_edge+1)%p->edges.size(); + Vector2 point = (_get_vertex(p->edges[prev].point) + _get_vertex(p->edges[prev_n].point))*0.5; + path.push_back(point); + p = p->edges[prev].C; + if (p==begin_poly) + break; + } + + path.push_back(begin_point); + + + path.invert();; + } + + return path; + } + + + return Vector(); + +} + + +Vector2 Navigation2D::get_closest_point(const Vector2& p_point) { + + Vector2 closest_point=Vector2(); + float closest_point_d=1e20; + + for (Map::Element*E=navpoly_map.front();E;E=E->next()) { + + if (!E->get().linked) + continue; + for(List::Element *F=E->get().polygons.front();F;F=F->next()) { + + Polygon &p=F->get(); + for(int i=2;i::Element*E=navpoly_map.front();E;E=E->next()) { + + if (!E->get().linked) + continue; + for(List::Element *F=E->get().polygons.front();F;F=F->next()) { + + Polygon &p=F->get(); + int es = p.edges.size(); + for(int i=0;i b.key) { + SWAP(a,b); + } + } + }; + + + struct NavMesh; + + + struct Polygon { + + struct Edge { + Point point; + Polygon *C; //connection + int C_edge; + Edge() { C=NULL; C_edge=-1; } + }; + + Vector edges; + + Vector2 center; + + float distance; + int prev_edge; + + NavMesh *owner; + }; + + + struct Connection { + + Polygon *A; + int A_edge; + Polygon *B; + int B_edge; + Connection() { A=NULL; B=NULL; A_edge=-1; B_edge=-1;} + }; + + Map connections; + + + struct NavMesh { + + Object *owner; + Matrix32 xform; + bool linked; + Ref navpoly; + List polygons; + + }; + + + + _FORCE_INLINE_ Point _get_point(const Vector2& p_pos) const { + + int x = int(Math::floor(p_pos.x/cell_size)); + int y = int(Math::floor(p_pos.y/cell_size)); + + Point p; + p.key=0; + p.x=x; + p.y=y; + return p; + + } + + _FORCE_INLINE_ Vector2 _get_vertex(const Point& p_point) const { + + return Vector2(p_point.x,p_point.y)*cell_size; + } + + + + void _navpoly_link(int p_id); + void _navpoly_unlink(int p_id); + + float cell_size; + Map navpoly_map; + int last_id; +#if 0 + void _clip_path(Vector& path,Polygon *from_poly, const Vector2& p_to_point, Polygon* p_to_poly); +#endif +protected: + + static void _bind_methods(); + +public: + + //API should be as dynamic as possible + int navpoly_create(const Ref& p_mesh,const Matrix32& p_xform,Object* p_owner=NULL); + void navpoly_set_transform(int p_id, const Matrix32& p_xform); + void navpoly_remove(int p_id); + + Vector get_simple_path(const Vector2& p_start, const Vector2& p_end,bool p_optimize=true); + Vector2 get_closest_point(const Vector2& p_point); + + Navigation2D(); +}; + + +#endif // Navigation2D2D_H diff --git a/scene/2d/navigation_polygon.cpp b/scene/2d/navigation_polygon.cpp new file mode 100644 index 0000000000..570a5b95b0 --- /dev/null +++ b/scene/2d/navigation_polygon.cpp @@ -0,0 +1,450 @@ +#include "navigation_polygon.h" +#include "navigation2d.h" +#include "triangulator.h" +#include "core_string_names.h" + +void NavigationPolygon::set_vertices(const DVector& p_vertices) { + + vertices=p_vertices; +} + +DVector NavigationPolygon::get_vertices() const{ + + return vertices; +} + + +void NavigationPolygon::_set_polygons(const Array& p_array) { + + polygons.resize(p_array.size()); + for(int i=0;i& p_polygon){ + + Polygon polygon; + polygon.indices=p_polygon; + polygons.push_back(polygon); + +} + +void NavigationPolygon::add_outline_at_index(const DVector& p_outline,int p_index) { + + outlines.insert(p_index,p_outline); +} + +int NavigationPolygon::get_polygon_count() const{ + + return polygons.size(); +} +Vector NavigationPolygon::get_polygon(int p_idx){ + + ERR_FAIL_INDEX_V(p_idx,polygons.size(),Vector()); + return polygons[p_idx].indices; +} +void NavigationPolygon::clear_polygons(){ + + polygons.clear(); +} + +void NavigationPolygon::add_outline(const DVector& p_outline) { + + outlines.push_back(p_outline); +} + +int NavigationPolygon::get_outline_count() const{ + + return outlines.size(); +} + +void NavigationPolygon::set_outline(int p_idx,const DVector& p_outline) { + ERR_FAIL_INDEX(p_idx,outlines.size()); + outlines[p_idx]=p_outline; +} + +void NavigationPolygon::remove_outline(int p_idx) { + + ERR_FAIL_INDEX(p_idx,outlines.size()); + outlines.remove(p_idx); + +} + +DVector NavigationPolygon::get_outline(int p_idx) const { + ERR_FAIL_INDEX_V(p_idx,outlines.size(),DVector()); + return outlines[p_idx]; +} + +void NavigationPolygon::clear_outlines(){ + + outlines.clear();; +} +void NavigationPolygon::make_polygons_from_outlines(){ + + std::list in_poly,out_poly; + + Vector2 outside_point(-1e10,-1e10); + + for(int i=0;i ol = outlines[i]; + int olsize = ol.size(); + if (olsize<3) + continue; + DVector::Read r=ol.read(); + for(int j=0;j ol = outlines[i]; + int olsize = ol.size(); + if (olsize<3) + continue; + DVector::Read r=ol.read(); + + int interscount=0; + //test if this is an outer outline + for(int k=0;k ol2 = outlines[k]; + int olsize2 = ol2.size(); + if (olsize2<3) + continue; + DVector::Read r2=ol2.read(); + + for(int l=0;l points; + for(std::list::iterator I = out_poly.begin();I!=out_poly.end();I++) { + + TriangulatorPoly& tp = *I; + + struct Polygon p; + + for(int i=0;i::Element *E=points.find(tp[i]); + if (!E) { + E=points.insert(tp[i],vertices.size()); + vertices.push_back(tp[i]); + } + p.indices.push_back(E->get()); + } + + polygons.push_back(p); + } + + emit_signal(CoreStringNames::get_singleton()->changed); +} + + +void NavigationPolygon::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_vertices","vertices"),&NavigationPolygon::set_vertices); + ObjectTypeDB::bind_method(_MD("get_vertices"),&NavigationPolygon::get_vertices); + + ObjectTypeDB::bind_method(_MD("add_polygon","polygon"),&NavigationPolygon::add_polygon); + ObjectTypeDB::bind_method(_MD("get_polygon_count"),&NavigationPolygon::get_polygon_count); + ObjectTypeDB::bind_method(_MD("get_polygon","idx"),&NavigationPolygon::get_polygon); + ObjectTypeDB::bind_method(_MD("clear_polygons"),&NavigationPolygon::clear_polygons); + + ObjectTypeDB::bind_method(_MD("add_outline","outline"),&NavigationPolygon::add_outline); + ObjectTypeDB::bind_method(_MD("add_outline_at_index","outline","index"),&NavigationPolygon::add_outline_at_index); + ObjectTypeDB::bind_method(_MD("get_outline_count"),&NavigationPolygon::get_outline_count); + ObjectTypeDB::bind_method(_MD("set_outline","idx","outline"),&NavigationPolygon::set_outline); + ObjectTypeDB::bind_method(_MD("get_outline","idx"),&NavigationPolygon::get_outline); + ObjectTypeDB::bind_method(_MD("remove_outline","idx"),&NavigationPolygon::remove_outline); + ObjectTypeDB::bind_method(_MD("clear_outlines"),&NavigationPolygon::clear_outlines); + ObjectTypeDB::bind_method(_MD("make_polygons_from_outlines"),&NavigationPolygon::make_polygons_from_outlines); + + ObjectTypeDB::bind_method(_MD("_set_polygons","polygons"),&NavigationPolygon::_set_polygons); + ObjectTypeDB::bind_method(_MD("_get_polygons"),&NavigationPolygon::_get_polygons); + + ObjectTypeDB::bind_method(_MD("_set_outlines","outlines"),&NavigationPolygon::_set_outlines); + ObjectTypeDB::bind_method(_MD("_get_outlines"),&NavigationPolygon::_get_outlines); + + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3_ARRAY,"vertices",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("set_vertices"),_SCS("get_vertices")); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY,"polygons",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_polygons"),_SCS("_get_polygons")); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY,"outlines",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_outlines"),_SCS("_get_outlines")); +} + +NavigationPolygon::NavigationPolygon() { + + +} + +void NavigationPolygonInstance::set_enabled(bool p_enabled) { + + if (enabled==p_enabled) + return; + enabled=p_enabled; + + if (!is_inside_tree()) + return; + + if (!enabled) { + + if (nav_id!=-1) { + navigation->navpoly_remove(nav_id); + nav_id=-1; + } + } else { + + if (navigation) { + + if (navpoly.is_valid()) { + + nav_id = navigation->navpoly_create(navpoly,get_relative_transform(navigation),this); + } + } + + } + + if (get_tree()->is_editor_hint()) + update(); + +// update_gizmo(); +} + +bool NavigationPolygonInstance::is_enabled() const { + + + return enabled; +} + + +///////////////////////////// + + +void NavigationPolygonInstance::_notification(int p_what) { + + + switch(p_what) { + case NOTIFICATION_ENTER_TREE: { + + Node2D *c=this; + while(c) { + + navigation=c->cast_to(); + if (navigation) { + + if (enabled && navpoly.is_valid()) { + + nav_id = navigation->navpoly_create(navpoly,get_relative_transform(navigation),this); + } + break; + } + + c=c->get_parent()->cast_to(); + } + + } break; + case NOTIFICATION_TRANSFORM_CHANGED: { + + if (navigation && nav_id!=-1) { + navigation->navpoly_set_transform(nav_id,get_relative_transform(navigation)); + } + + } break; + case NOTIFICATION_EXIT_TREE: { + + if (navigation) { + + if (nav_id!=-1) { + navigation->navpoly_remove(nav_id); + nav_id=-1; + } + } + navigation=NULL; + } break; + case NOTIFICATION_DRAW: { + + if (is_inside_tree() && get_tree()->is_editor_hint() && navpoly.is_valid()) { + + DVector verts=navpoly->get_vertices(); + int vsize = verts.size(); + if (vsize<3) + return; + + + Color color; + if (enabled) { + color=Color(0.1,0.8,1.0,0.4); + } else { + color=Color(1.0,0.8,0.1,0.4); + } + Vector colors; + Vector vertices; + vertices.resize(vsize); + colors.resize(vsize); + { + DVector::Read vr = verts.read(); + for(int i=0;i indices; + + + for(int i=0;iget_polygon_count();i++) { + Vector polygon = navpoly->get_polygon(i); + + for(int j=2;jcanvas_item_add_triangle_array(get_canvas_item(),indices,vertices,colors); + + } + } break; + + } +} + + +void NavigationPolygonInstance::set_navigation_polygon(const Ref& p_navpoly) { + + if (p_navpoly==navpoly) + return; + + if (navigation && nav_id!=-1) { + navigation->navpoly_remove(nav_id); + nav_id=-1; + } + if (navpoly.is_valid()) { + navpoly->disconnect(CoreStringNames::get_singleton()->changed,this,"_navpoly_changed"); + } + navpoly=p_navpoly; + + if (navpoly.is_valid()) { + navpoly->connect(CoreStringNames::get_singleton()->changed,this,"_navpoly_changed"); + } + + if (navigation && navpoly.is_valid() && enabled) { + nav_id = navigation->navpoly_create(navpoly,get_relative_transform(navigation),this); + } + //update_gizmo(); + _change_notify("navpoly"); + +} + +Ref NavigationPolygonInstance::get_navigation_polygon() const{ + + return navpoly; +} + +void NavigationPolygonInstance::_navpoly_changed() { + + if (is_inside_tree() && get_tree()->is_editor_hint()) + update(); +} + +void NavigationPolygonInstance::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_navigation_polygon","navpoly"),&NavigationPolygonInstance::set_navigation_polygon); + ObjectTypeDB::bind_method(_MD("get_navigation_polygon"),&NavigationPolygonInstance::get_navigation_polygon); + + ObjectTypeDB::bind_method(_MD("set_enabled","enabled"),&NavigationPolygonInstance::set_enabled); + ObjectTypeDB::bind_method(_MD("is_enabled"),&NavigationPolygonInstance::is_enabled); + + ObjectTypeDB::bind_method(_MD("_navpoly_changed"),&NavigationPolygonInstance::_navpoly_changed); + + ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"navpoly",PROPERTY_HINT_RESOURCE_TYPE,"NavigationPolygon"),_SCS("set_navigation_polygon"),_SCS("get_navigation_polygon")); + ADD_PROPERTY( PropertyInfo(Variant::BOOL,"enabled"),_SCS("set_enabled"),_SCS("is_enabled")); +} + +NavigationPolygonInstance::NavigationPolygonInstance() { + + navigation=NULL; + nav_id=-1; + enabled=true; + +} diff --git a/scene/2d/navigation_polygon.h b/scene/2d/navigation_polygon.h new file mode 100644 index 0000000000..01307a170b --- /dev/null +++ b/scene/2d/navigation_polygon.h @@ -0,0 +1,84 @@ +#ifndef NAVIGATION_POLYGON_H +#define NAVIGATION_POLYGON_H + +#include "scene/2d/node_2d.h" + + +class NavigationPolygon : public Resource { + + OBJ_TYPE( NavigationPolygon, Resource ); + + DVector vertices; + struct Polygon { + Vector indices; + }; + Vector polygons; + Vector< DVector > outlines; + +protected: + + static void _bind_methods(); + + void _set_polygons(const Array& p_array); + Array _get_polygons() const; + + void _set_outlines(const Array& p_array); + Array _get_outlines() const; + +public: + + + + void set_vertices(const DVector& p_vertices); + DVector get_vertices() const; + + void add_polygon(const Vector& p_polygon); + int get_polygon_count() const; + + void add_outline(const DVector& p_outline); + void add_outline_at_index(const DVector& p_outline,int p_index); + void set_outline(int p_idx,const DVector& p_outline); + DVector get_outline(int p_idx) const; + void remove_outline(int p_idx); + int get_outline_count() const; + + void clear_outlines(); + void make_polygons_from_outlines(); + + Vector get_polygon(int p_idx); + void clear_polygons(); + + NavigationPolygon(); +}; + + +class Navigation2D; + +class NavigationPolygonInstance : public Node2D { + + OBJ_TYPE(NavigationPolygonInstance,Node2D); + + bool enabled; + int nav_id; + Navigation2D *navigation; + Ref navpoly; + + void _navpoly_changed(); + +protected: + + void _notification(int p_what); + static void _bind_methods(); +public: + + void set_enabled(bool p_enabled); + bool is_enabled() const; + + void set_navigation_polygon(const Ref& p_navpoly); + Ref get_navigation_polygon() const; + + NavigationPolygonInstance(); +}; + + +#endif // NAVIGATIONPOLYGON_H diff --git a/scene/2d/node_2d.cpp b/scene/2d/node_2d.cpp index 8b4196ee7f..36b6b220b3 100644 --- a/scene/2d/node_2d.cpp +++ b/scene/2d/node_2d.cpp @@ -317,6 +317,18 @@ int Node2D::get_z() const{ return z; } +Matrix32 Node2D::get_relative_transform(const Node *p_parent) const { + + if (p_parent==this) + return Matrix32(); + + Node2D *parent_2d = get_parent()->cast_to(); + ERR_FAIL_COND_V(!parent_2d,Matrix32()); + if (p_parent==parent_2d) + return get_transform(); + else + return parent_2d->get_relative_transform(p_parent) * get_transform(); +} void Node2D::_bind_methods() { @@ -351,6 +363,8 @@ void Node2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("edit_set_pivot"),&Node2D::edit_set_pivot); + ObjectTypeDB::bind_method(_MD("get_relative_transform"),&Node2D::get_relative_transform); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2,"transform/pos"),_SCS("set_pos"),_SCS("get_pos")); ADD_PROPERTY(PropertyInfo(Variant::REAL,"transform/rot",PROPERTY_HINT_RANGE,"-1440,1440,0.1"),_SCS("_set_rotd"),_SCS("_get_rotd")); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2,"transform/scale"),_SCS("set_scale"),_SCS("get_scale")); diff --git a/scene/2d/node_2d.h b/scene/2d/node_2d.h index 61b8c829d6..7b059008c2 100644 --- a/scene/2d/node_2d.h +++ b/scene/2d/node_2d.h @@ -93,6 +93,9 @@ public: void set_z_as_relative(bool p_enabled); bool is_z_relative() const; + Matrix32 get_relative_transform(const Node *p_parent) const; + + Matrix32 get_transform() const; Node2D(); diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp index a82cfc7ea6..30e0241f23 100644 --- a/scene/gui/dialogs.cpp +++ b/scene/gui/dialogs.cpp @@ -328,8 +328,8 @@ AcceptDialog::AcceptDialog() { label->set_anchor(MARGIN_RIGHT,ANCHOR_END); label->set_anchor(MARGIN_BOTTOM,ANCHOR_END); label->set_begin( Point2( margin, margin) ); - label->set_end( Point2( margin, button_margin) ); - label->set_autowrap(true); + label->set_end( Point2( margin, button_margin+10) ); + //label->set_autowrap(true); add_child(label); hbc = memnew( HBoxContainer ); diff --git a/scene/gui/popup.cpp b/scene/gui/popup.cpp index bccd05d4fe..d58cb3da79 100644 --- a/scene/gui/popup.cpp +++ b/scene/gui/popup.cpp @@ -94,6 +94,8 @@ void Popup::popup_centered_minsize(const Size2& p_minsize) { Control *c=get_child(i)->cast_to(); if (!c) continue; + if (c->is_hidden()) + continue; Size2 minsize = c->get_combined_minimum_size(); @@ -114,6 +116,8 @@ void Popup::popup_centered_minsize(const Size2& p_minsize) { } + print_line(String(c->get_type())+": "+minsize); + total_minsize.width = MAX( total_minsize.width, minsize.width ); total_minsize.height = MAX( total_minsize.height, minsize.height ); } diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 9d907391ec..9600469e8a 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -102,6 +102,7 @@ #include "scene/2d/screen_button.h" #include "scene/2d/remote_transform_2d.h" #include "scene/2d/y_sort.h" +#include "scene/2d/navigation2d.h" #include "scene/2d/position_2d.h" #include "scene/2d/tile_map.h" @@ -575,6 +576,10 @@ void register_scene_types() { ObjectTypeDB::register_type(); ObjectTypeDB::register_type(); + ObjectTypeDB::register_type(); + ObjectTypeDB::register_type(); + ObjectTypeDB::register_type(); + OS::get_singleton()->yield(); //may take time to init ObjectTypeDB::register_type(); -- cgit v1.2.3 From d2f86cc09bf4136ebc1c2bbb8ec7b48a439c0371 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Sat, 14 Feb 2015 19:22:06 -0300 Subject: fixes to mouse warp -can warp now from viewport and control, in their respective coordinate systems -warp is now local to the window on Windows and OSX. IF YOU RUN OSX, PLEASE TEST THIS! And make sure it works!, new code is in OS_OSX::warp_mouse_pos. I don't have OSX so i can't test! --- scene/gui/control.cpp | 9 +++++++++ scene/gui/control.h | 2 +- scene/main/viewport.cpp | 9 +++++++++ scene/main/viewport.h | 2 ++ 4 files changed, 21 insertions(+), 1 deletion(-) (limited to 'scene') diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index ce268843b1..4d32c7ea9a 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -2688,6 +2688,12 @@ Control *Control::get_focus_owner() const { return data.window->window->key_focus; } + +void Control::warp_mouse(const Point2& p_to_pos) { + ERR_FAIL_COND(!is_inside_tree()); + get_viewport()->warp_mouse(get_global_transform().xform(p_to_pos)); +} + void Control::_bind_methods() { ObjectTypeDB::bind_method(_MD("_window_input_event"),&Control::_window_input_event); @@ -2784,6 +2790,9 @@ void Control::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_drag_preview","control:Control"),&Control::set_drag_preview); + ObjectTypeDB::bind_method(_MD("warp_mouse","to_pos"),&Control::warp_mouse); + + BIND_VMETHOD(MethodInfo("_input_event",PropertyInfo(Variant::INPUT_EVENT,"event"))); BIND_VMETHOD(MethodInfo(Variant::VECTOR2,"get_minimum_size")); BIND_VMETHOD(MethodInfo(Variant::OBJECT,"get_drag_data",PropertyInfo(Variant::VECTOR2,"pos"))); diff --git a/scene/gui/control.h b/scene/gui/control.h index 64b5a9b661..7e14bff098 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -380,7 +380,7 @@ public: void grab_click_focus(); - + void warp_mouse(const Point2& p_to_pos); Control(); ~Control(); diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index e6c787cf9e..fa163bf96d 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -29,6 +29,8 @@ #include "viewport.h" #include "os/os.h" #include "scene/3d/spatial.h" +#include "os/input.h" + //#include "scene/3d/camera.h" #include "servers/spatial_sound_server.h" @@ -1100,6 +1102,12 @@ void Viewport::_vp_unhandled_input(const InputEvent& p_ev) { } +void Viewport::warp_mouse(const Vector2& p_pos) { + + Vector2 gpos = (get_final_transform().affine_inverse() * _get_input_pre_xform()).affine_inverse().xform(p_pos); + Input::get_singleton()->warp_mouse_pos(gpos); +} + void Viewport::input(const InputEvent& p_event) { ERR_FAIL_COND(!is_inside_tree()); @@ -1289,6 +1297,7 @@ void Viewport::_bind_methods() { ObjectTypeDB::bind_method(_MD("is_audio_listener_2d","enable"), &Viewport::is_audio_listener_2d); ObjectTypeDB::bind_method(_MD("set_render_target_to_screen_rect"), &Viewport::set_render_target_to_screen_rect); + ObjectTypeDB::bind_method(_MD("warp_mouse","to_pos"), &Viewport::warp_mouse); ADD_PROPERTY( PropertyInfo(Variant::RECT2,"rect"), _SCS("set_rect"), _SCS("get_rect") ); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"own_world"), _SCS("set_use_own_world"), _SCS("is_using_own_world") ); diff --git a/scene/main/viewport.h b/scene/main/viewport.h index 4bb5735731..832a6b6107 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -246,6 +246,8 @@ public: void set_render_target_to_screen_rect(const Rect2& p_rect); Rect2 get_render_target_to_screen_rect() const; + void warp_mouse(const Vector2& p_pos); + void set_physics_object_picking(bool p_enable); bool get_physics_object_picking(); -- cgit v1.2.3 From 2185c018f6593e6d64b2beb62202d2291e2e008e Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Sun, 15 Feb 2015 01:19:46 -0300 Subject: begin new serialization framework also got rid of STL dependency on triangulator --- scene/2d/navigation_polygon.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'scene') diff --git a/scene/2d/navigation_polygon.cpp b/scene/2d/navigation_polygon.cpp index 570a5b95b0..fc69ea8a0d 100644 --- a/scene/2d/navigation_polygon.cpp +++ b/scene/2d/navigation_polygon.cpp @@ -113,7 +113,7 @@ void NavigationPolygon::clear_outlines(){ } void NavigationPolygon::make_polygons_from_outlines(){ - std::list in_poly,out_poly; + List in_poly,out_poly; Vector2 outside_point(-1e10,-1e10); @@ -194,9 +194,9 @@ void NavigationPolygon::make_polygons_from_outlines(){ vertices.resize(0); Map points; - for(std::list::iterator I = out_poly.begin();I!=out_poly.end();I++) { + for(List::Element*I = out_poly.front();I;I=I->next()) { - TriangulatorPoly& tp = *I; + TriangulatorPoly& tp = I->get(); struct Polygon p; -- cgit v1.2.3 From 4333aa240c68f22b235981bed56d11a592fdfd1d Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Sun, 15 Feb 2015 12:38:25 -0300 Subject: Godot UI is quick and snappy again! Changed linked listed sort to use auxiliary memory this fixes user interface performance issues. --- scene/gui/control.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'scene') diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 4d32c7ea9a..a8070be91d 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -2267,8 +2267,10 @@ void Control::_window_sort_subwindows() { if (!window->subwindow_order_dirty) return; + window->modal_stack.sort_custom(); window->subwindows.sort_custom(); + window->subwindow_order_dirty=false; } -- cgit v1.2.3 From 2bea642583efeb68886e71950384f297f2d7ee12 Mon Sep 17 00:00:00 2001 From: reduz Date: Mon, 16 Feb 2015 14:45:11 -0300 Subject: -Some more work on 2D Lights (NOT FUNCTIONAL YET!) --- scene/2d/light_2d.cpp | 182 +++++++++++++++++++++++++++++++++++++++++ scene/2d/light_2d.h | 80 ++++++++++++++++++ scene/register_scene_types.cpp | 2 + 3 files changed, 264 insertions(+) create mode 100644 scene/2d/light_2d.cpp create mode 100644 scene/2d/light_2d.h (limited to 'scene') diff --git a/scene/2d/light_2d.cpp b/scene/2d/light_2d.cpp new file mode 100644 index 0000000000..073e3a1645 --- /dev/null +++ b/scene/2d/light_2d.cpp @@ -0,0 +1,182 @@ +#include "light_2d.h" +#include "servers/visual_server.h" + +void Light2D::set_enabled( bool p_enabled) { + + VS::get_singleton()->canvas_light_set_enabled(canvas_light,p_enabled); + enabled=p_enabled; +} + +bool Light2D::is_enabled() const { + + return enabled; +} + +void Light2D::set_texture( const Ref& p_texture) { + + texture=p_texture; + if (texture.is_valid()) + VS::get_singleton()->canvas_light_set_texture(canvas_light,texture->get_rid()); + else + VS::get_singleton()->canvas_light_set_texture(canvas_light,RID()); +} + +Ref Light2D::get_texture() const { + + return texture; +} + +void Light2D::set_texture_offset( const Vector2& p_offset) { + + texture_offset=p_offset; + VS::get_singleton()->canvas_light_set_texture_offset(canvas_light,texture_offset); +} + +Vector2 Light2D::get_texture_offset() const { + + return texture_offset; +} + +void Light2D::set_color( const Color& p_color) { + + color=p_color; + VS::get_singleton()->canvas_light_set_color(canvas_light,color); + +} +Color Light2D::get_color() const { + + return color; +} + +void Light2D::set_height( float p_height) { + + height=p_height; + VS::get_singleton()->canvas_light_set_height(canvas_light,height); + +} +float Light2D::get_height() const { + + return height; +} + +void Light2D::set_z_range_min( int p_min_z) { + + z_min=p_min_z; + VS::get_singleton()->canvas_light_set_z_range(canvas_light,z_min,z_max); + +} +int Light2D::get_z_range_min() const { + + return z_min; +} + +void Light2D::set_z_range_max( int p_max_z) { + + z_max=p_max_z; + VS::get_singleton()->canvas_light_set_z_range(canvas_light,z_min,z_max); + +} +int Light2D::get_z_range_max() const { + + return z_max; +} + +void Light2D::set_item_mask( int p_mask) { + + item_mask=p_mask; + VS::get_singleton()->canvas_light_set_item_mask(canvas_light,item_mask); + +} + +int Light2D::get_item_mask() const { + + return item_mask; +} + +void Light2D::set_blend_mode( LightBlendMode p_blend_mode ) { + + blend_mode=p_blend_mode; + VS::get_singleton()->canvas_light_set_blend_mode(canvas_light,VS::CanvasLightBlendMode(blend_mode)); +} + +Light2D::LightBlendMode Light2D::get_blend_mode() const { + + return blend_mode; +} + +void Light2D::set_shadow_enabled( bool p_enabled) { + + shadow=p_enabled; + VS::get_singleton()->canvas_light_set_shadow_enabled(canvas_light,shadow); + +} +bool Light2D::is_shadow_enabled() const { + + return shadow; +} + +void Light2D::_bind_methods() { + + + ObjectTypeDB::bind_method(_MD("set_enabled","enabled"),&Light2D::set_enabled); + ObjectTypeDB::bind_method(_MD("is_enabled"),&Light2D::is_enabled); + + ObjectTypeDB::bind_method(_MD("set_texture","texture"),&Light2D::set_texture); + ObjectTypeDB::bind_method(_MD("get_texture"),&Light2D::get_texture); + + ObjectTypeDB::bind_method(_MD("set_texture_offset","texture_offset"),&Light2D::set_texture_offset); + ObjectTypeDB::bind_method(_MD("get_texture_offset"),&Light2D::get_texture_offset); + + ObjectTypeDB::bind_method(_MD("set_color","color"),&Light2D::set_color); + ObjectTypeDB::bind_method(_MD("get_color"),&Light2D::get_color); + + ObjectTypeDB::bind_method(_MD("set_height","height"),&Light2D::set_height); + ObjectTypeDB::bind_method(_MD("get_height"),&Light2D::get_height); + + ObjectTypeDB::bind_method(_MD("set_z_range_min","z"),&Light2D::set_z_range_min); + ObjectTypeDB::bind_method(_MD("get_z_range_min"),&Light2D::get_z_range_min); + + ObjectTypeDB::bind_method(_MD("set_z_range_max","z"),&Light2D::set_z_range_max); + ObjectTypeDB::bind_method(_MD("get_z_range_max"),&Light2D::get_z_range_max); + + ObjectTypeDB::bind_method(_MD("set_item_mask","item_mask"),&Light2D::set_item_mask); + ObjectTypeDB::bind_method(_MD("get_item_mask"),&Light2D::get_item_mask); + + ObjectTypeDB::bind_method(_MD("set_blend_mode","blend_mode"),&Light2D::set_blend_mode); + ObjectTypeDB::bind_method(_MD("get_blend_mode"),&Light2D::get_blend_mode); + + ObjectTypeDB::bind_method(_MD("set_shadow_enabled","enabled"),&Light2D::set_shadow_enabled); + ObjectTypeDB::bind_method(_MD("is_shadow_enabled"),&Light2D::is_shadow_enabled); + + ADD_PROPERTY( PropertyInfo(Variant::BOOL,"enabled"),_SCS("set_enabled"),_SCS("is_enabled")); + ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture"),_SCS("get_texture")); + ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"texture_offset"),_SCS("set_texture_offset"),_SCS("get_texture_offset")); + ADD_PROPERTY( PropertyInfo(Variant::COLOR,"color"),_SCS("set_color"),_SCS("get_color")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"height"),_SCS("set_height"),_SCS("get_height")); + ADD_PROPERTY( PropertyInfo(Variant::INT,"z_range_min",PROPERTY_HINT_RANGE,itos(VS::CANVAS_ITEM_Z_MIN)+","+itos(VS::CANVAS_ITEM_Z_MAX)+",1"),_SCS("set_z_range_min"),_SCS("get_z_range_min")); + ADD_PROPERTY( PropertyInfo(Variant::INT,"z_range_max",PROPERTY_HINT_RANGE,itos(VS::CANVAS_ITEM_Z_MIN)+","+itos(VS::CANVAS_ITEM_Z_MAX)+",1"),_SCS("set_z_range_max"),_SCS("get_z_range_max")); + ADD_PROPERTY( PropertyInfo(Variant::INT,"item_mask",PROPERTY_HINT_ALL_FLAGS),_SCS("set_item_mask"),_SCS("get_item_mask")); + ADD_PROPERTY( PropertyInfo(Variant::INT,"blend_mode",PROPERTY_HINT_ENUM,"Add,Sub,Mul,Dodge,Burn,Lighten,Darken,Overlay,Screen"),_SCS("set_blend_mode"),_SCS("get_blend_mode")); + ADD_PROPERTY( PropertyInfo(Variant::BOOL,"shadow_enabled"),_SCS("set_shadow_enabled"),_SCS("is_shadow_enabled")); + + +} + +Light2D::Light2D() { + + canvas_light=VisualServer::get_singleton()->canvas_light_create(); + enabled=true; + shadow=false; + color=Color(1,1,1); + height=0; + z_min=-1024; + z_max=1024; + item_mask=1; + blend_mode=LIGHT_BLEND_ADD; + +} + +Light2D::~Light2D() { + + VisualServer::get_singleton()->free(canvas_light); +} diff --git a/scene/2d/light_2d.h b/scene/2d/light_2d.h new file mode 100644 index 0000000000..ac8d587ea7 --- /dev/null +++ b/scene/2d/light_2d.h @@ -0,0 +1,80 @@ +#ifndef LIGHT_2D_H +#define LIGHT_2D_H + +#include "scene/2d/node_2d.h" + +class Light2D : public Node2D { + + OBJ_TYPE(Light2D,Node2D); +public: + + enum LightBlendMode { + LIGHT_BLEND_ADD, + LIGHT_BLEND_SUB, + LIGHT_BLEND_MULTIPLY, + LIGHT_BLEND_DODGE, + LIGHT_BLEND_BURN, + LIGHT_BLEND_LIGHTEN, + LIGHT_BLEND_DARKEN, + LIGHT_BLEND_OVERLAY, + LIGHT_BLEND_SCREEN, + }; + +private: + RID canvas_light; + bool enabled; + bool shadow; + Color color; + float height; + int z_min; + int z_max; + int item_mask; + LightBlendMode blend_mode; + Ref texture; + Vector2 texture_offset; + +protected: + + static void _bind_methods(); +public: + + + void set_enabled( bool p_enabled); + bool is_enabled() const; + + void set_texture( const Ref& p_texture); + Ref get_texture() const; + + void set_texture_offset( const Vector2& p_offset); + Vector2 get_texture_offset() const; + + void set_color( const Color& p_color); + Color get_color() const; + + void set_height( float p_height); + float get_height() const; + + void set_z_range_min( int p_min_z); + int get_z_range_min() const; + + void set_z_range_max( int p_max_z); + int get_z_range_max() const; + + void set_item_mask( int p_mask); + int get_item_mask() const; + + void set_blend_mode( LightBlendMode p_blend_mode ); + LightBlendMode get_blend_mode() const; + + void set_shadow_enabled( bool p_enabled); + bool is_shadow_enabled() const; + + + Light2D(); + ~Light2D(); +}; + + +VARIANT_ENUM_CAST(Light2D::LightBlendMode); + +#endif // LIGHT_2D_H diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 9600469e8a..89ce164ce9 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -79,6 +79,7 @@ #include "scene/resources/video_stream.h" #include "scene/2d/particles_2d.h" #include "scene/2d/path_2d.h" +#include "scene/2d/light_2d.h" #include "scene/2d/canvas_item.h" #include "scene/2d/sprite.h" @@ -472,6 +473,7 @@ void register_scene_types() { ObjectTypeDB::register_type(); ObjectTypeDB::register_type(); ObjectTypeDB::register_type(); + ObjectTypeDB::register_type(); ObjectTypeDB::register_type(); ObjectTypeDB::set_type_enabled("CollisionShape2D",false); -- cgit v1.2.3