diff options
Diffstat (limited to 'editor/plugins/tiles')
-rw-r--r-- | editor/plugins/tiles/atlas_merging_dialog.cpp | 12 | ||||
-rw-r--r-- | editor/plugins/tiles/tile_atlas_view.cpp | 49 | ||||
-rw-r--r-- | editor/plugins/tiles/tile_data_editors.cpp | 211 | ||||
-rw-r--r-- | editor/plugins/tiles/tile_map_editor.cpp | 208 | ||||
-rw-r--r-- | editor/plugins/tiles/tile_set_atlas_source_editor.cpp | 275 | ||||
-rw-r--r-- | editor/plugins/tiles/tile_set_atlas_source_editor.h | 1 | ||||
-rw-r--r-- | editor/plugins/tiles/tiles_editor_plugin.cpp | 2 |
7 files changed, 462 insertions, 296 deletions
diff --git a/editor/plugins/tiles/atlas_merging_dialog.cpp b/editor/plugins/tiles/atlas_merging_dialog.cpp index d54906c98c..2a8a3216ed 100644 --- a/editor/plugins/tiles/atlas_merging_dialog.cpp +++ b/editor/plugins/tiles/atlas_merging_dialog.cpp @@ -94,12 +94,14 @@ void AtlasMergingDialog::_generate_merged(Vector<Ref<TileSetAtlasSource>> p_atla } // Copy the texture. - Rect2i src_rect = atlas_source->get_tile_texture_region(tile_id); - Rect2 dst_rect_wide = Rect2i(new_tile_rect_in_altas.position * new_texture_region_size, new_tile_rect_in_altas.size * new_texture_region_size); - if (dst_rect_wide.get_end().x > output_image->get_width() || dst_rect_wide.get_end().y > output_image->get_height()) { - output_image->crop(MAX(dst_rect_wide.get_end().x, output_image->get_width()), MAX(dst_rect_wide.get_end().y, output_image->get_height())); + for (int frame = 0; frame < atlas_source->get_tile_animation_frames_count(tile_id); frame++) { + Rect2i src_rect = atlas_source->get_tile_texture_region(tile_id, frame); + Rect2 dst_rect_wide = Rect2i(new_tile_rect_in_altas.position * new_texture_region_size, new_tile_rect_in_altas.size * new_texture_region_size); + if (dst_rect_wide.get_end().x > output_image->get_width() || dst_rect_wide.get_end().y > output_image->get_height()) { + output_image->crop(MAX(dst_rect_wide.get_end().x, output_image->get_width()), MAX(dst_rect_wide.get_end().y, output_image->get_height())); + } + output_image->blit_rect(atlas_source->get_texture()->get_image(), src_rect, dst_rect_wide.get_center() - src_rect.size / 2); } - output_image->blit_rect(atlas_source->get_texture()->get_image(), src_rect, (dst_rect_wide.get_position() + dst_rect_wide.get_end()) / 2 - src_rect.size / 2); } // Compute the atlas offset. diff --git a/editor/plugins/tiles/tile_atlas_view.cpp b/editor/plugins/tiles/tile_atlas_view.cpp index 6e0a5b00b9..f21d5098d3 100644 --- a/editor/plugins/tiles/tile_atlas_view.cpp +++ b/editor/plugins/tiles/tile_atlas_view.cpp @@ -256,11 +256,15 @@ void TileAtlasView::_draw_base_tiles() { for (int i = 0; i < tile_set_atlas_source->get_tiles_count(); i++) { Vector2i atlas_coords = tile_set_atlas_source->get_tile_id(i); - // Update the y to max value. - Vector2i offset_pos = (margins + (atlas_coords * texture_region_size) + tile_set_atlas_source->get_tile_texture_region(atlas_coords).size / 2 + tile_set_atlas_source->get_tile_effective_texture_offset(atlas_coords, 0)); + for (int frame = 0; frame < tile_set_atlas_source->get_tile_animation_frames_count(atlas_coords); frame++) { + // Update the y to max value. + int animation_columns = tile_set_atlas_source->get_tile_animation_columns(atlas_coords); + Vector2i frame_coords = atlas_coords + (tile_set_atlas_source->get_tile_size_in_atlas(atlas_coords) + tile_set_atlas_source->get_tile_animation_separation(atlas_coords)) * ((animation_columns > 0) ? Vector2i(frame % animation_columns, frame / animation_columns) : Vector2i(frame, 0)); + Vector2i offset_pos = (margins + (frame_coords * texture_region_size) + tile_set_atlas_source->get_tile_texture_region(atlas_coords, frame).size / 2 + tile_set_atlas_source->get_tile_effective_texture_offset(atlas_coords, 0)); - // Draw the tile. - TileMap::draw_tile(base_tiles_draw->get_canvas_item(), offset_pos, tile_set, source_id, atlas_coords, 0); + // Draw the tile. + TileMap::draw_tile(base_tiles_draw->get_canvas_item(), offset_pos, tile_set, source_id, atlas_coords, 0, frame); + } } } } @@ -326,13 +330,18 @@ void TileAtlasView::_draw_base_tiles_shape_grid() { for (int i = 0; i < tile_set_atlas_source->get_tiles_count(); i++) { Vector2i tile_id = tile_set_atlas_source->get_tile_id(i); Vector2 in_tile_base_offset = tile_set_atlas_source->get_tile_effective_texture_offset(tile_id, 0); - Rect2i texture_region = tile_set_atlas_source->get_tile_texture_region(tile_id); - // Draw only if the tile shape fits in the texture region - Transform2D tile_xform; - tile_xform.set_origin(texture_region.position + texture_region.size / 2 + in_tile_base_offset); - tile_xform.set_scale(tile_shape_size); - tile_set->draw_tile_shape(base_tiles_shape_grid, tile_xform, grid_color); + for (int frame = 0; frame < tile_set_atlas_source->get_tile_animation_frames_count(tile_id); frame++) { + Color color = grid_color; + if (frame > 0) { + color.a *= 0.3; + } + Rect2i texture_region = tile_set_atlas_source->get_tile_texture_region(tile_id); + Transform2D tile_xform; + tile_xform.set_origin(texture_region.get_center() + in_tile_base_offset); + tile_xform.set_scale(tile_shape_size); + tile_set->draw_tile_shape(base_tiles_shape_grid, tile_xform, color); + } } } @@ -360,7 +369,7 @@ void TileAtlasView::_draw_alternatives() { Vector2i atlas_coords = tile_set_atlas_source->get_tile_id(i); current_pos.x = 0; int y_increment = 0; - Rect2i texture_region = tile_set_atlas_source->get_tile_texture_region(atlas_coords); + Size2i texture_region_size = tile_set_atlas_source->get_tile_texture_region(atlas_coords).size; int alternatives_count = tile_set_atlas_source->get_alternative_tiles_count(atlas_coords); for (int j = 1; j < alternatives_count; j++) { int alternative_id = tile_set_atlas_source->get_alternative_tile_id(atlas_coords, j); @@ -370,18 +379,18 @@ void TileAtlasView::_draw_alternatives() { // Update the y to max value. Vector2i offset_pos = current_pos; if (transposed) { - offset_pos = (current_pos + Vector2(texture_region.size.y, texture_region.size.x) / 2 + tile_set_atlas_source->get_tile_effective_texture_offset(atlas_coords, alternative_id)); - y_increment = MAX(y_increment, texture_region.size.x); + offset_pos = (current_pos + Vector2(texture_region_size.y, texture_region_size.x) / 2 + tile_set_atlas_source->get_tile_effective_texture_offset(atlas_coords, alternative_id)); + y_increment = MAX(y_increment, texture_region_size.x); } else { - offset_pos = (current_pos + texture_region.size / 2 + tile_set_atlas_source->get_tile_effective_texture_offset(atlas_coords, alternative_id)); - y_increment = MAX(y_increment, texture_region.size.y); + offset_pos = (current_pos + texture_region_size / 2 + tile_set_atlas_source->get_tile_effective_texture_offset(atlas_coords, alternative_id)); + y_increment = MAX(y_increment, texture_region_size.y); } // Draw the tile. TileMap::draw_tile(alternatives_draw->get_canvas_item(), offset_pos, tile_set, source_id, atlas_coords, alternative_id); // Increment the x position. - current_pos.x += transposed ? texture_region.size.y : texture_region.size.x; + current_pos.x += transposed ? texture_region_size.y : texture_region_size.x; } if (alternatives_count > 1) { current_pos.y += y_increment; @@ -513,10 +522,10 @@ void TileAtlasView::_update_alternative_tiles_rect_cache() { } Vector3i TileAtlasView::get_alternative_tile_at_pos(const Vector2 p_pos) const { - for (Map<Vector2, Map<int, Rect2i>>::Element *E_coords = alternative_tiles_rect_cache.front(); E_coords; E_coords = E_coords->next()) { - for (Map<int, Rect2i>::Element *E_alternative = E_coords->value().front(); E_alternative; E_alternative = E_alternative->next()) { - if (E_alternative->value().has_point(p_pos)) { - return Vector3i(E_coords->key().x, E_coords->key().y, E_alternative->key()); + for (const KeyValue<Vector2, Map<int, Rect2i>> &E_coords : alternative_tiles_rect_cache) { + for (const KeyValue<int, Rect2i> &E_alternative : E_coords.value) { + if (E_alternative.value.has_point(p_pos)) { + return Vector3i(E_coords.key.x, E_coords.key.y, E_alternative.key); } } } diff --git a/editor/plugins/tiles/tile_data_editors.cpp b/editor/plugins/tiles/tile_data_editors.cpp index 2a75a743a7..1a69d19d3c 100644 --- a/editor/plugins/tiles/tile_data_editors.cpp +++ b/editor/plugins/tiles/tile_data_editors.cpp @@ -231,10 +231,14 @@ void GenericTilePolygonEditor::_zoom_changed() { void GenericTilePolygonEditor::_advanced_menu_item_pressed(int p_item_pressed) { switch (p_item_pressed) { - case RESET_TO_DEFAULT_TILE: + case RESET_TO_DEFAULT_TILE: { undo_redo->create_action(TTR("Edit Polygons")); undo_redo->add_do_method(this, "clear_polygons"); - undo_redo->add_do_method(this, "add_polygon", tile_set->get_tile_shape_polygon()); + Vector<Vector2> polygon = tile_set->get_tile_shape_polygon(); + for (int i = 0; i < polygon.size(); i++) { + polygon.write[i] = polygon[i] * tile_set->get_tile_size(); + } + undo_redo->add_do_method(this, "add_polygon", polygon); undo_redo->add_do_method(base_control, "update"); undo_redo->add_do_method(this, "emit_signal", "polygons_changed"); undo_redo->add_undo_method(this, "clear_polygons"); @@ -244,8 +248,8 @@ void GenericTilePolygonEditor::_advanced_menu_item_pressed(int p_item_pressed) { undo_redo->add_undo_method(base_control, "update"); undo_redo->add_undo_method(this, "emit_signal", "polygons_changed"); undo_redo->commit_action(true); - break; - case CLEAR_TILE: + } break; + case CLEAR_TILE: { undo_redo->create_action(TTR("Edit Polygons")); undo_redo->add_do_method(this, "clear_polygons"); undo_redo->add_do_method(base_control, "update"); @@ -257,7 +261,7 @@ void GenericTilePolygonEditor::_advanced_menu_item_pressed(int p_item_pressed) { undo_redo->add_undo_method(base_control, "update"); undo_redo->add_undo_method(this, "emit_signal", "polygons_changed"); undo_redo->commit_action(true); - break; + } break; default: break; } @@ -308,6 +312,9 @@ void GenericTilePolygonEditor::_snap_to_tile_shape(Point2 &r_point, float &r_cur ERR_FAIL_COND(!tile_set.is_valid()); Vector<Point2> polygon = tile_set->get_tile_shape_polygon(); + for (int i = 0; i < polygon.size(); i++) { + polygon.write[i] = polygon[i] * tile_set->get_tile_size(); + } Point2 snapped_point = r_point; // Snap to polygon vertices. @@ -539,7 +546,11 @@ void GenericTilePolygonEditor::set_tile_set(Ref<TileSet> p_tile_set) { // Set the default tile shape clear_polygons(); if (p_tile_set.is_valid()) { - add_polygon(p_tile_set->get_tile_shape_polygon()); + Vector<Vector2> polygon = p_tile_set->get_tile_shape_polygon(); + for (int i = 0; i < polygon.size(); i++) { + polygon.write[i] = polygon[i] * p_tile_set->get_tile_size(); + } + add_polygon(polygon); } } tile_set = p_tile_set; @@ -622,7 +633,7 @@ void GenericTilePolygonEditor::_notification(int p_what) { button_delete->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("CurveDelete"), SNAME("EditorIcons"))); button_center_view->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("CenterView"), SNAME("EditorIcons"))); button_pixel_snap->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Snap"), SNAME("EditorIcons"))); - button_advanced_menu->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("GuiTabMenu"), SNAME("EditorIcons"))); + button_advanced_menu->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("GuiTabMenuHl"), SNAME("EditorIcons"))); break; } } @@ -745,10 +756,10 @@ Variant TileDataDefaultEditor::_get_value(TileSetAtlasSource *p_tile_set_atlas_s } void TileDataDefaultEditor::_setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, Map<TileMapCell, Variant> p_previous_values, Variant p_new_value) { - for (Map<TileMapCell, Variant>::Element *E = p_previous_values.front(); E; E = E->next()) { - Vector2i coords = E->key().get_atlas_coords(); - undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/%s", coords.x, coords.y, E->key().alternative_tile, property), E->get()); - undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/%s", coords.x, coords.y, E->key().alternative_tile, property), p_new_value); + for (const KeyValue<TileMapCell, Variant> &E : p_previous_values) { + Vector2i coords = E.key.get_atlas_coords(); + undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/%s", coords.x, coords.y, E.key.alternative_tile, property), E.value); + undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/%s", coords.x, coords.y, E.key.alternative_tile, property), p_new_value); } } @@ -1180,10 +1191,10 @@ Variant TileDataOcclusionShapeEditor::_get_value(TileSetAtlasSource *p_tile_set_ } void TileDataOcclusionShapeEditor::_setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, Map<TileMapCell, Variant> p_previous_values, Variant p_new_value) { - for (Map<TileMapCell, Variant>::Element *E = p_previous_values.front(); E; E = E->next()) { - Vector2i coords = E->key().get_atlas_coords(); - undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/occlusion_layer_%d/polygon", coords.x, coords.y, E->key().alternative_tile, occlusion_layer), E->get()); - undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/occlusion_layer_%d/polygon", coords.x, coords.y, E->key().alternative_tile, occlusion_layer), p_new_value); + for (const KeyValue<TileMapCell, Variant> &E : p_previous_values) { + Vector2i coords = E.key.get_atlas_coords(); + undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/occlusion_layer_%d/polygon", coords.x, coords.y, E.key.alternative_tile, occlusion_layer), E.value); + undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/occlusion_layer_%d/polygon", coords.x, coords.y, E.key.alternative_tile, occlusion_layer), p_new_value); } } @@ -1265,17 +1276,21 @@ void TileDataCollisionEditor::_polygons_changed() { } Variant TileDataCollisionEditor::_get_painted_value() { + Dictionary dict; + dict["linear_velocity"] = dummy_object->get("linear_velocity"); + dict["angular_velocity"] = dummy_object->get("angular_velocity"); Array array; for (int i = 0; i < polygon_editor->get_polygon_count(); i++) { ERR_FAIL_COND_V(polygon_editor->get_polygon(i).size() < 3, Variant()); - Dictionary dict; - dict["points"] = polygon_editor->get_polygon(i); - dict["one_way"] = dummy_object->get(vformat("polygon_%d_one_way", i)); - dict["one_way_margin"] = dummy_object->get(vformat("polygon_%d_one_way_margin", i)); - array.push_back(dict); + Dictionary polygon_dict; + polygon_dict["points"] = polygon_editor->get_polygon(i); + polygon_dict["one_way"] = dummy_object->get(vformat("polygon_%d_one_way", i)); + polygon_dict["one_way_margin"] = dummy_object->get(vformat("polygon_%d_one_way_margin", i)); + array.push_back(polygon_dict); } + dict["polygons"] = array; - return array; + return dict; } void TileDataCollisionEditor::_set_painted_value(TileSetAtlasSource *p_tile_set_atlas_source, Vector2 p_coords, int p_alternative_tile) { @@ -1291,12 +1306,14 @@ void TileDataCollisionEditor::_set_painted_value(TileSetAtlasSource *p_tile_set_ } _polygons_changed(); + dummy_object->set("linear_velocity", tile_data->get_constant_linear_velocity(physics_layer)); + dummy_object->set("angular_velocity", tile_data->get_constant_angular_velocity(physics_layer)); for (int i = 0; i < tile_data->get_collision_polygons_count(physics_layer); i++) { dummy_object->set(vformat("polygon_%d_one_way", i), tile_data->is_collision_polygon_one_way(physics_layer, i)); dummy_object->set(vformat("polygon_%d_one_way_margin", i), tile_data->get_collision_polygon_one_way_margin(physics_layer, i)); } - for (Map<StringName, EditorProperty *>::Element *E = property_editors.front(); E; E = E->next()) { - E->get()->update_property(); + for (const KeyValue<StringName, EditorProperty *> &E : property_editors) { + E.value->update_property(); } polygon_editor->set_background(p_tile_set_atlas_source->get_texture(), p_tile_set_atlas_source->get_tile_texture_region(p_coords), p_tile_set_atlas_source->get_tile_effective_texture_offset(p_coords, p_alternative_tile), tile_data->get_flip_h(), tile_data->get_flip_v(), tile_data->get_transpose(), tile_data->get_modulate()); @@ -1306,13 +1323,16 @@ void TileDataCollisionEditor::_set_value(TileSetAtlasSource *p_tile_set_atlas_so TileData *tile_data = Object::cast_to<TileData>(p_tile_set_atlas_source->get_tile_data(p_coords, p_alternative_tile)); ERR_FAIL_COND(!tile_data); - Array array = p_value; + Dictionary dict = p_value; + tile_data->set_constant_linear_velocity(physics_layer, dict["linear_velocity"]); + tile_data->set_constant_angular_velocity(physics_layer, dict["angular_velocity"]); + Array array = dict["polygons"]; tile_data->set_collision_polygons_count(physics_layer, array.size()); for (int i = 0; i < array.size(); i++) { - Dictionary dict = array[i]; - tile_data->set_collision_polygon_points(physics_layer, i, dict["points"]); - tile_data->set_collision_polygon_one_way(physics_layer, i, dict["one_way"]); - tile_data->set_collision_polygon_one_way_margin(physics_layer, i, dict["one_way_margin"]); + Dictionary polygon_dict = array[i]; + tile_data->set_collision_polygon_points(physics_layer, i, polygon_dict["points"]); + tile_data->set_collision_polygon_one_way(physics_layer, i, polygon_dict["one_way"]); + tile_data->set_collision_polygon_one_way_margin(physics_layer, i, polygon_dict["one_way_margin"]); } polygon_editor->set_background(p_tile_set_atlas_source->get_texture(), p_tile_set_atlas_source->get_tile_texture_region(p_coords), p_tile_set_atlas_source->get_tile_effective_texture_offset(p_coords, p_alternative_tile), tile_data->get_flip_h(), tile_data->get_flip_v(), tile_data->get_transpose(), tile_data->get_modulate()); @@ -1322,37 +1342,41 @@ Variant TileDataCollisionEditor::_get_value(TileSetAtlasSource *p_tile_set_atlas TileData *tile_data = Object::cast_to<TileData>(p_tile_set_atlas_source->get_tile_data(p_coords, p_alternative_tile)); ERR_FAIL_COND_V(!tile_data, Variant()); + Dictionary dict; + dict["linear_velocity"] = tile_data->get_constant_linear_velocity(physics_layer); + dict["angular_velocity"] = tile_data->get_constant_angular_velocity(physics_layer); Array array; for (int i = 0; i < tile_data->get_collision_polygons_count(physics_layer); i++) { - Dictionary dict; - dict["points"] = tile_data->get_collision_polygon_points(physics_layer, i); - dict["one_way"] = tile_data->is_collision_polygon_one_way(physics_layer, i); - dict["one_way_margin"] = tile_data->get_collision_polygon_one_way_margin(physics_layer, i); - array.push_back(dict); + Dictionary polygon_dict; + polygon_dict["points"] = tile_data->get_collision_polygon_points(physics_layer, i); + polygon_dict["one_way"] = tile_data->is_collision_polygon_one_way(physics_layer, i); + polygon_dict["one_way_margin"] = tile_data->get_collision_polygon_one_way_margin(physics_layer, i); + array.push_back(polygon_dict); } - return array; + dict["polygons"] = array; + return dict; } void TileDataCollisionEditor::_setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, Map<TileMapCell, Variant> p_previous_values, Variant p_new_value) { Array new_array = p_new_value; - for (Map<TileMapCell, Variant>::Element *E = p_previous_values.front(); E; E = E->next()) { - Array old_array = E->get(); + for (KeyValue<TileMapCell, Variant> &E : p_previous_values) { + Array old_array = E.value; - Vector2i coords = E->key().get_atlas_coords(); - undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/physics_layer_%d/polygons_count", coords.x, coords.y, E->key().alternative_tile, physics_layer), old_array.size()); + Vector2i coords = E.key.get_atlas_coords(); + undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/physics_layer_%d/polygons_count", coords.x, coords.y, E.key.alternative_tile, physics_layer), old_array.size()); for (int i = 0; i < old_array.size(); i++) { Dictionary dict = old_array[i]; - undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/physics_layer_%d/polygon_%d/points", coords.x, coords.y, E->key().alternative_tile, physics_layer, i), dict["points"]); - undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/physics_layer_%d/polygon_%d/one_way", coords.x, coords.y, E->key().alternative_tile, physics_layer, i), dict["one_way"]); - undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/physics_layer_%d/polygon_%d/one_way_margin", coords.x, coords.y, E->key().alternative_tile, physics_layer, i), dict["one_way_margin"]); + undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/physics_layer_%d/polygon_%d/points", coords.x, coords.y, E.key.alternative_tile, physics_layer, i), dict["points"]); + undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/physics_layer_%d/polygon_%d/one_way", coords.x, coords.y, E.key.alternative_tile, physics_layer, i), dict["one_way"]); + undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/physics_layer_%d/polygon_%d/one_way_margin", coords.x, coords.y, E.key.alternative_tile, physics_layer, i), dict["one_way_margin"]); } - undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/physics_layer_%d/polygons_count", coords.x, coords.y, E->key().alternative_tile, physics_layer), new_array.size()); + undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/physics_layer_%d/polygons_count", coords.x, coords.y, E.key.alternative_tile, physics_layer), new_array.size()); for (int i = 0; i < new_array.size(); i++) { Dictionary dict = new_array[i]; - undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/physics_layer_%d/polygon_%d/points", coords.x, coords.y, E->key().alternative_tile, physics_layer, i), dict["points"]); - undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/physics_layer_%d/polygon_%d/one_way", coords.x, coords.y, E->key().alternative_tile, physics_layer, i), dict["one_way"]); - undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/physics_layer_%d/polygon_%d/one_way_margin", coords.x, coords.y, E->key().alternative_tile, physics_layer, i), dict["one_way_margin"]); + undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/physics_layer_%d/polygon_%d/points", coords.x, coords.y, E.key.alternative_tile, physics_layer, i), dict["points"]); + undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/physics_layer_%d/polygon_%d/one_way", coords.x, coords.y, E.key.alternative_tile, physics_layer, i), dict["one_way"]); + undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/physics_layer_%d/polygon_%d/one_way_margin", coords.x, coords.y, E.key.alternative_tile, physics_layer, i), dict["one_way_margin"]); } } } @@ -1378,6 +1402,27 @@ TileDataCollisionEditor::TileDataCollisionEditor() { polygon_editor->connect("polygons_changed", callable_mp(this, &TileDataCollisionEditor::_polygons_changed)); add_child(polygon_editor); + dummy_object->add_dummy_property("linear_velocity"); + dummy_object->set("linear_velocity", Vector2()); + dummy_object->add_dummy_property("angular_velocity"); + dummy_object->set("angular_velocity", 0.0); + + EditorProperty *linear_velocity_editor = EditorInspectorDefaultPlugin::get_editor_for_property(dummy_object, Variant::VECTOR2, "linear_velocity", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT); + linear_velocity_editor->set_object_and_property(dummy_object, "linear_velocity"); + linear_velocity_editor->set_label("linear_velocity"); + linear_velocity_editor->connect("property_changed", callable_mp(this, &TileDataCollisionEditor::_property_value_changed).unbind(1)); + linear_velocity_editor->update_property(); + add_child(linear_velocity_editor); + property_editors["linear_velocity"] = linear_velocity_editor; + + EditorProperty *angular_velocity_editor = EditorInspectorDefaultPlugin::get_editor_for_property(dummy_object, Variant::FLOAT, "angular_velocity", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT); + angular_velocity_editor->set_object_and_property(dummy_object, "angular_velocity"); + angular_velocity_editor->set_label("angular_velocity"); + angular_velocity_editor->connect("property_changed", callable_mp(this, &TileDataCollisionEditor::_property_value_changed).unbind(1)); + angular_velocity_editor->update_property(); + add_child(angular_velocity_editor); + property_editors["angular_velocity"] = linear_velocity_editor; + _polygons_changed(); } @@ -1495,7 +1540,7 @@ void TileDataTerrainsEditor::forward_draw_over_atlas(TileAtlasView *p_tile_atlas TileData *tile_data = Object::cast_to<TileData>(p_tile_set_atlas_source->get_tile_data(hovered_coords, 0)); int terrain_set = tile_data->get_terrain_set(); Rect2i texture_region = p_tile_set_atlas_source->get_tile_texture_region(hovered_coords); - Vector2i position = (texture_region.position + texture_region.get_end()) / 2 + p_tile_set_atlas_source->get_tile_effective_texture_offset(hovered_coords, 0); + Vector2i position = texture_region.get_center() + p_tile_set_atlas_source->get_tile_effective_texture_offset(hovered_coords, 0); if (terrain_set >= 0 && terrain_set == int(dummy_object->get("terrain_set"))) { // Draw hovered bit. @@ -1540,7 +1585,7 @@ void TileDataTerrainsEditor::forward_draw_over_atlas(TileAtlasView *p_tile_atlas // Text p_canvas_item->draw_set_transform_matrix(Transform2D()); Rect2i texture_region = p_tile_set_atlas_source->get_tile_texture_region(coords); - Vector2i position = (texture_region.position + texture_region.get_end()) / 2 + p_tile_set_atlas_source->get_tile_effective_texture_offset(coords, 0); + Vector2i position = texture_region.get_center() + p_tile_set_atlas_source->get_tile_effective_texture_offset(coords, 0); Color color = Color(1, 1, 1); String text; @@ -1632,7 +1677,7 @@ void TileDataTerrainsEditor::forward_draw_over_atlas(TileAtlasView *p_tile_atlas Vector2i coords = E->get().get_atlas_coords(); Rect2i texture_region = p_tile_set_atlas_source->get_tile_texture_region(coords); - Vector2i position = (texture_region.position + texture_region.get_end()) / 2 + p_tile_set_atlas_source->get_tile_effective_texture_offset(coords, 0); + Vector2i position = texture_region.get_center() + p_tile_set_atlas_source->get_tile_effective_texture_offset(coords, 0); for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) { TileSet::CellNeighbor bit = TileSet::CellNeighbor(i); @@ -1668,7 +1713,7 @@ void TileDataTerrainsEditor::forward_draw_over_alternatives(TileAtlasView *p_til TileData *tile_data = Object::cast_to<TileData>(p_tile_set_atlas_source->get_tile_data(hovered_coords, hovered_alternative)); int terrain_set = tile_data->get_terrain_set(); Rect2i texture_region = p_tile_atlas_view->get_alternative_tile_rect(hovered_coords, hovered_alternative); - Vector2i position = (texture_region.position + texture_region.get_end()) / 2 + p_tile_set_atlas_source->get_tile_effective_texture_offset(hovered_coords, hovered_alternative); + Vector2i position = texture_region.get_center() + p_tile_set_atlas_source->get_tile_effective_texture_offset(hovered_coords, hovered_alternative); if (terrain_set == int(dummy_object->get("terrain_set"))) { // Draw hovered bit. @@ -1715,7 +1760,7 @@ void TileDataTerrainsEditor::forward_draw_over_alternatives(TileAtlasView *p_til // Text p_canvas_item->draw_set_transform_matrix(Transform2D()); Rect2i texture_region = p_tile_atlas_view->get_alternative_tile_rect(coords, alternative_tile); - Vector2i position = (texture_region.position + texture_region.get_end()) / 2 + p_tile_set_atlas_source->get_tile_effective_texture_offset(coords, 0); + Vector2i position = texture_region.get_center() + p_tile_set_atlas_source->get_tile_effective_texture_offset(coords, 0); Color color = Color(1, 1, 1); String text; @@ -1796,7 +1841,7 @@ void TileDataTerrainsEditor::forward_painting_atlas_gui_input(TileAtlasView *p_t // Set the terrains bits. Rect2i texture_region = p_tile_set_atlas_source->get_tile_texture_region(coords); - Vector2i position = (texture_region.position + texture_region.get_end()) / 2 + p_tile_set_atlas_source->get_tile_effective_texture_offset(coords, 0); + Vector2i position = texture_region.get_center() + p_tile_set_atlas_source->get_tile_effective_texture_offset(coords, 0); for (int j = 0; j < TileSet::CELL_NEIGHBOR_MAX; j++) { TileSet::CellNeighbor bit = TileSet::CellNeighbor(j); if (tile_data->is_valid_peering_bit_terrain(bit)) { @@ -1824,7 +1869,7 @@ void TileDataTerrainsEditor::forward_painting_atlas_gui_input(TileAtlasView *p_t TileData *tile_data = Object::cast_to<TileData>(p_tile_set_atlas_source->get_tile_data(coords, 0)); int terrain_set = tile_data->get_terrain_set(); Rect2i texture_region = p_tile_set_atlas_source->get_tile_texture_region(coords); - Vector2i position = (texture_region.position + texture_region.get_end()) / 2 + p_tile_set_atlas_source->get_tile_effective_texture_offset(coords, 0); + Vector2i position = texture_region.get_center() + p_tile_set_atlas_source->get_tile_effective_texture_offset(coords, 0); dummy_object->set("terrain_set", terrain_set); dummy_object->set("terrain", -1); for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) { @@ -1922,7 +1967,7 @@ void TileDataTerrainsEditor::forward_painting_atlas_gui_input(TileAtlasView *p_t // Set the terrain bit. Rect2i texture_region = p_tile_set_atlas_source->get_tile_texture_region(coords); - Vector2i position = (texture_region.position + texture_region.get_end()) / 2 + p_tile_set_atlas_source->get_tile_effective_texture_offset(coords, 0); + Vector2i position = texture_region.get_center() + p_tile_set_atlas_source->get_tile_effective_texture_offset(coords, 0); for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) { TileSet::CellNeighbor bit = TileSet::CellNeighbor(i); @@ -1976,16 +2021,16 @@ void TileDataTerrainsEditor::forward_painting_atlas_gui_input(TileAtlasView *p_t drag_type = DRAG_TYPE_NONE; } else if (drag_type == DRAG_TYPE_PAINT_TERRAIN_SET) { undo_redo->create_action(TTR("Painting Terrain Set")); - for (Map<TileMapCell, Variant>::Element *E = drag_modified.front(); E; E = E->next()) { - Dictionary dict = E->get(); - Vector2i coords = E->key().get_atlas_coords(); - undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrain_set", coords.x, coords.y, E->key().alternative_tile), drag_painted_value); - undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrain_set", coords.x, coords.y, E->key().alternative_tile), dict["terrain_set"]); + for (KeyValue<TileMapCell, Variant> &E : drag_modified) { + Dictionary dict = E.value; + Vector2i coords = E.key.get_atlas_coords(); + undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrain_set", coords.x, coords.y, E.key.alternative_tile), drag_painted_value); + undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrain_set", coords.x, coords.y, E.key.alternative_tile), dict["terrain_set"]); Array array = dict["terrain_peering_bits"]; for (int i = 0; i < array.size(); i++) { TileSet::CellNeighbor bit = TileSet::CellNeighbor(i); if (tile_set->is_valid_peering_bit_terrain(dict["terrain_set"], bit)) { - undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]), coords.x, coords.y, E->key().alternative_tile), array[i]); + undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]), coords.x, coords.y, E.key.alternative_tile), array[i]); } } } @@ -1996,17 +2041,17 @@ void TileDataTerrainsEditor::forward_painting_atlas_gui_input(TileAtlasView *p_t int terrain_set = int(painted["terrain_set"]); int terrain = int(painted["terrain"]); undo_redo->create_action(TTR("Painting Terrain")); - for (Map<TileMapCell, Variant>::Element *E = drag_modified.front(); E; E = E->next()) { - Dictionary dict = E->get(); - Vector2i coords = E->key().get_atlas_coords(); + for (KeyValue<TileMapCell, Variant> &E : drag_modified) { + Dictionary dict = E.value; + Vector2i coords = E.key.get_atlas_coords(); Array array = dict["terrain_peering_bits"]; for (int i = 0; i < array.size(); i++) { TileSet::CellNeighbor bit = TileSet::CellNeighbor(i); if (tile_set->is_valid_peering_bit_terrain(terrain_set, bit)) { - undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]), coords.x, coords.y, E->key().alternative_tile), terrain); + undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]), coords.x, coords.y, E.key.alternative_tile), terrain); } if (tile_set->is_valid_peering_bit_terrain(dict["terrain_set"], bit)) { - undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]), coords.x, coords.y, E->key().alternative_tile), array[i]); + undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]), coords.x, coords.y, E.key.alternative_tile), array[i]); } } } @@ -2055,7 +2100,7 @@ void TileDataTerrainsEditor::forward_painting_atlas_gui_input(TileAtlasView *p_t TileSet::CellNeighbor bit = TileSet::CellNeighbor(i); if (tile_set->is_valid_peering_bit_terrain(terrain_set, bit)) { Rect2i texture_region = p_tile_set_atlas_source->get_tile_texture_region(coords); - Vector2i position = (texture_region.position + texture_region.get_end()) / 2 + p_tile_set_atlas_source->get_tile_effective_texture_offset(coords, 0); + Vector2i position = texture_region.get_center() + p_tile_set_atlas_source->get_tile_effective_texture_offset(coords, 0); Vector<Vector2> polygon = tile_set->get_terrain_bit_polygon(terrain_set, bit); for (int j = 0; j < polygon.size(); j++) { @@ -2138,7 +2183,7 @@ void TileDataTerrainsEditor::forward_painting_alternatives_gui_input(TileAtlasVi // Set the terrains bits. Rect2i texture_region = p_tile_atlas_view->get_alternative_tile_rect(coords, alternative_tile); - Vector2i position = (texture_region.position + texture_region.get_end()) / 2 + p_tile_set_atlas_source->get_tile_effective_texture_offset(coords, alternative_tile); + Vector2i position = texture_region.get_center() + p_tile_set_atlas_source->get_tile_effective_texture_offset(coords, alternative_tile); for (int j = 0; j < TileSet::CELL_NEIGHBOR_MAX; j++) { TileSet::CellNeighbor bit = TileSet::CellNeighbor(j); if (tile_data->is_valid_peering_bit_terrain(bit)) { @@ -2167,7 +2212,7 @@ void TileDataTerrainsEditor::forward_painting_alternatives_gui_input(TileAtlasVi TileData *tile_data = Object::cast_to<TileData>(p_tile_set_atlas_source->get_tile_data(coords, alternative_tile)); int terrain_set = tile_data->get_terrain_set(); Rect2i texture_region = p_tile_atlas_view->get_alternative_tile_rect(coords, alternative_tile); - Vector2i position = (texture_region.position + texture_region.get_end()) / 2 + p_tile_set_atlas_source->get_tile_effective_texture_offset(coords, alternative_tile); + Vector2i position = texture_region.get_center() + p_tile_set_atlas_source->get_tile_effective_texture_offset(coords, alternative_tile); dummy_object->set("terrain_set", terrain_set); dummy_object->set("terrain", -1); for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) { @@ -2242,7 +2287,7 @@ void TileDataTerrainsEditor::forward_painting_alternatives_gui_input(TileAtlasVi // Set the terrain bit. Rect2i texture_region = p_tile_atlas_view->get_alternative_tile_rect(coords, alternative_tile); - Vector2i position = (texture_region.position + texture_region.get_end()) / 2 + p_tile_set_atlas_source->get_tile_effective_texture_offset(coords, alternative_tile); + Vector2i position = texture_region.get_center() + p_tile_set_atlas_source->get_tile_effective_texture_offset(coords, alternative_tile); for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) { TileSet::CellNeighbor bit = TileSet::CellNeighbor(i); if (tile_set->is_valid_peering_bit_terrain(terrain_set, bit)) { @@ -2259,14 +2304,14 @@ void TileDataTerrainsEditor::forward_painting_alternatives_gui_input(TileAtlasVi } else { if (drag_type == DRAG_TYPE_PAINT_TERRAIN_SET) { undo_redo->create_action(TTR("Painting Tiles Property")); - for (Map<TileMapCell, Variant>::Element *E = drag_modified.front(); E; E = E->next()) { - Dictionary dict = E->get(); - Vector2i coords = E->key().get_atlas_coords(); - undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrain_set", coords.x, coords.y, E->key().alternative_tile), dict["terrain_set"]); - undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrain_set", coords.x, coords.y, E->key().alternative_tile), drag_painted_value); + for (KeyValue<TileMapCell, Variant> &E : drag_modified) { + Dictionary dict = E.value; + Vector2i coords = E.key.get_atlas_coords(); + undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrain_set", coords.x, coords.y, E.key.alternative_tile), dict["terrain_set"]); + undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrain_set", coords.x, coords.y, E.key.alternative_tile), drag_painted_value); Array array = dict["terrain_peering_bits"]; for (int i = 0; i < array.size(); i++) { - undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]), coords.x, coords.y, E->key().alternative_tile), array[i]); + undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]), coords.x, coords.y, E.key.alternative_tile), array[i]); } } undo_redo->commit_action(false); @@ -2276,17 +2321,17 @@ void TileDataTerrainsEditor::forward_painting_alternatives_gui_input(TileAtlasVi int terrain_set = int(painted["terrain_set"]); int terrain = int(painted["terrain"]); undo_redo->create_action(TTR("Painting Terrain")); - for (Map<TileMapCell, Variant>::Element *E = drag_modified.front(); E; E = E->next()) { - Dictionary dict = E->get(); - Vector2i coords = E->key().get_atlas_coords(); + for (KeyValue<TileMapCell, Variant> &E : drag_modified) { + Dictionary dict = E.value; + Vector2i coords = E.key.get_atlas_coords(); Array array = dict["terrain_peering_bits"]; for (int i = 0; i < array.size(); i++) { TileSet::CellNeighbor bit = TileSet::CellNeighbor(i); if (tile_set->is_valid_peering_bit_terrain(terrain_set, bit)) { - undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]), coords.x, coords.y, E->key().alternative_tile), terrain); + undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]), coords.x, coords.y, E.key.alternative_tile), terrain); } if (tile_set->is_valid_peering_bit_terrain(dict["terrain_set"], bit)) { - undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]), coords.x, coords.y, E->key().alternative_tile), array[i]); + undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]), coords.x, coords.y, E.key.alternative_tile), array[i]); } } } @@ -2398,10 +2443,10 @@ Variant TileDataNavigationEditor::_get_value(TileSetAtlasSource *p_tile_set_atla } void TileDataNavigationEditor::_setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, Map<TileMapCell, Variant> p_previous_values, Variant p_new_value) { - for (Map<TileMapCell, Variant>::Element *E = p_previous_values.front(); E; E = E->next()) { - Vector2i coords = E->key().get_atlas_coords(); - undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/navigation_layer_%d/polygon", coords.x, coords.y, E->key().alternative_tile, navigation_layer), E->get()); - undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/navigation_layer_%d/polygon", coords.x, coords.y, E->key().alternative_tile, navigation_layer), p_new_value); + for (const KeyValue<TileMapCell, Variant> &E : p_previous_values) { + Vector2i coords = E.key.get_atlas_coords(); + undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/navigation_layer_%d/polygon", coords.x, coords.y, E.key.alternative_tile, navigation_layer), E.value); + undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/navigation_layer_%d/polygon", coords.x, coords.y, E.key.alternative_tile, navigation_layer), p_new_value); } } diff --git a/editor/plugins/tiles/tile_map_editor.cpp b/editor/plugins/tiles/tile_map_editor.cpp index acbd5d70ff..cc5ff90541 100644 --- a/editor/plugins/tiles/tile_map_editor.cpp +++ b/editor/plugins/tiles/tile_map_editor.cpp @@ -455,15 +455,15 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p switch (drag_type) { case DRAG_TYPE_PAINT: { Map<Vector2i, TileMapCell> to_draw = _draw_line(drag_start_mouse_pos, drag_last_mouse_pos, mpos); - for (Map<Vector2i, TileMapCell>::Element *E = to_draw.front(); E; E = E->next()) { - if (!erase_button->is_pressed() && E->get().source_id == TileSet::INVALID_SOURCE) { + for (const KeyValue<Vector2i, TileMapCell> &E : to_draw) { + if (!erase_button->is_pressed() && E.value.source_id == TileSet::INVALID_SOURCE) { continue; } - Vector2i coords = E->key(); + Vector2i coords = E.key; if (!drag_modified.has(coords)) { drag_modified.insert(coords, tile_map->get_cell(tile_map_layer, coords)); } - tile_map->set_cell(tile_map_layer, coords, E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile); + tile_map->set_cell(tile_map_layer, coords, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile); } } break; case DRAG_TYPE_BUCKET: { @@ -471,15 +471,15 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p for (int i = 0; i < line.size(); i++) { if (!drag_modified.has(line[i])) { Map<Vector2i, TileMapCell> to_draw = _draw_bucket_fill(line[i], bucket_continuous_checkbox->is_pressed()); - for (Map<Vector2i, TileMapCell>::Element *E = to_draw.front(); E; E = E->next()) { - if (!erase_button->is_pressed() && E->get().source_id == TileSet::INVALID_SOURCE) { + for (const KeyValue<Vector2i, TileMapCell> &E : to_draw) { + if (!erase_button->is_pressed() && E.value.source_id == TileSet::INVALID_SOURCE) { continue; } - Vector2i coords = E->key(); + Vector2i coords = E.key; if (!drag_modified.has(coords)) { drag_modified.insert(coords, tile_map->get_cell(tile_map_layer, coords)); } - tile_map->set_cell(tile_map_layer, coords, E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile); + tile_map->set_cell(tile_map_layer, coords, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile); } } } @@ -531,15 +531,15 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p drag_start_mouse_pos = mpos; drag_modified.clear(); Map<Vector2i, TileMapCell> to_draw = _draw_line(drag_start_mouse_pos, mpos, mpos); - for (Map<Vector2i, TileMapCell>::Element *E = to_draw.front(); E; E = E->next()) { - if (!erase_button->is_pressed() && E->get().source_id == TileSet::INVALID_SOURCE) { + for (const KeyValue<Vector2i, TileMapCell> &E : to_draw) { + if (!erase_button->is_pressed() && E.value.source_id == TileSet::INVALID_SOURCE) { continue; } - Vector2i coords = E->key(); + Vector2i coords = E.key; if (!drag_modified.has(coords)) { drag_modified.insert(coords, tile_map->get_cell(tile_map_layer, coords)); } - tile_map->set_cell(tile_map_layer, coords, E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile); + tile_map->set_cell(tile_map_layer, coords, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile); } } else if (tool_buttons_group->get_pressed_button() == line_tool_button) { drag_type = DRAG_TYPE_LINE; @@ -557,15 +557,15 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p for (int i = 0; i < line.size(); i++) { if (!drag_modified.has(line[i])) { Map<Vector2i, TileMapCell> to_draw = _draw_bucket_fill(line[i], bucket_continuous_checkbox->is_pressed()); - for (Map<Vector2i, TileMapCell>::Element *E = to_draw.front(); E; E = E->next()) { - if (!erase_button->is_pressed() && E->get().source_id == TileSet::INVALID_SOURCE) { + for (const KeyValue<Vector2i, TileMapCell> &E : to_draw) { + if (!erase_button->is_pressed() && E.value.source_id == TileSet::INVALID_SOURCE) { continue; } - Vector2i coords = E->key(); + Vector2i coords = E.key; if (!drag_modified.has(coords)) { drag_modified.insert(coords, tile_map->get_cell(tile_map_layer, coords)); } - tile_map->set_cell(tile_map_layer, coords, E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile); + tile_map->set_cell(tile_map_layer, coords, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile); } } } @@ -710,8 +710,8 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over // Expand the grid if needed if (expand_grid && !preview.is_empty()) { drawn_grid_rect = Rect2i(preview.front()->key(), Vector2i(1, 1)); - for (Map<Vector2i, TileMapCell>::Element *E = preview.front(); E; E = E->next()) { - drawn_grid_rect.expand_to(E->key()); + for (const KeyValue<Vector2i, TileMapCell> &E : preview) { + drawn_grid_rect.expand_to(E.key); } } } @@ -748,23 +748,23 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over } // Draw the preview. - for (Map<Vector2i, TileMapCell>::Element *E = preview.front(); E; E = E->next()) { + for (const KeyValue<Vector2i, TileMapCell> &E : preview) { Transform2D tile_xform; - tile_xform.set_origin(tile_map->map_to_world(E->key())); + tile_xform.set_origin(tile_map->map_to_world(E.key)); tile_xform.set_scale(tile_set->get_tile_size()); if (!erase_button->is_pressed() && random_tile_checkbox->is_pressed()) { tile_set->draw_tile_shape(p_overlay, xform * tile_xform, Color(1.0, 1.0, 1.0, 0.5), true); } else { - if (tile_set->has_source(E->get().source_id)) { - TileSetSource *source = *tile_set->get_source(E->get().source_id); + if (tile_set->has_source(E.value.source_id)) { + TileSetSource *source = *tile_set->get_source(E.value.source_id); TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source); if (atlas_source) { // Get tile data. - TileData *tile_data = Object::cast_to<TileData>(atlas_source->get_tile_data(E->get().get_atlas_coords(), E->get().alternative_tile)); + TileData *tile_data = Object::cast_to<TileData>(atlas_source->get_tile_data(E.value.get_atlas_coords(), E.value.alternative_tile)); // Compute the offset - Rect2i source_rect = atlas_source->get_tile_texture_region(E->get().get_atlas_coords()); - Vector2i tile_offset = atlas_source->get_tile_effective_texture_offset(E->get().get_atlas_coords(), E->get().alternative_tile); + Rect2i source_rect = atlas_source->get_tile_texture_region(E.value.get_atlas_coords()); + Vector2i tile_offset = atlas_source->get_tile_effective_texture_offset(E.value.get_atlas_coords(), E.value.alternative_tile); // Compute the destination rectangle in the CanvasItem. Rect2 dest_rect; @@ -772,9 +772,9 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over bool transpose = tile_data->get_transpose(); if (transpose) { - dest_rect.position = (tile_map->map_to_world(E->key()) - Vector2(dest_rect.size.y, dest_rect.size.x) / 2 - tile_offset); + dest_rect.position = (tile_map->map_to_world(E.key) - Vector2(dest_rect.size.y, dest_rect.size.x) / 2 - tile_offset); } else { - dest_rect.position = (tile_map->map_to_world(E->key()) - dest_rect.size / 2 - tile_offset); + dest_rect.position = (tile_map->map_to_world(E.key) - dest_rect.size / 2 - tile_offset); } dest_rect = xform.xform(dest_rect); @@ -790,7 +790,7 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over // Get the tile modulation. Color modulate = tile_data->get_modulate(); Color self_modulate = tile_map->get_self_modulate(); - modulate = Color(modulate.r * self_modulate.r, modulate.g * self_modulate.g, modulate.b * self_modulate.b, modulate.a * self_modulate.a); + modulate *= self_modulate; // Draw the tile. p_overlay->draw_texture_rect_region(atlas_source->get_texture(), dest_rect, source_rect, modulate * Color(1.0, 1.0, 1.0, 0.5), transpose, tile_set->is_uv_clipping()); @@ -1041,7 +1041,7 @@ Map<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_bucket_fill(Vector2i TypedArray<Vector2i> to_check; if (source.source_id == TileSet::INVALID_SOURCE) { Rect2i rect = tile_map->get_used_rect(); - if (rect.size.x <= 0 || rect.size.y <= 0) { + if (rect.has_no_area()) { rect = Rect2i(p_coords, Vector2i(1, 1)); } for (int x = boundaries.position.x; x < boundaries.get_end().x; x++) { @@ -1165,11 +1165,11 @@ void TileMapEditorTilesPlugin::_stop_dragging() { } undo_redo->create_action(TTR("Move tiles")); // Move the tiles. - for (Map<Vector2i, TileMapCell>::Element *E = cells_do.front(); E; E = E->next()) { - undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E->key(), E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile); + for (const KeyValue<Vector2i, TileMapCell> &E : cells_do) { + undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile); } - for (Map<Vector2i, TileMapCell>::Element *E = cells_undo.front(); E; E = E->next()) { - undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, E->key(), E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile); + for (const KeyValue<Vector2i, TileMapCell> &E : cells_undo) { + undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile); } // Update the selection. @@ -1205,41 +1205,41 @@ void TileMapEditorTilesPlugin::_stop_dragging() { } break; case DRAG_TYPE_PAINT: { undo_redo->create_action(TTR("Paint tiles")); - for (Map<Vector2i, TileMapCell>::Element *E = drag_modified.front(); E; E = E->next()) { - undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E->key(), tile_map->get_cell_source_id(tile_map_layer, E->key()), tile_map->get_cell_atlas_coords(tile_map_layer, E->key()), tile_map->get_cell_alternative_tile(tile_map_layer, E->key())); - undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, E->key(), E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile); + for (const KeyValue<Vector2i, TileMapCell> &E : drag_modified) { + undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E.key, tile_map->get_cell_source_id(tile_map_layer, E.key), tile_map->get_cell_atlas_coords(tile_map_layer, E.key), tile_map->get_cell_alternative_tile(tile_map_layer, E.key)); + undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile); } undo_redo->commit_action(false); } break; case DRAG_TYPE_LINE: { Map<Vector2i, TileMapCell> to_draw = _draw_line(drag_start_mouse_pos, drag_start_mouse_pos, mpos); undo_redo->create_action(TTR("Paint tiles")); - for (Map<Vector2i, TileMapCell>::Element *E = to_draw.front(); E; E = E->next()) { - if (!erase_button->is_pressed() && E->get().source_id == TileSet::INVALID_SOURCE) { + for (const KeyValue<Vector2i, TileMapCell> &E : to_draw) { + if (!erase_button->is_pressed() && E.value.source_id == TileSet::INVALID_SOURCE) { continue; } - undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E->key(), E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile); - undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, E->key(), tile_map->get_cell_source_id(tile_map_layer, E->key()), tile_map->get_cell_atlas_coords(tile_map_layer, E->key()), tile_map->get_cell_alternative_tile(tile_map_layer, E->key())); + undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile); + undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, E.key, tile_map->get_cell_source_id(tile_map_layer, E.key), tile_map->get_cell_atlas_coords(tile_map_layer, E.key), tile_map->get_cell_alternative_tile(tile_map_layer, E.key)); } undo_redo->commit_action(); } break; case DRAG_TYPE_RECT: { Map<Vector2i, TileMapCell> to_draw = _draw_rect(tile_map->world_to_map(drag_start_mouse_pos), tile_map->world_to_map(mpos)); undo_redo->create_action(TTR("Paint tiles")); - for (Map<Vector2i, TileMapCell>::Element *E = to_draw.front(); E; E = E->next()) { - if (!erase_button->is_pressed() && E->get().source_id == TileSet::INVALID_SOURCE) { + for (const KeyValue<Vector2i, TileMapCell> &E : to_draw) { + if (!erase_button->is_pressed() && E.value.source_id == TileSet::INVALID_SOURCE) { continue; } - undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E->key(), E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile); - undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, E->key(), tile_map->get_cell_source_id(tile_map_layer, E->key()), tile_map->get_cell_atlas_coords(tile_map_layer, E->key()), tile_map->get_cell_alternative_tile(tile_map_layer, E->key())); + undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile); + undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, E.key, tile_map->get_cell_source_id(tile_map_layer, E.key), tile_map->get_cell_atlas_coords(tile_map_layer, E.key), tile_map->get_cell_alternative_tile(tile_map_layer, E.key)); } undo_redo->commit_action(); } break; case DRAG_TYPE_BUCKET: { undo_redo->create_action(TTR("Paint tiles")); - for (Map<Vector2i, TileMapCell>::Element *E = drag_modified.front(); E; E = E->next()) { - undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E->key(), tile_map->get_cell_source_id(tile_map_layer, E->key()), tile_map->get_cell_atlas_coords(tile_map_layer, E->key()), tile_map->get_cell_alternative_tile(tile_map_layer, E->key())); - undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, E->key(), E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile); + for (const KeyValue<Vector2i, TileMapCell> &E : drag_modified) { + undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E.key, tile_map->get_cell_source_id(tile_map_layer, E.key), tile_map->get_cell_atlas_coords(tile_map_layer, E.key), tile_map->get_cell_alternative_tile(tile_map_layer, E.key)); + undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile); } undo_redo->commit_action(false); } break; @@ -1364,17 +1364,17 @@ void TileMapEditorTilesPlugin::_update_selection_pattern_from_tileset_selection( } int vertical_offset = 0; - for (Map<int, List<const TileMapCell *>>::Element *E_source = per_source.front(); E_source; E_source = E_source->next()) { + for (const KeyValue<int, List<const TileMapCell *>> &E_source : per_source) { // Per source. List<const TileMapCell *> unorganized; Rect2i encompassing_rect_coords; Map<Vector2i, const TileMapCell *> organized_pattern; - TileSetSource *source = *tile_set->get_source(E_source->key()); + TileSetSource *source = *tile_set->get_source(E_source.key); TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source); if (atlas_source) { // Organize using coordinates. - for (const TileMapCell *current : E_source->get()) { + for (const TileMapCell *current : E_source.value) { if (current->alternative_tile == 0) { organized_pattern[current->get_atlas_coords()] = current; } else { @@ -1393,14 +1393,14 @@ void TileMapEditorTilesPlugin::_update_selection_pattern_from_tileset_selection( } } else { // Add everything unorganized. - for (const TileMapCell *cell : E_source->get()) { + for (const TileMapCell *cell : E_source.value) { unorganized.push_back(cell); } } // Now add everything to the output pattern. - for (Map<Vector2i, const TileMapCell *>::Element *E_cell = organized_pattern.front(); E_cell; E_cell = E_cell->next()) { - selection_pattern->set_cell(E_cell->key() - encompassing_rect_coords.position + Vector2i(0, vertical_offset), E_cell->get()->source_id, E_cell->get()->get_atlas_coords(), E_cell->get()->alternative_tile); + for (const KeyValue<Vector2i, const TileMapCell *> &E_cell : organized_pattern) { + selection_pattern->set_cell(E_cell.key - encompassing_rect_coords.position + Vector2i(0, vertical_offset), E_cell.value->source_id, E_cell.value->get_atlas_coords(), E_cell.value->alternative_tile); } Vector2i organized_size = selection_pattern->get_size(); int unorganized_index = 0; @@ -1456,13 +1456,25 @@ void TileMapEditorTilesPlugin::_tile_atlas_control_draw() { Color selection_color = Color().from_hsv(Math::fposmod(grid_color.get_h() + 0.5, 1.0), grid_color.get_s(), grid_color.get_v(), 1.0); for (Set<TileMapCell>::Element *E = tile_set_selection.front(); E; E = E->next()) { if (E->get().source_id == source_id && E->get().alternative_tile == 0) { - tile_atlas_control->draw_rect(atlas->get_tile_texture_region(E->get().get_atlas_coords()), selection_color, false); + for (int frame = 0; frame < atlas->get_tile_animation_frames_count(E->get().get_atlas_coords()); frame++) { + Color color = selection_color; + if (frame > 0) { + color.a *= 0.3; + } + tile_atlas_control->draw_rect(atlas->get_tile_texture_region(E->get().get_atlas_coords(), frame), color, false); + } } } // Draw the hovered tile. if (hovered_tile.get_atlas_coords() != TileSetSource::INVALID_ATLAS_COORDS && hovered_tile.alternative_tile == 0 && !tile_set_dragging_selection) { - tile_atlas_control->draw_rect(atlas->get_tile_texture_region(hovered_tile.get_atlas_coords()), Color(1.0, 1.0, 1.0), false); + for (int frame = 0; frame < atlas->get_tile_animation_frames_count(hovered_tile.get_atlas_coords()); frame++) { + Color color = Color(1.0, 1.0, 1.0); + if (frame > 0) { + color.a *= 0.3; + } + tile_atlas_control->draw_rect(atlas->get_tile_texture_region(hovered_tile.get_atlas_coords(), frame), color, false); + } } // Draw the selection rect. @@ -2296,14 +2308,14 @@ Set<TileMapEditorTerrainsPlugin::TerrainsTilePattern> TileMapEditorTerrainsPlugi // Returns all tiles compatible with the given constraints. Set<TerrainsTilePattern> compatible_terrain_tile_patterns; - for (Map<TerrainsTilePattern, Set<TileMapCell>>::Element *E = per_terrain_terrains_tile_patterns_tiles[p_terrain_set].front(); E; E = E->next()) { + for (const KeyValue<TerrainsTilePattern, Set<TileMapCell>> &E : per_terrain_terrains_tile_patterns_tiles[p_terrain_set]) { int valid = true; int in_pattern_count = 0; for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) { TileSet::CellNeighbor bit = TileSet::CellNeighbor(i); if (tile_set->is_valid_peering_bit_terrain(p_terrain_set, bit)) { // Check if the bit is compatible with the constraints. - Constraint terrain_bit_constraint = Constraint(tile_map, p_position, bit, E->key()[in_pattern_count]); + Constraint terrain_bit_constraint = Constraint(tile_map, p_position, bit, E.key[in_pattern_count]); Set<Constraint>::Element *in_set_constraint_element = p_constraints.find(terrain_bit_constraint); if (in_set_constraint_element && in_set_constraint_element->get().get_terrain() != terrain_bit_constraint.get_terrain()) { @@ -2315,7 +2327,7 @@ Set<TileMapEditorTerrainsPlugin::TerrainsTilePattern> TileMapEditorTerrainsPlugi } if (valid) { - compatible_terrain_tile_patterns.insert(E->key()); + compatible_terrain_tile_patterns.insert(E.key); } } @@ -2356,15 +2368,15 @@ Set<TileMapEditorTerrainsPlugin::Constraint> TileMapEditorTerrainsPlugin::_get_c // Count the number of occurrences per terrain. Map<Vector2i, TileSet::CellNeighbor> overlapping_terrain_bits = c.get_overlapping_coords_and_peering_bits(); - for (Map<Vector2i, TileSet::CellNeighbor>::Element *E_overlapping = overlapping_terrain_bits.front(); E_overlapping; E_overlapping = E_overlapping->next()) { - if (!p_to_replace.has(E_overlapping->key())) { - TileMapCell neighbor_cell = tile_map->get_cell(tile_map_layer, E_overlapping->key()); + for (const KeyValue<Vector2i, TileSet::CellNeighbor> &E_overlapping : overlapping_terrain_bits) { + if (!p_to_replace.has(E_overlapping.key)) { + TileMapCell neighbor_cell = tile_map->get_cell(tile_map_layer, E_overlapping.key); TileData *neighbor_tile_data = nullptr; if (terrain_tiles.has(neighbor_cell) && terrain_tiles[neighbor_cell]->get_terrain_set() == p_terrain_set) { neighbor_tile_data = terrain_tiles[neighbor_cell]; } - int terrain = neighbor_tile_data ? neighbor_tile_data->get_peering_bit_terrain(TileSet::CellNeighbor(E_overlapping->get())) : -1; + int terrain = neighbor_tile_data ? neighbor_tile_data->get_peering_bit_terrain(TileSet::CellNeighbor(E_overlapping.value)) : -1; if (terrain_count.has(terrain)) { terrain_count[terrain] = 0; } @@ -2375,10 +2387,10 @@ Set<TileMapEditorTerrainsPlugin::Constraint> TileMapEditorTerrainsPlugin::_get_c // Get the terrain with the max number of occurrences. int max = 0; int max_terrain = -1; - for (Map<int, int>::Element *E_terrain_count = terrain_count.front(); E_terrain_count; E_terrain_count = E_terrain_count->next()) { - if (E_terrain_count->get() > max) { - max = E_terrain_count->get(); - max_terrain = E_terrain_count->key(); + for (const KeyValue<int, int> &E_terrain_count : terrain_count) { + if (E_terrain_count.value > max) { + max = E_terrain_count.value; + max_terrain = E_terrain_count.key; } } @@ -2446,15 +2458,15 @@ Map<Vector2i, TileMapEditorTerrainsPlugin::TerrainsTilePattern> TileMapEditorTer while (!to_replace.is_empty()) { // Compute the minimum number of tile possibilities for each cell. int min_nb_possibilities = 100000000; - for (Map<Vector2i, Set<TerrainsTilePattern>>::Element *E = per_cell_acceptable_tiles.front(); E; E = E->next()) { - min_nb_possibilities = MIN(min_nb_possibilities, E->get().size()); + for (const KeyValue<Vector2i, Set<TerrainsTilePattern>> &E : per_cell_acceptable_tiles) { + min_nb_possibilities = MIN(min_nb_possibilities, E.value.size()); } // Get the set of possible cells to fill. LocalVector<Vector2i> to_choose_from; - for (Map<Vector2i, Set<TerrainsTilePattern>>::Element *E = per_cell_acceptable_tiles.front(); E; E = E->next()) { - if (E->get().size() == min_nb_possibilities) { - to_choose_from.push_back(E->key()); + for (const KeyValue<Vector2i, Set<TerrainsTilePattern>> &E : per_cell_acceptable_tiles) { + if (E.value.size() == min_nb_possibilities) { + to_choose_from.push_back(E.key); } } @@ -2572,9 +2584,9 @@ Map<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_terrains(const Map // Add the constraints from the added tiles. Set<TileMapEditorTerrainsPlugin::Constraint> added_tiles_constraints_set; - for (Map<Vector2i, TerrainsTilePattern>::Element *E_to_paint = p_to_paint.front(); E_to_paint; E_to_paint = E_to_paint->next()) { - Vector2i coords = E_to_paint->key(); - TerrainsTilePattern terrains_tile_pattern = E_to_paint->get(); + for (const KeyValue<Vector2i, TerrainsTilePattern> &E_to_paint : p_to_paint) { + Vector2i coords = E_to_paint.key; + TerrainsTilePattern terrains_tile_pattern = E_to_paint.value; Set<TileMapEditorTerrainsPlugin::Constraint> cell_constraints = _get_constraints_from_added_tile(coords, p_terrain_set, terrains_tile_pattern); for (Set<TileMapEditorTerrainsPlugin::Constraint>::Element *E = cell_constraints.front(); E; E = E->next()) { @@ -2584,8 +2596,8 @@ Map<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_terrains(const Map // Build the list of potential tiles to replace. Set<Vector2i> potential_to_replace; - for (Map<Vector2i, TerrainsTilePattern>::Element *E_to_paint = p_to_paint.front(); E_to_paint; E_to_paint = E_to_paint->next()) { - Vector2i coords = E_to_paint->key(); + for (const KeyValue<Vector2i, TerrainsTilePattern> &E_to_paint : p_to_paint) { + Vector2i coords = E_to_paint.key; for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) { if (tile_map->is_existing_neighbor(TileSet::CellNeighbor(i))) { Vector2i neighbor = tile_map->get_neighbor_cell(coords, TileSet::CellNeighbor(i)); @@ -2600,8 +2612,8 @@ Map<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_terrains(const Map Set<Vector2i> to_replace; // Add the central tiles to the one to replace. TODO: maybe change that. - for (Map<Vector2i, TerrainsTilePattern>::Element *E_to_paint = p_to_paint.front(); E_to_paint; E_to_paint = E_to_paint->next()) { - to_replace.insert(E_to_paint->key()); + for (const KeyValue<Vector2i, TerrainsTilePattern> &E_to_paint : p_to_paint) { + to_replace.insert(E_to_paint.key); } // Add the constraints from the surroundings of the modified areas. @@ -2615,9 +2627,9 @@ Map<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_terrains(const Map Map<Constraint, Set<Vector2i>> source_tiles_of_constraint; for (Set<Constraint>::Element *E = removed_cells_constraints_set.front(); E; E = E->next()) { Map<Vector2i, TileSet::CellNeighbor> sources_of_constraint = E->get().get_overlapping_coords_and_peering_bits(); - for (Map<Vector2i, TileSet::CellNeighbor>::Element *E_source_tile_of_constraint = sources_of_constraint.front(); E_source_tile_of_constraint; E_source_tile_of_constraint = E_source_tile_of_constraint->next()) { - if (potential_to_replace.has(E_source_tile_of_constraint->key())) { - source_tiles_of_constraint[E->get()].insert(E_source_tile_of_constraint->key()); + for (const KeyValue<Vector2i, TileSet::CellNeighbor> &E_source_tile_of_constraint : sources_of_constraint) { + if (potential_to_replace.has(E_source_tile_of_constraint.key)) { + source_tiles_of_constraint[E->get()].insert(E_source_tile_of_constraint.key); } } } @@ -2634,8 +2646,8 @@ Map<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_terrains(const Map potential_to_replace.erase(to_add_to_remove); to_replace.insert(to_add_to_remove); to_replace_modified = true; - for (Map<Constraint, Set<Vector2i>>::Element *E_source_tiles_of_constraint = source_tiles_of_constraint.front(); E_source_tiles_of_constraint; E_source_tiles_of_constraint = E_source_tiles_of_constraint->next()) { - E_source_tiles_of_constraint->get().erase(to_add_to_remove); + for (KeyValue<Constraint, Set<Vector2i>> &E_source_tiles_of_constraint : source_tiles_of_constraint) { + E_source_tiles_of_constraint.value.erase(to_add_to_remove); } break; } @@ -2653,13 +2665,13 @@ Map<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_terrains(const Map Map<Vector2i, TerrainsTilePattern> wfc_output = _wave_function_collapse(to_replace, p_terrain_set, constraints); // Use the WFC run for the output. - for (Map<Vector2i, TerrainsTilePattern>::Element *E = wfc_output.front(); E; E = E->next()) { - output[E->key()] = _get_random_tile_from_pattern(p_terrain_set, E->get()); + for (const KeyValue<Vector2i, TerrainsTilePattern> &E : wfc_output) { + output[E.key] = _get_random_tile_from_pattern(p_terrain_set, E.value); } // Override the WFC results to make sure at least the painted tiles are actually painted. - for (Map<Vector2i, TerrainsTilePattern>::Element *E_to_paint = p_to_paint.front(); E_to_paint; E_to_paint = E_to_paint->next()) { - output[E_to_paint->key()] = _get_random_tile_from_pattern(p_terrain_set, E_to_paint->get()); + for (const KeyValue<Vector2i, TerrainsTilePattern> &E_to_paint : p_to_paint) { + output[E_to_paint.key] = _get_random_tile_from_pattern(p_terrain_set, E_to_paint.value); } return output; @@ -2737,9 +2749,9 @@ void TileMapEditorTerrainsPlugin::_stop_dragging() { } break; case DRAG_TYPE_PAINT: { undo_redo->create_action(TTR("Paint terrain")); - for (Map<Vector2i, TileMapCell>::Element *E = drag_modified.front(); E; E = E->next()) { - undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E->key(), tile_map->get_cell_source_id(tile_map_layer, E->key()), tile_map->get_cell_atlas_coords(tile_map_layer, E->key()), tile_map->get_cell_alternative_tile(tile_map_layer, E->key())); - undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, E->key(), E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile); + for (const KeyValue<Vector2i, TileMapCell> &E : drag_modified) { + undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E.key, tile_map->get_cell_source_id(tile_map_layer, E.key), tile_map->get_cell_atlas_coords(tile_map_layer, E.key), tile_map->get_cell_alternative_tile(tile_map_layer, E.key)); + undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile); } undo_redo->commit_action(false); } break; @@ -2813,11 +2825,11 @@ bool TileMapEditorTerrainsPlugin::forward_canvas_gui_input(const Ref<InputEvent> to_draw[line[i]] = selected_terrains_tile_pattern; } Map<Vector2i, TileMapCell> modified = _draw_terrains(to_draw, selected_terrain_set); - for (Map<Vector2i, TileMapCell>::Element *E = modified.front(); E; E = E->next()) { - if (!drag_modified.has(E->key())) { - drag_modified[E->key()] = tile_map->get_cell(tile_map_layer, E->key()); + for (const KeyValue<Vector2i, TileMapCell> &E : modified) { + if (!drag_modified.has(E.key)) { + drag_modified[E.key] = tile_map->get_cell(tile_map_layer, E.key); } - tile_map->set_cell(tile_map_layer, E->key(), E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile); + tile_map->set_cell(tile_map_layer, E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile); } } } break; @@ -2852,9 +2864,9 @@ bool TileMapEditorTerrainsPlugin::forward_canvas_gui_input(const Ref<InputEvent> terrains_to_draw[tile_map->world_to_map(mpos)] = selected_terrains_tile_pattern; Map<Vector2i, TileMapCell> to_draw = _draw_terrains(terrains_to_draw, selected_terrain_set); - for (Map<Vector2i, TileMapCell>::Element *E = to_draw.front(); E; E = E->next()) { - drag_modified[E->key()] = tile_map->get_cell(tile_map_layer, E->key()); - tile_map->set_cell(tile_map_layer, E->key(), E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile); + for (const KeyValue<Vector2i, TileMapCell> &E : to_draw) { + drag_modified[E.key] = tile_map->get_cell(tile_map_layer, E.key); + tile_map->set_cell(tile_map_layer, E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile); } } } @@ -3181,7 +3193,7 @@ TileMapEditorTerrainsPlugin::TileMapEditorTerrainsPlugin() { paint_tool_button->set_toggle_mode(true); paint_tool_button->set_button_group(tool_buttons_group); paint_tool_button->set_pressed(true); - paint_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/paint_tool", "Paint", KEY_E)); + paint_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/paint_tool", "Paint", KEY_D)); paint_tool_button->connect("pressed", callable_mp(this, &TileMapEditorTerrainsPlugin::_update_toolbar)); tilemap_tiles_tools_buttons->add_child(paint_tool_button); diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp index c3a3f40e00..bc026146ef 100644 --- a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp +++ b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp @@ -87,7 +87,7 @@ void TileSetAtlasSourceEditor::TileSetAtlasSourceProxyObject::_get_property_list p_list->push_back(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D")); p_list->push_back(PropertyInfo(Variant::VECTOR2I, "margins", PROPERTY_HINT_NONE, "")); p_list->push_back(PropertyInfo(Variant::VECTOR2I, "separation", PROPERTY_HINT_NONE, "")); - p_list->push_back(PropertyInfo(Variant::VECTOR2I, "tile_size", PROPERTY_HINT_NONE, "")); + p_list->push_back(PropertyInfo(Variant::VECTOR2I, "texture_region_size", PROPERTY_HINT_NONE, "")); } void TileSetAtlasSourceEditor::TileSetAtlasSourceProxyObject::_bind_methods() { @@ -135,45 +135,81 @@ bool TileSetAtlasSourceEditor::AtlasTileProxyObject::_set(const StringName &p_na const Vector2i &coords = tiles.front()->get().tile; const int &alternative = tiles.front()->get().alternative; - if (alternative == 0 && p_name == "atlas_coords") { - Vector2i as_vector2i = Vector2i(p_value); - ERR_FAIL_COND_V(!tile_set_atlas_source->can_move_tile_in_atlas(coords, as_vector2i), false); + if (alternative == 0) { + Vector<String> components = String(p_name).split("/", true, 2); + if (p_name == "atlas_coords") { + Vector2i as_vector2i = Vector2i(p_value); + bool has_room_for_tile = tile_set_atlas_source->has_room_for_tile(as_vector2i, tile_set_atlas_source->get_tile_size_in_atlas(coords), tile_set_atlas_source->get_tile_animation_columns(coords), tile_set_atlas_source->get_tile_animation_separation(coords), tile_set_atlas_source->get_tile_animation_frames_count(coords), coords); + ERR_FAIL_COND_V(!has_room_for_tile, false); + + if (tiles_set_atlas_source_editor->selection.front()->get().tile == coords) { + tiles_set_atlas_source_editor->selection.clear(); + tiles_set_atlas_source_editor->selection.insert({ as_vector2i, 0 }); + tiles_set_atlas_source_editor->_update_tile_id_label(); + } - if (tiles_set_atlas_source_editor->selection.front()->get().tile == coords) { - tiles_set_atlas_source_editor->selection.clear(); - tiles_set_atlas_source_editor->selection.insert({ as_vector2i, 0 }); - tiles_set_atlas_source_editor->_update_tile_id_label(); + tile_set_atlas_source->move_tile_in_atlas(coords, as_vector2i); + tiles.clear(); + tiles.insert({ as_vector2i, 0 }); + emit_signal(SNAME("changed"), "atlas_coords"); + return true; + } else if (p_name == "size_in_atlas") { + Vector2i as_vector2i = Vector2i(p_value); + bool has_room_for_tile = tile_set_atlas_source->has_room_for_tile(coords, as_vector2i, tile_set_atlas_source->get_tile_animation_columns(coords), tile_set_atlas_source->get_tile_animation_separation(coords), tile_set_atlas_source->get_tile_animation_frames_count(coords), coords); + ERR_FAIL_COND_V(!has_room_for_tile, false); + tile_set_atlas_source->move_tile_in_atlas(coords, TileSetSource::INVALID_ATLAS_COORDS, as_vector2i); + emit_signal(SNAME("changed"), "size_in_atlas"); + return true; + } else if (p_name == "animation_columns") { + bool has_room_for_tile = tile_set_atlas_source->has_room_for_tile(coords, tile_set_atlas_source->get_tile_size_in_atlas(coords), p_value, tile_set_atlas_source->get_tile_animation_separation(coords), tile_set_atlas_source->get_tile_animation_frames_count(coords), coords); + ERR_FAIL_COND_V(!has_room_for_tile, false); + tile_set_atlas_source->set_tile_animation_columns(coords, p_value); + emit_signal(SNAME("changed"), "animation_columns"); + return true; + } else if (p_name == "animation_separation") { + bool has_room_for_tile = tile_set_atlas_source->has_room_for_tile(coords, tile_set_atlas_source->get_tile_size_in_atlas(coords), tile_set_atlas_source->get_tile_animation_columns(coords), p_value, tile_set_atlas_source->get_tile_animation_frames_count(coords), coords); + ERR_FAIL_COND_V(!has_room_for_tile, false); + tile_set_atlas_source->set_tile_animation_separation(coords, p_value); + emit_signal(SNAME("changed"), "animation_separation"); + return true; + } else if (p_name == "animation_speed") { + tile_set_atlas_source->set_tile_animation_speed(coords, p_value); + emit_signal(SNAME("changed"), "animation_speed"); + return true; + } else if (p_name == "animation_frames_count") { + bool has_room_for_tile = tile_set_atlas_source->has_room_for_tile(coords, tile_set_atlas_source->get_tile_size_in_atlas(coords), tile_set_atlas_source->get_tile_animation_columns(coords), tile_set_atlas_source->get_tile_animation_separation(coords), p_value, coords); + ERR_FAIL_COND_V(!has_room_for_tile, false); + tile_set_atlas_source->set_tile_animation_frames_count(coords, p_value); + notify_property_list_changed(); + emit_signal(SNAME("changed"), "animation_separation"); + return true; + } else if (components.size() == 2 && components[0].begins_with("animation_frame_") && components[0].trim_prefix("animation_frame_").is_valid_int()) { + int frame = components[0].trim_prefix("animation_frame_").to_int(); + ERR_FAIL_INDEX_V(frame, tile_set_atlas_source->get_tile_animation_frames_count(coords), false); + if (components[1] == "duration") { + tile_set_atlas_source->set_tile_animation_frame_duration(coords, frame, p_value); + return true; + } } + } else if (alternative > 0) { + if (p_name == "alternative_id") { + int as_int = int(p_value); + ERR_FAIL_COND_V(as_int < 0, false); + ERR_FAIL_COND_V_MSG(tile_set_atlas_source->has_alternative_tile(coords, as_int), false, vformat("Cannot change alternative tile ID. Another alternative exists with id %d for tile at coords %s.", as_int, coords)); + + if (tiles_set_atlas_source_editor->selection.front()->get().alternative == alternative) { + tiles_set_atlas_source_editor->selection.clear(); + tiles_set_atlas_source_editor->selection.insert({ coords, as_int }); + } - tile_set_atlas_source->move_tile_in_atlas(coords, as_vector2i); - tiles.clear(); - tiles.insert({ as_vector2i, 0 }); - emit_signal(SNAME("changed"), "atlas_coords"); - return true; - } else if (alternative == 0 && p_name == "size_in_atlas") { - Vector2i as_vector2i = Vector2i(p_value); - ERR_FAIL_COND_V(!tile_set_atlas_source->can_move_tile_in_atlas(coords, TileSetSource::INVALID_ATLAS_COORDS, as_vector2i), false); + int previous_alternative_tile = alternative; + tiles.clear(); + tiles.insert({ coords, as_int }); // tiles must be updated before. + tile_set_atlas_source->set_alternative_tile_id(coords, previous_alternative_tile, as_int); - tile_set_atlas_source->move_tile_in_atlas(coords, TileSetSource::INVALID_ATLAS_COORDS, as_vector2i); - emit_signal(SNAME("changed"), "size_in_atlas"); - return true; - } else if (alternative > 0 && p_name == "alternative_id") { - int as_int = int(p_value); - ERR_FAIL_COND_V(as_int < 0, false); - ERR_FAIL_COND_V_MSG(tile_set_atlas_source->has_alternative_tile(coords, as_int), false, vformat("Cannot change alternative tile ID. Another alternative exists with id %d for tile at coords %s.", as_int, coords)); - - if (tiles_set_atlas_source_editor->selection.front()->get().alternative == alternative) { - tiles_set_atlas_source_editor->selection.clear(); - tiles_set_atlas_source_editor->selection.insert({ coords, as_int }); + emit_signal(SNAME("changed"), "alternative_id"); + return true; } - - int previous_alternative_tile = alternative; - tiles.clear(); - tiles.insert({ coords, as_int }); // tiles must be updated before. - tile_set_atlas_source->set_alternative_tile_id(coords, previous_alternative_tile, as_int); - - emit_signal(SNAME("changed"), "alternative_id"); - return true; } } @@ -206,15 +242,41 @@ bool TileSetAtlasSourceEditor::AtlasTileProxyObject::_get(const StringName &p_na const Vector2i &coords = tiles.front()->get().tile; const int &alternative = tiles.front()->get().alternative; - if (alternative == 0 && p_name == "atlas_coords") { - r_ret = coords; - return true; - } else if (alternative == 0 && p_name == "size_in_atlas") { - r_ret = tile_set_atlas_source->get_tile_size_in_atlas(coords); - return true; - } else if (alternative > 0 && p_name == "alternative_id") { - r_ret = alternative; - return true; + if (alternative == 0) { + Vector<String> components = String(p_name).split("/", true, 2); + if (p_name == "atlas_coords") { + r_ret = coords; + return true; + } else if (p_name == "size_in_atlas") { + r_ret = tile_set_atlas_source->get_tile_size_in_atlas(coords); + return true; + } else if (p_name == "animation_columns") { + r_ret = tile_set_atlas_source->get_tile_animation_columns(coords); + return true; + } else if (p_name == "animation_separation") { + r_ret = tile_set_atlas_source->get_tile_animation_separation(coords); + return true; + } else if (p_name == "animation_speed") { + r_ret = tile_set_atlas_source->get_tile_animation_speed(coords); + return true; + } else if (p_name == "animation_frames_count") { + r_ret = tile_set_atlas_source->get_tile_animation_frames_count(coords); + return true; + } else if (components.size() == 2 && components[0].begins_with("animation_frame_") && components[0].trim_prefix("animation_frame_").is_valid_int()) { + int frame = components[0].trim_prefix("animation_frame_").to_int(); + if (components[1] == "duration") { + if (frame < 0 || frame >= tile_set_atlas_source->get_tile_animation_frames_count(coords)) { + return false; + } + r_ret = tile_set_atlas_source->get_tile_animation_frame_duration(coords, frame); + return true; + } + } + } else if (alternative > 0) { + if (p_name == "alternative_id") { + r_ret = alternative; + return true; + } } } @@ -246,6 +308,20 @@ void TileSetAtlasSourceEditor::AtlasTileProxyObject::_get_property_list(List<Pro if (tiles.front()->get().alternative == 0) { p_list->push_back(PropertyInfo(Variant::VECTOR2I, "atlas_coords", PROPERTY_HINT_NONE, "")); p_list->push_back(PropertyInfo(Variant::VECTOR2I, "size_in_atlas", PROPERTY_HINT_NONE, "")); + + // Animation. + p_list->push_back(PropertyInfo(Variant::NIL, "Animation", PROPERTY_HINT_NONE, "animation_", PROPERTY_USAGE_GROUP)); + p_list->push_back(PropertyInfo(Variant::INT, "animation_columns", PROPERTY_HINT_NONE, "")); + p_list->push_back(PropertyInfo(Variant::VECTOR2I, "animation_separation", PROPERTY_HINT_NONE, "")); + p_list->push_back(PropertyInfo(Variant::FLOAT, "animation_speed", PROPERTY_HINT_NONE, "")); + p_list->push_back(PropertyInfo(Variant::INT, "animation_frames_count", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_ARRAY, "Frames,animation_frame_")); + if (tile_set_atlas_source->get_tile_animation_frames_count(tiles.front()->get().tile) == 1) { + p_list->push_back(PropertyInfo(Variant::FLOAT, "animation_frame_0/duration", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_READ_ONLY)); + } else { + for (int i = 0; i < tile_set_atlas_source->get_tile_animation_frames_count(tiles.front()->get().tile); i++) { + p_list->push_back(PropertyInfo(Variant::FLOAT, vformat("animation_frame_%d/duration", i), PROPERTY_HINT_NONE, "")); + } + } } else { p_list->push_back(PropertyInfo(Variant::INT, "alternative_id", PROPERTY_HINT_NONE, "")); } @@ -598,9 +674,9 @@ void TileSetAtlasSourceEditor::_update_tile_data_editors() { #undef ADD_TILE_DATA_EDITOR // Add tile data editors as children. - for (Map<String, TileDataEditor *>::Element *E = tile_data_editors.front(); E; E = E->next()) { + for (KeyValue<String, TileDataEditor *> &E : tile_data_editors) { // Tile Data Editor. - TileDataEditor *tile_data_editor = E->get(); + TileDataEditor *tile_data_editor = E.value; if (!tile_data_editor->is_inside_tree()) { tile_data_painting_editor_container->add_child(tile_data_editor); } @@ -640,9 +716,9 @@ void TileSetAtlasSourceEditor::_update_current_tile_data_editor() { } // Hide all editors but the current one. - for (Map<String, TileDataEditor *>::Element *E = tile_data_editors.front(); E; E = E->next()) { - E->get()->hide(); - E->get()->get_toolbar()->hide(); + for (const KeyValue<String, TileDataEditor *> &E : tile_data_editors) { + E.value->hide(); + E.value->get_toolbar()->hide(); } if (tile_data_editors.has(property)) { current_tile_data_editor = tile_data_editors[property]; @@ -846,15 +922,15 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_gui_input(const Ref<InputEven CursorShape cursor_shape = CURSOR_ARROW; bool can_grow[4]; for (int i = 0; i < 4; i++) { - can_grow[i] = tile_set_atlas_source->can_move_tile_in_atlas(selected.tile, selected.tile + directions[i]); + can_grow[i] = tile_set_atlas_source->has_room_for_tile(selected.tile + directions[i], tile_set_atlas_source->get_tile_size_in_atlas(selected.tile), tile_set_atlas_source->get_tile_animation_columns(selected.tile), tile_set_atlas_source->get_tile_animation_separation(selected.tile), tile_set_atlas_source->get_tile_animation_frames_count(selected.tile), selected.tile); can_grow[i] |= (i % 2 == 0) ? size_in_atlas.y > 1 : size_in_atlas.x > 1; } for (int i = 0; i < 4; i++) { - Vector2 pos = rect.position + Vector2(rect.size.x, rect.size.y) * coords[i]; + Vector2 pos = rect.position + rect.size * coords[i]; if (can_grow[i] && can_grow[(i + 3) % 4] && Rect2(pos, zoomed_size).has_point(mouse_local_pos)) { cursor_shape = (i % 2) ? CURSOR_BDIAGSIZE : CURSOR_FDIAGSIZE; } - Vector2 next_pos = rect.position + Vector2(rect.size.x, rect.size.y) * coords[(i + 1) % 4]; + Vector2 next_pos = rect.position + rect.size * coords[(i + 1) % 4]; if (can_grow[i] && Rect2((pos + next_pos) / 2.0, zoomed_size).has_point(mouse_local_pos)) { cursor_shape = (i % 2) ? CURSOR_HSIZE : CURSOR_VSIZE; } @@ -869,7 +945,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_gui_input(const Ref<InputEven Rect2i new_rect = Rect2i(start_base_tiles_coords, new_base_tiles_coords - start_base_tiles_coords).abs(); new_rect.size += Vector2i(1, 1); // Check if the new tile can fit in the new rect. - if (tile_set_atlas_source->can_move_tile_in_atlas(drag_current_tile, new_rect.position, new_rect.size)) { + if (tile_set_atlas_source->has_room_for_tile(new_rect.position, new_rect.size, tile_set_atlas_source->get_tile_animation_columns(drag_current_tile), tile_set_atlas_source->get_tile_animation_separation(drag_current_tile), tile_set_atlas_source->get_tile_animation_frames_count(drag_current_tile), drag_current_tile)) { // Move and resize the tile. tile_set_atlas_source->move_tile_in_atlas(drag_current_tile, new_rect.position, new_rect.size); drag_current_tile = new_rect.position; @@ -908,7 +984,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_gui_input(const Ref<InputEven Vector2 mouse_offset = (Vector2(tile_set_atlas_source->get_tile_size_in_atlas(drag_current_tile)) / 2.0 - Vector2(0.5, 0.5)) * tile_set->get_tile_size(); Vector2i coords = tile_atlas_view->get_atlas_tile_coords_at_pos(tile_atlas_control->get_local_mouse_position() - mouse_offset); coords = coords.max(Vector2i(0, 0)).min(grid_size - Vector2i(1, 1)); - if (drag_current_tile != coords && tile_set_atlas_source->can_move_tile_in_atlas(drag_current_tile, coords)) { + if (drag_current_tile != coords && tile_set_atlas_source->has_room_for_tile(coords, tile_set_atlas_source->get_tile_size_in_atlas(drag_current_tile), tile_set_atlas_source->get_tile_animation_columns(drag_current_tile), tile_set_atlas_source->get_tile_animation_separation(drag_current_tile), tile_set_atlas_source->get_tile_animation_frames_count(drag_current_tile), drag_current_tile)) { tile_set_atlas_source->move_tile_in_atlas(drag_current_tile, coords); selection.clear(); selection.insert({ coords, 0 }); @@ -948,7 +1024,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_gui_input(const Ref<InputEven new_rect.set_end(Vector2i(new_rect.get_end().x, MAX(new_base_tiles_coords.y, old_rect.position.y + 1))); } - if (tile_set_atlas_source->can_move_tile_in_atlas(drag_current_tile, new_rect.position, new_rect.size)) { + if (tile_set_atlas_source->has_room_for_tile(new_rect.position, new_rect.size, tile_set_atlas_source->get_tile_animation_columns(drag_current_tile), tile_set_atlas_source->get_tile_animation_separation(drag_current_tile), tile_set_atlas_source->get_tile_animation_frames_count(drag_current_tile), drag_current_tile)) { tile_set_atlas_source->move_tile_in_atlas(drag_current_tile, new_rect.position, new_rect.size); selection.clear(); selection.insert({ new_rect.position, 0 }); @@ -1056,11 +1132,11 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_gui_input(const Ref<InputEven CursorShape cursor_shape = CURSOR_ARROW; bool can_grow[4]; for (int i = 0; i < 4; i++) { - can_grow[i] = tile_set_atlas_source->can_move_tile_in_atlas(selected.tile, selected.tile + directions[i]); + can_grow[i] = tile_set_atlas_source->has_room_for_tile(selected.tile + directions[i], tile_set_atlas_source->get_tile_size_in_atlas(selected.tile), tile_set_atlas_source->get_tile_animation_columns(selected.tile), tile_set_atlas_source->get_tile_animation_separation(selected.tile), tile_set_atlas_source->get_tile_animation_frames_count(selected.tile), selected.tile); can_grow[i] |= (i % 2 == 0) ? size_in_atlas.y > 1 : size_in_atlas.x > 1; } for (int i = 0; i < 4; i++) { - Vector2 pos = rect.position + Vector2(rect.size.x, rect.size.y) * coords[i]; + Vector2 pos = rect.position + rect.size * coords[i]; if (can_grow[i] && can_grow[(i + 3) % 4] && Rect2(pos, zoomed_size).has_point(mouse_local_pos)) { drag_type = (DragType)((int)DRAG_TYPE_RESIZE_TOP_LEFT + i * 2); drag_start_mouse_pos = mouse_local_pos; @@ -1069,7 +1145,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_gui_input(const Ref<InputEven drag_start_tile_shape = Rect2i(selected.tile, tile_set_atlas_source->get_tile_size_in_atlas(selected.tile)); cursor_shape = (i % 2) ? CURSOR_BDIAGSIZE : CURSOR_FDIAGSIZE; } - Vector2 next_pos = rect.position + Vector2(rect.size.x, rect.size.y) * coords[(i + 1) % 4]; + Vector2 next_pos = rect.position + rect.size * coords[(i + 1) % 4]; if (can_grow[i] && Rect2((pos + next_pos) / 2.0, zoomed_size).has_point(mouse_local_pos)) { drag_type = (DragType)((int)DRAG_TYPE_RESIZE_TOP + i * 2); drag_start_mouse_pos = mouse_local_pos; @@ -1511,37 +1587,45 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_draw() { TileSelection selected = E->get(); if (selected.alternative == 0) { // Draw the rect. - Rect2 region = tile_set_atlas_source->get_tile_texture_region(selected.tile); - tile_atlas_control->draw_rect(region, selection_color, false); + for (int frame = 0; frame < tile_set_atlas_source->get_tile_animation_frames_count(selected.tile); frame++) { + Color color = selection_color; + if (frame > 0) { + color.a *= 0.3; + } + Rect2 region = tile_set_atlas_source->get_tile_texture_region(selected.tile, frame); + tile_atlas_control->draw_rect(region, color, false); + } } } if (selection.size() == 1) { // Draw the resize handles (only when it's possible to expand). TileSelection selected = selection.front()->get(); - Vector2i size_in_atlas = tile_set_atlas_source->get_tile_size_in_atlas(selected.tile); - Size2 zoomed_size = resize_handle->get_size() / tile_atlas_view->get_zoom(); - Rect2 region = tile_set_atlas_source->get_tile_texture_region(selected.tile); - Rect2 rect = region.grow_individual(zoomed_size.x, zoomed_size.y, 0, 0); - Vector2i coords[] = { Vector2i(0, 0), Vector2i(1, 0), Vector2i(1, 1), Vector2i(0, 1) }; - Vector2i directions[] = { Vector2i(0, -1), Vector2i(1, 0), Vector2i(0, 1), Vector2i(-1, 0) }; - bool can_grow[4]; - for (int i = 0; i < 4; i++) { - can_grow[i] = tile_set_atlas_source->can_move_tile_in_atlas(selected.tile, selected.tile + directions[i]); - can_grow[i] |= (i % 2 == 0) ? size_in_atlas.y > 1 : size_in_atlas.x > 1; - } - for (int i = 0; i < 4; i++) { - Vector2 pos = rect.position + Vector2(rect.size.x, rect.size.y) * coords[i]; - if (can_grow[i] && can_grow[(i + 3) % 4]) { - tile_atlas_control->draw_texture_rect(resize_handle, Rect2(pos, zoomed_size), false); - } else { - tile_atlas_control->draw_texture_rect(resize_handle_disabled, Rect2(pos, zoomed_size), false); + if (selected.alternative == 0) { + Vector2i size_in_atlas = tile_set_atlas_source->get_tile_size_in_atlas(selected.tile); + Size2 zoomed_size = resize_handle->get_size() / tile_atlas_view->get_zoom(); + Rect2 region = tile_set_atlas_source->get_tile_texture_region(selected.tile); + Rect2 rect = region.grow_individual(zoomed_size.x, zoomed_size.y, 0, 0); + Vector2i coords[] = { Vector2i(0, 0), Vector2i(1, 0), Vector2i(1, 1), Vector2i(0, 1) }; + Vector2i directions[] = { Vector2i(0, -1), Vector2i(1, 0), Vector2i(0, 1), Vector2i(-1, 0) }; + bool can_grow[4]; + for (int i = 0; i < 4; i++) { + can_grow[i] = tile_set_atlas_source->has_room_for_tile(selected.tile + directions[i], tile_set_atlas_source->get_tile_size_in_atlas(selected.tile), tile_set_atlas_source->get_tile_animation_columns(selected.tile), tile_set_atlas_source->get_tile_animation_separation(selected.tile), tile_set_atlas_source->get_tile_animation_frames_count(selected.tile), selected.tile); + can_grow[i] |= (i % 2 == 0) ? size_in_atlas.y > 1 : size_in_atlas.x > 1; } - Vector2 next_pos = rect.position + Vector2(rect.size.x, rect.size.y) * coords[(i + 1) % 4]; - if (can_grow[i]) { - tile_atlas_control->draw_texture_rect(resize_handle, Rect2((pos + next_pos) / 2.0, zoomed_size), false); - } else { - tile_atlas_control->draw_texture_rect(resize_handle_disabled, Rect2((pos + next_pos) / 2.0, zoomed_size), false); + for (int i = 0; i < 4; i++) { + Vector2 pos = rect.position + rect.size * coords[i]; + if (can_grow[i] && can_grow[(i + 3) % 4]) { + tile_atlas_control->draw_texture_rect(resize_handle, Rect2(pos, zoomed_size), false); + } else { + tile_atlas_control->draw_texture_rect(resize_handle_disabled, Rect2(pos, zoomed_size), false); + } + Vector2 next_pos = rect.position + rect.size * coords[(i + 1) % 4]; + if (can_grow[i]) { + tile_atlas_control->draw_texture_rect(resize_handle, Rect2((pos + next_pos) / 2.0, zoomed_size), false); + } else { + tile_atlas_control->draw_texture_rect(resize_handle_disabled, Rect2((pos + next_pos) / 2.0, zoomed_size), false); + } } } } @@ -1550,7 +1634,9 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_draw() { if (drag_type == DRAG_TYPE_REMOVE_TILES) { // Draw the tiles to be removed. for (Set<Vector2i>::Element *E = drag_modified_tiles.front(); E; E = E->next()) { - tile_atlas_control->draw_rect(tile_set_atlas_source->get_tile_texture_region(E->get()), Color(0.0, 0.0, 0.0), false); + for (int frame = 0; frame < tile_set_atlas_source->get_tile_animation_frames_count(E->get()); frame++) { + tile_atlas_control->draw_rect(tile_set_atlas_source->get_tile_texture_region(E->get(), frame), Color(0.0, 0.0, 0.0), false); + } } } else if (drag_type == DRAG_TYPE_RECT_SELECT || drag_type == DRAG_TYPE_REMOVE_TILES_USING_RECT) { // Draw tiles to be removed. @@ -1617,7 +1703,13 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_draw() { Vector2i hovered_tile = tile_set_atlas_source->get_tile_at_coords(hovered_base_tile_coords); if (hovered_tile != TileSetSource::INVALID_ATLAS_COORDS) { // Draw existing hovered tile. - tile_atlas_control->draw_rect(tile_set_atlas_source->get_tile_texture_region(hovered_tile), Color(1.0, 1.0, 1.0), false); + for (int frame = 0; frame < tile_set_atlas_source->get_tile_animation_frames_count(hovered_tile); frame++) { + Color color = Color(1.0, 1.0, 1.0); + if (frame > 0) { + color.a *= 0.3; + } + tile_atlas_control->draw_rect(tile_set_atlas_source->get_tile_texture_region(hovered_tile, frame), color, false); + } } else { // Draw empty tile, only in add/remove tiles mode. if (tools_button_group->get_pressed_button() == tool_setup_atlas_source_button) { @@ -1638,7 +1730,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_unscaled_draw() { for (int i = 0; i < tile_set_atlas_source->get_tiles_count(); i++) { Vector2i coords = tile_set_atlas_source->get_tile_id(i); Rect2i texture_region = tile_set_atlas_source->get_tile_texture_region(coords); - Vector2i position = (texture_region.position + texture_region.get_end()) / 2 + tile_set_atlas_source->get_tile_effective_texture_offset(coords, 0); + Vector2i position = texture_region.get_center() + tile_set_atlas_source->get_tile_effective_texture_offset(coords, 0); Transform2D xform = tile_atlas_control->get_parent_control()->get_transform(); xform.translate(position); @@ -1661,7 +1753,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_unscaled_draw() { continue; } Rect2i texture_region = tile_set_atlas_source->get_tile_texture_region(E->get().tile); - Vector2i position = (texture_region.position + texture_region.get_end()) / 2 + tile_set_atlas_source->get_tile_effective_texture_offset(E->get().tile, 0); + Vector2i position = texture_region.get_center() + tile_set_atlas_source->get_tile_effective_texture_offset(E->get().tile, 0); Transform2D xform = tile_atlas_control->get_parent_control()->get_transform(); xform.translate(position); @@ -1805,7 +1897,7 @@ void TileSetAtlasSourceEditor::_tile_alternatives_control_unscaled_draw() { continue; } Rect2i rect = tile_atlas_view->get_alternative_tile_rect(coords, alternative_tile); - Vector2 position = (rect.get_position() + rect.get_end()) / 2; + Vector2 position = rect.get_center(); Transform2D xform = alternative_tiles_control->get_parent_control()->get_transform(); xform.translate(position); @@ -1829,7 +1921,7 @@ void TileSetAtlasSourceEditor::_tile_alternatives_control_unscaled_draw() { continue; } Rect2i rect = tile_atlas_view->get_alternative_tile_rect(E->get().tile, E->get().alternative); - Vector2 position = (rect.get_position() + rect.get_end()) / 2; + Vector2 position = rect.get_center(); Transform2D xform = alternative_tiles_control->get_parent_control()->get_transform(); xform.translate(position); @@ -1854,6 +1946,11 @@ void TileSetAtlasSourceEditor::_tile_set_atlas_source_changed() { tile_set_atlas_source_changed_needs_update = true; } +void TileSetAtlasSourceEditor::_tile_proxy_object_changed(String p_what) { + tile_set_atlas_source_changed_needs_update = false; // Avoid updating too many things. + _update_atlas_view(); +} + void TileSetAtlasSourceEditor::_atlas_source_proxy_object_changed(String p_what) { if (p_what == "texture" && !atlas_source_proxy_object->get("texture").is_null()) { confirm_auto_create_tiles->popup_centered(); @@ -2114,7 +2211,7 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() { middle_vbox_container->add_child(tile_inspector_label); tile_proxy_object = memnew(AtlasTileProxyObject(this)); - tile_proxy_object->connect("changed", callable_mp(this, &TileSetAtlasSourceEditor::_update_atlas_view).unbind(1)); + tile_proxy_object->connect("changed", callable_mp(this, &TileSetAtlasSourceEditor::_tile_proxy_object_changed)); tile_inspector = memnew(EditorInspector); tile_inspector->set_undo_redo(undo_redo); diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.h b/editor/plugins/tiles/tile_set_atlas_source_editor.h index 501416c340..6448b55feb 100644 --- a/editor/plugins/tiles/tile_set_atlas_source_editor.h +++ b/editor/plugins/tiles/tile_set_atlas_source_editor.h @@ -264,6 +264,7 @@ private: AcceptDialog *confirm_auto_create_tiles; void _tile_set_atlas_source_changed(); + void _tile_proxy_object_changed(String p_what); void _atlas_source_proxy_object_changed(String p_what); void _undo_redo_inspector_callback(Object *p_undo_redo, Object *p_edited, String p_property, Variant p_new_value); diff --git a/editor/plugins/tiles/tiles_editor_plugin.cpp b/editor/plugins/tiles/tiles_editor_plugin.cpp index 79b869b511..f51f4625a9 100644 --- a/editor/plugins/tiles/tiles_editor_plugin.cpp +++ b/editor/plugins/tiles/tiles_editor_plugin.cpp @@ -146,7 +146,7 @@ void TilesEditor::synchronize_atlas_view(Object *p_current) { ERR_FAIL_COND(!tile_atlas_view); if (tile_atlas_view->is_visible_in_tree()) { - tile_atlas_view->set_transform(atlas_view_zoom, Vector2(atlas_view_scroll.x, atlas_view_scroll.y)); + tile_atlas_view->set_transform(atlas_view_zoom, atlas_view_scroll); } } |