Support auto create tiles when adding multiple atlases
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`
This commit is contained in:
parent
ff5c884153
commit
c8a94ea3e8
|
@ -1672,6 +1672,8 @@ void TileSetAtlasSourceEditor::_menu_option(int p_option) {
|
||||||
_update_tile_id_label();
|
_update_tile_id_label();
|
||||||
} break;
|
} break;
|
||||||
case ADVANCED_AUTO_CREATE_TILES: {
|
case ADVANCED_AUTO_CREATE_TILES: {
|
||||||
|
atlases_to_auto_create_tiles.clear();
|
||||||
|
atlases_to_auto_create_tiles.append(tile_set_atlas_source);
|
||||||
_auto_create_tiles();
|
_auto_create_tiles();
|
||||||
} break;
|
} break;
|
||||||
case ADVANCED_AUTO_REMOVE_TILES: {
|
case ADVANCED_AUTO_REMOVE_TILES: {
|
||||||
|
@ -2096,6 +2098,8 @@ void TileSetAtlasSourceEditor::_tile_proxy_object_changed(String p_what) {
|
||||||
|
|
||||||
void TileSetAtlasSourceEditor::_atlas_source_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()) {
|
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();
|
confirm_auto_create_tiles->popup_centered();
|
||||||
} else if (p_what == "id") {
|
} else if (p_what == "id") {
|
||||||
emit_signal(SNAME("source_id_changed"), atlas_source_proxy_object->get_id());
|
emit_signal(SNAME("source_id_changed"), atlas_source_proxy_object->get_id());
|
||||||
|
@ -2242,54 +2246,61 @@ void TileSetAtlasSourceEditor::edit(Ref<TileSet> p_tile_set, TileSetAtlasSource
|
||||||
_update_current_tile_data_editor();
|
_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);
|
tool_setup_atlas_source_button->set_pressed(true);
|
||||||
|
atlases_to_auto_create_tiles = p_atlases;
|
||||||
confirm_auto_create_tiles->popup_centered();
|
confirm_auto_create_tiles->popup_centered();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TileSetAtlasSourceEditor::_auto_create_tiles() {
|
void TileSetAtlasSourceEditor::_auto_create_tiles() {
|
||||||
if (!tile_set_atlas_source) {
|
for (Ref<TileSetAtlasSource> &atlas_source : atlases_to_auto_create_tiles) {
|
||||||
return;
|
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 we do have opaque pixels, create a tile.
|
||||||
if (texture.is_valid()) {
|
if (is_opaque) {
|
||||||
Vector2i margins = tile_set_atlas_source->get_margins();
|
undo_redo->add_do_method(*atlas_source, "create_tile", coords);
|
||||||
Vector2i separation = tile_set_atlas_source->get_separation();
|
undo_redo->add_undo_method(*atlas_source, "remove_tile", coords);
|
||||||
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 (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() {
|
void TileSetAtlasSourceEditor::_auto_remove_tiles() {
|
||||||
|
@ -2644,6 +2655,7 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() {
|
||||||
confirm_auto_create_tiles->set_ok_button_text(TTR("Yes"));
|
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->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("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);
|
add_child(confirm_auto_create_tiles);
|
||||||
|
|
||||||
// Inspector plugin.
|
// Inspector plugin.
|
||||||
|
|
|
@ -270,7 +270,9 @@ private:
|
||||||
// -- Misc --
|
// -- Misc --
|
||||||
void _auto_create_tiles();
|
void _auto_create_tiles();
|
||||||
void _auto_remove_tiles();
|
void _auto_remove_tiles();
|
||||||
|
void _cancel_auto_create_tiles();
|
||||||
AcceptDialog *confirm_auto_create_tiles = nullptr;
|
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;
|
Vector2i _get_drag_offset_tile_coords(const Vector2i &p_offset) const;
|
||||||
|
|
||||||
void _tile_set_changed();
|
void _tile_set_changed();
|
||||||
|
@ -288,7 +290,7 @@ protected:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void edit(Ref<TileSet> p_tile_set, TileSetAtlasSource *p_tile_set_source, int p_source_id);
|
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();
|
||||||
~TileSetAtlasSourceEditor();
|
~TileSetAtlasSourceEditor();
|
||||||
|
|
|
@ -57,35 +57,9 @@ void TileSetEditor::_drop_data_fw(const Point2 &p_point, const Variant &p_data,
|
||||||
|
|
||||||
if (p_from == sources_list) {
|
if (p_from == sources_list) {
|
||||||
// Handle dropping a texture in the list of atlas resources.
|
// Handle dropping a texture in the list of atlas resources.
|
||||||
int source_id = TileSet::INVALID_SOURCE;
|
|
||||||
int added = 0;
|
|
||||||
Dictionary d = p_data;
|
Dictionary d = p_data;
|
||||||
Vector<String> files = d["files"];
|
Vector<String> files = d["files"];
|
||||||
for (int i = 0; i < files.size(); i++) {
|
_load_texture_files(files);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,6 +100,43 @@ bool TileSetEditor::_can_drop_data_fw(const Point2 &p_point, const Variant &p_da
|
||||||
return false;
|
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) {
|
void TileSetEditor::_update_sources_list(int force_selected_id) {
|
||||||
if (tile_set.is_null()) {
|
if (tile_set.is_null()) {
|
||||||
return;
|
return;
|
||||||
|
@ -226,30 +237,6 @@ void TileSetEditor::_update_sources_list(int force_selected_id) {
|
||||||
TilesEditorUtils::get_singleton()->set_sources_lists_current(sources_list->get_current());
|
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) {
|
void TileSetEditor::_source_selected(int p_source_index) {
|
||||||
ERR_FAIL_COND(!tile_set.is_valid());
|
ERR_FAIL_COND(!tile_set.is_valid());
|
||||||
|
|
||||||
|
@ -308,8 +295,8 @@ void TileSetEditor::_source_add_id_pressed(int p_id_pressed) {
|
||||||
if (!texture_file_dialog) {
|
if (!texture_file_dialog) {
|
||||||
texture_file_dialog = memnew(EditorFileDialog);
|
texture_file_dialog = memnew(EditorFileDialog);
|
||||||
add_child(texture_file_dialog);
|
add_child(texture_file_dialog);
|
||||||
texture_file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE);
|
texture_file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILES);
|
||||||
texture_file_dialog->connect("file_selected", callable_mp(this, &TileSetEditor::_texture_file_selected));
|
texture_file_dialog->connect("files_selected", callable_mp(this, &TileSetEditor::_load_texture_files));
|
||||||
|
|
||||||
List<String> extensions;
|
List<String> extensions;
|
||||||
ResourceLoader::get_recognized_extensions_for_type("Texture2D", &extensions);
|
ResourceLoader::get_recognized_extensions_for_type("Texture2D", &extensions);
|
||||||
|
|
|
@ -68,6 +68,7 @@ private:
|
||||||
|
|
||||||
void _drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);
|
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;
|
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);
|
void _update_sources_list(int force_selected_id = -1);
|
||||||
|
|
||||||
|
@ -78,7 +79,6 @@ private:
|
||||||
MenuButton *sources_advanced_menu_button = nullptr;
|
MenuButton *sources_advanced_menu_button = nullptr;
|
||||||
ItemList *sources_list = nullptr;
|
ItemList *sources_list = nullptr;
|
||||||
Ref<Texture2D> missing_texture_texture;
|
Ref<Texture2D> missing_texture_texture;
|
||||||
void _texture_file_selected(const String &p_path);
|
|
||||||
void _source_selected(int p_source_index);
|
void _source_selected(int p_source_index);
|
||||||
void _source_delete_pressed();
|
void _source_delete_pressed();
|
||||||
void _source_add_id_pressed(int p_id_pressed);
|
void _source_add_id_pressed(int p_id_pressed);
|
||||||
|
|
Loading…
Reference in New Issue