Skip to content

Commit

Permalink
Support auto create tiles when adding multiple atlases
Browse files Browse the repository at this point in the history
TileSet add button support multiple files
Join most of the code of `_drop_data_fw()` and `_texture_file_selected()` in a new function `_load_texture_files()`
Rename `init_source` to `init_new_atlases`
  • Loading branch information
thiagola92 committed Aug 27, 2023
1 parent ff5c884 commit c8a94ea
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 90 deletions.
82 changes: 47 additions & 35 deletions editor/plugins/tiles/tile_set_atlas_source_editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1672,6 +1672,8 @@ void TileSetAtlasSourceEditor::_menu_option(int p_option) {
_update_tile_id_label();
} break;
case ADVANCED_AUTO_CREATE_TILES: {
atlases_to_auto_create_tiles.clear();
atlases_to_auto_create_tiles.append(tile_set_atlas_source);
_auto_create_tiles();
} break;
case ADVANCED_AUTO_REMOVE_TILES: {
Expand Down Expand Up @@ -2096,6 +2098,8 @@ void TileSetAtlasSourceEditor::_tile_proxy_object_changed(String p_what) {

void TileSetAtlasSourceEditor::_atlas_source_proxy_object_changed(String p_what) {
if (p_what == "texture" && !atlas_source_proxy_object->get("texture").is_null()) {
atlases_to_auto_create_tiles.clear();
atlases_to_auto_create_tiles.append(tile_set_atlas_source);
confirm_auto_create_tiles->popup_centered();
} else if (p_what == "id") {
emit_signal(SNAME("source_id_changed"), atlas_source_proxy_object->get_id());
Expand Down Expand Up @@ -2242,54 +2246,61 @@ void TileSetAtlasSourceEditor::edit(Ref<TileSet> p_tile_set, TileSetAtlasSource
_update_current_tile_data_editor();
}

void TileSetAtlasSourceEditor::init_source() {
void TileSetAtlasSourceEditor::init_new_atlases(const Vector<Ref<TileSetAtlasSource>> &p_atlases) {
tool_setup_atlas_source_button->set_pressed(true);
atlases_to_auto_create_tiles = p_atlases;
confirm_auto_create_tiles->popup_centered();
}

void TileSetAtlasSourceEditor::_auto_create_tiles() {
if (!tile_set_atlas_source) {
return;
}
for (Ref<TileSetAtlasSource> &atlas_source : atlases_to_auto_create_tiles) {
if (atlas_source.is_valid()) {
Ref<Texture2D> texture = atlas_source->get_texture();
if (texture.is_valid()) {
Vector2i margins = atlas_source->get_margins();
Vector2i separation = atlas_source->get_separation();
Vector2i texture_region_size = atlas_source->get_texture_region_size();
Size2i grid_size = atlas_source->get_atlas_grid_size();
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
undo_redo->create_action(TTR("Create tiles in non-transparent texture regions"));
for (int y = 0; y < grid_size.y; y++) {
for (int x = 0; x < grid_size.x; x++) {
// Check if we have a tile at the coord.
Vector2i coords = Vector2i(x, y);
if (atlas_source->get_tile_at_coords(coords) == TileSetSource::INVALID_ATLAS_COORDS) {
// Check if the texture is empty at the given coords.
Rect2i region = Rect2i(margins + (coords * (texture_region_size + separation)), texture_region_size);
bool is_opaque = false;
for (int region_x = region.get_position().x; region_x < region.get_end().x; region_x++) {
for (int region_y = region.get_position().y; region_y < region.get_end().y; region_y++) {
if (texture->is_pixel_opaque(region_x, region_y)) {
is_opaque = true;
break;
}
}
if (is_opaque) {
break;
}
}

Ref<Texture2D> texture = tile_set_atlas_source->get_texture();
if (texture.is_valid()) {
Vector2i margins = tile_set_atlas_source->get_margins();
Vector2i separation = tile_set_atlas_source->get_separation();
Vector2i texture_region_size = tile_set_atlas_source->get_texture_region_size();
Size2i grid_size = tile_set_atlas_source->get_atlas_grid_size();
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
undo_redo->create_action(TTR("Create tiles in non-transparent texture regions"));
for (int y = 0; y < grid_size.y; y++) {
for (int x = 0; x < grid_size.x; x++) {
// Check if we have a tile at the coord
Vector2i coords = Vector2i(x, y);
if (tile_set_atlas_source->get_tile_at_coords(coords) == TileSetSource::INVALID_ATLAS_COORDS) {
// Check if the texture is empty at the given coords.
Rect2i region = Rect2i(margins + (coords * (texture_region_size + separation)), texture_region_size);
bool is_opaque = false;
for (int region_x = region.get_position().x; region_x < region.get_end().x; region_x++) {
for (int region_y = region.get_position().y; region_y < region.get_end().y; region_y++) {
if (texture->is_pixel_opaque(region_x, region_y)) {
is_opaque = true;
break;
// If we do have opaque pixels, create a tile.
if (is_opaque) {
undo_redo->add_do_method(*atlas_source, "create_tile", coords);
undo_redo->add_undo_method(*atlas_source, "remove_tile", coords);
}
}
if (is_opaque) {
break;
}
}

// If we do have opaque pixels, create a tile.
if (is_opaque) {
undo_redo->add_do_method(tile_set_atlas_source, "create_tile", coords);
undo_redo->add_undo_method(tile_set_atlas_source, "remove_tile", coords);
}
}
undo_redo->commit_action();
}
}
undo_redo->commit_action();
}

_cancel_auto_create_tiles();
}

void TileSetAtlasSourceEditor::_cancel_auto_create_tiles() {
atlases_to_auto_create_tiles.clear();
}

void TileSetAtlasSourceEditor::_auto_remove_tiles() {
Expand Down Expand Up @@ -2644,6 +2655,7 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() {
confirm_auto_create_tiles->set_ok_button_text(TTR("Yes"));
confirm_auto_create_tiles->add_cancel_button()->set_text(TTR("No"));
confirm_auto_create_tiles->connect("confirmed", callable_mp(this, &TileSetAtlasSourceEditor::_auto_create_tiles));
confirm_auto_create_tiles->connect("canceled", callable_mp(this, &TileSetAtlasSourceEditor::_cancel_auto_create_tiles));
add_child(confirm_auto_create_tiles);

// Inspector plugin.
Expand Down
4 changes: 3 additions & 1 deletion editor/plugins/tiles/tile_set_atlas_source_editor.h
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,9 @@ class TileSetAtlasSourceEditor : public HSplitContainer {
// -- Misc --
void _auto_create_tiles();
void _auto_remove_tiles();
void _cancel_auto_create_tiles();
AcceptDialog *confirm_auto_create_tiles = nullptr;
Vector<Ref<TileSetAtlasSource>> atlases_to_auto_create_tiles;
Vector2i _get_drag_offset_tile_coords(const Vector2i &p_offset) const;

void _tile_set_changed();
Expand All @@ -288,7 +290,7 @@ class TileSetAtlasSourceEditor : public HSplitContainer {

public:
void edit(Ref<TileSet> p_tile_set, TileSetAtlasSource *p_tile_set_source, int p_source_id);
void init_source();
void init_new_atlases(const Vector<Ref<TileSetAtlasSource>> &p_atlases);

TileSetAtlasSourceEditor();
~TileSetAtlasSourceEditor();
Expand Down
93 changes: 40 additions & 53 deletions editor/plugins/tiles/tile_set_editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,35 +57,9 @@ void TileSetEditor::_drop_data_fw(const Point2 &p_point, const Variant &p_data,

if (p_from == sources_list) {
// Handle dropping a texture in the list of atlas resources.
int source_id = TileSet::INVALID_SOURCE;
int added = 0;
Dictionary d = p_data;
Vector<String> files = d["files"];
for (int i = 0; i < files.size(); i++) {
Ref<Texture2D> resource = ResourceLoader::load(files[i]);
if (resource.is_valid()) {
// Retrieve the id for the next created source.
source_id = tile_set->get_next_source_id();

// Actually create the new source.
Ref<TileSetAtlasSource> atlas_source = memnew(TileSetAtlasSource);
atlas_source->set_texture(resource);
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
undo_redo->create_action(TTR("Add a new atlas source"));
undo_redo->add_do_method(*tile_set, "add_source", atlas_source, source_id);
undo_redo->add_do_method(*atlas_source, "set_texture_region_size", tile_set->get_tile_size());
undo_redo->add_undo_method(*tile_set, "remove_source", source_id);
undo_redo->commit_action();
added += 1;
}
}

if (added == 1) {
tile_set_atlas_source_editor->init_source();
}

// Update the selected source (thus triggering an update).
_update_sources_list(source_id);
_load_texture_files(files);
}
}

Expand Down Expand Up @@ -126,6 +100,43 @@ bool TileSetEditor::_can_drop_data_fw(const Point2 &p_point, const Variant &p_da
return false;
}

void TileSetEditor::_load_texture_files(const Vector<String> &p_paths) {
int source_id = TileSet::INVALID_SOURCE;
Vector<Ref<TileSetAtlasSource>> atlases;

for (const String &p_path : p_paths) {
Ref<Texture2D> texture = ResourceLoader::load(p_path);

if (texture.is_null()) {
EditorNode::get_singleton()->show_warning(TTR("Invalid texture selected."));
continue;
}

// Retrieve the id for the next created source.
source_id = tile_set->get_next_source_id();

// Actually create the new source.
Ref<TileSetAtlasSource> atlas_source = memnew(TileSetAtlasSource);
atlas_source->set_texture(texture);

EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
undo_redo->create_action(TTR("Add a new atlas source"));
undo_redo->add_do_method(*tile_set, "add_source", atlas_source, source_id);
undo_redo->add_do_method(*atlas_source, "set_texture_region_size", tile_set->get_tile_size());
undo_redo->add_undo_method(*tile_set, "remove_source", source_id);
undo_redo->commit_action();

atlases.append(atlas_source);
}

if (!atlases.is_empty()) {
tile_set_atlas_source_editor->init_new_atlases(atlases);
}

// Update the selected source (thus triggering an update).
_update_sources_list(source_id);
}

void TileSetEditor::_update_sources_list(int force_selected_id) {
if (tile_set.is_null()) {
return;
Expand Down Expand Up @@ -226,30 +237,6 @@ void TileSetEditor::_update_sources_list(int force_selected_id) {
TilesEditorUtils::get_singleton()->set_sources_lists_current(sources_list->get_current());
}

void TileSetEditor::_texture_file_selected(const String &p_path) {
Ref<Texture2D> texture = ResourceLoader::load(p_path);
if (texture.is_null()) {
EditorNode::get_singleton()->show_warning(TTR("Invalid texture selected."));
return;
}

int source_id = tile_set->get_next_source_id();

Ref<TileSetAtlasSource> atlas_source = memnew(TileSetAtlasSource);
atlas_source->set_texture(texture);

// Add a new source.
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
undo_redo->create_action(TTR("Add atlas source"));
undo_redo->add_do_method(*tile_set, "add_source", atlas_source, source_id);
undo_redo->add_do_method(*atlas_source, "set_texture_region_size", tile_set->get_tile_size());
undo_redo->add_undo_method(*tile_set, "remove_source", source_id);
undo_redo->commit_action();

_update_sources_list(source_id);
tile_set_atlas_source_editor->init_source();
}

void TileSetEditor::_source_selected(int p_source_index) {
ERR_FAIL_COND(!tile_set.is_valid());

Expand Down Expand Up @@ -308,8 +295,8 @@ void TileSetEditor::_source_add_id_pressed(int p_id_pressed) {
if (!texture_file_dialog) {
texture_file_dialog = memnew(EditorFileDialog);
add_child(texture_file_dialog);
texture_file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE);
texture_file_dialog->connect("file_selected", callable_mp(this, &TileSetEditor::_texture_file_selected));
texture_file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILES);
texture_file_dialog->connect("files_selected", callable_mp(this, &TileSetEditor::_load_texture_files));

List<String> extensions;
ResourceLoader::get_recognized_extensions_for_type("Texture2D", &extensions);
Expand Down
2 changes: 1 addition & 1 deletion editor/plugins/tiles/tile_set_editor.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ class TileSetEditor : public Control {

void _drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);
bool _can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const;
void _load_texture_files(const Vector<String> &p_paths);

void _update_sources_list(int force_selected_id = -1);

Expand All @@ -78,7 +79,6 @@ class TileSetEditor : public Control {
MenuButton *sources_advanced_menu_button = nullptr;
ItemList *sources_list = nullptr;
Ref<Texture2D> missing_texture_texture;
void _texture_file_selected(const String &p_path);
void _source_selected(int p_source_index);
void _source_delete_pressed();
void _source_add_id_pressed(int p_id_pressed);
Expand Down

0 comments on commit c8a94ea

Please sign in to comment.