Merge pull request #65903 from groud/improve_terrain_painting

Right-click to erase TileSet terrains and bugfixes
This commit is contained in:
Rémi Verschelde 2022-09-30 17:44:48 +02:00
commit e69b7083d4
2 changed files with 124 additions and 83 deletions

View file

@ -1977,6 +1977,7 @@ void TileDataTerrainsEditor::forward_painting_atlas_gui_input(TileAtlasView *p_t
}
}
drag_last_pos = mm->get_position();
accept_event();
} else if (drag_type == DRAG_TYPE_PAINT_TERRAIN_BITS) {
int terrain_set = Dictionary(drag_painted_value)["terrain_set"];
int terrain = Dictionary(drag_painted_value)["terrain"];
@ -2026,14 +2027,15 @@ void TileDataTerrainsEditor::forward_painting_atlas_gui_input(TileAtlasView *p_t
}
}
drag_last_pos = mm->get_position();
accept_event();
}
}
Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid()) {
if (mb->get_button_index() == MouseButton::LEFT) {
if (mb->get_button_index() == MouseButton::LEFT || mb->get_button_index() == MouseButton::RIGHT) {
if (mb->is_pressed()) {
if (picker_button->is_pressed()) {
if (mb->get_button_index() == MouseButton::LEFT && picker_button->is_pressed()) {
Vector2i coords = p_tile_atlas_view->get_atlas_tile_coords_at_pos(mb->get_position());
coords = p_tile_set_atlas_source->get_tile_at_coords(coords);
if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
@ -2060,6 +2062,7 @@ void TileDataTerrainsEditor::forward_painting_atlas_gui_input(TileAtlasView *p_t
terrain_set_property_editor->update_property();
_update_terrain_selector();
picker_button->set_pressed(false);
accept_event();
}
} else {
Vector2i coords = p_tile_atlas_view->get_atlas_tile_coords_at_pos(mb->get_position());
@ -2071,6 +2074,10 @@ void TileDataTerrainsEditor::forward_painting_atlas_gui_input(TileAtlasView *p_t
int terrain_set = int(dummy_object->get("terrain_set"));
int terrain = int(dummy_object->get("terrain"));
if (terrain_set == -1 || !tile_data || tile_data->get_terrain_set() != terrain_set) {
// Paint terrain sets.
if (mb->get_button_index() == MouseButton::RIGHT) {
terrain_set = -1;
}
if (mb->is_ctrl_pressed()) {
// Paint terrain set with rect.
drag_type = DRAG_TYPE_PAINT_TERRAIN_SET_RECT;
@ -2106,9 +2113,14 @@ void TileDataTerrainsEditor::forward_painting_atlas_gui_input(TileAtlasView *p_t
}
drag_last_pos = mb->get_position();
}
accept_event();
} else if (tile_data->get_terrain_set() == terrain_set) {
// Paint terrain bits.
if (mb->get_button_index() == MouseButton::RIGHT) {
terrain = -1;
}
if (mb->is_ctrl_pressed()) {
// Paint terrain set with rect.
// Paint terrain bits with rect.
drag_type = DRAG_TYPE_PAINT_TERRAIN_BITS_RECT;
drag_modified.clear();
Dictionary painted_dict;
@ -2163,6 +2175,7 @@ void TileDataTerrainsEditor::forward_painting_atlas_gui_input(TileAtlasView *p_t
}
drag_last_pos = mb->get_position();
}
accept_event();
}
}
} else {
@ -2190,18 +2203,21 @@ void TileDataTerrainsEditor::forward_painting_atlas_gui_input(TileAtlasView *p_t
for (const TileMapCell &E : edited) {
Vector2i coords = E.get_atlas_coords();
TileData *tile_data = p_tile_set_atlas_source->get_tile_data(coords, 0);
undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrain_set", coords.x, coords.y, E.alternative_tile), tile_data->get_terrain_set());
undo_redo->add_do_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrain_set", coords.x, coords.y, E.alternative_tile), drag_painted_value);
undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrain", coords.x, coords.y, E.alternative_tile), tile_data->get_terrain());
for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
if (tile_data->is_valid_terrain_peering_bit(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.alternative_tile), tile_data->get_terrain_peering_bit(bit));
undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrain_set", coords.x, coords.y, E.alternative_tile), tile_data->get_terrain_set());
if (tile_data->get_terrain_set() >= 0) {
undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrain", coords.x, coords.y, E.alternative_tile), tile_data->get_terrain());
for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
if (tile_data->is_valid_terrain_peering_bit(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.alternative_tile), tile_data->get_terrain_peering_bit(bit));
}
}
}
}
undo_redo->commit_action(true);
drag_type = DRAG_TYPE_NONE;
accept_event();
} else if (drag_type == DRAG_TYPE_PAINT_TERRAIN_SET) {
undo_redo->create_action(TTR("Painting Terrain Set"));
for (KeyValue<TileMapCell, Variant> &E : drag_modified) {
@ -2209,17 +2225,20 @@ void TileDataTerrainsEditor::forward_painting_atlas_gui_input(TileAtlasView *p_t
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"]);
undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrain", coords.x, coords.y, E.key.alternative_tile), dict["terrain"]);
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_terrain_peering_bit(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]);
if (int(dict["terrain_set"]) >= 0) {
undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrain", coords.x, coords.y, E.key.alternative_tile), dict["terrain"]);
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_terrain_peering_bit(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->commit_action(false);
drag_type = DRAG_TYPE_NONE;
accept_event();
} else if (drag_type == DRAG_TYPE_PAINT_TERRAIN_BITS) {
Dictionary painted = Dictionary(drag_painted_value);
int terrain_set = int(painted["terrain_set"]);
@ -2243,6 +2262,7 @@ void TileDataTerrainsEditor::forward_painting_atlas_gui_input(TileAtlasView *p_t
}
undo_redo->commit_action(false);
drag_type = DRAG_TYPE_NONE;
accept_event();
} else if (drag_type == DRAG_TYPE_PAINT_TERRAIN_BITS_RECT) {
Dictionary painted = Dictionary(drag_painted_value);
int terrain_set = int(painted["terrain_set"]);
@ -2312,6 +2332,7 @@ void TileDataTerrainsEditor::forward_painting_atlas_gui_input(TileAtlasView *p_t
}
undo_redo->commit_action(true);
drag_type = DRAG_TYPE_NONE;
accept_event();
}
}
}
@ -2348,6 +2369,7 @@ void TileDataTerrainsEditor::forward_painting_alternatives_gui_input(TileAtlasVi
}
drag_last_pos = mm->get_position();
accept_event();
} else if (drag_type == DRAG_TYPE_PAINT_TERRAIN_BITS) {
Dictionary painted = Dictionary(drag_painted_value);
int terrain_set = int(painted["terrain_set"]);
@ -2400,14 +2422,15 @@ void TileDataTerrainsEditor::forward_painting_alternatives_gui_input(TileAtlasVi
}
}
drag_last_pos = mm->get_position();
accept_event();
}
}
Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid()) {
if (mb->get_button_index() == MouseButton::LEFT) {
if (mb->get_button_index() == MouseButton::LEFT || mb->get_button_index() == MouseButton::RIGHT) {
if (mb->is_pressed()) {
if (picker_button->is_pressed()) {
if (mb->get_button_index() == MouseButton::LEFT && picker_button->is_pressed()) {
Vector3i tile = p_tile_atlas_view->get_alternative_tile_at_pos(mb->get_position());
Vector2i coords = Vector2i(tile.x, tile.y);
int alternative_tile = tile.z;
@ -2437,6 +2460,7 @@ void TileDataTerrainsEditor::forward_painting_alternatives_gui_input(TileAtlasVi
terrain_set_property_editor->update_property();
_update_terrain_selector();
picker_button->set_pressed(false);
accept_event();
}
} else {
int terrain_set = int(dummy_object->get("terrain_set"));
@ -2446,75 +2470,87 @@ void TileDataTerrainsEditor::forward_painting_alternatives_gui_input(TileAtlasVi
Vector2i coords = Vector2i(tile.x, tile.y);
int alternative_tile = tile.z;
TileData *tile_data = p_tile_set_atlas_source->get_tile_data(coords, alternative_tile);
if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
TileData *tile_data = p_tile_set_atlas_source->get_tile_data(coords, alternative_tile);
if (terrain_set == -1 || !tile_data || tile_data->get_terrain_set() != terrain_set) {
drag_type = DRAG_TYPE_PAINT_TERRAIN_SET;
drag_modified.clear();
drag_painted_value = int(dummy_object->get("terrain_set"));
if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
TileMapCell cell;
cell.source_id = 0;
cell.set_atlas_coords(coords);
cell.alternative_tile = alternative_tile;
Dictionary dict;
dict["terrain_set"] = tile_data->get_terrain_set();
Array array;
for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
array.push_back(tile_data->is_valid_terrain_peering_bit(bit) ? tile_data->get_terrain_peering_bit(bit) : -1);
if (terrain_set == -1 || !tile_data || tile_data->get_terrain_set() != terrain_set) {
// Paint terrain sets.
if (mb->get_button_index() == MouseButton::RIGHT) {
terrain_set = -1;
}
dict["terrain_peering_bits"] = array;
drag_modified[cell] = dict;
tile_data->set_terrain_set(drag_painted_value);
}
drag_last_pos = mb->get_position();
} else if (tile_data->get_terrain_set() == terrain_set) {
// Paint terrain bits.
drag_type = DRAG_TYPE_PAINT_TERRAIN_BITS;
drag_modified.clear();
Dictionary painted_dict;
painted_dict["terrain_set"] = terrain_set;
painted_dict["terrain"] = terrain;
drag_painted_value = painted_dict;
if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
TileMapCell cell;
cell.source_id = 0;
cell.set_atlas_coords(coords);
cell.alternative_tile = alternative_tile;
// Save the old terrain_set and terrains bits.
Dictionary dict;
dict["terrain_set"] = tile_data->get_terrain_set();
dict["terrain"] = tile_data->get_terrain();
Array array;
for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
array.push_back(tile_data->is_valid_terrain_peering_bit(bit) ? tile_data->get_terrain_peering_bit(bit) : -1);
drag_type = DRAG_TYPE_PAINT_TERRAIN_SET;
drag_modified.clear();
drag_painted_value = int(dummy_object->get("terrain_set"));
if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
TileMapCell cell;
cell.source_id = 0;
cell.set_atlas_coords(coords);
cell.alternative_tile = alternative_tile;
Dictionary dict;
dict["terrain_set"] = tile_data->get_terrain_set();
Array array;
for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
array.push_back(tile_data->is_valid_terrain_peering_bit(bit) ? tile_data->get_terrain_peering_bit(bit) : -1);
}
dict["terrain_peering_bits"] = array;
drag_modified[cell] = dict;
tile_data->set_terrain_set(drag_painted_value);
}
dict["terrain_peering_bits"] = array;
drag_modified[cell] = dict;
// Set the terrain bit.
Rect2i texture_region = p_tile_atlas_view->get_alternative_tile_rect(coords, alternative_tile);
Vector2i position = texture_region.get_center() + p_tile_set_atlas_source->get_tile_effective_texture_offset(coords, alternative_tile);
Vector<Vector2> polygon = tile_set->get_terrain_polygon(terrain_set);
if (Geometry2D::is_point_in_polygon(mb->get_position() - position, polygon)) {
tile_data->set_terrain(terrain);
drag_last_pos = mb->get_position();
accept_event();
} else if (tile_data->get_terrain_set() == terrain_set) {
// Paint terrain bits.
if (mb->get_button_index() == MouseButton::RIGHT) {
terrain = -1;
}
for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
if (tile_set->is_valid_terrain_peering_bit(terrain_set, bit)) {
polygon = tile_set->get_terrain_peering_bit_polygon(terrain_set, bit);
if (Geometry2D::is_point_in_polygon(mb->get_position() - position, polygon)) {
tile_data->set_terrain_peering_bit(bit, terrain);
// Paint terrain bits.
drag_type = DRAG_TYPE_PAINT_TERRAIN_BITS;
drag_modified.clear();
Dictionary painted_dict;
painted_dict["terrain_set"] = terrain_set;
painted_dict["terrain"] = terrain;
drag_painted_value = painted_dict;
if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
TileMapCell cell;
cell.source_id = 0;
cell.set_atlas_coords(coords);
cell.alternative_tile = alternative_tile;
// Save the old terrain_set and terrains bits.
Dictionary dict;
dict["terrain_set"] = tile_data->get_terrain_set();
dict["terrain"] = tile_data->get_terrain();
Array array;
for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
array.push_back(tile_data->is_valid_terrain_peering_bit(bit) ? tile_data->get_terrain_peering_bit(bit) : -1);
}
dict["terrain_peering_bits"] = array;
drag_modified[cell] = dict;
// Set the terrain bit.
Rect2i texture_region = p_tile_atlas_view->get_alternative_tile_rect(coords, alternative_tile);
Vector2i position = texture_region.get_center() + p_tile_set_atlas_source->get_tile_effective_texture_offset(coords, alternative_tile);
Vector<Vector2> polygon = tile_set->get_terrain_polygon(terrain_set);
if (Geometry2D::is_point_in_polygon(mb->get_position() - position, polygon)) {
tile_data->set_terrain(terrain);
}
for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
if (tile_set->is_valid_terrain_peering_bit(terrain_set, bit)) {
polygon = tile_set->get_terrain_peering_bit_polygon(terrain_set, bit);
if (Geometry2D::is_point_in_polygon(mb->get_position() - position, polygon)) {
tile_data->set_terrain_peering_bit(bit, terrain);
}
}
}
}
drag_last_pos = mb->get_position();
accept_event();
}
drag_last_pos = mb->get_position();
}
}
} else {
@ -2523,16 +2559,19 @@ void TileDataTerrainsEditor::forward_painting_alternatives_gui_input(TileAtlasVi
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);
undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrain", coords.x, coords.y, E.key.alternative_tile), dict["terrain"]);
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/terrain_set", coords.x, coords.y, E.key.alternative_tile), dict["terrain_set"]);
if (int(dict["terrain_set"]) >= 0) {
undo_redo->add_undo_property(p_tile_set_atlas_source, vformat("%d:%d/%d/terrain", coords.x, coords.y, E.key.alternative_tile), dict["terrain"]);
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->commit_action(false);
drag_type = DRAG_TYPE_NONE;
accept_event();
} else if (drag_type == DRAG_TYPE_PAINT_TERRAIN_BITS) {
Dictionary painted = Dictionary(drag_painted_value);
int terrain_set = int(painted["terrain_set"]);
@ -2556,6 +2595,7 @@ void TileDataTerrainsEditor::forward_painting_alternatives_gui_input(TileAtlasVi
}
undo_redo->commit_action(false);
drag_type = DRAG_TYPE_NONE;
accept_event();
}
}
}

View file

@ -5275,6 +5275,7 @@ void TileData::set_terrain_set(int p_terrain_set) {
}
if (tile_set) {
ERR_FAIL_COND(p_terrain_set >= tile_set->get_terrain_sets_count());
terrain = -1;
for (int i = 0; i < 16; i++) {
terrain_peering_bits[i] = -1;
}