diff --git a/LICENSE.md b/LICENSE.md index 122736f5f19..ca0a9702f74 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -21,3 +21,7 @@ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +********************************************************************** + diff --git a/demos/2d/isometric_light/character_shder.res b/demos/2d/isometric_light/character_shder.res new file mode 100644 index 00000000000..ca221f766c8 Binary files /dev/null and b/demos/2d/isometric_light/character_shder.res differ diff --git a/demos/2d/isometric_light/column.scn b/demos/2d/isometric_light/column.scn new file mode 100644 index 00000000000..f0b76838850 Binary files /dev/null and b/demos/2d/isometric_light/column.scn differ diff --git a/demos/2d/isometric_light/cubio.gd b/demos/2d/isometric_light/cubio.gd new file mode 100644 index 00000000000..30c766936cb --- /dev/null +++ b/demos/2d/isometric_light/cubio.gd @@ -0,0 +1,96 @@ + +extends KinematicBody2D + +# member variables here, example: +# var a=2 +# var b="textvar" + +const MAX_SPEED = 300.0 +const IDLE_SPEED = 10.0 +const ACCEL=5.0 +const VSCALE=0.5 +const SHOOT_INTERVAL=0.3 + +var speed=Vector2() +var current_anim="" +var current_mirror=false + +var shoot_countdown=0 + +func _input(ev): + if (ev.type==InputEvent.MOUSE_BUTTON and ev.button_index==1 and ev.pressed and shoot_countdown<=0): + var pos = get_canvas_transform().affine_inverse() * ev.pos + var dir = (pos-get_global_pos()).normalized() + var bullet = preload("res://shoot.scn").instance() + bullet.advance_dir=dir + bullet.set_pos( get_global_pos() + dir * 60 ) + get_parent().add_child(bullet) + shoot_countdown=SHOOT_INTERVAL + + + + +func _fixed_process(delta): + + shoot_countdown-=delta + var dir = Vector2() + if (Input.is_action_pressed("up")): + dir+=Vector2(0,-1) + if (Input.is_action_pressed("down")): + dir+=Vector2(0,1) + if (Input.is_action_pressed("left")): + dir+=Vector2(-1,0) + if (Input.is_action_pressed("right")): + dir+=Vector2(1,0) + + if (dir!=Vector2()): + dir=dir.normalized() + speed = speed.linear_interpolate(dir*MAX_SPEED,delta*ACCEL) + var motion = speed * delta + motion.y*=VSCALE + motion=move(motion) + + if (is_colliding()): + var n = get_collision_normal() + motion=n.slide(motion) + move(motion) + + var next_anim="" + var next_mirror=false + + if (dir==Vector2() and speed.length()IDLE_SPEED*0.1): + var angle = atan2(abs(speed.x),speed.y) + + next_mirror = speed.x>0 + if (angleshadow_buffer.is_valid()); + + bool has_shadow = light->shadow_buffer.is_valid() && ci->light_mask&light->item_shadow_mask; + + canvas_shader.set_conditional(CanvasShaderGLES2::USE_SHADOWS,has_shadow); bool light_rebind = canvas_shader.bind(); @@ -9302,7 +9305,9 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_POS,light->light_shader_pos); canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_COLOR,light->color); canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_HEIGHT,light->height); - if (light->shadow_buffer.is_valid()) { + canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_LOCAL_MATRIX,light->xform_cache.affine_inverse()); + + if (has_shadow) { CanvasLightShadow *cls = canvas_light_shadow_owner.get(light->shadow_buffer); glActiveTexture(GL_TEXTURE0+max_texture_units-3); @@ -9313,7 +9318,6 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const canvas_shader.set_uniform(CanvasShaderGLES2::SHADOW_TEXTURE,max_texture_units-3); canvas_shader.set_uniform(CanvasShaderGLES2::SHADOW_MATRIX,light->shadow_matrix_cache); - canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_LOCAL_MATRIX,light->xform_cache.affine_inverse()); canvas_shader.set_uniform(CanvasShaderGLES2::SHADOW_ESM_MULTIPLIER,light->shadow_esm_mult); } diff --git a/drivers/gles2/shader_compiler_gles2.cpp b/drivers/gles2/shader_compiler_gles2.cpp index b2052c7cbb5..be40043573e 100644 --- a/drivers/gles2/shader_compiler_gles2.cpp +++ b/drivers/gles2/shader_compiler_gles2.cpp @@ -808,12 +808,19 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() { mode_replace_table[4]["POINT_COORD"]="gl_PointCoord"; mode_replace_table[4]["TIME"]="time"; - mode_replace_table[5]["SRC_COLOR"]="color"; - mode_replace_table[5]["COLOR"]="color"; + mode_replace_table[5]["POSITION"]="gl_Position"; mode_replace_table[5]["NORMAL"]="normal"; - mode_replace_table[5]["LIGHT_DIR"]="light_dir"; - mode_replace_table[5]["LIGHT_DISTANCE"]="light_distance"; - mode_replace_table[5]["LIGHT"]="light"; + mode_replace_table[5]["UV"]="uv_interp"; + mode_replace_table[5]["COLOR"]="color"; + mode_replace_table[5]["TEXTURE"]="texture"; + mode_replace_table[5]["TEXTURE_PIXEL_SIZE"]="texpixel_size"; + mode_replace_table[5]["VAR1"]="var1_interp"; + mode_replace_table[5]["VAR2"]="var2_interp"; + mode_replace_table[5]["LIGHT_VEC"]="light_vec"; + mode_replace_table[5]["LIGHT_HEIGHT"]="light_height"; + mode_replace_table[5]["LIGHT_COLOR"]="light"; + mode_replace_table[5]["LIGHT"]="light_out"; + mode_replace_table[5]["SCREEN_UV"]="screen_uv"; mode_replace_table[5]["POINT_COORD"]="gl_PointCoord"; mode_replace_table[5]["TIME"]="time"; diff --git a/drivers/gles2/shaders/canvas.glsl b/drivers/gles2/shaders/canvas.glsl index 9022f30d7f6..0e19736fd53 100644 --- a/drivers/gles2/shaders/canvas.glsl +++ b/drivers/gles2/shaders/canvas.glsl @@ -26,6 +26,7 @@ uniform float time; #ifdef USE_LIGHTING uniform highp mat4 light_matrix; +uniform highp mat4 light_local_matrix; uniform vec2 light_pos; varying vec4 light_uv_interp; @@ -80,7 +81,7 @@ VERTEX_SHADER_CODE #ifdef USE_LIGHTING light_uv_interp.xy = (light_matrix * outvec).xy; - light_uv_interp.zw = outvec.xy-light_pos; + light_uv_interp.zw =(light_local_matrix * outvec).xy; #ifdef USE_SHADOWS pos=outvec.xy; #endif @@ -164,7 +165,6 @@ uniform sampler2D shadow_texture; uniform float shadow_attenuation; uniform highp mat4 shadow_matrix; -uniform highp mat4 light_local_matrix; highp varying vec2 pos; uniform float shadowpixel_size; @@ -188,7 +188,7 @@ void main() { vec4 color = color_interp; #if defined(NORMAL_USED) - vec3 normal = vec3(0,0,1); + vec3 normal = vec3(0.0,0.0,1.0); #endif @@ -197,6 +197,7 @@ void main() { vec2 screen_uv = gl_FragCoord.xy*screen_uv_mult; #endif + { FRAGMENT_SHADER_CODE } @@ -213,120 +214,29 @@ FRAGMENT_SHADER_CODE #ifdef USE_LIGHTING + vec2 light_vec = light_uv_interp.zw;; //for shadow and normal mapping + #if defined(NORMAL_USED) normal.xy = mat2(local_rot.xy,local_rot.zw) * normal.xy; #endif float att=1.0; - vec4 light = texture2D(light_texture,light_uv_interp.xy) * light_color; -#ifdef USE_SHADOWS - - - vec2 lpos = (light_local_matrix * vec4(pos,0.0,1.0)).xy; - float angle_to_light = -atan(lpos.x,lpos.y); - float PI = 3.14159265358979323846264; - /*int i = int(mod(floor((angle_to_light+7.0*PI/6.0)/(4.0*PI/6.0))+1.0, 3.0)); // +1 pq os indices estao em ordem 2,0,1 nos arrays - float ang*/ - - float su,sz; - - float abs_angle = abs(angle_to_light); - vec2 point; - float sh; - if (abs_angle<45.0*PI/180.0) { - point = lpos; - sh=0+(1.0/8.0); - } else if (abs_angle>135.0*PI/180.0) { - point = -lpos; - sh = 0.5+(1.0/8.0); - } else if (angle_to_light>0) { - - point = vec2(lpos.y,-lpos.x); - sh = 0.25+(1.0/8.0); - } else { - - point = vec2(-lpos.y,lpos.x); - sh = 0.75+(1.0/8.0); - - } - - - vec4 s = shadow_matrix * vec4(point,0.0,1.0); - s.xyz/=s.w; - su=s.x*0.5+0.5; - sz=s.z*0.5+0.5; - - float shadow_attenuation; - -#ifdef SHADOW_PCF5 - - shadow_attenuation=0.0; - shadow_attenuation += texture2D(shadow_texture,vec2(su,sh)).z135.0*PI/180.0) { + point = -light_vec; + sh = 0.5+(1.0/8.0); + } else if (angle_to_light>0.0) { + + point = vec2(light_vec.y,-light_vec.x); + sh = 0.25+(1.0/8.0); + } else { + + point = vec2(-light_vec.y,light_vec.x); + sh = 0.75+(1.0/8.0); + + } + + + vec4 s = shadow_matrix * vec4(point,0.0,1.0); + s.xyz/=s.w; + su=s.x*0.5+0.5; + sz=s.z*0.5+0.5; + + float shadow_attenuation; + +#ifdef SHADOW_PCF5 + + shadow_attenuation=0.0; + shadow_attenuation += texture2D(shadow_texture,vec2(su,sh)).zcanvas_light_set_item_shadow_mask(canvas_light,item_shadow_mask); + +} + +int Light2D::get_item_shadow_mask() const { + + return item_shadow_mask; +} + void Light2D::set_subtract_mode( bool p_enable ) { subtract_mode=p_enable; @@ -246,6 +258,9 @@ void Light2D::_bind_methods() { 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_item_shadow_mask","item_shadow_mask"),&Light2D::set_item_shadow_mask); + ObjectTypeDB::bind_method(_MD("get_item_shadow_mask"),&Light2D::get_item_shadow_mask); + ObjectTypeDB::bind_method(_MD("set_subtract_mode","enable"),&Light2D::set_subtract_mode); ObjectTypeDB::bind_method(_MD("get_subtract_mode"),&Light2D::get_subtract_mode); @@ -272,6 +287,7 @@ void Light2D::_bind_methods() { ADD_PROPERTY( PropertyInfo(Variant::BOOL,"shadow/enabled"),_SCS("set_shadow_enabled"),_SCS("is_shadow_enabled")); ADD_PROPERTY( PropertyInfo(Variant::INT,"shadow/buffer_size",PROPERTY_HINT_RANGE,"32,16384,1"),_SCS("set_shadow_buffer_size"),_SCS("get_shadow_buffer_size")); ADD_PROPERTY( PropertyInfo(Variant::REAL,"shadow/esm_multiplier",PROPERTY_HINT_RANGE,"1,4096,0.1"),_SCS("set_shadow_esm_multiplier"),_SCS("get_shadow_esm_multiplier")); + ADD_PROPERTY( PropertyInfo(Variant::INT,"shadow/item_mask",PROPERTY_HINT_ALL_FLAGS),_SCS("set_item_shadow_mask"),_SCS("get_item_shadow_mask")); } @@ -288,6 +304,7 @@ Light2D::Light2D() { layer_min=0; layer_max=0; item_mask=1; + item_shadow_mask=1; subtract_mode=false; shadow_buffer_size=2048; shadow_esm_multiplier=80; diff --git a/scene/2d/light_2d.h b/scene/2d/light_2d.h index 89f351c3cd8..26dc1f4d444 100644 --- a/scene/2d/light_2d.h +++ b/scene/2d/light_2d.h @@ -17,6 +17,7 @@ private: int layer_min; int layer_max; int item_mask; + int item_shadow_mask; int shadow_buffer_size; float shadow_esm_multiplier; bool subtract_mode; @@ -64,6 +65,9 @@ public: void set_item_mask( int p_mask); int get_item_mask() const; + void set_item_shadow_mask( int p_mask); + int get_item_shadow_mask() const; + void set_subtract_mode( bool p_enable ); bool get_subtract_mode() const; diff --git a/scene/2d/light_occluder_2d.cpp b/scene/2d/light_occluder_2d.cpp index 186ea2e248f..6ebd499f714 100644 --- a/scene/2d/light_occluder_2d.cpp +++ b/scene/2d/light_occluder_2d.cpp @@ -18,7 +18,8 @@ void OccluderPolygon2D::set_closed(bool p_closed) { if (closed==p_closed) return; closed=p_closed; - VS::get_singleton()->canvas_occluder_polygon_set_shape(occ_polygon,polygon,closed); + if (polygon.size()) + VS::get_singleton()->canvas_occluder_polygon_set_shape(occ_polygon,polygon,closed); emit_changed(); } @@ -56,9 +57,9 @@ void OccluderPolygon2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_polygon","polygon"),&OccluderPolygon2D::set_polygon); ObjectTypeDB::bind_method(_MD("get_polygon"),&OccluderPolygon2D::get_polygon); - ADD_PROPERTY( PropertyInfo(Variant::VECTOR2_ARRAY,"polygon"),_SCS("set_polygon"),_SCS("get_polygon")); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"closed"),_SCS("set_closed"),_SCS("is_closed")); ADD_PROPERTY( PropertyInfo(Variant::INT,"cull_mode",PROPERTY_HINT_ENUM,"Disabled,ClockWise,CounterClockWise"),_SCS("set_cull_mode"),_SCS("get_cull_mode")); + ADD_PROPERTY( PropertyInfo(Variant::VECTOR2_ARRAY,"polygon"),_SCS("set_polygon"),_SCS("get_polygon")); BIND_CONSTANT(CULL_DISABLED); BIND_CONSTANT(CULL_CLOCKWISE); diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index 75e7957cb81..b9d87c1224c 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -30,12 +30,32 @@ #include "io/marshalls.h" #include "servers/physics_2d_server.h" #include "method_bind_ext.inc" + +int TileMap::_get_quadrant_size() const { + + if (y_sort_mode) + return 1; + else + return quadrant_size; +} + void TileMap::_notification(int p_what) { switch(p_what) { case NOTIFICATION_ENTER_TREE: { + Node2D *c=this; + while(c) { + + navigation=c->cast_to(); + if (navigation) { + break; + } + + c=c->get_parent()->cast_to(); + } + pending_update=true; _update_dirty_quadrants(); RID space = get_world_2d()->get_space(); @@ -47,6 +67,25 @@ void TileMap::_notification(int p_what) { case NOTIFICATION_EXIT_TREE: { _update_quadrant_space(RID()); + for (Map::Element *E=quadrant_map.front();E;E=E->next()) { + + Quadrant &q=E->get(); + if (navigation) { + for(Map::Element *E=q.navpoly_ids.front();E;E=E->next()) { + + navigation->navpoly_remove(E->get().id); + } + q.navpoly_ids.clear(); + } + + for(Map::Element *E=q.occluder_instances.front();E;E=E->next()) { + VS::get_singleton()->free(E->get().id); + } + q.occluder_instances.clear(); + } + + navigation=NULL; + } break; case NOTIFICATION_TRANSFORM_CHANGED: { @@ -74,6 +113,10 @@ void TileMap::_update_quadrant_transform() { Matrix32 global_transform = get_global_transform(); + Matrix32 nav_rel; + if (navigation) + nav_rel = get_relative_transform(navigation); + for (Map::Element *E=quadrant_map.front();E;E=E->next()) { Quadrant &q=E->get(); @@ -81,6 +124,17 @@ void TileMap::_update_quadrant_transform() { xform.set_origin( q.pos ); xform = global_transform * xform; Physics2DServer::get_singleton()->body_set_state(q.body,Physics2DServer::BODY_STATE_TRANSFORM,xform); + + if (navigation) { + for(Map::Element *E=q.navpoly_ids.front();E;E=E->next()) { + + navigation->navpoly_set_transform(E->get().id,nav_rel * E->get().xform); + } + } + + for(Map::Element *E=q.occluder_instances.front();E;E=E->next()) { + VS::get_singleton()->canvas_light_occluder_set_transform(E->get().id,global_transform * E->get().xform); + } } } @@ -161,6 +215,33 @@ bool TileMap::get_center_y() const { return center_y; } +void TileMap::_fix_cell_transform(Matrix32& xform,const Cell& c,Vector2& offset,const Size2 &sc) { + + Size2 s=sc; + + if (c.transpose) { + SWAP(xform.elements[0].x, xform.elements[0].y); + SWAP(xform.elements[1].x, xform.elements[1].y); + SWAP(offset.x, offset.y); + SWAP(s.x, s.y); + } + if (c.flip_h) { + xform.elements[0].x=-xform.elements[0].x; + xform.elements[1].x=-xform.elements[1].x; + if (tile_origin==TILE_ORIGIN_TOP_LEFT) + offset.x=s.x-offset.x; + } + if (c.flip_v) { + xform.elements[0].y=-xform.elements[0].y; + xform.elements[1].y=-xform.elements[1].y; + if (tile_origin==TILE_ORIGIN_TOP_LEFT) + offset.y=s.y-offset.y; + } + xform.elements[2].x+=offset.x; + xform.elements[2].y+=offset.y; + +} + void TileMap::_update_dirty_quadrants() { if (!pending_update) @@ -173,15 +254,42 @@ void TileMap::_update_dirty_quadrants() { VisualServer *vs = VisualServer::get_singleton(); Physics2DServer *ps = Physics2DServer::get_singleton(); Vector2 tofs = get_cell_draw_offset(); + Vector2 tcenter = cell_size/2; + Matrix32 nav_rel; + if (navigation) + nav_rel = get_relative_transform(navigation); + + Vector2 qofs; while (dirty_quadrant_list.first()) { Quadrant &q = *dirty_quadrant_list.first()->self(); - vs->canvas_item_clear(q.canvas_item); + for (List::Element *E=q.canvas_items.front();E;E=E->next()) { + + vs->free(E->get()); + } + + q.canvas_items.clear(); + ps->body_clear_shapes(q.body); int shape_idx=0; + if (navigation) { + for(Map::Element *E=q.navpoly_ids.front();E;E=E->next()) { + + navigation->navpoly_remove(E->get().id); + } + q.navpoly_ids.clear(); + } + + for(Map::Element *E=q.occluder_instances.front();E;E=E->next()) { + VS::get_singleton()->free(E->get().id); + } + q.occluder_instances.clear(); + Ref prev_material; + RID prev_canvas_item; + for(int i=0;i::Element *E=tile_map.find( q.cells[i] ); @@ -192,11 +300,35 @@ void TileMap::_update_dirty_quadrants() { Ref tex = tile_set->tile_get_texture(c.id); Vector2 tile_ofs = tile_set->tile_get_texture_offset(c.id); - Vector2 offset = _map_to_world(E->key().x, E->key().y) - q.pos + tofs; + Vector2 wofs = _map_to_world(E->key().x, E->key().y); + Vector2 offset = wofs - q.pos + tofs; if (!tex.is_valid()) continue; + Ref mat = tile_set->tile_get_material(c.id); + + RID canvas_item; + + if (prev_canvas_item==RID() || prev_material!=mat) { + + canvas_item=vs->canvas_item_create(); + if (mat.is_valid()) + vs->canvas_item_set_material(canvas_item,mat->get_rid()); + vs->canvas_item_set_parent( canvas_item, get_canvas_item() ); + Matrix32 xform; + xform.set_origin( q.pos ); + vs->canvas_item_set_transform( canvas_item, xform ); + q.canvas_items.push_back(canvas_item); + + prev_canvas_item=canvas_item; + prev_material=mat; + + } else { + canvas_item=prev_canvas_item; + } + + Rect2 r = tile_set->tile_get_region(c.id); Size2 s = tex->get_size(); @@ -223,12 +355,32 @@ void TileMap::_update_dirty_quadrants() { if (c.flip_v) rect.size.y=-rect.size.y; + Vector2 center_ofs; + + if (tile_origin==TILE_ORIGIN_TOP_LEFT) { + rect.pos+=tile_ofs; + } else if (tile_origin==TILE_ORIGIN_CENTER) { + rect.pos+=tcenter; + + Vector2 center = (s/2) - tile_ofs; + center_ofs=tcenter-(s/2); + + if (c.flip_h) + rect.pos.x-=s.x-center.x; + else + rect.pos.x-=center.x; + + if (c.flip_v) + rect.pos.y-=s.y-center.y; + else + rect.pos.y-=center.y; + } + - rect.pos+=tile_ofs; if (r==Rect2()) { - tex->draw_rect(q.canvas_item,rect,false,Color(1,1,1),c.transpose); + tex->draw_rect(canvas_item,rect,false,Color(1,1,1),c.transpose); } else { - tex->draw_rect_region(q.canvas_item,rect,r,Color(1,1,1),c.transpose); + tex->draw_rect_region(canvas_item,rect,r,Color(1,1,1),c.transpose); } Vector< Ref > shapes = tile_set->tile_get_shapes(c.id); @@ -242,32 +394,48 @@ void TileMap::_update_dirty_quadrants() { Vector2 shape_ofs = tile_set->tile_get_shape_offset(c.id); Matrix32 xform; xform.set_origin(offset.floor()); - if (c.transpose) { - SWAP(xform.elements[0].x, xform.elements[0].y); - SWAP(xform.elements[1].x, xform.elements[1].y); - SWAP(shape_ofs.x, shape_ofs.y); - SWAP(s.x, s.y); - } - if (c.flip_h) { - xform.elements[0].x=-xform.elements[0].x; - xform.elements[1].x=-xform.elements[1].x; - shape_ofs.x=s.x-shape_ofs.x; - } - if (c.flip_v) { - xform.elements[0].y=-xform.elements[0].y; - xform.elements[1].y=-xform.elements[1].y; - shape_ofs.y=s.y-shape_ofs.y; - } - xform.elements[2].x+=shape_ofs.x; - xform.elements[2].y+=shape_ofs.y; - + _fix_cell_transform(xform,c,shape_ofs+center_ofs,s); 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)); } } + + if (navigation) { + Ref navpoly = tile_set->tile_get_navigation_polygon(c.id); + Vector2 npoly_ofs = tile_set->tile_get_navigation_polygon_offset(c.id); + Matrix32 xform; + xform.set_origin(offset.floor()+q.pos); + _fix_cell_transform(xform,c,npoly_ofs+center_ofs,s); + + int pid = navigation->navpoly_create(navpoly,nav_rel * xform); + + Quadrant::NavPoly np; + np.id=pid; + np.xform=xform; + q.navpoly_ids[E->key()]=np; + } + + + Ref occluder=tile_set->tile_get_light_occluder(c.id); + if (occluder.is_valid()) { + + Vector2 occluder_ofs = tile_set->tile_get_occluder_offset(c.id); + Matrix32 xform; + xform.set_origin(offset.floor()+q.pos); + _fix_cell_transform(xform,c,occluder_ofs+center_ofs,s); + + RID orid = VS::get_singleton()->canvas_light_occluder_create(); + VS::get_singleton()->canvas_light_occluder_set_transform(orid,get_global_transform() * xform); + VS::get_singleton()->canvas_light_occluder_set_polygon(orid,occluder->get_rid()); + VS::get_singleton()->canvas_light_occluder_attach_to_canvas(orid,get_canvas()); + Quadrant::Occluder oc; + oc.xform=xform; + oc.id=orid; + q.occluder_instances[E->key()]=oc; + } } dirty_quadrant_list.remove( dirty_quadrant_list.first() ); @@ -282,10 +450,10 @@ void TileMap::_update_dirty_quadrants() { for (Map::Element *E=quadrant_map.front();E;E=E->next()) { Quadrant &q=E->get(); - if (q.canvas_item.is_valid()) { - VS::get_singleton()->canvas_item_raise(q.canvas_item); - } + for (List::Element *E=q.canvas_items.front();E;E=E->next()) { + VS::get_singleton()->canvas_item_raise(E->get()); + } } quadrant_order_dirty=false; @@ -308,10 +476,10 @@ void TileMap::_recompute_rect_cache() { Rect2 r; - r.pos=_map_to_world(E->key().x*quadrant_size, E->key().y*quadrant_size); - r.expand_to( _map_to_world(E->key().x*quadrant_size+quadrant_size, E->key().y*quadrant_size) ); - r.expand_to( _map_to_world(E->key().x*quadrant_size+quadrant_size, E->key().y*quadrant_size+quadrant_size) ); - r.expand_to( _map_to_world(E->key().x*quadrant_size, E->key().y*quadrant_size+quadrant_size) ); + r.pos=_map_to_world(E->key().x*_get_quadrant_size(), E->key().y*_get_quadrant_size()); + r.expand_to( _map_to_world(E->key().x*_get_quadrant_size()+_get_quadrant_size(), E->key().y*_get_quadrant_size()) ); + r.expand_to( _map_to_world(E->key().x*_get_quadrant_size()+_get_quadrant_size(), E->key().y*_get_quadrant_size()+_get_quadrant_size()) ); + r.expand_to( _map_to_world(E->key().x*_get_quadrant_size(), E->key().y*_get_quadrant_size()+_get_quadrant_size()) ); if (E==quadrant_map.front()) r_total=r; else @@ -322,7 +490,7 @@ void TileMap::_recompute_rect_cache() { if (r_total==Rect2()) { rect_cache=Rect2(-10,-10,20,20); } else { - rect_cache=r_total.grow(MAX(cell_size.x,cell_size.y)*quadrant_size); + rect_cache=r_total.grow(MAX(cell_size.x,cell_size.y)*_get_quadrant_size()); } item_rect_changed(); @@ -338,11 +506,13 @@ Map::Element *TileMap::_create_quadrant(const Matrix32 xform; //xform.set_origin(Point2(p_qk.x,p_qk.y)*cell_size*quadrant_size); Quadrant q; - q.pos = _map_to_world(p_qk.x*quadrant_size,p_qk.y*quadrant_size); + q.pos = _map_to_world(p_qk.x*_get_quadrant_size(),p_qk.y*_get_quadrant_size()); + q.pos+=get_cell_draw_offset(); + if (tile_origin==TILE_ORIGIN_CENTER) + q.pos+=cell_size/2; + xform.set_origin( q.pos ); - 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.canvas_item = VisualServer::get_singleton()->canvas_item_create(); 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); @@ -366,10 +536,27 @@ void TileMap::_erase_quadrant(Map::Element *Q) { Quadrant &q=Q->get(); Physics2DServer::get_singleton()->free(q.body); - VisualServer::get_singleton()->free(q.canvas_item); + for (List::Element *E=q.canvas_items.front();E;E=E->next()) { + + VisualServer::get_singleton()->free(E->get()); + } + q.canvas_items.clear(); if (q.dirty_list.in_list()) dirty_quadrant_list.remove(&q.dirty_list); + if (navigation) { + for(Map::Element *E=q.navpoly_ids.front();E;E=E->next()) { + + navigation->navpoly_remove(E->get().id); + } + q.navpoly_ids.clear(); + } + + for(Map::Element *E=q.occluder_instances.front();E;E=E->next()) { + VS::get_singleton()->free(E->get().id); + } + q.occluder_instances.clear(); + quadrant_map.erase(Q); rect_cache_dirty=true; } @@ -397,7 +584,7 @@ void TileMap::set_cell(int p_x,int p_y,int p_tile,bool p_flip_x,bool p_flip_y,bo if (!E && p_tile==INVALID_CELL) return; //nothing to do - PosKey qk(p_x/quadrant_size,p_y/quadrant_size); + PosKey qk(p_x/_get_quadrant_size(),p_y/_get_quadrant_size()); if (p_tile==INVALID_CELL) { //erase existing tile_map.erase(pk); @@ -495,7 +682,7 @@ void TileMap::_recreate_quadrants() { for (Map::Element *E=tile_map.front();E;E=E->next()) { - PosKey qk(E->key().x/quadrant_size,E->key().y/quadrant_size); + PosKey qk(E->key().x/_get_quadrant_size(),E->key().y/_get_quadrant_size()); Map::Element *Q=quadrant_map.find(qk); if (!Q) { @@ -511,6 +698,7 @@ void TileMap::_recreate_quadrants() { } + void TileMap::_clear_quadrants() { while (quadrant_map.size()) { @@ -678,6 +866,20 @@ void TileMap::set_half_offset(HalfOffset p_half_offset) { emit_signal("settings_changed"); } +void TileMap::set_tile_origin(TileOrigin p_tile_origin) { + + _clear_quadrants(); + tile_origin=p_tile_origin; + _recreate_quadrants(); + emit_signal("settings_changed"); +} + +TileMap::TileOrigin TileMap::get_tile_origin() const{ + + return tile_origin; +} + + Vector2 TileMap::get_cell_draw_offset() const { switch(mode) { @@ -804,6 +1006,21 @@ Vector2 TileMap::world_to_map(const Vector2& p_pos) const{ return ret.floor(); } +void TileMap::set_y_sort_mode(bool p_enable) { + + _clear_quadrants(); + y_sort_mode=p_enable; + VS::get_singleton()->canvas_item_set_sort_children_by_y(get_canvas_item(),y_sort_mode); + _recreate_quadrants(); + emit_signal("settings_changed"); + +} + +bool TileMap::is_y_sort_mode_enabled() const { + + return y_sort_mode; +} + void TileMap::_bind_methods() { @@ -829,12 +1046,18 @@ void TileMap::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_quadrant_size","size"),&TileMap::set_quadrant_size); ObjectTypeDB::bind_method(_MD("get_quadrant_size"),&TileMap::get_quadrant_size); + ObjectTypeDB::bind_method(_MD("set_tile_origin","origin"),&TileMap::set_tile_origin); + ObjectTypeDB::bind_method(_MD("get_tile_origin"),&TileMap::get_tile_origin); + ObjectTypeDB::bind_method(_MD("set_center_x","enable"),&TileMap::set_center_x); ObjectTypeDB::bind_method(_MD("get_center_x"),&TileMap::get_center_x); 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_y_sort_mode","enable"),&TileMap::set_y_sort_mode); + ObjectTypeDB::bind_method(_MD("is_y_sort_mode_enabled"),&TileMap::is_y_sort_mode_enabled); + 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); @@ -871,6 +1094,8 @@ 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,"cell/tile_origin",PROPERTY_HINT_ENUM,"Top Left,Center"),_SCS("set_tile_origin"),_SCS("get_tile_origin")); + ADD_PROPERTY( PropertyInfo(Variant::BOOL,"cell/y_sort"),_SCS("set_y_sort_mode"),_SCS("is_y_sort_mode_enabled")); 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")); @@ -886,6 +1111,8 @@ void TileMap::_bind_methods() { BIND_CONSTANT( HALF_OFFSET_X ); BIND_CONSTANT( HALF_OFFSET_Y ); BIND_CONSTANT( HALF_OFFSET_DISABLED ); + BIND_CONSTANT( TILE_ORIGIN_TOP_LEFT ); + BIND_CONSTANT( TILE_ORIGIN_CENTER ); } @@ -906,9 +1133,12 @@ TileMap::TileMap() { mode=MODE_SQUARE; half_offset=HALF_OFFSET_DISABLED; use_kinematic=false; + navigation=NULL; + y_sort_mode=false; fp_adjust=0.01; fp_adjust=0.01; + tile_origin=TILE_ORIGIN_TOP_LEFT; } TileMap::~TileMap() { diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h index fe1067fc1d9..3facc9e8b78 100644 --- a/scene/2d/tile_map.h +++ b/scene/2d/tile_map.h @@ -30,6 +30,7 @@ #define TILE_MAP_H #include "scene/2d/node_2d.h" +#include "scene/2d/navigation2d.h" #include "scene/resources/tile_set.h" #include "self_list.h" #include "vset.h" @@ -51,6 +52,12 @@ public: HALF_OFFSET_DISABLED, }; + enum TileOrigin { + TILE_ORIGIN_TOP_LEFT, + TILE_ORIGIN_CENTER + }; + + private: Ref tile_set; @@ -61,6 +68,7 @@ private: Matrix32 custom_transform; HalfOffset half_offset; bool use_kinematic; + Navigation2D *navigation; union PosKey { @@ -98,15 +106,29 @@ private: struct Quadrant { Vector2 pos; - RID canvas_item; + List canvas_items; RID body; SelfList dirty_list; + struct NavPoly { + int id; + Matrix32 xform; + }; + + struct Occluder { + RID id; + Matrix32 xform; + }; + + + Map navpoly_ids; + Map occluder_instances; + VSet 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;} + void operator=(const Quadrant& q) { pos=q.pos; canvas_items=q.canvas_items; body=q.body; cells=q.cells; navpoly_ids=q.navpoly_ids; occluder_instances=q.occluder_instances; } + Quadrant(const Quadrant& q) : dirty_list(this) { pos=q.pos; canvas_items=q.canvas_items; body=q.body; cells=q.cells; occluder_instances=q.occluder_instances; navpoly_ids=q.navpoly_ids;} Quadrant() : dirty_list(this) {} }; @@ -119,11 +141,14 @@ private: Rect2 rect_cache; bool rect_cache_dirty; bool quadrant_order_dirty; + bool y_sort_mode; float fp_adjust; float friction; float bounce; uint32_t collision_layer; + TileOrigin tile_origin; + void _fix_cell_transform(Matrix32& xform, const Cell& c, Vector2 &offset, const Size2 &s); Map::Element *_create_quadrant(const PosKey& p_qk); void _erase_quadrant(Map::Element *Q); @@ -135,6 +160,9 @@ private: void _update_quadrant_transform(); void _recompute_rect_cache(); + _FORCE_INLINE_ int _get_quadrant_size() const; + + void _set_tile_data(const DVector& p_data); DVector _get_tile_data() const; @@ -195,6 +223,9 @@ public: void set_half_offset(HalfOffset p_half_offset); HalfOffset get_half_offset() const; + void set_tile_origin(TileOrigin p_tile_origin); + TileOrigin get_tile_origin() const; + void set_custom_transform(const Matrix32& p_xform); Matrix32 get_custom_transform() const; @@ -204,6 +235,9 @@ public: Vector2 map_to_world(const Vector2& p_pos, bool p_ignore_ofs=false) const; Vector2 world_to_map(const Vector2& p_pos) const; + void set_y_sort_mode(bool p_enable); + bool is_y_sort_mode_enabled() const; + void clear(); TileMap(); @@ -212,5 +246,6 @@ public: VARIANT_ENUM_CAST(TileMap::Mode); VARIANT_ENUM_CAST(TileMap::HalfOffset); +VARIANT_ENUM_CAST(TileMap::TileOrigin); #endif // TILE_MAP_H diff --git a/scene/2d/visibility_notifier_2d.cpp b/scene/2d/visibility_notifier_2d.cpp index 22534eeb0e3..cd3c788b659 100644 --- a/scene/2d/visibility_notifier_2d.cpp +++ b/scene/2d/visibility_notifier_2d.cpp @@ -32,6 +32,7 @@ #include "scene/2d/physics_body_2d.h" #include "scene/animation/animation_player.h" #include "scene/scene_string_names.h" +#include "particles_2d.h" void VisibilityNotifier2D::_enter_viewport(Viewport* p_viewport) { @@ -188,6 +189,15 @@ void VisibilityEnabler2D::_find_nodes(Node* p_node) { } + if (enabler[ENABLER_PAUSE_PARTICLES]) { + + Particles2D *ps = p_node->cast_to(); + if (ps) { + add=true; + } + + } + if (add) { p_node->connect(SceneStringNames::get_singleton()->exit_tree,this,"_node_removed",varray(p_node),CONNECT_ONESHOT); @@ -271,6 +281,15 @@ void VisibilityEnabler2D::_change_node_state(Node* p_node,bool p_enabled) { } } + { + Particles2D *ps=p_node->cast_to(); + + if (ps) { + + ps->set_emitting(p_enabled); + } + } + } @@ -292,9 +311,11 @@ void VisibilityEnabler2D::_bind_methods(){ ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"enabler/pause_animations"),_SCS("set_enabler"),_SCS("is_enabler_enabled"), ENABLER_PAUSE_ANIMATIONS ); ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"enabler/freeze_bodies"),_SCS("set_enabler"),_SCS("is_enabler_enabled"), ENABLER_FREEZE_BODIES); + ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"enabler/pause_particles"),_SCS("set_enabler"),_SCS("is_enabler_enabled"), ENABLER_PAUSE_PARTICLES); BIND_CONSTANT( ENABLER_FREEZE_BODIES ); BIND_CONSTANT( ENABLER_PAUSE_ANIMATIONS ); + BIND_CONSTANT( ENABLER_PAUSE_PARTICLES ); BIND_CONSTANT( ENABLER_MAX); } @@ -320,3 +341,4 @@ VisibilityEnabler2D::VisibilityEnabler2D() { } + diff --git a/scene/2d/visibility_notifier_2d.h b/scene/2d/visibility_notifier_2d.h index cdf52ecb27f..621c470d5d5 100644 --- a/scene/2d/visibility_notifier_2d.h +++ b/scene/2d/visibility_notifier_2d.h @@ -73,6 +73,7 @@ public: enum Enabler { ENABLER_PAUSE_ANIMATIONS, ENABLER_FREEZE_BODIES, + ENABLER_PAUSE_PARTICLES, ENABLER_MAX }; diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index a8070be91d0..86f442fd8cd 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -940,68 +940,68 @@ void Control::_window_input_event(InputEvent p_event) { case InputEvent::MOUSE_BUTTON: { - window->key_event_accepted=false; + window->key_event_accepted=false; - Point2 mpos =(get_canvas_transform()).affine_inverse().xform(Point2(p_event.mouse_button.x,p_event.mouse_button.y)); - if (p_event.mouse_button.pressed) { + Point2 mpos =(get_canvas_transform()).affine_inverse().xform(Point2(p_event.mouse_button.x,p_event.mouse_button.y)); + if (p_event.mouse_button.pressed) { - Size2 pos = mpos; - if (window->mouse_focus && p_event.mouse_button.button_index!=window->mouse_focus_button) { + Size2 pos = mpos; + if (window->mouse_focus && p_event.mouse_button.button_index!=window->mouse_focus_button) { - //do not steal mouse focus and stuff + //do not steal mouse focus and stuff - } else { + } else { - _window_sort_modal_stack(); - while (!window->modal_stack.empty()) { + _window_sort_modal_stack(); + while (!window->modal_stack.empty()) { - Control *top = window->modal_stack.back()->get(); - if (!top->has_point(top->get_global_transform().affine_inverse().xform(pos))) { + Control *top = window->modal_stack.back()->get(); + if (!top->has_point(top->get_global_transform().affine_inverse().xform(pos))) { - if (top->data.modal_exclusive) { - //cancel event, sorry, modal exclusive EATS UP ALL - get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,"windows","_cancel_input_ID",p_event.ID); - get_tree()->set_input_as_handled(); - return; // no one gets the event if exclusive NO ONE + if (top->data.modal_exclusive) { + //cancel event, sorry, modal exclusive EATS UP ALL + get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,"windows","_cancel_input_ID",p_event.ID); + get_tree()->set_input_as_handled(); + return; // no one gets the event if exclusive NO ONE + } + + top->notification(NOTIFICATION_MODAL_CLOSE); + top->_modal_stack_remove(); + top->hide(); + } else { + break; } + } - top->notification(NOTIFICATION_MODAL_CLOSE); - top->_modal_stack_remove(); - top->hide(); - } else { + + + Matrix32 parent_xform; + + if (data.parent_canvas_item) + parent_xform=data.parent_canvas_item->get_global_transform(); + + + + window->mouse_focus = _find_control_at_pos(this,pos,parent_xform,window->focus_inv_xform); + //print_line("has mf "+itos(window->mouse_focus!=NULL)); + window->mouse_focus_button=p_event.mouse_button.button_index; + + if (!window->mouse_focus) { break; } + + if (p_event.mouse_button.button_index==BUTTON_LEFT) { + window->drag_accum=Vector2(); + window->drag_attempted=false; + window->drag_data=Variant(); + } + + } - - - Matrix32 parent_xform; - - if (data.parent_canvas_item) - parent_xform=data.parent_canvas_item->get_global_transform(); - - - - window->mouse_focus = _find_control_at_pos(this,pos,parent_xform,window->focus_inv_xform); - //print_line("has mf "+itos(window->mouse_focus!=NULL)); - window->mouse_focus_button=p_event.mouse_button.button_index; - - if (!window->mouse_focus) { - break; - } - - if (p_event.mouse_button.button_index==BUTTON_LEFT) { - window->drag_accum=Vector2(); - window->drag_attempted=false; - window->drag_data=Variant(); - } - - - } - p_event.mouse_button.global_x = pos.x; p_event.mouse_button.global_y = pos.y; @@ -1020,8 +1020,8 @@ void Control::_window_input_event(InputEvent p_event) { /*if (bool(GLOBAL_DEF("debug/print_clicked_control",false))) { - print_line(String(window->mouse_focus->get_path())+" - "+pos); - }*/ + print_line(String(window->mouse_focus->get_path())+" - "+pos); + }*/ #endif if (window->mouse_focus->get_focus_mode()!=FOCUS_NONE && window->mouse_focus!=window->key_focus && p_event.mouse_button.button_index==BUTTON_LEFT) { @@ -1033,10 +1033,12 @@ void Control::_window_input_event(InputEvent p_event) { if (window->mouse_focus->can_process()) { _window_call_input(window->mouse_focus,p_event); } - + get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,"windows","_cancel_input_ID",p_event.ID); get_tree()->set_input_as_handled(); + window->tooltip_popup->hide(); + } else { if (window->drag_preview && p_event.mouse_button.button_index==BUTTON_LEFT) { diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp index 208ba5bb661..338804e0e10 100644 --- a/scene/resources/tile_set.cpp +++ b/scene/resources/tile_set.cpp @@ -46,6 +46,8 @@ bool TileSet::_set(const StringName& p_name, const Variant& p_value) { tile_set_texture(id,p_value); else if (what=="tex_offset") tile_set_texture_offset(id,p_value); + else if (what=="material") + tile_set_material(id,p_value); else if (what=="shape_offset") tile_set_shape_offset(id,p_value); else if (what=="region") @@ -54,6 +56,14 @@ bool TileSet::_set(const StringName& p_name, const Variant& p_value) { tile_set_shape(id,p_value); else if (what=="shapes") _tile_set_shapes(id,p_value); + else if (what=="occluder") + tile_set_light_occluder(id,p_value); + else if (what=="occluder_offset") + tile_set_occluder_offset(id,p_value); + else if (what=="navigation") + tile_set_navigation_polygon(id,p_value); + else if (what=="navigation_offset") + tile_set_navigation_polygon_offset(id,p_value); else return false; @@ -79,6 +89,8 @@ bool TileSet::_get(const StringName& p_name,Variant &r_ret) const{ r_ret=tile_get_texture(id); else if (what=="tex_offset") r_ret=tile_get_texture_offset(id); + else if (what=="material") + r_ret=tile_get_material(id); else if (what=="shape_offset") r_ret=tile_get_shape_offset(id); else if (what=="region") @@ -87,6 +99,14 @@ bool TileSet::_get(const StringName& p_name,Variant &r_ret) const{ r_ret=tile_get_shape(id); else if (what=="shapes") r_ret=_tile_get_shapes(id); + else if (what=="occluder") + r_ret=tile_get_light_occluder(id); + else if (what=="occluder_offset") + r_ret=tile_get_occluder_offset(id); + else if (what=="navigation") + r_ret=tile_get_navigation_polygon(id); + else if (what=="navigation_offset") + r_ret=tile_get_navigation_polygon_offset(id); else return false; @@ -103,8 +123,13 @@ void TileSet::_get_property_list( List *p_list) const{ p_list->push_back(PropertyInfo(Variant::STRING,pre+"name")); p_list->push_back(PropertyInfo(Variant::OBJECT,pre+"texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture")); p_list->push_back(PropertyInfo(Variant::VECTOR2,pre+"tex_offset")); - p_list->push_back(PropertyInfo(Variant::VECTOR2,pre+"shape_offset")); + p_list->push_back(PropertyInfo(Variant::OBJECT,pre+"material",PROPERTY_HINT_RESOURCE_TYPE,"CanvasItemMaterial")); p_list->push_back(PropertyInfo(Variant::RECT2,pre+"region")); + p_list->push_back(PropertyInfo(Variant::VECTOR2,pre+"occluder_offset")); + p_list->push_back(PropertyInfo(Variant::OBJECT,pre+"occluder",PROPERTY_HINT_RESOURCE_TYPE,"OccluderPolygon2D")); + p_list->push_back(PropertyInfo(Variant::VECTOR2,pre+"navigation_offset")); + p_list->push_back(PropertyInfo(Variant::OBJECT,pre+"navigation",PROPERTY_HINT_RESOURCE_TYPE,"NavigationPolygon")); + p_list->push_back(PropertyInfo(Variant::VECTOR2,pre+"shape_offset")); p_list->push_back(PropertyInfo(Variant::OBJECT,pre+"shape",PROPERTY_HINT_RESOURCE_TYPE,"Shape2D",PROPERTY_USAGE_EDITOR)); p_list->push_back(PropertyInfo(Variant::ARRAY,pre+"shapes",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR)); } @@ -134,6 +159,22 @@ Ref TileSet::tile_get_texture(int p_id) const { } + +void TileSet::tile_set_material(int p_id,const Ref &p_material) { + + ERR_FAIL_COND(!tile_map.has(p_id)); + tile_map[p_id].material=p_material; + emit_changed(); + +} + +Ref TileSet::tile_get_material(int p_id) const{ + + ERR_FAIL_COND_V(!tile_map.has(p_id),Ref()); + return tile_map[p_id].material; +} + + void TileSet::tile_set_texture_offset(int p_id,const Vector2 &p_offset) { ERR_FAIL_COND(!tile_map.has(p_id)); @@ -210,6 +251,58 @@ Ref TileSet::tile_get_shape(int p_id) const { } +void TileSet::tile_set_light_occluder(int p_id,const Ref &p_light_occluder) { + + ERR_FAIL_COND(!tile_map.has(p_id)); + tile_map[p_id].occluder=p_light_occluder; + +} + +Ref TileSet::tile_get_light_occluder(int p_id) const{ + + ERR_FAIL_COND_V(!tile_map.has(p_id),Ref()); + return tile_map[p_id].occluder; + +} + +void TileSet::tile_set_navigation_polygon_offset(int p_id,const Vector2& p_offset) { + + ERR_FAIL_COND(!tile_map.has(p_id)); + tile_map[p_id].navigation_polygon_offset=p_offset; + +} + +Vector2 TileSet::tile_get_navigation_polygon_offset(int p_id) const{ + ERR_FAIL_COND_V(!tile_map.has(p_id),Vector2()); + return tile_map[p_id].navigation_polygon_offset; +} + +void TileSet::tile_set_navigation_polygon(int p_id,const Ref &p_navigation_polygon) { + + ERR_FAIL_COND(!tile_map.has(p_id)); + tile_map[p_id].navigation_polygon=p_navigation_polygon; + +} + +Ref TileSet::tile_get_navigation_polygon(int p_id) const { + + ERR_FAIL_COND_V(!tile_map.has(p_id),Ref()); + return tile_map[p_id].navigation_polygon; + +} + +void TileSet::tile_set_occluder_offset(int p_id,const Vector2& p_offset) { + + ERR_FAIL_COND(!tile_map.has(p_id)); + tile_map[p_id].occluder_offset=p_offset; + +} + +Vector2 TileSet::tile_get_occluder_offset(int p_id) const{ + ERR_FAIL_COND_V(!tile_map.has(p_id),Vector2()); + return tile_map[p_id].occluder_offset; +} + void TileSet::tile_set_shapes(int p_id,const Vector > &p_shapes) { ERR_FAIL_COND(!tile_map.has(p_id)); @@ -319,6 +412,8 @@ void TileSet::_bind_methods() { ObjectTypeDB::bind_method(_MD("tile_get_name","id"),&TileSet::tile_get_name); ObjectTypeDB::bind_method(_MD("tile_set_texture","id","texture:Texture"),&TileSet::tile_set_texture); ObjectTypeDB::bind_method(_MD("tile_get_texture:Texture","id"),&TileSet::tile_get_texture); + ObjectTypeDB::bind_method(_MD("tile_set_material","id","material:CanvasItemMaterial"),&TileSet::tile_set_material); + ObjectTypeDB::bind_method(_MD("tile_get_material:CanvasItemMaterial","id"),&TileSet::tile_get_material); ObjectTypeDB::bind_method(_MD("tile_set_texture_offset","id","texture_offset"),&TileSet::tile_set_texture_offset); ObjectTypeDB::bind_method(_MD("tile_get_texture_offset","id"),&TileSet::tile_get_texture_offset); ObjectTypeDB::bind_method(_MD("tile_set_shape_offset","id","shape_offset"),&TileSet::tile_set_shape_offset); @@ -329,6 +424,15 @@ void TileSet::_bind_methods() { ObjectTypeDB::bind_method(_MD("tile_get_shape:Shape2D","id"),&TileSet::tile_get_shape); ObjectTypeDB::bind_method(_MD("tile_set_shapes","id","shapes"),&TileSet::_tile_set_shapes); ObjectTypeDB::bind_method(_MD("tile_get_shapes","id"),&TileSet::_tile_get_shapes); + ObjectTypeDB::bind_method(_MD("tile_set_navigation_polygon","id","navigation_polygon:NavigationPolygon"),&TileSet::tile_set_navigation_polygon); + ObjectTypeDB::bind_method(_MD("tile_get_navigation_polygon:NavigationPolygon","id"),&TileSet::tile_get_navigation_polygon); + ObjectTypeDB::bind_method(_MD("tile_set_navigation_polygon_offset","id","navigation_polygon_offset"),&TileSet::tile_set_navigation_polygon_offset); + ObjectTypeDB::bind_method(_MD("tile_get_navigation_polygon_offset","id"),&TileSet::tile_get_navigation_polygon_offset); + ObjectTypeDB::bind_method(_MD("tile_set_light_occluder","id","light_occluder:OccluderPolygon2D"),&TileSet::tile_set_light_occluder); + ObjectTypeDB::bind_method(_MD("tile_get_light_occluder:OccluderPolygon2D","id"),&TileSet::tile_get_light_occluder); + ObjectTypeDB::bind_method(_MD("tile_set_occluder_offset","id","occluder_offset"),&TileSet::tile_set_occluder_offset); + ObjectTypeDB::bind_method(_MD("tile_get_occluder_offset","id"),&TileSet::tile_get_occluder_offset); + ObjectTypeDB::bind_method(_MD("remove_tile","id"),&TileSet::remove_tile); ObjectTypeDB::bind_method(_MD("clear"),&TileSet::clear); ObjectTypeDB::bind_method(_MD("get_last_unused_tile_id"),&TileSet::get_last_unused_tile_id); diff --git a/scene/resources/tile_set.h b/scene/resources/tile_set.h index ddbb1b59a64..0234755a533 100644 --- a/scene/resources/tile_set.h +++ b/scene/resources/tile_set.h @@ -32,6 +32,8 @@ #include "resource.h" #include "scene/resources/shape_2d.h" #include "scene/resources/texture.h" +#include "scene/2d/light_occluder_2d.h" +#include "scene/2d/navigation_polygon.h" class TileSet : public Resource { @@ -45,6 +47,11 @@ class TileSet : public Resource { Vector2 shape_offset; Rect2i region; Vector > shapes; + Vector2 occluder_offset; + Ref occluder; + Vector2 navigation_polygon_offset; + Ref navigation_polygon; + Ref material; }; Map tile_map; @@ -84,6 +91,21 @@ public: void tile_set_shape(int p_id,const Ref &p_shape); Ref tile_get_shape(int p_id) const; + void tile_set_material(int p_id,const Ref &p_material); + Ref tile_get_material(int p_id) const; + + void tile_set_occluder_offset(int p_id,const Vector2& p_offset); + Vector2 tile_get_occluder_offset(int p_id) const; + + void tile_set_light_occluder(int p_id,const Ref &p_light_occluder); + Ref tile_get_light_occluder(int p_id) const; + + void tile_set_navigation_polygon_offset(int p_id,const Vector2& p_offset); + Vector2 tile_get_navigation_polygon_offset(int p_id) const; + + void tile_set_navigation_polygon(int p_id,const Ref &p_navigation_polygon); + Ref tile_get_navigation_polygon(int p_id) const; + void tile_set_shapes(int p_id,const Vector > &p_shapes); Vector > tile_get_shapes(int p_id) const; diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h index 62ab8b3c560..d2a1c48c46b 100644 --- a/servers/visual/rasterizer.h +++ b/servers/visual/rasterizer.h @@ -582,6 +582,7 @@ public: int layer_min; int layer_max; int item_mask; + int item_shadow_mask; bool subtract; RID texture; Vector2 texture_offset; @@ -613,6 +614,7 @@ public: layer_min=0; layer_max=0; item_mask=1; + item_shadow_mask=-1; subtract=false; texture_cache=NULL; next_ptr=NULL; diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp index f178c27ed02..e53fe8f82de 100644 --- a/servers/visual/shader_language.cpp +++ b/servers/visual/shader_language.cpp @@ -1149,11 +1149,19 @@ const ShaderLanguage::BuiltinsDef ShaderLanguage::ci_fragment_builtins_defs[]={ const ShaderLanguage::BuiltinsDef ShaderLanguage::ci_light_builtins_defs[]={ - { "COLOR", TYPE_VEC4}, + { "POSITION", TYPE_VEC4}, { "NORMAL", TYPE_VEC3}, - { "LIGHT_DIR", TYPE_VEC2}, - { "LIGHT_DISTANCE", TYPE_FLOAT}, - { "LIGHT", TYPE_VEC3}, + { "UV", TYPE_VEC2}, + { "COLOR", TYPE_VEC4}, + { "TEXTURE", TYPE_TEXTURE}, + { "TEXTURE_PIXEL_SIZE", TYPE_VEC2}, + { "VAR1", TYPE_VEC4}, + { "VAR2", TYPE_VEC4}, + { "SCREEN_UV", TYPE_VEC2}, + { "LIGHT_VEC", TYPE_VEC2}, + { "LIGHT_HEIGHT", TYPE_FLOAT}, + { "LIGHT_COLOR", TYPE_VEC4}, + { "LIGHT", TYPE_VEC4}, { "POINT_COORD", TYPE_VEC2}, // { "SCREEN_POS", TYPE_VEC2}, // { "SCREEN_TEXEL_SIZE", TYPE_VEC2}, diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp index 3bcf0b8a3e1..1c16f51e896 100644 --- a/servers/visual/visual_server_raster.cpp +++ b/servers/visual/visual_server_raster.cpp @@ -3954,6 +3954,15 @@ void VisualServerRaster::canvas_light_set_item_mask(RID p_light, int p_mask){ } +void VisualServerRaster::canvas_light_set_item_shadow_mask(RID p_light, int p_mask){ + + Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + clight->item_shadow_mask=p_mask; + +} + + void VisualServerRaster::canvas_light_set_subtract_mode(RID p_light, bool p_enable) { @@ -4559,6 +4568,13 @@ void VisualServerRaster::free( RID p_rid ) { } + if (occluder->canvas.is_valid() && canvas_owner.owns(occluder->canvas)) { + + Canvas *canvas = canvas_owner.get(occluder->canvas); + canvas->occluders.erase(occluder); + + } + canvas_light_occluder_owner.free( p_rid ); memdelete(occluder); @@ -6906,6 +6922,8 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_ Rasterizer::CanvasLight *lights_with_shadow=NULL; Rect2 shadow_rect; + int light_count=0; + for (Map::Element *E=p_viewport->canvas_map.front();E;E=E->next()) { Matrix32 xf = p_viewport->global_transform * E->get().transform; @@ -6944,10 +6962,13 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_ cl->radius_cache=cl->rect_cache.size.length(); } + + light_count++; } } } + //print_line("lights: "+itos(light_count)); canvas_map[ Viewport::CanvasKey( E->key(), E->get().layer) ]=&E->get(); } @@ -7007,7 +7028,7 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_ } - rasterizer->canvas_debug_viewport_shadows(lights_with_shadow); + //rasterizer->canvas_debug_viewport_shadows(lights_with_shadow); } //capture diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h index b9a3f833643..7d7bbe1d711 100644 --- a/servers/visual/visual_server_raster.h +++ b/servers/visual/visual_server_raster.h @@ -1164,6 +1164,7 @@ public: virtual void canvas_light_set_z_range(RID p_light, int p_min_z,int p_max_z); virtual void canvas_light_set_layer_range(RID p_light, int p_min_layer,int p_max_layer); virtual void canvas_light_set_item_mask(RID p_light, int p_mask); + virtual void canvas_light_set_item_shadow_mask(RID p_light, int p_mask); virtual void canvas_light_set_subtract_mode(RID p_light, bool p_enable); virtual void canvas_light_set_shadow_enabled(RID p_light, bool p_enabled); diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h index 1890f7b7600..bccb096e1be 100644 --- a/servers/visual/visual_server_wrap_mt.h +++ b/servers/visual/visual_server_wrap_mt.h @@ -1158,6 +1158,7 @@ public: FUNC3(canvas_light_set_layer_range,RID,int,int); FUNC3(canvas_light_set_z_range,RID,int,int); FUNC2(canvas_light_set_item_mask,RID,int); + FUNC2(canvas_light_set_item_shadow_mask,RID,int); FUNC2(canvas_light_set_subtract_mode,RID,bool); FUNC2(canvas_light_set_shadow_enabled,RID,bool); diff --git a/servers/visual_server.h b/servers/visual_server.h index ccf6978ae39..9404ea040c6 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -1013,6 +1013,7 @@ public: virtual void canvas_light_set_z_range(RID p_light, int p_min_z,int p_max_z)=0; virtual void canvas_light_set_layer_range(RID p_light, int p_min_layer,int p_max_layer)=0; virtual void canvas_light_set_item_mask(RID p_light, int p_mask)=0; + virtual void canvas_light_set_item_shadow_mask(RID p_light, int p_mask)=0; virtual void canvas_light_set_subtract_mode(RID p_light, bool p_enable)=0; virtual void canvas_light_set_shadow_enabled(RID p_light, bool p_enabled)=0; diff --git a/tools/editor/plugins/canvas_item_editor_plugin.cpp b/tools/editor/plugins/canvas_item_editor_plugin.cpp index 514f4b6525a..fdec72332e6 100644 --- a/tools/editor/plugins/canvas_item_editor_plugin.cpp +++ b/tools/editor/plugins/canvas_item_editor_plugin.cpp @@ -87,7 +87,7 @@ Dictionary CanvasItemEditor::get_state() const { state["ofs"]=Point2(h_scroll->get_val(),v_scroll->get_val()); // state["ofs"]=-transform.get_origin(); state["use_snap"]=is_snap_active(); - state["snap"]=snap; + state["snap_vec"]=Vector2(get_snap()); state["pixel_snap"]=pixel_snap; return state; } @@ -111,7 +111,15 @@ void CanvasItemEditor::set_state(const Dictionary& p_state){ } if (state.has("snap")) { - snap=state["snap"]; + snap_x->set_val(state["snap"]); + snap_y->set_val(state["snap"]); + } + + if (state.has("snap_vec")) { + Vector2 sv = state["snap_vec"]; + snap_x->set_val(sv.x); + snap_y->set_val(sv.y); + viewport->update(); } if (state.has("pixel_snap")) { @@ -300,7 +308,7 @@ void CanvasItemEditor::_key_move(const Vector2& p_dir, bool p_snap, KeyMoveMODE Vector2 drag = p_dir; if (p_snap) - drag*=snap; + drag*=get_snap(); undo_redo->add_undo_method(canvas_item,"edit_set_state",canvas_item->edit_get_state()); @@ -554,6 +562,13 @@ void CanvasItemEditor::_append_canvas_item(CanvasItem *c) { } +void CanvasItemEditor::_snap_changed(double) { + + viewport->update(); +} + + + void CanvasItemEditor::_dialog_value_changed(double) { if (updating_value_dialog) @@ -563,7 +578,7 @@ void CanvasItemEditor::_dialog_value_changed(double) { case SNAP_CONFIGURE: { - snap=dialog_val->get_val(); + // snap=dialog_val->get_val(); viewport->update(); } break; case ZOOM_SET: { @@ -1165,7 +1180,7 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) { continue; } - if (pixel_snap || (is_snap_active() && snap>0)) { + if (pixel_snap || (is_snap_active() && get_snap().x>0 && get_snap().y>0)) { if (drag!=DRAG_ALL) { dfrom=drag_point_from; @@ -1174,14 +1189,14 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) { Vector2 newpos = drag_point_from + (dto-dfrom); Vector2 disp; - if (!is_snap_active() || snap<1) { + if (!is_snap_active() || get_snap().x<1 || get_snap().y<1) { disp.x = Math::fposmod(newpos.x,1); disp.y = Math::fposmod(newpos.y,1); } else { - disp.x = Math::fposmod(newpos.x,snap); - disp.y = Math::fposmod(newpos.y,snap); + disp.x = Math::fposmod(newpos.x,get_snap().x); + disp.y = Math::fposmod(newpos.y,get_snap().y); } dto-=disp; } @@ -1477,7 +1492,7 @@ void CanvasItemEditor::_viewport_draw() { _update_scrollbars(); RID ci=viewport->get_canvas_item(); - if (snap>0 && is_snap_active() && true ) { + if (get_snap().x>0 && get_snap().y>0 && is_snap_active() && true ) { Size2 s = viewport->get_size(); @@ -1485,7 +1500,7 @@ void CanvasItemEditor::_viewport_draw() { Matrix32 xform = transform.affine_inverse(); for(int i=0;iset_icon(get_icon("Group","EditorIcons")); ungroup_button->set_icon(get_icon("Ungroup","EditorIcons")); key_insert_button->set_icon(get_icon("Key","EditorIcons")); + snap_x->connect("value_changed",this,"_snap_changed"); + snap_y->connect("value_changed",this,"_snap_changed"); } @@ -2002,7 +2019,7 @@ Point2 CanvasItemEditor::snapify(const Point2& p_pos) const { Vector2 pos = p_pos; - if (!active || snap<1) { + if (!active || get_snap().x<1 || get_snap().y<1) { if (pixel_snap) { @@ -2014,8 +2031,8 @@ Point2 CanvasItemEditor::snapify(const Point2& p_pos) const { } - pos.x=Math::stepify(pos.x,snap); - pos.y=Math::stepify(pos.y,snap); + pos.x=Math::stepify(pos.x,get_snap().x); + pos.y=Math::stepify(pos.y,get_snap().y); return pos; @@ -2038,15 +2055,46 @@ void CanvasItemEditor::_popup_callback(int p_op) { int idx = edit_menu->get_popup()->get_item_index(SNAP_USE_PIXEL); edit_menu->get_popup()->set_item_checked(idx,pixel_snap); } break; + case SNAP_OBJECT_CENTERS: { + + List &selection = editor_selection->get_selected_node_list(); + + undo_redo->create_action("Snap Object Centers"); + for(List::Element *E=selection.front();E;E=E->next()) { + + CanvasItem *canvas_item = E->get()->cast_to(); + if (!canvas_item) + continue; + if (!canvas_item->is_visible()) + continue; + Node2D* node = canvas_item->cast_to(); + if (!node) + continue; + + Matrix32 gtrans = node->get_global_transform(); + gtrans.elements[2]=snapify(gtrans.elements[2]); + + undo_redo->add_do_method(node,"set_global_transform",gtrans); + undo_redo->add_undo_method(node,"set_global_transform",node->get_global_transform()); + } + + undo_redo->add_do_method(viewport,"update"); + undo_redo->add_undo_method(viewport,"update"); + undo_redo->commit_action(); + + } break; case SNAP_CONFIGURE: { updating_value_dialog=true; + snap_dialog->popup_centered_minsize(); +/* dialog_label->set_text("Snap (Pixels):"); dialog_val->set_min(1); dialog_val->set_step(1); dialog_val->set_max(4096); dialog_val->set_val(snap); value_dialog->popup_centered(Size2(200,85)); + */ updating_value_dialog=false; } break; @@ -2604,6 +2652,7 @@ void CanvasItemEditor::_bind_methods() { ObjectTypeDB::bind_method("_unhandled_key_input",&CanvasItemEditor::_unhandled_key_input); ObjectTypeDB::bind_method("_viewport_draw",&CanvasItemEditor::_viewport_draw); ObjectTypeDB::bind_method("_viewport_input_event",&CanvasItemEditor::_viewport_input_event); + ObjectTypeDB::bind_method("_snap_changed",&CanvasItemEditor::_snap_changed); ADD_SIGNAL( MethodInfo("item_lock_status_changed") ); ADD_SIGNAL( MethodInfo("item_group_status_changed") ); @@ -2812,6 +2861,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { p->add_item("Configure Snap..",SNAP_CONFIGURE); p->add_separator(); p->add_check_item("Use Pixel Snap",SNAP_USE_PIXEL); + p->add_item("Snap Selected Object Centers",SNAP_OBJECT_CENTERS); p->add_separator(); p->add_item("Expand to Parent",EXPAND_TO_PARENT,KEY_MASK_CMD|KEY_P); p->add_separator(); @@ -2918,12 +2968,33 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { dialog_val->connect("value_changed",this,"_dialog_value_changed"); select_sb = Ref( memnew( StyleBoxTexture) ); + snap_dialog = memnew( AcceptDialog ); + VBoxContainer *snap_vb = memnew( VBoxContainer ); + snap_dialog->add_child(snap_vb); + snap_dialog->set_child_rect(snap_vb); + snap_dialog->set_title("Snap Configuration"); + snap_x = memnew( SpinBox ); + snap_x->set_custom_minimum_size(Size2(250,0)); + snap_y = memnew( SpinBox ); + snap_x->set_min(1); + snap_x->set_max(4096); + snap_x->set_step(1); + snap_x->set_val(10); + snap_y->set_min(1); + snap_y->set_max(4096); + snap_y->set_step(1); + snap_y->set_val(10); + snap_vb->add_margin_child("Snap X",snap_x); + snap_vb->add_margin_child("Snap Y",snap_y); + add_child(snap_dialog); + + key_pos=true; key_rot=true; key_scale=false; zoom=1; - snap=10; + //snap=10; updating_value_dialog=false; box_selecting=false; //zoom=0.5; diff --git a/tools/editor/plugins/canvas_item_editor_plugin.h b/tools/editor/plugins/canvas_item_editor_plugin.h index 6648d486e84..91607428265 100644 --- a/tools/editor/plugins/canvas_item_editor_plugin.h +++ b/tools/editor/plugins/canvas_item_editor_plugin.h @@ -77,6 +77,7 @@ class CanvasItemEditor : public VBoxContainer { SNAP_USE, SNAP_CONFIGURE, SNAP_USE_PIXEL, + SNAP_OBJECT_CENTERS, ZOOM_IN, ZOOM_OUT, ZOOM_RESET, @@ -143,7 +144,6 @@ class CanvasItemEditor : public VBoxContainer { Matrix32 transform; float zoom; - int snap; bool pixel_snap; bool box_selecting; Point2 box_selecting_to; @@ -250,7 +250,11 @@ class CanvasItemEditor : public VBoxContainer { AcceptDialog *value_dialog; Label *dialog_label; SpinBox *dialog_val; - + + AcceptDialog *snap_dialog; + SpinBox *snap_x; + SpinBox *snap_y; + CanvasItem *ref_item; void _add_canvas_item(CanvasItem *p_canvas_item); @@ -289,6 +293,7 @@ class CanvasItemEditor : public VBoxContainer { void _viewport_input_event(const InputEvent& p_event); void _viewport_draw(); + void _snap_changed(double); HSplitContainer *palette_split; VSplitContainer *bottom_split; @@ -335,7 +340,7 @@ protected: public: bool is_snap_active() const; - int get_snap() const { return snap; } + Size2i get_snap() const { return Size2i(snap_x->get_val(),snap_y->get_val()); } Matrix32 get_canvas_transform() const { return transform; } diff --git a/tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp b/tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp index dab6df9a39a..9a0d5b4066b 100644 --- a/tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp +++ b/tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp @@ -369,6 +369,7 @@ void CollisionPolygon2DEditor::edit(Node *p_collision_polygon) { wip.clear(); wip_active=false; edited_point=-1; + canvas_item_editor->get_viewport_control()->update(); } else { node=NULL; diff --git a/tools/editor/plugins/light_occluder_2d_editor_plugin.cpp b/tools/editor/plugins/light_occluder_2d_editor_plugin.cpp index c1fb81b66a0..5fa3d8ac8fa 100644 --- a/tools/editor/plugins/light_occluder_2d_editor_plugin.cpp +++ b/tools/editor/plugins/light_occluder_2d_editor_plugin.cpp @@ -96,7 +96,7 @@ bool LightOccluder2DEditor::forward_input_event(const InputEvent& p_event) { create_poly->set_text("No OccluderPolygon2D resource on this node.\nCreate and assign one?"); create_poly->popup_centered_minsize(); } - return false; + return (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1); } switch(p_event.type) { @@ -389,7 +389,7 @@ void LightOccluder2DEditor::edit(Node *p_collision_polygon) { wip.clear(); wip_active=false; edited_point=-1; - + canvas_item_editor->get_viewport_control()->update(); } else { node=NULL; @@ -402,6 +402,8 @@ void LightOccluder2DEditor::edit(Node *p_collision_polygon) { void LightOccluder2DEditor::_create_poly() { + if (!node) + return; undo_redo->create_action("Create Occluder Polygon"); undo_redo->add_do_method(node,"set_occluder_polygon",Ref(memnew( OccluderPolygon2D))); undo_redo->add_undo_method(node,"set_occluder_polygon",Variant(REF())); diff --git a/tools/editor/plugins/navigation_polygon_editor_plugin.cpp b/tools/editor/plugins/navigation_polygon_editor_plugin.cpp index 599d18c8bb8..163accfdd38 100644 --- a/tools/editor/plugins/navigation_polygon_editor_plugin.cpp +++ b/tools/editor/plugins/navigation_polygon_editor_plugin.cpp @@ -36,6 +36,9 @@ void NavigationPolygonEditor::_node_removed(Node *p_node) { void NavigationPolygonEditor::_create_nav() { + if (!node) + return; + undo_redo->create_action("Create Navigation Polygon"); undo_redo->add_do_method(node,"set_navigation_polygon",Ref(memnew( NavigationPolygon))); undo_redo->add_undo_method(node,"set_navigation_polygon",Variant(REF())); @@ -107,7 +110,7 @@ bool NavigationPolygonEditor::forward_input_event(const InputEvent& p_event) { create_nav->set_text("No NavigationPolygon resource on this node.\nCreate and assign one?"); create_nav->popup_centered_minsize(); } - return false; + return (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1);; } @@ -445,6 +448,7 @@ void NavigationPolygonEditor::edit(Node *p_collision_polygon) { wip.clear(); wip_active=false; edited_point=-1; + canvas_item_editor->get_viewport_control()->update(); } else { node=NULL; diff --git a/tools/editor/plugins/tile_map_editor_plugin.cpp b/tools/editor/plugins/tile_map_editor_plugin.cpp index 47727a00c21..79e43f90123 100644 --- a/tools/editor/plugins/tile_map_editor_plugin.cpp +++ b/tools/editor/plugins/tile_map_editor_plugin.cpp @@ -640,19 +640,53 @@ void TileMapEditor::_canvas_draw() { Ref t = ts->tile_get_texture(st); if (t.is_valid()) { - Vector2 from = xform.xform(ts->tile_get_texture_offset(st)+node->map_to_world(over_tile)+node->get_cell_draw_offset()); + Vector2 from = node->map_to_world(over_tile)+node->get_cell_draw_offset(); Rect2 r = ts->tile_get_region(st); Size2 sc = xform.get_scale(); if (mirror_x->is_pressed()) sc.x*=-1.0; if (mirror_y->is_pressed()) sc.y*=-1.0; - if (r==Rect2()) { - canvas_item_editor->draw_texture_rect(t,Rect2(from,t->get_size()*sc),false,Color(1,1,1,0.5),transpose->is_pressed()); + Rect2 rect; + if (r==Rect2()) { + rect=Rect2(from,t->get_size()); } else { - canvas_item_editor->draw_texture_rect_region(t,Rect2(from,r.get_size()*sc),r,Color(1,1,1,0.5),transpose->is_pressed()); + rect=Rect2(from,r.get_size()); + } + + + if (node->get_tile_origin()==TileMap::TILE_ORIGIN_TOP_LEFT) { + rect.pos+=ts->tile_get_texture_offset(st); + + } else if (node->get_tile_origin()==TileMap::TILE_ORIGIN_CENTER) { + rect.pos+=node->get_cell_size()/2; + Vector2 s = r.size; + + Vector2 center = (s/2) - ts->tile_get_texture_offset(st); + + + if (mirror_x->is_pressed()) + rect.pos.x-=s.x-center.x; + else + rect.pos.x-=center.x; + + if (mirror_y->is_pressed()) + rect.pos.y-=s.y-center.y; + else + rect.pos.y-=center.y; + } + + rect.pos=xform.xform(rect.pos); + rect.size*=sc; + + if (r==Rect2()) { + + canvas_item_editor->draw_texture_rect(t,rect,false,Color(1,1,1,0.5),transpose->is_pressed()); + } else { + + canvas_item_editor->draw_texture_rect_region(t,rect,r,Color(1,1,1,0.5),transpose->is_pressed()); } } } diff --git a/tools/editor/plugins/tile_set_editor_plugin.cpp b/tools/editor/plugins/tile_set_editor_plugin.cpp index a51caf7d54a..8ff77209349 100644 --- a/tools/editor/plugins/tile_set_editor_plugin.cpp +++ b/tools/editor/plugins/tile_set_editor_plugin.cpp @@ -37,83 +37,103 @@ void TileSetEditor::edit(const Ref& p_tileset) { void TileSetEditor::_import_scene(Node *scene, Ref p_library, bool p_merge) { if (!p_merge) - p_library->clear(); + p_library->clear(); for(int i=0;iget_child_count();i++) { - Node *child = scene->get_child(i); + Node *child = scene->get_child(i); - if (!child->cast_to()) { - if (child->get_child_count()>0) { - child=child->get_child(0); - if (!child->cast_to()) { - continue; - } + if (!child->cast_to()) { + if (child->get_child_count()>0) { + child=child->get_child(0); + if (!child->cast_to()) { + continue; + } - } else - continue; + } else + continue; - } + } - Sprite *mi = child->cast_to(); - Ref texture=mi->get_texture(); - if (texture.is_null()) + Sprite *mi = child->cast_to(); + Ref texture=mi->get_texture(); + Ref material=mi->get_material(); + + if (texture.is_null()) continue; - int id = p_library->find_tile_by_name(mi->get_name()); - if (id<0) { + int id = p_library->find_tile_by_name(mi->get_name()); + if (id<0) { - id=p_library->get_last_unused_tile_id(); - p_library->create_tile(id); - p_library->tile_set_name(id,mi->get_name()); - } + id=p_library->get_last_unused_tile_id(); + p_library->create_tile(id); + p_library->tile_set_name(id,mi->get_name()); + } - p_library->tile_set_texture(id,texture); - Vector2 phys_offset; - if (mi->is_centered()) { - Size2 s; - if (mi->is_region()) { - s=mi->get_region_rect().size; - } else { - s=texture->get_size(); - } - phys_offset+=-s/2; - } - if (mi->is_region()) { - p_library->tile_set_region(id,mi->get_region_rect()); - } + p_library->tile_set_texture(id,texture); + p_library->tile_set_material(id,material); - Vector >collisions; + Vector2 phys_offset; - for(int j=0;jget_child_count();j++) { - - Node *child2 = mi->get_child(j); - if (!child2->cast_to()) - continue; - StaticBody2D *sb = child2->cast_to(); - if (sb->get_shape_count()==0) - continue; - Ref collision=sb->get_shape(0); - if (collision.is_valid()) { - collisions.push_back(collision); + if (mi->is_centered()) { + Size2 s; + if (mi->is_region()) { + s=mi->get_region_rect().size; + } else { + s=texture->get_size(); } - } + phys_offset+=-s/2; + } + if (mi->is_region()) { + p_library->tile_set_region(id,mi->get_region_rect()); + } - if (collisions.size()) { + Vector >collisions; + Ref nav_poly; + Ref occluder; - p_library->tile_set_shapes(id,collisions); - p_library->tile_set_shape_offset(id,-phys_offset); - } else { - p_library->tile_set_shape_offset(id,Vector2()); + for(int j=0;jget_child_count();j++) { + + Node *child2 = mi->get_child(j); + + if (child2->cast_to()) + nav_poly=child2->cast_to()->get_navigation_polygon(); + + if (child2->cast_to()) + occluder=child2->cast_to()->get_occluder_polygon(); + + if (!child2->cast_to()) + continue; + StaticBody2D *sb = child2->cast_to(); + if (sb->get_shape_count()==0) + continue; + Ref collision=sb->get_shape(0); + if (collision.is_valid()) { + collisions.push_back(collision); + } + } + + if (collisions.size()) { + + p_library->tile_set_shapes(id,collisions); + p_library->tile_set_shape_offset(id,-phys_offset); + } else { + p_library->tile_set_shape_offset(id,Vector2()); + + } + + p_library->tile_set_texture_offset(id,mi->get_offset()); + p_library->tile_set_navigation_polygon(id,nav_poly); + p_library->tile_set_light_occluder(id,occluder); + p_library->tile_set_occluder_offset(id,-phys_offset); + p_library->tile_set_navigation_polygon_offset(id,-phys_offset); - } - p_library->tile_set_texture_offset(id,mi->get_offset()); } } @@ -121,23 +141,23 @@ void TileSetEditor::_menu_confirm() { switch(option) { - case MENU_OPTION_REMOVE_ITEM: { + case MENU_OPTION_REMOVE_ITEM: { - tileset->remove_tile(to_erase); - } break; - case MENU_OPTION_MERGE_FROM_SCENE: - case MENU_OPTION_CREATE_FROM_SCENE: { + tileset->remove_tile(to_erase); + } break; + case MENU_OPTION_MERGE_FROM_SCENE: + case MENU_OPTION_CREATE_FROM_SCENE: { - EditorNode *en = editor; - Node * scene = en->get_edited_scene(); - if (!scene) - break; + EditorNode *en = editor; + Node * scene = en->get_edited_scene(); + if (!scene) + break; - _import_scene(scene,tileset,option==MENU_OPTION_MERGE_FROM_SCENE); + _import_scene(scene,tileset,option==MENU_OPTION_MERGE_FROM_SCENE); - } break; + } break; } } @@ -165,11 +185,11 @@ void TileSetEditor::_menu_cbk(int p_option) { cd->set_text("Create from scene?"); cd->popup_centered(Size2(300,60)); } break; - case MENU_OPTION_MERGE_FROM_SCENE: { + case MENU_OPTION_MERGE_FROM_SCENE: { - cd->set_text("Merge from scene?"); - cd->popup_centered(Size2(300,60)); - } break; + cd->set_text("Merge from scene?"); + cd->popup_centered(Size2(300,60)); + } break; } } diff --git a/tools/editor/plugins/tile_set_editor_plugin.h b/tools/editor/plugins/tile_set_editor_plugin.h index 2531ec55bf4..1248b4e007f 100644 --- a/tools/editor/plugins/tile_set_editor_plugin.h +++ b/tools/editor/plugins/tile_set_editor_plugin.h @@ -56,7 +56,7 @@ class TileSetEditor : public Control { int option; void _menu_cbk(int p_option); - void _menu_confirm(); + void _menu_confirm(); static void _import_scene(Node *p_scene, Ref p_library, bool p_merge); diff --git a/tools/editor/property_editor.cpp b/tools/editor/property_editor.cpp index 25c39b31739..fb4c1342630 100644 --- a/tools/editor/property_editor.cpp +++ b/tools/editor/property_editor.cpp @@ -1860,7 +1860,7 @@ void PropertyEditor::set_item_text(TreeItem *p_item, int p_type, const String& p if (has_icon(res->get_type(),"EditorIcons")) { - p_item->set_icon(1,get_icon(res->get_type(),"EditorIcons")); + p_item->set_icon(0,get_icon(res->get_type(),"EditorIcons")); } else { Dictionary d = p_item->get_metadata(0); @@ -1870,10 +1870,10 @@ void PropertyEditor::set_item_text(TreeItem *p_item, int p_type, const String& p if (has_icon(hint_text,"EditorIcons")) { - p_item->set_icon(1,get_icon(hint_text,"EditorIcons")); + p_item->set_icon(0,get_icon(hint_text,"EditorIcons")); } else { - p_item->set_icon(1,get_icon("Object","EditorIcons")); + p_item->set_icon(0,get_icon("Object","EditorIcons")); } }