mirror of
				https://github.com/godotengine/godot.git
				synced 2025-10-31 05:31:01 +00:00 
			
		
		
		
	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
					
				
					 4 changed files with 91 additions and 90 deletions
				
			
		|  | @ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 thiagola92
						thiagola92